Common storage of original MAC address

Pokala, Ravi rpokala at panasas.com
Wed Sep 3 15:55:51 UTC 2014


-----Original Message-----
From: <Pokala>, Ravi Pokala <rpokala at panasas.com>
Date: Tuesday, August 26, 2014 at 11:35 PM
To: "freebsd-hackers at freebsd.org" <freebsd-hackers at freebsd.org>, Ryan
Stone <rysto32 at gmail.com>, Brooks Davis <brooks at freebsd.org>
Subject: Re: Common storage of original MAC address

> Doesn't this restore the original MAC on LAGG teardown?

It looks like that code does indeed restore the working MAC when the lagg
is torn down; see the example output below.

> If someone can enumerate the places where we want to restore the
>original LLADDR but currently don't, then I'll add that.

I never did hear from anyone, but it appears to be moot - as mentioned
above, the LAGG driver restores the original LLADDR.

> If what I've done so far looks good, I'll continue to the next steps:
>changing the places where we want to auto-restore the HW LLADDR (see my
>question above), and updating `ifconfig' to report and restore the HW
>LLADDR.

No one pointed my at places where we want to auto-restore, but don't.
Similarly, since we *do* auto-restore, there's no restore-related change
needed for `ifconfig'. That just leaves reporting, which is included in
the patch below.

If there are no objections to this, could a willing committer contact me
privately so we can work out the details of getting this submitted to
-CURRENT?

Thanks,

Ravi

