summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2015-05-20 08:54:37 +0000
committermpi <mpi@openbsd.org>2015-05-20 08:54:37 +0000
commit13da665488d68a5b20a68abc846fb1610cd97fa9 (patch)
tree493cfe7be5593a4b813078e263739c7b8cfd39f3
parentDo not increment if_opackets in if_output(). It might make sense to do (diff)
downloadwireguard-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.c42
-rw-r--r--sys/net/if_vlan_var.h3
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