Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Jun 2016 11:44:36 +0200 (CEST)
From:      Arnaud YSMAL <arnaud.ysmal@stormshield.eu>
To:        freebsd-net@freebsd.org
Subject:   [Patch] Changing mac address does not always work
Message-ID:  <494678734.3111275.1465379076220.JavaMail.zimbra@stormshield.eu>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi,

Configuring the network card with the following commands (in this specific order) does not work.
# ifconfig em0 down
# ifconfig em0 mtu 1500
# ifconfig em0 ether 12:34:56:12:34:56
# ifconfig em0 192.168.1.1/24
# ifconfig em0 up

I was able to reproduce this issue on 10.3-RELEASE and HEAD with ix and em drivers.

>From what I understand:
- When setting the mtu, the driver calls the init of the interface which sets the IFF_DRV_RUNNING flag
- When setting the mac address, if_setlladdr (from if.c) copy the mac address but does nothing else (the interface is not up)
- When setting the ip address, the driver does not call the init as the IFF_DRV_RUNNING is already set.
- When setting the up flag, same as above, the IFF_DRV_RUNNING is already set.

In this case the network card does not work as the mac address filter is not up to date.

The enclosed path fixes this issue,
It changes if_setlladdr in if.c to call the ifp->if_ioctl function with the IFF_UP flag clear even when the interface is not up.
The driver will then call its stop function which clear the IFF_DRV_RUNNING.
The init will be called when setting the ip address or the up flag.

Do you have any advice regarding this patch?

Arnaud
[-- Attachment #2 --]
diff --git sys/net/if.c sys/net/if.c
index 4d475d9..2515927 100644
--- sys/net/if.c
+++ sys/net/if.c
@@ -3394,6 +3394,7 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
 	struct sockaddr_dl *sdl;
 	struct ifaddr *ifa;
 	struct ifreq ifr;
+	int is_up;
 
 	IF_ADDR_RLOCK(ifp);
 	ifa = ifp->if_addr;
@@ -3431,16 +3432,17 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
 	}
 
 	/*
-	 * If the interface is already up, we need
+	 * If the interface is already up or inited, we need
 	 * to re-init it in order to reprogram its
 	 * address filter.
 	 */
-	if ((ifp->if_flags & IFF_UP) != 0) {
-		if (ifp->if_ioctl) {
-			ifp->if_flags &= ~IFF_UP;
-			ifr.ifr_flags = ifp->if_flags & 0xffff;
-			ifr.ifr_flagshigh = ifp->if_flags >> 16;
-			(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+	is_up = ifp->if_flags & IFF_UP;
+	if (ifp->if_ioctl) {
+		ifp->if_flags &= ~IFF_UP;
+		ifr.ifr_flags = ifp->if_flags & 0xffff;
+		ifr.ifr_flagshigh = ifp->if_flags >> 16;
+		(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+		if (is_up) {
 			ifp->if_flags |= IFF_UP;
 			ifr.ifr_flags = ifp->if_flags & 0xffff;
 			ifr.ifr_flagshigh = ifp->if_flags >> 16;

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?494678734.3111275.1465379076220.JavaMail.zimbra>