Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys/net Pull up following revision(s) (requested by knaka...
details: https://anonhg.NetBSD.org/src/rev/acec486664c8
branches: netbsd-8
changeset: 434013:acec486664c8
user: snj <snj%NetBSD.org@localhost>
date: Wed Jun 21 17:39:24 2017 +0000
description:
Pull up following revision(s) (requested by knakahara in ticket #41):
sys/net/if_vlan.c: revision 1.98
sys/net/if_vlanvar.h: revision 1.10
vlan(4) MP-ify. contributed by s-yamaguchi@IIJ, thanks.
diffstat:
sys/net/if_vlan.c | 840 ++++++++++++++++++++++++++++++++++++++++++++------
sys/net/if_vlanvar.h | 33 +-
2 files changed, 758 insertions(+), 115 deletions(-)
diffs (truncated from 1315 to 300 lines):
diff -r 946789acfea2 -r acec486664c8 sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Thu Jun 15 05:48:45 2017 +0000
+++ b/sys/net/if_vlan.c Wed Jun 21 17:39:24 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vlan.c,v 1.97 2017/05/29 02:55:49 ozaki-r Exp $ */
+/* $NetBSD: if_vlan.c,v 1.97.2.1 2017/06/21 17:39:24 snj Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.97 2017/05/29 02:55:49 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.97.2.1 2017/06/21 17:39:24 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -86,6 +86,7 @@
#endif
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/queue.h>
@@ -95,6 +96,12 @@
#include <sys/proc.h>
#include <sys/kauth.h>
#include <sys/mutex.h>
+#include <sys/kmem.h>
+#include <sys/cpu.h>
+#include <sys/pserialize.h>
+#include <sys/psref.h>
+#include <sys/pslist.h>
+#include <sys/atomic.h>
#include <sys/device.h>
#include <sys/module.h>
@@ -116,6 +123,10 @@
#include "ioconf.h"
+#ifdef NET_MPSAFE
+#define VLAN_MPSAFE 1
+#endif
+
struct vlan_mc_entry {
LIST_ENTRY(vlan_mc_entry) mc_entries;
/*
@@ -131,21 +142,33 @@
#define mc_enm mc_u.mcu_enm
+
+struct ifvlan_linkmib {
+ struct ifvlan *ifvm_ifvlan;
+ const struct vlan_multisw *ifvm_msw;
+ int ifvm_encaplen; /* encapsulation length */
+ int ifvm_mtufudge; /* MTU fudged by this much */
+ int ifvm_mintu; /* min transmission unit */
+ uint16_t ifvm_proto; /* encapsulation ethertype */
+ uint16_t ifvm_tag; /* tag to apply on packets */
+ struct ifnet *ifvm_p; /* parent interface of this vlan */
+
+ struct psref_target ifvm_psref;
+};
+
struct ifvlan {
union {
struct ethercom ifvu_ec;
} ifv_u;
- struct ifnet *ifv_p; /* parent interface of this vlan */
- struct ifv_linkmib {
- const struct vlan_multisw *ifvm_msw;
- int ifvm_encaplen; /* encapsulation length */
- int ifvm_mtufudge; /* MTU fudged by this much */
- int ifvm_mintu; /* min transmission unit */
- uint16_t ifvm_proto; /* encapsulation ethertype */
- uint16_t ifvm_tag; /* tag to apply on packets */
- } ifv_mib;
+ struct ifvlan_linkmib *ifv_mib; /*
+ * reader must use vlan_getref_linkmib()
+ * instead of direct dereference
+ */
+ kmutex_t ifv_lock; /* writer lock for ifv_mib */
+
LIST_HEAD(__vlan_mchead, vlan_mc_entry) ifv_mc_listhead;
LIST_ENTRY(ifvlan) ifv_list;
+ struct pslist_entry ifv_hash;
int ifv_flags;
};
@@ -179,15 +202,47 @@
static int vlan_clone_create(struct if_clone *, int);
static int vlan_clone_destroy(struct ifnet *);
-static int vlan_config(struct ifvlan *, struct ifnet *);
+static int vlan_config(struct ifvlan *, struct ifnet *,
+ uint16_t);
static int vlan_ioctl(struct ifnet *, u_long, void *);
static void vlan_start(struct ifnet *);
+static int vlan_transmit(struct ifnet *, struct mbuf *);
static void vlan_unconfig(struct ifnet *);
+static int vlan_unconfig_locked(struct ifvlan *,
+ struct ifvlan_linkmib *);
+static void vlan_hash_init(void);
+static int vlan_hash_fini(void);
+static struct ifvlan_linkmib* vlan_getref_linkmib(struct ifvlan *,
+ struct psref *);
+static void vlan_putref_linkmib(struct ifvlan_linkmib *,
+ struct psref *);
+static void vlan_linkmib_update(struct ifvlan *,
+ struct ifvlan_linkmib *);
+static struct ifvlan_linkmib* vlan_lookup_tag_psref(struct ifnet *,
+ uint16_t, struct psref *);
+static int tag_hash_func(uint16_t, u_long);
-/* XXX This should be a hash table with the tag as the basis of the key. */
-static LIST_HEAD(, ifvlan) ifv_list;
+LIST_HEAD(vlan_ifvlist, ifvlan);
+static struct {
+ kmutex_t lock;
+ struct vlan_ifvlist list;
+} ifv_list __cacheline_aligned;
+
-static kmutex_t ifv_mtx __cacheline_aligned;
+#if !defined(VLAN_TAG_HASH_SIZE)
+#define VLAN_TAG_HASH_SIZE 32
+#endif
+static struct {
+ kmutex_t lock;
+ struct pslist_head *lists;
+ u_long mask;
+} ifv_hash __cacheline_aligned = {
+ .lists = NULL,
+ .mask = 0,
+};
+
+pserialize_t vlan_psz __read_mostly;
+static struct psref_class *ifvm_psref_class __read_mostly;
struct if_clone vlan_cloner =
IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
@@ -208,10 +263,15 @@
static void
vlaninit(void)
{
+ mutex_init(&ifv_list.lock, MUTEX_DEFAULT, IPL_NONE);
+ LIST_INIT(&ifv_list.list);
- LIST_INIT(&ifv_list);
- mutex_init(&ifv_mtx, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&ifv_hash.lock, MUTEX_DEFAULT, IPL_NONE);
+ vlan_psz = pserialize_create();
+ ifvm_psref_class = psref_class_create("vlanlinkmib", IPL_SOFTNET);
if_clone_attach(&vlan_cloner);
+
+ vlan_hash_init();
}
static int
@@ -219,15 +279,24 @@
{
int error = 0;
- if (!LIST_EMPTY(&ifv_list))
- error = EBUSY;
+ mutex_enter(&ifv_list.lock);
+ if (!LIST_EMPTY(&ifv_list.list)) {
+ mutex_exit(&ifv_list.lock);
+ return EBUSY;
+ }
+ mutex_exit(&ifv_list.lock);
- if (error == 0) {
- if_clone_detach(&vlan_cloner);
- mutex_destroy(&ifv_mtx);
- }
+ error = vlan_hash_fini();
+ if (error != 0)
+ return error;
- return error;
+ if_clone_detach(&vlan_cloner);
+ psref_class_destroy(ifvm_psref_class);
+ pserialize_destroy(vlan_psz);
+ mutex_destroy(&ifv_hash.lock);
+ mutex_destroy(&ifv_list.lock);
+
+ return 0;
}
static void
@@ -252,20 +321,32 @@
{
struct ifvlan *ifv;
struct ifnet *ifp;
- int s;
+ struct ifvlan_linkmib *mib;
ifv = malloc(sizeof(struct ifvlan), M_DEVBUF, M_WAITOK|M_ZERO);
+ mib = kmem_zalloc(sizeof(struct ifvlan_linkmib), KM_SLEEP);
ifp = &ifv->ifv_if;
LIST_INIT(&ifv->ifv_mc_listhead);
- s = splnet();
- LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list);
- splx(s);
+ mib->ifvm_ifvlan = ifv;
+ mib->ifvm_p = NULL;
+ psref_target_init(&mib->ifvm_psref, ifvm_psref_class);
+
+ mutex_init(&ifv->ifv_lock, MUTEX_DEFAULT, IPL_NONE);
+ ifv->ifv_mib = mib;
+
+ mutex_enter(&ifv_list.lock);
+ LIST_INSERT_HEAD(&ifv_list.list, ifv, ifv_list);
+ mutex_exit(&ifv_list.lock);
if_initname(ifp, ifc->ifc_name, unit);
ifp->if_softc = ifv;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+#ifdef VLAN_MPSAFE
+ ifp->if_extflags = IFEF_START_MPSAFE;
+#endif
ifp->if_start = vlan_start;
+ ifp->if_transmit = vlan_transmit;
ifp->if_ioctl = vlan_ioctl;
IFQ_SET_READY(&ifp->if_snd);
@@ -280,47 +361,66 @@
vlan_clone_destroy(struct ifnet *ifp)
{
struct ifvlan *ifv = ifp->if_softc;
- int s;
- s = splnet();
+ mutex_enter(&ifv_list.lock);
LIST_REMOVE(ifv, ifv_list);
+ mutex_exit(&ifv_list.lock);
+
vlan_unconfig(ifp);
if_detach(ifp);
- splx(s);
+ psref_target_destroy(&ifv->ifv_mib->ifvm_psref, ifvm_psref_class);
+ kmem_free(ifv->ifv_mib, sizeof(struct ifvlan_linkmib));
+ mutex_destroy(&ifv->ifv_lock);
free(ifv, M_DEVBUF);
return (0);
}
/*
- * Configure a VLAN interface. Must be called at splnet().
+ * Configure a VLAN interface.
*/
static int
-vlan_config(struct ifvlan *ifv, struct ifnet *p)
+vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag)
{
struct ifnet *ifp = &ifv->ifv_if;
- int error;
+ struct ifvlan_linkmib *nmib = NULL;
+ struct ifvlan_linkmib *omib = NULL;
+ struct psref_target *nmib_psref = NULL;
+ int error = 0;
+ int idx;
+ bool omib_cleanup = false;
+
+ nmib = kmem_alloc(sizeof(*nmib), KM_SLEEP);
- if (ifv->ifv_p != NULL)
- return (EBUSY);
+ mutex_enter(&ifv->ifv_lock);
+ omib = ifv->ifv_mib;
+
+ if (omib->ifvm_p != NULL) {
+ error = EBUSY;
+ goto done;
+ }
+
+ *nmib = *omib;
+ nmib_psref = &nmib->ifvm_psref;
+
+ psref_target_init(nmib_psref, ifvm_psref_class);
switch (p->if_type) {
case IFT_ETHER:
{
struct ethercom *ec = (void *) p;
-
- ifv->ifv_msw = &vlan_ether_multisw;
- ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
- ifv->ifv_mintu = ETHERMIN;
+ nmib->ifvm_msw = &vlan_ether_multisw;
+ nmib->ifvm_encaplen = ETHER_VLAN_ENCAP_LEN;
+ nmib->ifvm_mintu = ETHERMIN;
Home |
Main Index |
Thread Index |
Old Index