From owner-freebsd-bugs@FreeBSD.ORG Wed Jun 29 13:01:32 2005 Return-Path: X-Original-To: freebsd-bugs@FreeBSD.org Delivered-To: freebsd-bugs@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2737B16A41C for ; Wed, 29 Jun 2005 13:01:32 +0000 (GMT) (envelope-from yar@comp.chem.msu.su) Received: from comp.chem.msu.su (comp.chem.msu.su [158.250.32.97]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7130643D49 for ; Wed, 29 Jun 2005 13:01:30 +0000 (GMT) (envelope-from yar@comp.chem.msu.su) Received: from comp.chem.msu.su (localhost [127.0.0.1]) by comp.chem.msu.su (8.13.3/8.13.3) with ESMTP id j5TD1S8T051390; Wed, 29 Jun 2005 17:01:28 +0400 (MSD) (envelope-from yar@comp.chem.msu.su) Received: (from yar@localhost) by comp.chem.msu.su (8.13.3/8.13.3/Submit) id j5TD1RPJ051385; Wed, 29 Jun 2005 17:01:27 +0400 (MSD) (envelope-from yar) Date: Wed, 29 Jun 2005 17:01:27 +0400 From: Yar Tikhiy To: dan@obluda.cz Message-ID: <20050629130127.GA51085@comp.chem.msu.su> References: <200506141202.j5EC28O7026407@freefall.freebsd.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200506141202.j5EC28O7026407@freefall.freebsd.org> User-Agent: Mutt/1.5.9i Cc: freebsd-bugs@FreeBSD.org Subject: Re: kern/81978: [ PATCH ] if_vlan didn't pass the ALLMULTI to the parent interface X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Jun 2005 13:01:32 -0000 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: