On Thu, 2006-10-19 at 17:02 +0200, Or Gerlitz wrote: > Doug Ledford wrote: > > ... and reviewing arpingib > > (which I'm going to remove from the ipoibtools and fix the native arping > > in RHEL5 to work properly over IB without needing a new flag, the -A or > > -U flags should be sufficient assuming those modes worked at all over IB > > which they don't in either the native arping or the patched arpingib in > > ipoibtools). I should get to it today though. > > Would you mind send the patch to arping for review?
OK, this patch to arping actually makes it work for me in all modes (duplicate address detection, arp response, and unsolicited arp response). You shouldn't need any new flags to arping with this patch, you should be able to just use the existing modes of operation as they were intended to make the ipoibha.pl script work. There's still some debugging printf's in the patch, so don't consider this a final version. How's it work? The getsockname() function will return the full hw address if you give it a buffer large enough to do so. So, instead of allocating a single struct sockaddr_ll for me and he, which caps the address size at 8 bytes, allocate two and let the extra 12 bytes run over into the second struct element. Adjust the send_to and recv_from calls to accomodate this intentional size overrun. Finally, don't assume the broadcast address is all 1's, use sysfs to get the actual device broadcast address and convert it from text to binary (which will accommodate any possible future interface types that similarly don't have all 1's for broadcast address without requiring any recoding). That's all I had to do in order to get it to work for me. -- Doug Ledford <[EMAIL PROTECTED]> GPG KeyID: CFBFF194 http://people.redhat.com/dledford Infiniband specific RPMs available at http://people.redhat.com/dledford/Infiniband
--- arping.c.infiniband 2006-10-18 13:59:13.000000000 -0400 +++ arping.c 2006-11-02 12:11:15.000000000 -0500 @@ -29,6 +29,7 @@ #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <sysfs/libsysfs.h> #include "SNAPSHOT.h" @@ -48,8 +49,13 @@ int unicasting; int s; int broadcast_only; -struct sockaddr_ll me; -struct sockaddr_ll he; +/* + * Make these two structs have padding at the end so the overly long Infiniband + * hardware addresses can have the remainder of their address tacked onto + * the end of the struct without overlapping anything. + */ +struct sockaddr_ll me[2]; +struct sockaddr_ll he[2]; struct timeval start, last; @@ -124,7 +130,8 @@ int send_pack(int s, struct in_addr src, p+=4; gettimeofday(&now, NULL); - err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE)); + err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, (ah->ar_hln > 8) ? + sizeof(*HE) + ah->ar_hln - 8 : sizeof(*HE)); if (err == p-buf) { last = now; sent++; @@ -174,7 +181,7 @@ void catcher(void) if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) { count--; - send_pack(s, src, dst, &me, &he); + send_pack(s, src, dst, &me[0], &he[0]); if (count == 0 && unsolicited) finish(); } @@ -221,7 +228,7 @@ int recv_pack(unsigned char *buf, int le return 0; if (ah->ar_pln != 4) return 0; - if (ah->ar_hln != me.sll_halen) + if (ah->ar_hln != me[0].sll_halen) return 0; if (len < sizeof(*ah) + 2*(4 + ah->ar_hln)) return 0; @@ -232,7 +239,7 @@ int recv_pack(unsigned char *buf, int le return 0; if (src.s_addr != dst_ip.s_addr) return 0; - if (memcmp(p+ah->ar_hln+4, &me.sll_addr, ah->ar_hln)) + if (memcmp(p+ah->ar_hln+4, &me[0].sll_addr, ah->ar_hln)) return 0; } else { /* DAD packet was: @@ -250,7 +257,7 @@ int recv_pack(unsigned char *buf, int le */ if (src_ip.s_addr != dst.s_addr) return 0; - if (memcmp(p, &me.sll_addr, me.sll_halen) == 0) + if (memcmp(p, &me[0].sll_addr, me[0].sll_halen) == 0) return 0; if (src.s_addr && src.s_addr != dst_ip.s_addr) return 0; @@ -266,7 +273,7 @@ int recv_pack(unsigned char *buf, int le printf("for %s ", inet_ntoa(dst_ip)); s_printed = 1; } - if (memcmp(p+ah->ar_hln+4, me.sll_addr, ah->ar_hln)) { + if (memcmp(p+ah->ar_hln+4, me[0].sll_addr, ah->ar_hln)) { if (!s_printed) printf("for "); printf("["); @@ -292,7 +299,7 @@ int recv_pack(unsigned char *buf, int le if (quit_on_reply) finish(); if(!broadcast_only) { - memcpy(he.sll_addr, p, me.sll_halen); + memcpy(he[0].sll_addr, p, me[0].sll_halen); unicasting=1; } return 1; @@ -458,9 +465,9 @@ main(int argc, char **argv) close(probe_fd); }; - me.sll_family = AF_PACKET; - me.sll_ifindex = ifindex; - me.sll_protocol = htons(ETH_P_ARP); + me[0].sll_family = AF_PACKET; + me[0].sll_ifindex = ifindex; + me[0].sll_protocol = htons(ETH_P_ARP); if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { perror("bind"); exit(2); @@ -473,14 +480,44 @@ main(int argc, char **argv) exit(2); } } - if (me.sll_halen == 0) { + if (me[0].sll_halen == 0) { if (!quiet) printf("Interface \"%s\" is not ARPable (no ll address)\n", device); exit(dad?0:2); } - - he = me; - memset(he.sll_addr, -1, min(he.sll_halen, sizeof he.sll_addr)); + printf("halen=%d, hw addr=", me[0].sll_halen); + for(ch=0; ch<me[0].sll_halen; ch++) { + printf("%02x", me[0].sll_addr[ch]); + if (ch<(me[0].sll_halen - 1)) + printf(":"); + } + printf("\n"); + he[0] = me[0]; + he[1] = me[1]; + { + struct sysfs_class_device *dev; + struct sysfs_attribute *brdcast; + char *next_ch; + + dev = sysfs_open_class_device("net", device); + if (!dev) { + perror("sysfs class device"); + exit(2); + } + brdcast = sysfs_get_classdev_attr(dev, "broadcast"); + if (!brdcast) { + perror("sysfs attribute broadcast"); + exit(2); + } + if (sysfs_read_attribute(brdcast)) { + perror("sysfs read brdcast"); + exit(2); + } + for (ch=0; ch<he[0].sll_halen; ch++) { + he[0].sll_addr[ch] = strtol(brdcast->value + (ch*3), + &next_ch, 16); + } + } if (!quiet) { printf("ARPING %s ", inet_ntoa(dst)); @@ -500,7 +537,7 @@ main(int argc, char **argv) while(1) { sigset_t sset, osset; unsigned char packet[4096]; - struct sockaddr_ll from; + struct sockaddr_ll from[2]; int alen = sizeof(from); int cc; @@ -513,7 +550,7 @@ main(int argc, char **argv) sigaddset(&sset, SIGALRM); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); - recv_pack(packet, cc, &from); + recv_pack(packet, cc, &from[0]); if(received == count) exit(0); sigprocmask(SIG_SETMASK, &osset, NULL);
signature.asc
Description: This is a digitally signed message part
_______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general