From 13da665488d68a5b20a68abc846fb1610cd97fa9 Mon Sep 17 00:00:00 2001 From: mpi Date: Wed, 20 May 2015 08:54:37 +0000 Subject: [PATCH] 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@ --- sys/net/if_vlan.c | 42 ++++++++++++++++++++---------------------- 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 -- 2.20.1