Keep track of the ifih corresponding to a vlan instance to ease its
authormpi <mpi@openbsd.org>
Wed, 20 May 2015 08:54:37 +0000 (08:54 +0000)
committermpi <mpi@openbsd.org>
Wed, 20 May 2015 08:54:37 +0000 (08:54 +0000)
removal.

As soon as carp(4) will be converted to the new if_input() API it
will be possible to add multiple vlan(4) and carp(4) pseudo-ifps on
top of the same parent interface.  When such thing happens we can no
longer assume that the first pseudo-ifp to be destroyed will be the
last configured.

ok dlg@

sys/net/if_vlan.c
sys/net/if_vlan_var.h

index 7ba86fe..2859e98 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_vlan.c,v 1.122 2015/05/20 08:28:54 mpi Exp $       */
+/*     $OpenBSD: if_vlan.c,v 1.123 2015/05/20 08:54:37 mpi Exp $       */
 
 /*
  * Copyright 1998 Massachusetts Institute of Technology
@@ -370,7 +370,6 @@ vlan_input(struct mbuf *m, void *hdr)
 int
 vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
 {
-       struct ifih             *vlan_ifih;
        struct sockaddr_dl      *sdl1, *sdl2;
        struct vlan_taghash     *tagh;
        u_int                    flags;
@@ -381,14 +380,15 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
        if (ifv->ifv_p == p && ifv->ifv_tag == tag) /* noop */
                return (0);
 
-       /* Share an ifih between multiple vlan(4) instances. */
-       vlan_ifih = SLIST_FIRST(&p->if_inputs);
-       if (vlan_ifih->ifih_input != vlan_input) {
-               vlan_ifih = malloc(sizeof(*vlan_ifih), M_DEVBUF, M_NOWAIT);
-               if (vlan_ifih == NULL)
+       /* Can we share an ifih between multiple vlan(4) instances? */
+       ifv->ifv_ifih = SLIST_FIRST(&p->if_inputs);
+       if (ifv->ifv_ifih->ifih_input != vlan_input) {
+               ifv->ifv_ifih = malloc(sizeof(*ifv->ifv_ifih), M_DEVBUF,
+                   M_NOWAIT);
+               if (ifv->ifv_ifih == NULL)
                        return (ENOMEM);
-               vlan_ifih->ifih_input = vlan_input;
-               vlan_ifih->ifih_refcnt = 0;
+               ifv->ifv_ifih->ifih_input = vlan_input;
+               ifv->ifv_ifih->ifih_refcnt = 0;
        }
 
        /* Remember existing interface flags and reset the interface */
@@ -443,10 +443,6 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
 
        ifv->ifv_tag = tag;
 
-       /* Change input handler of the physical interface. */
-       if (++vlan_ifih->ifih_refcnt == 1)
-               SLIST_INSERT_HEAD(&p->if_inputs, vlan_ifih, ifih_next);
-
        /* Register callback for physical link state changes */
        ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,
            vlan_vlandev_state, ifv);
@@ -458,7 +454,12 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
        vlan_vlandev_state(ifv);
 
        tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
+
        s = splnet();
+       /* Change input handler of the physical interface. */
+       if (++ifv->ifv_ifih->ifih_refcnt == 1)
+               SLIST_INSERT_HEAD(&p->if_inputs, ifv->ifv_ifih, ifih_next);
+
        LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list);
        splx(s);
 
@@ -468,7 +469,6 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
 int
 vlan_unconfig(struct ifnet *ifp, struct ifnet *newp)
 {
-       struct ifih             *vlan_ifih;
        struct sockaddr_dl      *sdl;
        struct ifvlan           *ifv;
        struct ifnet            *p;
@@ -486,6 +486,12 @@ vlan_unconfig(struct ifnet *ifp, struct ifnet *newp)
 
        s = splnet();
        LIST_REMOVE(ifv, ifv_list);
+
+       /* Restore previous input handler. */
+       if (--ifv->ifv_ifih->ifih_refcnt == 0) {
+               SLIST_REMOVE(&p->if_inputs, ifv->ifv_ifih, ifih, ifih_next);
+               free(ifv->ifv_ifih, M_DEVBUF, sizeof(*ifv->ifv_ifih));
+       }
        splx(s);
 
        hook_disestablish(p->if_linkstatehooks, ifv->lh_cookie);
@@ -496,14 +502,6 @@ vlan_unconfig(struct ifnet *ifp, struct ifnet *newp)
                if_link_state_change(ifp);
        }
 
-       /* Restore previous input handler. */
-       vlan_ifih = SLIST_FIRST(&p->if_inputs);
-       KASSERT(vlan_ifih->ifih_input == vlan_input);
-       if (--vlan_ifih->ifih_refcnt == 0) {
-               SLIST_REMOVE_HEAD(&p->if_inputs, ifih_next);
-               free(vlan_ifih, M_DEVBUF, sizeof(*vlan_ifih));
-       }
-
        /*
         * Since the interface is being unconfigured, we need to
         * empty the list of multicast groups that we may have joined
index f02540d..324ed2b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_vlan_var.h,v 1.25 2015/05/19 11:09:24 mpi Exp $    */
+/*     $OpenBSD: if_vlan_var.h,v 1.26 2015/05/20 08:54:37 mpi Exp $    */
 
 /*
  * Copyright 1998 Massachusetts Institute of Technology
@@ -87,6 +87,7 @@ struct        ifvlan {
        int ifv_flags;
        void *lh_cookie;
        void *dh_cookie;
+       struct ifih *ifv_ifih;
 };
 
 #define        ifv_if          ifv_ac.ac_if