4693f0
commit 7546434030d456b13b2eda6138f183ac3bf29751
4693f0
Author: Feras Daoud <ferasda@mellanox.com>
4693f0
Date:   Wed Aug 9 18:27:32 2017 +0300
4693f0
4693f0
    ptp4l: Add IPoIB interface support for ptp4l
4693f0
    
4693f0
    The current implementation of ptp4l always assumes 6 octets MAC
4693f0
    address, which is correct for Ethernet interfaces but not for IPoIB
4693f0
    interfaces (that have 20 octets MAC), therefore running ptp4l over
4693f0
    IPoIB interface does not function correctly.
4693f0
    
4693f0
    In Infiniband, every interface has three identifiers:
4693f0
    GUID, GID, and LID.
4693f0
    The GUID is similar in concept to a MAC address. From RFC4392:
4693f0
    The EUI-64 portion of a GID is referred to as the Global Unique
4693f0
    Identifier (GUID) and is the only persistent identifier of a port.
4693f0
    
4693f0
    Therefore, to support IPoIB interfaces, the GUID of the port should
4693f0
    be used instead of the MAC.
4693f0
    This patch checks the interface type before creating the clock identity,
4693f0
    for Infiniband ports, it retrieves the GUID of the port using sysfs
4693f0
    and use it to create the clock identity.
4693f0
    
4693f0
    sysfs method was chosen since the GUID is the 6 lsb bytes of
4693f0
    the 20 byte device address, and SIOCGIFHWADDR ioctl call returns
4693f0
    the 14 msb bytes of the device address, so it is not possible to
4693f0
    get the GUID using SIOCGIFHWADDR ioctl call.
4693f0
    
4693f0
    [ RC: fixed trivial coding style error, space after switch keyword. ]
4693f0
    
4693f0
    Signed-off-by: Feras Daoud <ferasda@mellanox.com>
4693f0
    Reviewed-by: Alex Vesker <valex@mellanox.com>
4693f0
4693f0
diff --git a/address.h b/address.h
4693f0
index 7578f91..35ef05f 100644
4693f0
--- a/address.h
4693f0
+++ b/address.h
4693f0
@@ -24,6 +24,7 @@
4693f0
 #include <netpacket/packet.h>
4693f0
 #include <sys/socket.h>
4693f0
 #include <sys/un.h>
4693f0
+#include <net/if_arp.h>
4693f0
 
4693f0
 struct address {
4693f0
 	socklen_t len;
4693f0
diff --git a/ether.h b/ether.h
4693f0
index ce3d663..8ec9669 100644
4693f0
--- a/ether.h
4693f0
+++ b/ether.h
4693f0
@@ -22,7 +22,13 @@
4693f0
 
4693f0
 #include <stdint.h>
4693f0
 
4693f0
-#define MAC_LEN 6
4693f0
+#define EUI48 6
4693f0
+#define EUI64 8
4693f0
+
4693f0
+#define MAC_LEN  EUI48
4693f0
+#define GUID_LEN EUI64
4693f0
+
4693f0
+#define GUID_OFFSET 36
4693f0
 
4693f0
 typedef uint8_t eth_addr[MAC_LEN];
4693f0
 
4693f0
diff --git a/sk.c b/sk.c
4693f0
index 63ec206..0cf55c5 100644
4693f0
--- a/sk.c
4693f0
+++ b/sk.c
4693f0
@@ -159,10 +159,55 @@ failed:
4693f0
 	return -1;
4693f0
 }
4693f0
 
4693f0
+static int sk_interface_guidaddr(const char *name, unsigned char *guid)
4693f0
+{
4693f0
+	char file_name[64], buf[64], addr[8];
4693f0
+	FILE *f;
4693f0
+	char *err;
4693f0
+	int res;
4693f0
+
4693f0
+	snprintf(file_name, sizeof buf, "/sys/class/net/%s/address", name);
4693f0
+	f = fopen(file_name, "r");
4693f0
+	if (!f) {
4693f0
+		pr_err("failed to open %s: %m", buf);
4693f0
+		return -1;
4693f0
+	}
4693f0
+
4693f0
+	/* Set the file position to the beginning of the GUID */
4693f0
+	res = fseek(f, GUID_OFFSET, SEEK_SET);
4693f0
+	if (res) {
4693f0
+		pr_err("fseek failed: %m");
4693f0
+		goto error;
4693f0
+	}
4693f0
+
4693f0
+	err = fgets(buf, sizeof buf, f);
4693f0
+	if (err == NULL) {
4693f0
+		pr_err("fseek failed: %m");
4693f0
+		goto error;
4693f0
+	}
4693f0
+
4693f0
+	res = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
4693f0
+			   &addr[0], &addr[1], &addr[2], &addr[3],
4693f0
+			   &addr[4], &addr[5], &addr[6], &addr[7]);
4693f0
+	if (res != GUID_LEN) {
4693f0
+		pr_err("sscanf failed: %m");
4693f0
+		goto error;
4693f0
+	}
4693f0
+
4693f0
+	memcpy(guid, addr, GUID_LEN);
4693f0
+	fclose(f);
4693f0
+
4693f0
+	return 0;
4693f0
+
4693f0
+error:
4693f0
+	fclose(f);
4693f0
+	return -1;
4693f0
+}
4693f0
+
4693f0
 int sk_interface_macaddr(const char *name, struct address *mac)
