summaryrefslogtreecommitdiff
path: root/networking/zcip.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 23:40:26 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 23:40:26 +0000
commitbd7bb299c0e9ee5ff52c9d12b46fb14a907b34da (patch)
tree117a635e9457e1a932bc64941db5869e33179fc9 /networking/zcip.c
parent459be35234cc24b69309eb0ee22600024c73713e (diff)
downloadbusybox-w32-bd7bb299c0e9ee5ff52c9d12b46fb14a907b34da.tar.gz
busybox-w32-bd7bb299c0e9ee5ff52c9d12b46fb14a907b34da.tar.bz2
busybox-w32-bd7bb299c0e9ee5ff52c9d12b46fb14a907b34da.zip
wget: use monotonic_sec instead of gettimeofday
zcip: use monotonic_us instead of gettimeofday udhcpcd: simpler, shorter random_xid() function old new delta monotonic_sec - 41 +41 find_pair 164 180 +16 run_list_real 2018 2028 +10 cmp_main 547 555 +8 collect_ctx 112 119 +7 singlemount 4544 4549 +5 time_main 1124 1128 +4 static.start_sec - 4 +4 static.lastupdate_sec - 4 +4 sock - 4 +4 read_package_field 253 257 +4 pick 38 40 +2 get_next_line 145 147 +2 count_lines 59 61 +2 process_stdin 435 433 -2 xstrtoul_range_sfx 229 226 -3 static.initialized 4 1 -3 dhcprelay_main 1125 1122 -3 catcher 380 377 -3 arping_main 1969 1966 -3 s 8 4 -4 cfg 4 - -4 static.lastupdate 8 - -8 start 8 - -8 random_xid 95 33 -62 .rodata 129114 129050 -64 zcip_main 1731 1576 -155 progressmeter 1035 867 -168 ------------------------------------------------------------------------------ (add/remove: 4/3 grow/shrink: 10/11 up/down: 113/-490) Total: -377 bytes
Diffstat (limited to 'networking/zcip.c')
-rw-r--r--networking/zcip.c115
1 files changed, 53 insertions, 62 deletions
diff --git a/networking/zcip.c b/networking/zcip.c
index eb0a7ba41..de4ee0b1a 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -23,7 +23,6 @@
23// - avoid silent script failures, especially under load... 23// - avoid silent script failures, especially under load...
24// - link status monitoring (restart on link-up; stop on link-down) 24// - link status monitoring (restart on link-up; stop on link-down)
25 25
26#include "libbb.h"
27#include <syslog.h> 26#include <syslog.h>
28#include <poll.h> 27#include <poll.h>
29#include <sys/wait.h> 28#include <sys/wait.h>
@@ -31,10 +30,13 @@
31#include <net/ethernet.h> 30#include <net/ethernet.h>
32#include <net/if.h> 31#include <net/if.h>
33#include <net/if_arp.h> 32#include <net/if_arp.h>
34
35#include <linux/if_packet.h> 33#include <linux/if_packet.h>
36#include <linux/sockios.h> 34#include <linux/sockios.h>
37 35
36#include "libbb.h"
37
38/* We don't need more than 32 bits of the counter */
39#define MONOTONIC_US() ((unsigned)monotonic_us())
38 40
39struct arp_packet { 41struct arp_packet {
40 struct ether_header hdr; 42 struct ether_header hdr;
@@ -78,15 +80,12 @@ static void pick(struct in_addr *ip)
78{ 80{
79 unsigned tmp; 81 unsigned tmp;
80 82
81 /* use cheaper math than lrand48() mod N */
82 do { 83 do {
83 tmp = (lrand48() >> 16) & IN_CLASSB_HOST; 84 tmp = rand() & IN_CLASSB_HOST;
84 } while (tmp > (IN_CLASSB_HOST - 0x0200)); 85 } while (tmp > (IN_CLASSB_HOST - 0x0200));
85 ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp); 86 ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
86} 87}
87 88
88/* TODO: we need a flag to direct bb_[p]error_msg output to stderr. */
89
90/** 89/**
91 * Broadcast an ARP packet. 90 * Broadcast an ARP packet.
92 */ 91 */
@@ -151,7 +150,7 @@ static int run(char *argv[3], const char *intf, struct in_addr *ip)
151 */ 150 */
152static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs) 151static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs)
153{ 152{
154 return lrand48() % (secs * 1000); 153 return rand() % (secs * 1000);
155} 154}
156 155
157/** 156/**
@@ -176,29 +175,31 @@ int zcip_main(int argc, char **argv)
176 struct ifreq ifr; 175 struct ifreq ifr;
177 char *intf; 176 char *intf;
178 char *script_av[3]; 177 char *script_av[3];
179 suseconds_t timeout; // milliseconds 178 int timeout_ms; /* must be signed */
180 unsigned conflicts; 179 unsigned conflicts;
181 unsigned nprobes; 180 unsigned nprobes;
182 unsigned nclaims; 181 unsigned nclaims;
183 int ready; 182 int ready;
184 int verbose; 183 int verbose;
185 } L; 184 } L;
186#define null_ip (L.null_ip ) 185#define null_ip (L.null_ip )
187#define null_addr (L.null_addr) 186#define null_addr (L.null_addr )
188#define saddr (L.saddr ) 187#define saddr (L.saddr )
189#define ip (L.ip ) 188#define ip (L.ip )
190#define ifr (L.ifr ) 189#define ifr (L.ifr )
191#define intf (L.intf ) 190#define intf (L.intf )
192#define script_av (L.script_av) 191#define script_av (L.script_av )
193#define timeout (L.timeout ) 192#define timeout_ms (L.timeout_ms)
194#define conflicts (L.conflicts) 193#define conflicts (L.conflicts )
195#define nprobes (L.nprobes ) 194#define nprobes (L.nprobes )
196#define nclaims (L.nclaims ) 195#define nclaims (L.nclaims )
197#define ready (L.ready ) 196#define ready (L.ready )
198#define verbose (L.verbose ) 197#define verbose (L.verbose )
199 198
200 memset(&L, 0, sizeof(L)); 199 memset(&L, 0, sizeof(L));
201 200
201 srand(MONOTONIC_US());
202
202#define FOREGROUND (opts & 1) 203#define FOREGROUND (opts & 1)
203#define QUIT (opts & 2) 204#define QUIT (opts & 2)
204 // parse commandline: prog [options] ifname script 205 // parse commandline: prog [options] ifname script
@@ -282,7 +283,7 @@ int zcip_main(int argc, char **argv)
282 // - defend it, within limits 283 // - defend it, within limits
283 while (1) { 284 while (1) {
284 struct pollfd fds[1]; 285 struct pollfd fds[1];
285 struct timeval tv1; 286 unsigned deadline_us;
286 struct arp_packet p; 287 struct arp_packet p;
287 288
288 int source_ip_conflict = 0; 289 int source_ip_conflict = 0;
@@ -293,24 +294,18 @@ int zcip_main(int argc, char **argv)
293 fds[0].revents = 0; 294 fds[0].revents = 0;
294 295
295 // poll, being ready to adjust current timeout 296 // poll, being ready to adjust current timeout
296 if (!timeout) { 297 if (!timeout_ms) {
297 timeout = ms_rdelay(PROBE_WAIT); 298 timeout_ms = ms_rdelay(PROBE_WAIT);
298 // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to 299 // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
299 // make the kernel filter out all packets except 300 // make the kernel filter out all packets except
300 // ones we'd care about. 301 // ones we'd care about.
301 } 302 }
302 // set tv1 to the point in time when we timeout 303 // set deadline_us to the point in time when we timeout
303 gettimeofday(&tv1, NULL); 304 deadline_us = MONOTONIC_US() + timeout_ms * 1000;
304 tv1.tv_usec += (timeout % 1000) * 1000;
305 while (tv1.tv_usec > 1000000) {
306 tv1.tv_usec -= 1000000;
307 tv1.tv_sec++;
308 }
309 tv1.tv_sec += timeout / 1000;
310 305
311 VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n", 306 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
312 timeout, intf, nprobes, nclaims); 307 timeout_ms, intf, nprobes, nclaims);
313 switch (poll(fds, 1, timeout)) { 308 switch (poll(fds, 1, timeout_ms)) {
314 309
315 // timeout 310 // timeout
316 case 0: 311 case 0:
@@ -321,25 +316,24 @@ int zcip_main(int argc, char **argv)
321 // have been received, so we can progress through the states 316 // have been received, so we can progress through the states
322 if (nprobes < PROBE_NUM) { 317 if (nprobes < PROBE_NUM) {
323 nprobes++; 318 nprobes++;
324 VDBG("probe/%d %s@%s\n", 319 VDBG("probe/%u %s@%s\n",
325 nprobes, intf, inet_ntoa(ip)); 320 nprobes, intf, inet_ntoa(ip));
326 arp(fd, &saddr, ARPOP_REQUEST, 321 arp(fd, &saddr, ARPOP_REQUEST,
327 &eth_addr, null_ip, 322 &eth_addr, null_ip,
328 &null_addr, ip); 323 &null_addr, ip);
329 timeout = PROBE_MIN * 1000; 324 timeout_ms = PROBE_MIN * 1000;
330 timeout += ms_rdelay(PROBE_MAX 325 timeout_ms += ms_rdelay(PROBE_MAX - PROBE_MIN);
331 - PROBE_MIN);
332 } 326 }
333 else { 327 else {
334 // Switch to announce state. 328 // Switch to announce state.
335 state = ANNOUNCE; 329 state = ANNOUNCE;
336 nclaims = 0; 330 nclaims = 0;
337 VDBG("announce/%d %s@%s\n", 331 VDBG("announce/%u %s@%s\n",
338 nclaims, intf, inet_ntoa(ip)); 332 nclaims, intf, inet_ntoa(ip));
339 arp(fd, &saddr, ARPOP_REQUEST, 333 arp(fd, &saddr, ARPOP_REQUEST,
340 &eth_addr, ip, 334 &eth_addr, ip,
341 &eth_addr, ip); 335 &eth_addr, ip);
342 timeout = ANNOUNCE_INTERVAL * 1000; 336 timeout_ms = ANNOUNCE_INTERVAL * 1000;
343 } 337 }
344 break; 338 break;
345 case RATE_LIMIT_PROBE: 339 case RATE_LIMIT_PROBE:
@@ -347,24 +341,24 @@ int zcip_main(int argc, char **argv)
347 // have been received, so we can move immediately to the announce state 341 // have been received, so we can move immediately to the announce state
348 state = ANNOUNCE; 342 state = ANNOUNCE;
349 nclaims = 0; 343 nclaims = 0;
350 VDBG("announce/%d %s@%s\n", 344 VDBG("announce/%u %s@%s\n",
351 nclaims, intf, inet_ntoa(ip)); 345 nclaims, intf, inet_ntoa(ip));
352 arp(fd, &saddr, ARPOP_REQUEST, 346 arp(fd, &saddr, ARPOP_REQUEST,
353 &eth_addr, ip, 347 &eth_addr, ip,
354 &eth_addr, ip); 348 &eth_addr, ip);
355 timeout = ANNOUNCE_INTERVAL * 1000; 349 timeout_ms = ANNOUNCE_INTERVAL * 1000;
356 break; 350 break;
357 case ANNOUNCE: 351 case ANNOUNCE:
358 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 352 // timeouts in the ANNOUNCE state mean no conflicting ARP packets
359 // have been received, so we can progress through the states 353 // have been received, so we can progress through the states
360 if (nclaims < ANNOUNCE_NUM) { 354 if (nclaims < ANNOUNCE_NUM) {
361 nclaims++; 355 nclaims++;
362 VDBG("announce/%d %s@%s\n", 356 VDBG("announce/%u %s@%s\n",
363 nclaims, intf, inet_ntoa(ip)); 357 nclaims, intf, inet_ntoa(ip));
364 arp(fd, &saddr, ARPOP_REQUEST, 358 arp(fd, &saddr, ARPOP_REQUEST,
365 &eth_addr, ip, 359 &eth_addr, ip,
366 &eth_addr, ip); 360 &eth_addr, ip);
367 timeout = ANNOUNCE_INTERVAL * 1000; 361 timeout_ms = ANNOUNCE_INTERVAL * 1000;
368 } 362 }
369 else { 363 else {
370 // Switch to monitor state. 364 // Switch to monitor state.
@@ -375,7 +369,7 @@ int zcip_main(int argc, char **argv)
375 run(script_av, intf, &ip); 369 run(script_av, intf, &ip);
376 ready = 1; 370 ready = 1;
377 conflicts = 0; 371 conflicts = 0;
378 timeout = -1; // Never timeout in the monitor state. 372 timeout_ms = -1; // Never timeout in the monitor state.
379 373
380 // NOTE: all other exit paths 374 // NOTE: all other exit paths
381 // should deconfig ... 375 // should deconfig ...
@@ -386,14 +380,14 @@ int zcip_main(int argc, char **argv)
386 case DEFEND: 380 case DEFEND:
387 // We won! No ARP replies, so just go back to monitor. 381 // We won! No ARP replies, so just go back to monitor.
388 state = MONITOR; 382 state = MONITOR;
389 timeout = -1; 383 timeout_ms = -1;
390 conflicts = 0; 384 conflicts = 0;
391 break; 385 break;
392 default: 386 default:
393 // Invalid, should never happen. Restart the whole protocol. 387 // Invalid, should never happen. Restart the whole protocol.
394 state = PROBE; 388 state = PROBE;
395 pick(&ip); 389 pick(&ip);
396 timeout = 0; 390 timeout_ms = 0;
397 nprobes = 0; 391 nprobes = 0;
398 nclaims = 0; 392 nclaims = 0;
399 break; 393 break;
@@ -403,20 +397,17 @@ int zcip_main(int argc, char **argv)
403 case 1: 397 case 1:
404 // We need to adjust the timeout in case we didn't receive 398 // We need to adjust the timeout in case we didn't receive
405 // a conflicting packet. 399 // a conflicting packet.
406 if (timeout > 0) { 400 if (timeout_ms > 0) {
407 struct timeval tv2; 401 unsigned diff = deadline_us - MONOTONIC_US();
408 402 if ((int)(diff) < 0) {
409 gettimeofday(&tv2, NULL);
410 if (timercmp(&tv1, &tv2, <)) {
411 // Current time is greater than the expected timeout time. 403 // Current time is greater than the expected timeout time.
412 // Should never happen. 404 // Should never happen.
413 VDBG("missed an expected timeout\n"); 405 VDBG("missed an expected timeout\n");
414 timeout = 0; 406 timeout_ms = 0;
415 } else { 407 } else {
416 VDBG("adjusting timeout\n"); 408 VDBG("adjusting timeout\n");
417 timersub(&tv1, &tv2, &tv1); 409 timeout_ms = diff / 1000;
418 timeout = 1000 * tv1.tv_sec 410 if (!timeout_ms) timeout_ms = 1;
419 + tv1.tv_usec / 1000;
420 } 411 }
421 } 412 }
422 413
@@ -484,13 +475,13 @@ int zcip_main(int argc, char **argv)
484 conflicts++; 475 conflicts++;
485 if (conflicts >= MAX_CONFLICTS) { 476 if (conflicts >= MAX_CONFLICTS) {
486 VDBG("%s ratelimit\n", intf); 477 VDBG("%s ratelimit\n", intf);
487 timeout = RATE_LIMIT_INTERVAL * 1000; 478 timeout_ms = RATE_LIMIT_INTERVAL * 1000;
488 state = RATE_LIMIT_PROBE; 479 state = RATE_LIMIT_PROBE;
489 } 480 }
490 481
491 // restart the whole protocol 482 // restart the whole protocol
492 pick(&ip); 483 pick(&ip);
493 timeout = 0; 484 timeout_ms = 0;
494 nprobes = 0; 485 nprobes = 0;
495 nclaims = 0; 486 nclaims = 0;
496 } 487 }
@@ -500,7 +491,7 @@ int zcip_main(int argc, char **argv)
500 if (source_ip_conflict) { 491 if (source_ip_conflict) {
501 VDBG("monitor conflict -- defending\n"); 492 VDBG("monitor conflict -- defending\n");
502 state = DEFEND; 493 state = DEFEND;
503 timeout = DEFEND_INTERVAL * 1000; 494 timeout_ms = DEFEND_INTERVAL * 1000;
504 arp(fd, &saddr, 495 arp(fd, &saddr,
505 ARPOP_REQUEST, 496 ARPOP_REQUEST,
506 &eth_addr, ip, 497 &eth_addr, ip,
@@ -518,7 +509,7 @@ int zcip_main(int argc, char **argv)
518 509
519 // restart the whole protocol 510 // restart the whole protocol
520 pick(&ip); 511 pick(&ip);
521 timeout = 0; 512 timeout_ms = 0;
522 nprobes = 0; 513 nprobes = 0;
523 nclaims = 0; 514 nclaims = 0;
524 } 515 }
@@ -528,7 +519,7 @@ int zcip_main(int argc, char **argv)
528 VDBG("invalid state -- starting over\n"); 519 VDBG("invalid state -- starting over\n");
529 state = PROBE; 520 state = PROBE;
530 pick(&ip); 521 pick(&ip);
531 timeout = 0; 522 timeout_ms = 0;
532 nprobes = 0; 523 nprobes = 0;
533 nclaims = 0; 524 nclaims = 0;
534 break; 525 break;