Date: Wed, 29 Jun 2005 17:01:27 +0400 From: Yar Tikhiy <yar@FreeBSD.org> To: dan@obluda.cz Cc: freebsd-bugs@FreeBSD.org Subject: Re: kern/81978: [ PATCH ] if_vlan didn't pass the ALLMULTI to the parent interface Message-ID: <20050629130127.GA51085@comp.chem.msu.su> In-Reply-To: <200506141202.j5EC28O7026407@freefall.freebsd.org> References: <200506141202.j5EC28O7026407@freefall.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Dan,
Would you mind testing the following patch in 5-STABLE?
I tried to reduce code duplication since the cases of
promiscuous and all-multi modes are very close. Thanks!
Apropos, how do you turn on all-multicast mode on an
interface? It doesn't seem possible from the userland
using ioctl(2).
--
Yar
Index: if_vlan.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vlan.c,v
retrieving revision 1.73.2.2
diff -u -r1.73.2.2 if_vlan.c
--- if_vlan.c 31 Jan 2005 23:26:23 -0000 1.73.2.2
+++ if_vlan.c 29 Jun 2005 11:40:16 -0000
@@ -79,6 +79,7 @@
struct ifvlan {
struct arpcom ifv_ac; /* make this an interface */
struct ifnet *ifv_p; /* parent inteface of this vlan */
+ int ifv_pflags; /* special flags we have set on parent */
struct ifv_linkmib {
int ifvm_parent;
int ifvm_encaplen; /* encapsulation length */
@@ -89,7 +90,6 @@
} ifv_mib;
SLIST_HEAD(__vlan_mchead, vlan_mc_entry) vlan_mc_listhead;
LIST_ENTRY(ifvlan) ifv_list;
- int ifv_flags;
};
#define ifv_if ifv_ac.ac_if
#define ifv_tag ifv_mib.ifvm_tag
@@ -97,8 +97,6 @@
#define ifv_mtufudge ifv_mib.ifvm_mtufudge
#define ifv_mintu ifv_mib.ifvm_mintu
-#define IFVF_PROMISC 0x01 /* promiscuous mode enabled */
-
SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN");
SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency");
@@ -122,11 +120,13 @@
static void vlan_ifinit(void *foo);
static void vlan_input(struct ifnet *ifp, struct mbuf *m);
static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
+static int
+ vlan_setflag(struct ifnet *ifp, int flag, int (*func)(struct ifnet *, int));
+static int vlan_setflags(struct ifnet *ifp);
static int vlan_setmulti(struct ifnet *ifp);
static int vlan_unconfig(struct ifnet *ifp);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p);
static void vlan_link_state(struct ifnet *ifp, int link);
-static int vlan_set_promisc(struct ifnet *ifp);
static struct ifnet *vlan_clone_match_ethertag(struct if_clone *,
const char *, int *);
@@ -411,8 +411,8 @@
ifp->if_flags |= IFF_RUNNING;
VLAN_UNLOCK();
- /* Update promiscuous mode, if necessary. */
- vlan_set_promisc(ifp);
+ /* Update flags on the parent, if necessary. */
+ vlan_setflags(ifp);
}
return (0);
@@ -648,7 +648,7 @@
ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
ifv->ifv_mintu = ETHERMIN;
- ifv->ifv_flags = 0;
+ ifv->ifv_pflags = 0;
/*
* The active VLAN counter on the parent is used
@@ -772,8 +772,8 @@
/* Disconnect from parent. */
ifv->ifv_p = NULL;
+ ifv->ifv_pflags = 0;
ifv->ifv_if.if_mtu = ETHERMTU; /* XXX why not 0? */
- ifv->ifv_flags = 0;
ifv->ifv_if.if_link_state = LINK_STATE_UNKNOWN;
/* Clear our MAC address. */
@@ -787,27 +787,41 @@
return (0);
}
+/* Handle a reference counted flag that should be set on the parent as well */
static int
-vlan_set_promisc(struct ifnet *ifp)
+vlan_setflag(struct ifnet *ifp, int flag, int (*func)(struct ifnet *, int))
{
- struct ifvlan *ifv = ifp->if_softc;
- int error = 0;
+ struct ifvlan *ifv;
+ int error, status;
- if ((ifp->if_flags & IFF_PROMISC) != 0) {
- if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
- error = ifpromisc(ifv->ifv_p, 1);
- if (error == 0)
- ifv->ifv_flags |= IFVF_PROMISC;
- }
- } else {
- if ((ifv->ifv_flags & IFVF_PROMISC) != 0) {
- error = ifpromisc(ifv->ifv_p, 0);
- if (error == 0)
- ifv->ifv_flags &= ~IFVF_PROMISC;
- }
+ /* XXX VLAN_LOCK_ASSERT(); */
+
+ ifv = ifp->if_softc;
+ status = ifp->if_flags & flag;
+
+ if (status != (ifv->ifv_pflags & flag)) {
+ error = (*func)(ifv->ifv_p, status);
+ if (error)
+ return (error);
+ ifv->ifv_pflags &= ~flag;
+ ifv->ifv_pflags |= status;
}
+ return (0);
+}
- return (error);
+/* Handle IFF_* flags that require certain changes in the parent's status */
+static int
+vlan_setflags(struct ifnet *ifp)
+{
+ int error;
+
+ error = vlan_setflag(ifp, IFF_PROMISC, ifpromisc);
+ if (error)
+ return (error);
+ error = vlan_setflag(ifp, IFF_ALLMULTI, if_allmulti);
+ if (error)
+ return (error);
+ return (0);
}
/* Inform all vlans that their parent has changed link state */
@@ -948,8 +962,8 @@
ifp->if_flags |= IFF_RUNNING;
VLAN_UNLOCK();
- /* Update promiscuous mode, if necessary. */
- vlan_set_promisc(ifp);
+ /* Update flags on the parent, if necessary. */
+ vlan_setflags(ifp);
break;
case SIOCGETVLAN:
@@ -966,11 +980,11 @@
case SIOCSIFFLAGS:
/*
- * For promiscuous mode, we enable promiscuous mode on
- * the parent if we need promiscuous on the VLAN interface.
+ * We should propagate selected flags to the parent,
+ * e.g., promiscuous mode.
*/
if (ifv->ifv_p != NULL)
- error = vlan_set_promisc(ifp);
+ error = vlan_setflags(ifp);
break;
case SIOCADDMULTI:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050629130127.GA51085>