4693f0
 {
4693f0
 	struct ifreq ifreq;
4693f0
-	int err, fd;
4693f0
+	int err, fd, type;
4693f0
 
4693f0
 	memset(&ifreq, 0, sizeof(ifreq));
4693f0
 	strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name) - 1);
4693f0
@@ -180,9 +225,23 @@ int sk_interface_macaddr(const char *name, struct address *mac)
4693f0
 		return -1;
4693f0
 	}
4693f0
 
4693f0
+	/* Get interface type */
4693f0
+	type = ifreq.ifr_hwaddr.sa_family;
4693f0
+	switch (type) {
4693f0
+		case ARPHRD_INFINIBAND:
4693f0
+			err = sk_interface_guidaddr(name, mac->sll.sll_addr);
4693f0
+			if (err) {
4693f0
+				pr_err("fail to get address using sysfs: %m");
4693f0
+				return -1;
4693f0
+			}
4693f0
+			mac->sll.sll_halen = EUI64;
4693f0
+			break;
4693f0
+		default:
4693f0
+			memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN);
4693f0
+			mac->sll.sll_halen = EUI48;
4693f0
+	}
4693f0
+
4693f0
 	mac->sll.sll_family = AF_PACKET;
4693f0
-	mac->sll.sll_halen = MAC_LEN;
4693f0
-	memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN);
4693f0
 	mac->len = sizeof(mac->sll);
4693f0
 	close(fd);
4693f0
 	return 0;
4693f0
diff --git a/util.c b/util.c
4693f0
index 2b880ff..62f2638 100644
4693f0
--- a/util.c
4693f0
+++ b/util.c
4693f0
@@ -135,14 +135,32 @@ int generate_clock_identity(struct ClockIdentity *ci, const char *name)
4693f0
 
4693f0
 	if (sk_interface_macaddr(name, &addr))
4693f0
 		return -1;
4693f0
-	ci->id[0] = addr.sll.sll_addr[0];
4693f0
-	ci->id[1] = addr.sll.sll_addr[1];
4693f0
-	ci->id[2] = addr.sll.sll_addr[2];
4693f0
-	ci->id[3] = 0xFF;
4693f0
-	ci->id[4] = 0xFE;
4693f0
-	ci->id[5] = addr.sll.sll_addr[3];
4693f0
-	ci->id[6] = addr.sll.sll_addr[4];
4693f0
-	ci->id[7] = addr.sll.sll_addr[5];
4693f0
+
4693f0
+	switch (addr.sll.sll_halen) {
4693f0
+		case EUI48:
4693f0
+			ci->id[0] = addr.sll.sll_addr[0];
4693f0
+			ci->id[1] = addr.sll.sll_addr[1];
4693f0
+			ci->id[2] = addr.sll.sll_addr[2];
4693f0
+			ci->id[3] = 0xFF;
4693f0
+			ci->id[4] = 0xFE;
4693f0
+			ci->id[5] = addr.sll.sll_addr[3];
4693f0
+			ci->id[6] = addr.sll.sll_addr[4];
4693f0
+			ci->id[7] = addr.sll.sll_addr[5];
4693f0
+			break;
4693f0
+		case EUI64:
4693f0
+			ci->id[0] = addr.sll.sll_addr[0];
4693f0
+			ci->id[1] = addr.sll.sll_addr[1];
4693f0
+			ci->id[2] = addr.sll.sll_addr[2];
4693f0
+			ci->id[3] = addr.sll.sll_addr[3];
4693f0
+			ci->id[4] = addr.sll.sll_addr[4];
4693f0
+			ci->id[5] = addr.sll.sll_addr[5];
4693f0
+			ci->id[6] = addr.sll.sll_addr[6];
4693f0
+			ci->id[7] = addr.sll.sll_addr[7];
4693f0
+			break;
4693f0
+		default:
4693f0
+			return -1;
4693f0
+	}
4693f0
+
4693f0
 	return 0;
4693f0
 }
4693f0
 
4693f0
commit fd2646263f0fb1a31dde53e67ac24971ab1f90f4
4693f0
Author: Miroslav Lichvar <mlichvar@redhat.com>
4693f0
Date:   Mon Oct 16 11:29:48 2017 +0200
4693f0
4693f0
    sk: don't leak socket when reading of IB GUID fails.
4693f0
    
4693f0
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
4693f0
4693f0
diff --git a/sk.c b/sk.c
4693f0
index 0cf55c5..2c7593b 100644
4693f0
--- a/sk.c
4693f0
+++ b/sk.c
4693f0
@@ -225,6 +225,8 @@ int sk_interface_macaddr(const char *name, struct address *mac)
4693f0
 		return -1;
4693f0
 	}
4693f0
 
4693f0
+	close(fd);
4693f0
+
4693f0
 	/* Get interface type */
4693f0
 	type = ifreq.ifr_hwaddr.sa_family;
4693f0
 	switch (type) {
4693f0
@@ -243,7 +245,6 @@ int sk_interface_macaddr(const char *name, struct address *mac)
4693f0
 
4693f0
 	mac->sll.sll_family = AF_PACKET;
4693f0
 	mac->len = sizeof(mac->sll);
4693f0
-	close(fd);
4693f0
 	return 0;
4693f0
 }
4693f0