diff options
author | 2015-05-20 08:54:37 +0000 | |
---|---|---|
committer | 2015-05-20 08:54:37 +0000 | |
commit | 13da665488d68a5b20a68abc846fb1610cd97fa9 (patch) | |
tree | 493cfe7be5593a4b813078e263739c7b8cfd39f3 | |
parent | Do not increment if_opackets in if_output(). It might make sense to do (diff) | |
download | wireguard-openbsd-13da665488d68a5b20a68abc846fb1610cd97fa9.tar.xz wireguard-openbsd-13da665488d68a5b20a68abc846fb1610cd97fa9.zip |
Keep track of the ifih corresponding to a vlan instance to ease its
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@
-rw-r--r-- | sys/net/if_vlan.c | 42 | ||||
-rw-r--r-- | sys/net/if_vlan_var.h | 3 |
2 files changed, 22 insertions, 23 deletions
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 7ba86fe9f74..2859e98a72a 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -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 diff --git a/sys/net/if_vlan_var.h b/sys/net/if_vlan_var.h index f02540d42b9..324ed2bfa34 100644 --- a/sys/net/if_vlan_var.h +++ b/sys/net/if_vlan_var.h @@ -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 |