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);

Attachment: 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

Reply via email to