Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys preserve gif(4) configs by psref(9) like vlan(4) and l2t...



details:   https://anonhg.NetBSD.org/src/rev/420ff1ab6e22
branches:  trunk
changeset: 357778:420ff1ab6e22
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Nov 27 05:02:22 2017 +0000

description:
preserve gif(4) configs by psref(9) like vlan(4) and l2tp(4).

After Tx side does not use softint, gif(4) can use psref(9) for config
preservation like vlan(4) and l2tp(4).

update locking notes later.

diffstat:

 sys/net/if_gif.c       |  494 +++++++++++++++++++++++++++---------------------
 sys/net/if_gif.h       |   72 ++++++-
 sys/netinet/in_gif.c   |  107 +++++-----
 sys/netinet/in_gif.h   |   12 +-
 sys/netinet6/in6_gif.c |  106 +++++----
 sys/netinet6/in6_gif.h |   12 +-
 6 files changed, 470 insertions(+), 333 deletions(-)

diffs (truncated from 1578 to 300 lines):

diff -r ca870021d587 -r 420ff1ab6e22 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Mon Nov 27 01:34:06 2017 +0000
+++ b/sys/net/if_gif.c  Mon Nov 27 05:02:22 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.132 2017/11/16 03:07:18 ozaki-r Exp $     */
+/*     $NetBSD: if_gif.c,v 1.133 2017/11/27 05:02:22 knakahara Exp $   */
 /*     $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $    */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.132 2017/11/16 03:07:18 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.133 2017/11/27 05:02:22 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -57,6 +57,9 @@
 #include <sys/xcall.h>
 #include <sys/device.h>
 #include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/pserialize.h>
+#include <sys/psref.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -102,6 +105,9 @@
        kmutex_t lock;
 } gif_softcs __cacheline_aligned;
 
+pserialize_t gif_psz __read_mostly;
+struct psref_class *gv_psref_class __read_mostly;
+
 static void    gif_ro_init_pc(void *, void *, struct cpu_info *);
 static void    gif_ro_fini_pc(void *, void *, struct cpu_info *);
 
@@ -110,6 +116,7 @@
                           const struct sockaddr *, const struct rtentry *);
 static void    gif_start(struct ifnet *);
 static int     gif_transmit(struct ifnet *, struct mbuf *);
+static int     gif_transmit_direct(struct gif_variant *, struct mbuf *);
 static int     gif_ioctl(struct ifnet *, u_long, void *);
 static int     gif_set_tunnel(struct ifnet *, struct sockaddr *,
                               struct sockaddr *);
@@ -119,9 +126,10 @@
 static int     gif_clone_destroy(struct ifnet *);
 static int     gif_check_nesting(struct ifnet *, struct mbuf *);
 
-static int     gif_encap_attach(struct gif_softc *);
-static int     gif_encap_detach(struct gif_softc *);
-static void    gif_encap_pause(struct gif_softc *);
+static int     gif_encap_attach(struct gif_variant *);
+static int     gif_encap_detach(struct gif_variant *);
+
+static void    gif_update_variant(struct gif_softc *, struct gif_variant *);
 
 static struct if_clone gif_cloner =
     IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
@@ -216,6 +224,9 @@
        LIST_INIT(&gif_softcs.list);
        if_clone_attach(&gif_cloner);
 
+       gif_psz = pserialize_create();
+       gv_psref_class = psref_class_create("gifvar", IPL_SOFTNET);
+
        gif_sysctl_setup();
 }
 
@@ -231,6 +242,9 @@
        }
 
        if (error == 0) {
+               psref_class_destroy(gv_psref_class);
+               pserialize_destroy(gif_psz);
+
                if_clone_detach(&gif_cloner);
                sysctl_teardown(&gif_sysctl);
        }
@@ -242,6 +256,7 @@
 gif_clone_create(struct if_clone *ifc, int unit)
 {
        struct gif_softc *sc;
+       struct gif_variant *var;
        int rv;
 
        sc = kmem_zalloc(sizeof(struct gif_softc), KM_SLEEP);
@@ -254,6 +269,12 @@
                return rv;
        }
 
+       var = kmem_zalloc(sizeof(*var), KM_SLEEP);
+       var->gv_softc = sc;
+       psref_target_init(&var->gv_psref, gv_psref_class);
+
+       sc->gif_var = var;
+       mutex_init(&sc->gif_lock, MUTEX_DEFAULT, IPL_NONE);
        sc->gif_ro_percpu = percpu_alloc(sizeof(struct gif_ro));
        percpu_foreach(sc->gif_ro_percpu, gif_ro_init_pc, NULL);
 