---------------------------- ghwlladdr.patch ---------------------------
Index: sbin/ifconfig/af_link.c
===================================================================
--- sbin/ifconfig/af_link.c	(revision 270916)
+++ sbin/ifconfig/af_link.c	(working copy)
@@ -42,6 +42,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ifaddrs.h>
+#include <unistd.h>
 
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -61,9 +62,30 @@
 		if ((sdl->sdl_type == IFT_ETHER ||
 		    sdl->sdl_type == IFT_L2VLAN ||
 		    sdl->sdl_type == IFT_BRIDGE) &&
-		    sdl->sdl_alen == ETHER_ADDR_LEN)
+		    sdl->sdl_alen == ETHER_ADDR_LEN) {
+			struct ifreq ifr;
+			int s_hw;
 			printf("\tether %s\n",
 			    ether_ntoa((struct ether_addr *)LLADDR(sdl)));
+			strncpy(ifr.ifr_name, ifa->ifa_name,
+			    sizeof(ifr.ifr_name));
+			memcpy(&ifr.ifr_addr, ifa->ifa_addr,
+			    sizeof(ifa->ifa_addr->sa_len));
+			ifr.ifr_addr.sa_family = AF_LOCAL;
+			if ((s_hw = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
+				warn("socket(AF_LOCAL,SOCK_DGRAM)");
+				return;
+			}
+			if (ioctl(s_hw, SIOCGHWLLADDR, &ifr) < 0) {
+				warn("SIOCGHWLLADDR");
+				close(s_hw);
+				return;
+			}
+			printf("\thwaddr %s\n",
+			    ether_ntoa((const struct ether_addr *)
+			    &ifr.ifr_addr.sa_data));
+			close(s_hw);
+		}
 		else {
 			int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
 
Index: sys/net/if.c
===================================================================
--- sys/net/if.c	(revision 270916)
+++ sys/net/if.c	(working copy)
@@ -2554,6 +2554,10 @@
 		EVENTHANDLER_INVOKE(iflladdr_event, ifp);
 		break;
 
+	case SIOCGHWLLADDR:
+		error = if_gethwlladdr(ifp, ifr);
+		break;
+
 	case SIOCAIFGROUP:
 	{
 		struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
@@ -3427,6 +3431,33 @@
 }
 
 /*
+ * Get the link layer address that was read from the hardware at probe.
+ *
+ * At this time we only support certain types of interfaces.
+ */
+int
+if_gethwlladdr(struct ifnet *ifp, struct ifreq *ifr)
+{
+	switch (ifp->if_type) {
+	case IFT_ETHER:
+	case IFT_FDDI:
+	case IFT_XETHER:
+	case IFT_ISO88025:
+	case IFT_L2VLAN:
+	case IFT_BRIDGE:
+	case IFT_ARCNET:
+	case IFT_IEEE8023ADLAG:
+	case IFT_IEEE80211:
+		bcopy(&IFP2AC(ifp)->hw_lladdr, ifr->ifr_addr.sa_data, ETHER_ADDR_LEN);
+		ifr->ifr_addr.sa_len = ETHER_ADDR_LEN;
+		break;
+	default:
+		return (ENODEV);
+	}
+	return (0);
+}
+
+/*
  * The name argument must be a pointer to storage which will last as
  * long as the interface does.  For physical devices, the result of
  * device_get_name(dev) is a good choice and for pseudo-devices a
Index: sys/net/if_arp.h
===================================================================
--- sys/net/if_arp.h	(revision 270916)
+++ sys/net/if_arp.h	(working copy)
@@ -102,9 +102,11 @@
  * Structure shared between the ethernet driver modules and
  * the address resolution code.
  */
+#include <net/ethernet.h>
 struct	arpcom {
 	struct 	ifnet *ac_ifp;		/* network-visible interface */
 	void	*ac_netgraph;		/* ng_ether(4) netgraph node info */
+	struct 	ether_addr hw_lladdr;	/* original lladdr from hardware */
 };
 #define IFP2AC(ifp) ((struct arpcom *)(ifp->if_l2com))
 #define AC2IFP(ac) ((ac)->ac_ifp)
Index: sys/net/if_ethersubr.c
===================================================================
--- sys/net/if_ethersubr.c	(revision 270916)
+++ sys/net/if_ethersubr.c	(working copy)
@@ -841,6 +841,7 @@
 	sdl->sdl_type = IFT_ETHER;
 	sdl->sdl_alen = ifp->if_addrlen;
 	bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
+	bcopy(lla, &IFP2AC(ifp)->hw_lladdr, ifp->if_addrlen);
 
 	bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
 	if (ng_ether_attach_p != NULL)
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h	(revision 270916)
+++ sys/net/if_var.h	(working copy)
@@ -501,6 +501,7 @@
 void	if_ref(struct ifnet *);
 void	if_rele(struct ifnet *);
 int	if_setlladdr(struct ifnet *, const u_char *, int);
+int	if_gethwlladdr(struct ifnet *, struct ifreq *);
 void	if_up(struct ifnet *);
 int	ifioctl(struct socket *, u_long, caddr_t, struct thread *);
 int	ifpromisc(struct ifnet *, int);
Index: sys/sys/sockio.h
===================================================================
--- sys/sys/sockio.h	(revision 270916)
+++ sys/sys/sockio.h	(working copy)
@@ -97,6 +97,7 @@
 #define	SIOCGIFSTATUS	_IOWR('i', 59, struct ifstat)	/* get IF status */
 #define	SIOCSIFLLADDR	 _IOW('i', 60, struct ifreq)	/* set linklevel addr
*/
 #define	SIOCGI2C	_IOWR('i', 61, struct ifstat)	/* get I2C data  */
+#define	SIOCGHWLLADDR	_IOWR('i', 62, struct ifreq)	/* get hw lladdr */
 
 #define	SIOCSIFPHYADDR	 _IOW('i', 70, struct ifaliasreq) /* set gif
addres */
 #define	SIOCGIFPSRCADDR	_IOWR('i', 71, struct ifreq)	/* get gif psrc addr
*/
---------------------------- example output ----------------------------
root at fbsd-X:~ #	: Output from 'ifconfig'. Note the new 'hwaddr' line, and
root at fbsd-X:~ #	: that it has the same value as the 'ether' line, because
no
root at fbsd-X:~ #	: MAC manipulation has been done yet:
root at fbsd-X:~ #	ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:9d:28:32
	hwaddr 08:00:27:9d:28:32
	inet 192.168.1.10 netmask 0xffffff00 broadcast 192.168.1.255
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:f0:8f:8a
	hwaddr 08:00:27:f0:8f:8a
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em2: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:d2:48:a3
	hwaddr 08:00:27:d2:48:a3
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
	options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
	inet6 ::1 prefixlen 128
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
	inet 127.0.0.1 netmask 0xff000000
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
root at fbsd-X:~ #	: Create a 'lagg0' from 'em1' and 'em2'
root at fbsd-X:~ #	ifconfig lagg0 create laggproto lacp laggport em1 laggport
em2
root at fbsd-X:~ #	: Output from 'ifconfig'. Note that 'em2's 'ether' value
has
root at fbsd-X:~ #	: changed to match 'em1's 'ether' value, but 'em2's
'hwaddr'
root at fbsd-X:~ #	: value is unchanged.
root at fbsd-X:~ #	ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:9d:28:32
	hwaddr 08:00:27:9d:28:32
	inet 192.168.1.10 netmask 0xffffff00 broadcast 192.168.1.255
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:f0:8f:8a
	hwaddr 08:00:27:f0:8f:8a
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em2: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:f0:8f:8a
	hwaddr 08:00:27:d2:48:a3
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
	options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
	inet6 ::1 prefixlen 128
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
	inet 127.0.0.1 netmask 0xff000000
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
lagg0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:f0:8f:8a
	hwaddr 00:00:00:00:00:00
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect
	status: no carrier
	laggproto lacp lagghash l2,l3,l4
	laggport: em2 flags=0<>
	laggport: em1 flags=0<>
root at fbsd-X:~ #	: Destroy lagg0
root at fbsd-X:~ #	ifconfig lagg0 destroy
root at fbsd-X:~ #	: Output from 'ifconfig'. Note that 'em2's 'ether' value
has
root at fbsd-X:~ #	: returned to its original value, which once again matches
root at fbsd-X:~ #	: 'em2's 'hwaddr' value, which has remained unchanged.
root at fbsd-X:~ #	ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:9d:28:32
	hwaddr 08:00:27:9d:28:32
	inet 192.168.1.10 netmask 0xffffff00 broadcast 192.168.1.255
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:f0:8f:8a
	hwaddr 08:00:27:f0:8f:8a
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
em2: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
	ether 08:00:27:d2:48:a3
	hwaddr 08:00:27:d2:48:a3
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
	options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
	inet6 ::1 prefixlen 128
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
	inet 127.0.0.1 netmask 0xff000000
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
root at fbsd-X:~ #	



More information about the freebsd-hackers mailing list