svn commit: r334094 - head/sys/net

Luca Pizzamiglio pizzamig at FreeBSD.org
Wed May 23 13:10:59 UTC 2018


Author: pizzamig (ports committer)
Date: Wed May 23 13:10:57 2018
New Revision: 334094
URL: https://svnweb.freebsd.org/changeset/base/334094

Log:
  Improve MAC address uniqueness on if_epair(4).
  
  As reported in PR184149, it can happen that epair devices can have the same
  MAC address.
  This solution is based on a 32-bit hash, obtained combining the if_index of
  the a interface and the hostid.
  If the hostid is zero, a random number is used.
  
  PR:		184149
  Reviewed by:	wollman, eugen
  Approved by:	cognet
  Differential Revision:	https://reviews.freebsd.org/D15329

Modified:
  head/sys/net/if_epair.c

Modified: head/sys/net/if_epair.c
==============================================================================
--- head/sys/net/if_epair.c	Wed May 23 12:10:16 2018	(r334093)
+++ head/sys/net/if_epair.c	Wed May 23 13:10:57 2018	(r334094)
@@ -53,10 +53,14 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/hash.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
+#include <sys/libkern.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/module.h>
+#include <sys/proc.h>
 #include <sys/refcount.h>
 #include <sys/queue.h>
 #include <sys/smp.h>
@@ -713,6 +717,9 @@ epair_clone_create(struct if_clone *ifc, char *name, s
 	struct ifnet *ifp;
 	char *dp;
 	int error, unit, wildcard;
+	uint64_t hostid;
+	uint32_t key[3];
+	uint32_t hash;
 	uint8_t eaddr[ETHER_ADDR_LEN];	/* 00:00:00:00:00:00 */
 
 	/*
@@ -724,14 +731,12 @@ epair_clone_create(struct if_clone *ifc, char *name, s
 	if (params) {
 		scb = (struct epair_softc *)params;
 		ifp = scb->ifp;
-		/* Assign a hopefully unique, locally administered etheraddr. */
-		eaddr[0] = 0x02;
-		eaddr[3] = (ifp->if_index >> 8) & 0xff;
-		eaddr[4] = ifp->if_index & 0xff;
+		/* Copy epairNa etheraddr and change the last byte. */
+		memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
 		eaddr[5] = 0x0b;
 		ether_ifattach(ifp, eaddr);
 		/* Correctly set the name for the cloner list. */
-		strlcpy(name, scb->ifp->if_xname, len);
+		strlcpy(name, ifp->if_xname, len);
 		return (0);
 	}
 
@@ -835,10 +840,21 @@ epair_clone_create(struct if_clone *ifc, char *name, s
 	ifp->if_init  = epair_init;
 	if_setsendqlen(ifp, ifqmaxlen);
 	if_setsendqready(ifp);
-	/* Assign a hopefully unique, locally administered etheraddr. */
+
+	/*
+	 * Calculate the etheraddr hashing the hostid and the
+	 * interface index. The result would be hopefully unique
+	 */
+	getcredhostid(curthread->td_ucred, (unsigned long *)&hostid);
+	if (hostid == 0) 
+		arc4rand(&hostid, sizeof(hostid), 0);
+	key[0] = (uint32_t)ifp->if_index;
+	key[1] = (uint32_t)(hostid & 0xffffffff);
+	key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff);
+	hash = jenkins_hash32(key, 3, 0);
+
 	eaddr[0] = 0x02;
-	eaddr[3] = (ifp->if_index >> 8) & 0xff;
-	eaddr[4] = ifp->if_index & 0xff;
+	memcpy(&eaddr[1], &hash, 4);
 	eaddr[5] = 0x0a;
 	ether_ifattach(ifp, eaddr);
 	sca->if_qflush = ifp->if_qflush;


More information about the svn-src-all mailing list