Module Name:    src
Committed By:   roy
Date:           Sat Sep 26 18:38:09 UTC 2020

Modified Files:
        src/sys/net: if_ethersubr.c if_vlan.c if_vlanvar.h

Log Message:
vlan: match the interface link state with that of the parent

Now addresses on a vlan will detach and undergo duplicate address
dectection on link state changes just as on a standard interface.


To generate a diff of this commit:
cvs rdiff -u -r1.288 -r1.289 src/sys/net/if_ethersubr.c
cvs rdiff -u -r1.152 -r1.153 src/sys/net/if_vlan.c
cvs rdiff -u -r1.13 -r1.14 src/sys/net/if_vlanvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_ethersubr.c
diff -u src/sys/net/if_ethersubr.c:1.288 src/sys/net/if_ethersubr.c:1.289
--- src/sys/net/if_ethersubr.c:1.288	Fri Aug 28 06:27:49 2020
+++ src/sys/net/if_ethersubr.c	Sat Sep 26 18:38:09 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ethersubr.c,v 1.288 2020/08/28 06:27:49 ozaki-r Exp $	*/
+/*	$NetBSD: if_ethersubr.c,v 1.289 2020/09/26 18:38:09 roy Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.288 2020/08/28 06:27:49 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.289 2020/09/26 18:38:09 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -979,6 +979,17 @@ ether_snprintf(char *buf, size_t len, co
 	return buf;
 }
 
+static void
+ether_link_state_changed(struct ifnet *ifp, int link_state)
+{
+#if NVLAN > 0
+	struct ethercom *ec = (void *)ifp;
+
+	if (ec->ec_nvlans)
+		vlan_link_state_changed(ifp, link_state);
+#endif
+}
+
 /*
  * Perform common duties while attaching to interface list
  */
@@ -993,6 +1004,7 @@ ether_ifattach(struct ifnet *ifp, const 
 	ifp->if_mtu = ETHERMTU;
 	ifp->if_output = ether_output;
 	ifp->_if_input = ether_input;
+	ifp->if_link_state_changed = ether_link_state_changed;
 	if (ifp->if_baudrate == 0)
 		ifp->if_baudrate = IF_Mbps(10);		/* just a default */
 

Index: src/sys/net/if_vlan.c
diff -u src/sys/net/if_vlan.c:1.152 src/sys/net/if_vlan.c:1.153
--- src/sys/net/if_vlan.c:1.152	Fri Jun 12 11:04:45 2020
+++ src/sys/net/if_vlan.c	Sat Sep 26 18:38:09 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_vlan.c,v 1.152 2020/06/12 11:04:45 roy Exp $	*/
+/*	$NetBSD: if_vlan.c,v 1.153 2020/09/26 18:38:09 roy Exp $	*/
 
 /*
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.152 2020/06/12 11:04:45 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.153 2020/09/26 18:38:09 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -355,9 +355,8 @@ vlan_clone_create(struct if_clone *ifc, 
 	if_initname(ifp, ifc->ifc_name, unit);
 	ifp->if_softc = ifv;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE;
 #ifdef NET_MPSAFE
-	ifp->if_extflags |= IFEF_MPSAFE;
+	ifp->if_extflags = IFEF_MPSAFE;
 #endif
 	ifp->if_start = vlan_start;
 	ifp->if_transmit = vlan_transmit;
@@ -371,6 +370,13 @@ vlan_clone_create(struct if_clone *ifc, 
 		goto fail;
 	}
 
+	/*
+	 * Set the link state to down.
+	 * When the parent interface attaches we will use that link state.
+	 * When the parent interface link state changes, so will ours.
+	 */
+	ifp->if_link_state = LINK_STATE_DOWN;
+
 	vlan_reset_linkname(ifp);
 	if_register(ifp);
 	return 0;
@@ -562,6 +568,12 @@ vlan_config(struct ifvlan *ifv, struct i
 	nmib_psref = NULL;
 	omib_cleanup = true;
 
+
+	/*
+	 * We inherit the parents link state.
+	 */
+	if_link_state_change(&ifv->ifv_if, p->if_link_state);
+
 done:
 	mutex_exit(&ifv->ifv_lock);
 
@@ -1669,6 +1681,35 @@ out:
 }
 
 /*
+ * If the parent link state changed, the vlan link state should change also.
+ */
+void
+vlan_link_state_changed(struct ifnet *p, int link_state)
+{
+	struct ifvlan *ifv;
+	struct ifvlan_linkmib *mib;
+	struct psref psref;
+	struct ifnet *ifp;
+
+	mutex_enter(&ifv_list.lock);
+
+	LIST_FOREACH(ifv, &ifv_list.list, ifv_list) {
+		mib = vlan_getref_linkmib(ifv, &psref);
+		if (mib == NULL)
+			continue;
+
+		if (mib->ifvm_p == p) {
+			ifp = &mib->ifvm_ifvlan->ifv_if;
+			if_link_state_change(ifp, link_state);
+		}
+
+		vlan_putref_linkmib(mib, &psref);
+	}
+
+	mutex_exit(&ifv_list.lock);
+}
+
+/*
  * Module infrastructure
  */
 #include "if_module.h"

Index: src/sys/net/if_vlanvar.h
diff -u src/sys/net/if_vlanvar.h:1.13 src/sys/net/if_vlanvar.h:1.14
--- src/sys/net/if_vlanvar.h:1.13	Mon Jan 15 16:36:51 2018
+++ src/sys/net/if_vlanvar.h	Sat Sep 26 18:38:09 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_vlanvar.h,v 1.13 2018/01/15 16:36:51 maxv Exp $	*/
+/*	$NetBSD: if_vlanvar.h,v 1.14 2020/09/26 18:38:09 roy Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -83,6 +83,7 @@ struct vlanreq {
 #ifdef _KERNEL
 void	vlan_input(struct ifnet *, struct mbuf *);
 void	vlan_ifdetach(struct ifnet *);
+void	vlan_link_state_changed(struct ifnet *, int);
 
 /*
  * Locking notes:

Reply via email to