@@ -268,8 +289,6 @@
 {
        int rv;
 
-       sc->encap_cookie4 = sc->encap_cookie6 = NULL;
-
        sc->gif_if.if_addrlen = 0;
        sc->gif_if.if_mtu    = GIF_MTU;
        sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
@@ -325,6 +344,7 @@
 gif_clone_destroy(struct ifnet *ifp)
 {
        struct gif_softc *sc = (void *) ifp;
+       struct gif_variant *var;
 
        LIST_REMOVE(sc, gif_list);
 
@@ -335,6 +355,10 @@
        percpu_foreach(sc->gif_ro_percpu, gif_ro_fini_pc, NULL);
        percpu_free(sc->gif_ro_percpu, sizeof(struct gif_ro));
 
+       mutex_destroy(&sc->gif_lock);
+
+       var = sc->gif_var;
+       kmem_free(var, sizeof(*var));
        kmem_free(sc, sizeof(struct gif_softc));
 
        return 0;
@@ -346,6 +370,9 @@
 {
        struct ip ip;
        struct gif_softc *sc;
+       struct gif_variant *var;
+       struct psref psref;
+       int ret = 0;
 
        sc = arg;
        if (sc == NULL)
@@ -355,9 +382,13 @@
            != (IFF_UP|IFF_RUNNING))
                return 0;
 
+       var = gif_getref_variant(sc, &psref);
+       if (var->gv_psrc == NULL || var->gv_pdst == NULL)
+               goto out;
+
        /* no physical address */
-       if (!sc->gif_psrc || !sc->gif_pdst)
-               return 0;
+       if (!var->gv_psrc || !var->gv_pdst)
+               goto out;
 
        switch (proto) {
 #ifdef INET
@@ -369,36 +400,42 @@
                break;
 #endif
        default:
-               return 0;
+               goto out;
        }
 
        /* Bail on short packets */
        KASSERT(m->m_flags & M_PKTHDR);
        if (m->m_pkthdr.len < sizeof(ip))
-               return 0;
+               goto  out;
 
        m_copydata(m, 0, sizeof(ip), &ip);
 
        switch (ip.ip_v) {
 #ifdef INET
        case 4:
-               if (sc->gif_psrc->sa_family != AF_INET ||
-                   sc->gif_pdst->sa_family != AF_INET)
-                       return 0;
-               return gif_encapcheck4(m, off, proto, arg);
+               if (var->gv_psrc->sa_family != AF_INET ||
+                   var->gv_pdst->sa_family != AF_INET)
+                       goto out;
+               ret = gif_encapcheck4(m, off, proto, var);
+               break;
 #endif
 #ifdef INET6
        case 6:
                if (m->m_pkthdr.len < sizeof(struct ip6_hdr))
-                       return 0;
-               if (sc->gif_psrc->sa_family != AF_INET6 ||
-                   sc->gif_pdst->sa_family != AF_INET6)
-                       return 0;
-               return gif_encapcheck6(m, off, proto, arg);
+                       goto out;
+               if (var->gv_psrc->sa_family != AF_INET6 ||
+                   var->gv_pdst->sa_family != AF_INET6)
+                       goto out;
+               ret = gif_encapcheck6(m, off, proto, var);
+               break;
 #endif
        default:
-               return 0;
+               goto out;
        }
+
+out:
+       gif_putref_variant(var, &psref);
+       return ret;
 }
 #endif
 
@@ -444,6 +481,8 @@
     const struct rtentry *rt)
 {
        struct gif_softc *sc = ifp->if_softc;
+       struct gif_variant *var = NULL;
+       struct psref psref;
        int error = 0;
 
        IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
@@ -453,16 +492,22 @@
                goto end;
        }
 
-       m->m_flags &= ~(M_BCAST|M_MCAST);
-       if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ||
-           sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+       if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                m_freem(m);
                error = ENETDOWN;
                goto end;
        }
 
+       var = gif_getref_variant(sc, &psref);
+       if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
+               m_freem(m);
+               error = ENETDOWN;
+               goto end;
+       }
        /* XXX should we check if our outer source is legal? */
 
+       m->m_flags &= ~(M_BCAST|M_MCAST);
+
        /* use DLT_NULL encapsulation here to pass inner af type */
        M_PREPEND(m, sizeof(int), M_DONTWAIT);
        if (!m) {
@@ -475,8 +520,10 @@
        m->m_pkthdr.csum_flags = 0;
        m->m_pkthdr.csum_data = 0;
 
-       error = if_transmit_lock(ifp, m);
-  end:
+       error = gif_transmit_direct(var, m);
+end:
+       if (var != NULL)
+               gif_putref_variant(var, &psref);
        if (error)
                ifp->if_oerrors++;
        return error;
@@ -486,12 +533,17 @@
 gif_start(struct ifnet *ifp)
 {
        struct gif_softc *sc;
+       struct gif_variant *var;
        struct mbuf *m;
+       struct psref psref;
        int family;
        int len;
        int error;
 
        sc = ifp->if_softc;
+       var = gif_getref_variant(sc, &psref);
+
+       KASSERT(var->gv_output != NULL);
 
        /* output processing */
        while (1) {
@@ -513,33 +565,7 @@
 
                len = m->m_pkthdr.len;
 
-               /* dispatch to output logic based on outer AF */
-               switch (sc->gif_psrc->sa_family) {
-#ifdef INET
-               case AF_INET:
-                       /* XXX
-                        * To add mutex_enter(softnet_lock) or
-                        * KASSERT(mutex_owned(softnet_lock)) here, we shold
-                        * coordinate softnet_lock between in6_if_up() and
-                        * in6_purgeif().
-                        */
-                       error = in_gif_output(ifp, family, m);
-                       break;
-#endif
-#ifdef INET6
-               case AF_INET6:
-                       /* XXX
-                        * the same as in_gif_output()
-                        */
-                       error = in6_gif_output(ifp, family, m);
-                       break;



Home | Main Index | Thread Index | Old Index