diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-17 19:09:05 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-17 19:09:05 +0000 |
commit | 459be35234cc24b69309eb0ee22600024c73713e (patch) | |
tree | 15ac4122d9c42ec75ba68d342827e37fcb1306ed /networking/arping.c | |
parent | e79dd06782175d50f639180cde5b2c56933aa2ee (diff) | |
download | busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.gz busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.bz2 busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.zip |
hwclock: size optimizations
libbb/time.c: new file, introducing monotonic_us()
pscan, traceroute, arping: use it instead of gettimeofday
ping, zcip: TODO
function old new delta
monotonic_us - 89 +89
find_pair 164 180 +16
.rodata 129747 129763 +16
refresh 1144 1152 +8
............
timeout 8 4 -4
static.start 8 4 -4
last 8 4 -4
parse_conf 1303 1284 -19
time_main 1149 1124 -25
gettimeofday_us 39 - -39
arping_main 2042 1969 -73
hwclock_main 594 501 -93
catcher 485 380 -105
traceroute_main 4300 4117 -183
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 8/11 up/down: 157/-562) Total: -405 bytes
Diffstat (limited to 'networking/arping.c')
-rw-r--r-- | networking/arping.c | 125 |
1 files changed, 55 insertions, 70 deletions
diff --git a/networking/arping.c b/networking/arping.c index 1b2604902..a022e70ea 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -8,9 +8,6 @@ | |||
8 | * Busybox port: Nick Fedchik <nick@fedchik.org.ua> | 8 | * Busybox port: Nick Fedchik <nick@fedchik.org.ua> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //#include <sys/ioctl.h> | ||
12 | //#include <signal.h> | ||
13 | |||
14 | #include <arpa/inet.h> | 11 | #include <arpa/inet.h> |
15 | #include <net/if.h> | 12 | #include <net/if.h> |
16 | #include <netinet/ether.h> | 13 | #include <netinet/ether.h> |
@@ -18,42 +15,42 @@ | |||
18 | 15 | ||
19 | #include "libbb.h" | 16 | #include "libbb.h" |
20 | 17 | ||
18 | /* We don't expect to see 1000+ seconds delay, unsigned is enough */ | ||
19 | #define MONOTONIC_US() ((unsigned)monotonic_us()) | ||
20 | |||
21 | static struct in_addr src; | 21 | static struct in_addr src; |
22 | static struct in_addr dst; | 22 | static struct in_addr dst; |
23 | static struct sockaddr_ll me; | 23 | static struct sockaddr_ll me; |
24 | static struct sockaddr_ll he; | 24 | static struct sockaddr_ll he; |
25 | static struct timeval last; | 25 | static unsigned last; |
26 | 26 | ||
27 | enum cfg_e { | 27 | enum { |
28 | dad = 1, | 28 | DAD = 1, |
29 | unsolicited = 2, | 29 | UNSOLICITED = 2, |
30 | advert = 4, | 30 | ADVERT = 4, |
31 | quiet = 8, | 31 | QUIET = 8, |
32 | quit_on_reply = 16, | 32 | QUIT_ON_REPLY = 16, |
33 | broadcast_only = 32, | 33 | BCAST_ONLY = 32, |
34 | unicasting = 64 | 34 | UNICASTING = 64 |
35 | }; | 35 | }; |
36 | static int cfg; | 36 | static int cfg; |
37 | 37 | ||
38 | static int s; | 38 | static int s; |
39 | static unsigned count = UINT_MAX; | 39 | static unsigned count = UINT_MAX; |
40 | static unsigned timeout; | 40 | static unsigned timeout_us; |
41 | static int sent; | 41 | static int sent; |
42 | static int brd_sent; | 42 | static int brd_sent; |
43 | static int received; | 43 | static int received; |
44 | static int brd_recv; | 44 | static int brd_recv; |
45 | static int req_recv; | 45 | static int req_recv; |
46 | 46 | ||
47 | #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ | ||
48 | ((tv1).tv_usec-(tv2).tv_usec)/1000 ) | ||
49 | |||
50 | static int send_pack(int sock, struct in_addr *src_addr, | 47 | static int send_pack(int sock, struct in_addr *src_addr, |
51 | struct in_addr *dst_addr, struct sockaddr_ll *ME, | 48 | struct in_addr *dst_addr, struct sockaddr_ll *ME, |
52 | struct sockaddr_ll *HE) | 49 | struct sockaddr_ll *HE) |
53 | { | 50 | { |
54 | int err; | 51 | int err; |
55 | struct timeval now; | 52 | unsigned now; |
56 | RESERVE_CONFIG_UBUFFER(buf, 256); | 53 | unsigned char buf[256]; |
57 | struct arphdr *ah = (struct arphdr *) buf; | 54 | struct arphdr *ah = (struct arphdr *) buf; |
58 | unsigned char *p = (unsigned char *) (ah + 1); | 55 | unsigned char *p = (unsigned char *) (ah + 1); |
59 | 56 | ||
@@ -62,7 +59,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
62 | ah->ar_pro = htons(ETH_P_IP); | 59 | ah->ar_pro = htons(ETH_P_IP); |
63 | ah->ar_hln = ME->sll_halen; | 60 | ah->ar_hln = ME->sll_halen; |
64 | ah->ar_pln = 4; | 61 | ah->ar_pln = 4; |
65 | ah->ar_op = cfg & advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); | 62 | ah->ar_op = cfg & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); |
66 | 63 | ||
67 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 64 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
68 | p += ME->sll_halen; | 65 | p += ME->sll_halen; |
@@ -70,7 +67,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
70 | memcpy(p, src_addr, 4); | 67 | memcpy(p, src_addr, 4); |
71 | p += 4; | 68 | p += 4; |
72 | 69 | ||
73 | if (cfg & advert) | 70 | if (cfg & ADVERT) |
74 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 71 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
75 | else | 72 | else |
76 | memcpy(p, &HE->sll_addr, ah->ar_hln); | 73 | memcpy(p, &HE->sll_addr, ah->ar_hln); |
@@ -79,21 +76,21 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
79 | memcpy(p, dst_addr, 4); | 76 | memcpy(p, dst_addr, 4); |
80 | p += 4; | 77 | p += 4; |
81 | 78 | ||
82 | gettimeofday(&now, NULL); | 79 | now = MONOTONIC_US(); |
83 | err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); | 80 | err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); |
84 | if (err == p - buf) { | 81 | if (err == p - buf) { |
85 | last = now; | 82 | last = now; |
86 | sent++; | 83 | sent++; |
87 | if (!(cfg & unicasting)) | 84 | if (!(cfg & UNICASTING)) |
88 | brd_sent++; | 85 | brd_sent++; |
89 | } | 86 | } |
90 | RELEASE_CONFIG_BUFFER(buf); | ||
91 | return err; | 87 | return err; |
92 | } | 88 | } |
93 | 89 | ||
90 | static void finish(void) ATTRIBUTE_NORETURN; | ||
94 | static void finish(void) | 91 | static void finish(void) |
95 | { | 92 | { |
96 | if (!(cfg & quiet)) { | 93 | if (!(cfg & QUIET)) { |
97 | printf("Sent %d probe(s) (%d broadcast(s))\n" | 94 | printf("Sent %d probe(s) (%d broadcast(s))\n" |
98 | "Received %d repl%s" | 95 | "Received %d repl%s" |
99 | " (%d request(s), %d broadcast(s))\n", | 96 | " (%d request(s), %d broadcast(s))\n", |
@@ -101,30 +98,31 @@ static void finish(void) | |||
101 | received, (received == 1) ? "ies" : "y", | 98 | received, (received == 1) ? "ies" : "y", |
102 | req_recv, brd_recv); | 99 | req_recv, brd_recv); |
103 | } | 100 | } |
104 | if (cfg & dad) | 101 | if (cfg & DAD) |
105 | exit(!!received); | 102 | exit(!!received); |
106 | if (cfg & unsolicited) | 103 | if (cfg & UNSOLICITED) |
107 | exit(0); | 104 | exit(0); |
108 | exit(!received); | 105 | exit(!received); |
109 | } | 106 | } |
110 | 107 | ||
111 | static void catcher(void) | 108 | static void catcher(void) |
112 | { | 109 | { |
113 | struct timeval tv; | 110 | static unsigned start; |
114 | static struct timeval start; | ||
115 | 111 | ||
116 | gettimeofday(&tv, NULL); | 112 | unsigned now; |
117 | 113 | ||
118 | if (start.tv_sec == 0) | 114 | now = MONOTONIC_US(); |
119 | start = tv; | 115 | if (start == 0) |
116 | start = now; | ||
120 | 117 | ||
121 | if (count-- == 0 | 118 | if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000))) |
122 | || (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500)) | ||
123 | finish(); | 119 | finish(); |
124 | 120 | ||
125 | if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { | 121 | count--; |
122 | |||
123 | if (last == 0 || (now - last) > 500000) { | ||
126 | send_pack(s, &src, &dst, &me, &he); | 124 | send_pack(s, &src, &dst, &me, &he); |
127 | if (count == 0 && (cfg & unsolicited)) | 125 | if (count == 0 && (cfg & UNSOLICITED)) |
128 | finish(); | 126 | finish(); |
129 | } | 127 | } |
130 | alarm(1); | 128 | alarm(1); |
@@ -162,7 +160,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
162 | return 0; | 160 | return 0; |
163 | memcpy(&src_ip, p + ah->ar_hln, 4); | 161 | memcpy(&src_ip, p + ah->ar_hln, 4); |
164 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); | 162 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); |
165 | if (!(cfg & dad)) { | 163 | if (!(cfg & DAD)) { |
166 | if (src_ip.s_addr != dst.s_addr) | 164 | if (src_ip.s_addr != dst.s_addr) |
167 | return 0; | 165 | return 0; |
168 | if (src.s_addr != dst_ip.s_addr) | 166 | if (src.s_addr != dst_ip.s_addr) |
@@ -190,11 +188,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
190 | if (src.s_addr && src.s_addr != dst_ip.s_addr) | 188 | if (src.s_addr && src.s_addr != dst_ip.s_addr) |
191 | return 0; | 189 | return 0; |
192 | } | 190 | } |
193 | if (!(cfg & quiet)) { | 191 | if (!(cfg & QUIET)) { |
194 | int s_printed = 0; | 192 | int s_printed = 0; |
195 | struct timeval tv; | ||
196 | |||
197 | gettimeofday(&tv, NULL); | ||
198 | 193 | ||
199 | printf("%scast re%s from %s [%s]", | 194 | printf("%scast re%s from %s [%s]", |
200 | FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", | 195 | FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", |
@@ -212,13 +207,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
212 | ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); | 207 | ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); |
213 | } | 208 | } |
214 | 209 | ||
215 | if (last.tv_sec) { | 210 | if (last) { |
216 | long usecs = (tv.tv_sec - last.tv_sec) * 1000000 + | 211 | printf(" %u.%03ums\n", last / 1000, last % 1000); |
217 | tv.tv_usec - last.tv_usec; | ||
218 | long msecs = (usecs + 500) / 1000; | ||
219 | |||
220 | usecs -= msecs * 1000 - 500; | ||
221 | printf(" %ld.%03ldms\n", msecs, usecs); | ||
222 | } else { | 212 | } else { |
223 | printf(" UNSOLICITED?\n"); | 213 | printf(" UNSOLICITED?\n"); |
224 | } | 214 | } |
@@ -229,11 +219,11 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
229 | brd_recv++; | 219 | brd_recv++; |
230 | if (ah->ar_op == htons(ARPOP_REQUEST)) | 220 | if (ah->ar_op == htons(ARPOP_REQUEST)) |
231 | req_recv++; | 221 | req_recv++; |
232 | if (cfg & quit_on_reply) | 222 | if (cfg & QUIT_ON_REPLY) |
233 | finish(); | 223 | finish(); |
234 | if (!(cfg & broadcast_only)) { | 224 | if (!(cfg & BCAST_ONLY)) { |
235 | memcpy(he.sll_addr, p, me.sll_halen); | 225 | memcpy(he.sll_addr, p, me.sll_halen); |
236 | cfg |= unicasting; | 226 | cfg |= UNICASTING; |
237 | } | 227 | } |
238 | return 1; | 228 | return 1; |
239 | } | 229 | } |
@@ -245,6 +235,7 @@ int arping_main(int argc, char **argv) | |||
245 | int ifindex; | 235 | int ifindex; |
246 | char *source = NULL; | 236 | char *source = NULL; |
247 | char *target; | 237 | char *target; |
238 | unsigned char *packet; | ||
248 | 239 | ||
249 | s = xsocket(PF_PACKET, SOCK_DGRAM, 0); | 240 | s = xsocket(PF_PACKET, SOCK_DGRAM, 0); |
250 | 241 | ||
@@ -258,28 +249,23 @@ int arping_main(int argc, char **argv) | |||
258 | /* Dad also sets quit_on_reply. | 249 | /* Dad also sets quit_on_reply. |
259 | * Advert also sets unsolicited. | 250 | * Advert also sets unsolicited. |
260 | */ | 251 | */ |
261 | opt_complementary = "Df:AU"; | 252 | opt_complementary = "=1:Df:AU"; |
262 | opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", | 253 | opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", |
263 | &_count, &_timeout, &device, &source); | 254 | &_count, &_timeout, &device, &source); |
264 | cfg |= opt & 0x3f; /* set respective flags */ | 255 | cfg |= opt & 0x3f; /* set respective flags */ |
265 | if (opt & 0x40) /* -c: count */ | 256 | if (opt & 0x40) /* -c: count */ |
266 | count = xatou(_count); | 257 | count = xatou(_count); |
267 | if (opt & 0x80) /* -w: timeout */ | 258 | if (opt & 0x80) /* -w: timeout */ |
268 | timeout = xatoul_range(_timeout, 0, INT_MAX/2000); | 259 | timeout_us = xatou_range(_timeout, 0, INT_MAX/2000000) * 1000000; |
269 | //if (opt & 0x100) /* -i: interface */ | 260 | //if (opt & 0x100) /* -I: interface */ |
270 | if (strlen(device) > IF_NAMESIZE) { | 261 | if (strlen(device) >= IF_NAMESIZE) { |
271 | bb_error_msg_and_die("interface name '%s' is too long", | 262 | bb_error_msg_and_die("interface name '%s' is too long", |
272 | device); | 263 | device); |
273 | } | 264 | } |
274 | //if (opt & 0x200) /* -s: source */ | 265 | //if (opt & 0x200) /* -s: source */ |
275 | } | 266 | } |
276 | argc -= optind; | ||
277 | argv += optind; | ||
278 | |||
279 | if (argc != 1) | ||
280 | bb_show_usage(); | ||
281 | 267 | ||
282 | target = *argv; | 268 | target = argv[optind]; |
283 | 269 | ||
284 | xfunc_error_retval = 2; | 270 | xfunc_error_retval = 2; |
285 | 271 | ||
@@ -301,7 +287,7 @@ int arping_main(int argc, char **argv) | |||
301 | } | 287 | } |
302 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { | 288 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { |
303 | bb_error_msg("interface %s is not ARPable", device); | 289 | bb_error_msg("interface %s is not ARPable", device); |
304 | return (cfg & dad ? 0 : 2); | 290 | return (cfg & DAD ? 0 : 2); |
305 | } | 291 | } |
306 | } | 292 | } |
307 | 293 | ||
@@ -317,10 +303,10 @@ int arping_main(int argc, char **argv) | |||
317 | bb_error_msg_and_die("invalid source address %s", source); | 303 | bb_error_msg_and_die("invalid source address %s", source); |
318 | } | 304 | } |
319 | 305 | ||
320 | if (!(cfg & dad) && (cfg & unsolicited) && src.s_addr == 0) | 306 | if (!(cfg & DAD) && (cfg & UNSOLICITED) && src.s_addr == 0) |
321 | src = dst; | 307 | src = dst; |
322 | 308 | ||
323 | if (!(cfg & dad) || src.s_addr) { | 309 | if (!(cfg & DAD) || src.s_addr) { |
324 | struct sockaddr_in saddr; | 310 | struct sockaddr_in saddr; |
325 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); | 311 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); |
326 | 312 | ||
@@ -333,7 +319,7 @@ int arping_main(int argc, char **argv) | |||
333 | if (src.s_addr) { | 319 | if (src.s_addr) { |
334 | saddr.sin_addr = src; | 320 | saddr.sin_addr = src; |
335 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); | 321 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
336 | } else if (!(cfg & dad)) { | 322 | } else if (!(cfg & DAD)) { |
337 | socklen_t alen = sizeof(saddr); | 323 | socklen_t alen = sizeof(saddr); |
338 | 324 | ||
339 | saddr.sin_port = htons(1025); | 325 | saddr.sin_port = htons(1025); |
@@ -364,18 +350,18 @@ int arping_main(int argc, char **argv) | |||
364 | } | 350 | } |
365 | if (me.sll_halen == 0) { | 351 | if (me.sll_halen == 0) { |
366 | bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); | 352 | bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); |
367 | return (cfg & dad ? 0 : 2); | 353 | return (cfg & DAD ? 0 : 2); |
368 | } | 354 | } |
369 | he = me; | 355 | he = me; |
370 | memset(he.sll_addr, -1, he.sll_halen); | 356 | memset(he.sll_addr, -1, he.sll_halen); |
371 | 357 | ||
372 | if (!(cfg & quiet)) { | 358 | if (!(cfg & QUIET)) { |
373 | printf("ARPING to %s from %s via %s\n", | 359 | printf("ARPING to %s from %s via %s\n", |
374 | inet_ntoa(dst), inet_ntoa(src), | 360 | inet_ntoa(dst), inet_ntoa(src), |
375 | device ? device : "unknown"); | 361 | device ? device : "unknown"); |
376 | } | 362 | } |
377 | 363 | ||
378 | if (!src.s_addr && !(cfg & dad)) { | 364 | if (!src.s_addr && !(cfg & DAD)) { |
379 | bb_error_msg_and_die("no src address in the non-DAD mode"); | 365 | bb_error_msg_and_die("no src address in the non-DAD mode"); |
380 | } | 366 | } |
381 | 367 | ||
@@ -394,9 +380,9 @@ int arping_main(int argc, char **argv) | |||
394 | 380 | ||
395 | catcher(); | 381 | catcher(); |
396 | 382 | ||
383 | packet = xmalloc(4096); | ||
397 | while (1) { | 384 | while (1) { |
398 | sigset_t sset, osset; | 385 | sigset_t sset, osset; |
399 | RESERVE_CONFIG_UBUFFER(packet, 4096); | ||
400 | struct sockaddr_ll from; | 386 | struct sockaddr_ll from; |
401 | socklen_t alen = sizeof(from); | 387 | socklen_t alen = sizeof(from); |
402 | int cc; | 388 | int cc; |
@@ -412,6 +398,5 @@ int arping_main(int argc, char **argv) | |||
412 | sigprocmask(SIG_BLOCK, &sset, &osset); | 398 | sigprocmask(SIG_BLOCK, &sset, &osset); |
413 | recv_pack(packet, cc, &from); | 399 | recv_pack(packet, cc, &from); |
414 | sigprocmask(SIG_SETMASK, &osset, NULL); | 400 | sigprocmask(SIG_SETMASK, &osset, NULL); |
415 | RELEASE_CONFIG_BUFFER(packet); | ||
416 | } | 401 | } |
417 | } | 402 | } |