Source-Changes-HG archive

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

[src/trunk]: src/sys/net Don't use IFQ_ENQUEUE/IFQ_DEQUEUE in the MP-ified in...



details:   https://anonhg.NetBSD.org/src/rev/e2275ad1f338
branches:  trunk
changeset: 346268:e2275ad1f338
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Jul 04 04:43:46 2016 +0000

description:
Don't use IFQ_ENQUEUE/IFQ_DEQUEUE in the MP-ified interface without whole lock.

That causes reoder per flow, as there can be below situation
    (1) CPU#A does IFQ_DEQUEUE
    (2) CPU#A sleeps by some reason
    (3) CPU#B does IFQ_DEQUEUE

diffstat:

 sys/net/if_gif.c |  94 ++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 71 insertions(+), 23 deletions(-)

diffs (143 lines):

diff -r 6b469ba608f7 -r e2275ad1f338 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Mon Jul 04 04:40:13 2016 +0000
+++ b/sys/net/if_gif.c  Mon Jul 04 04:43:46 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.118 2016/07/04 04:40:13 knakahara Exp $   */
+/*     $NetBSD: if_gif.c,v 1.119 2016/07/04 04:43:46 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.118 2016/07/04 04:40:13 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.119 2016/07/04 04:43:46 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -100,6 +100,7 @@
 static int     gif_output(struct ifnet *, struct mbuf *,
                           const struct sockaddr *, const struct rtentry *);
 static void    gif_start(struct ifnet *);
+static int     gif_transmit(struct ifnet *, struct mbuf *);
 static int     gif_ioctl(struct ifnet *, u_long, void *);
 static int     gif_set_tunnel(struct ifnet *, struct sockaddr *,
                               struct sockaddr *);
@@ -195,6 +196,8 @@
        sc->gif_if.if_extflags  = IFEF_NO_LINK_STATE_CHANGE;
        sc->gif_if.if_ioctl  = gif_ioctl;
        sc->gif_if.if_output = gif_output;
+       sc->gif_if.if_start = gif_start;
+       sc->gif_if.if_transmit = gif_transmit;
        sc->gif_if.if_type   = IFT_GIF;
        sc->gif_if.if_dlt    = DLT_NULL;
        sc->gif_if.if_softc  = sc;
@@ -327,9 +330,6 @@
 {
        struct gif_softc *sc = ifp->if_softc;
        int error = 0;
-#ifndef GIF_MPSAFE
-       int s;
-#endif
 
        IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
 
@@ -360,24 +360,7 @@
        m->m_pkthdr.csum_flags = 0;
        m->m_pkthdr.csum_data = 0;
 
-#ifndef GIF_MPSAFE
-       s = splnet();
-#endif
-       IFQ_ENQUEUE(&ifp->if_snd, m, error);
-       if (error) {
-#ifndef GIF_MPSAFE
-               splx(s);
-#endif
-               goto end;
-       }
-#ifndef GIF_MPSAFE
-       splx(s);
-#endif
-
-       gif_start(ifp);
-
-       error = 0;
-
+       error = if_transmit_lock(ifp, m);
   end:
        if (error)
                ifp->if_oerrors++;
@@ -460,6 +443,71 @@
        }
 }
 
+static int
+gif_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+       struct gif_softc *sc;
+       int family;
+       int len;
+       int error;
+
+       sc = ifp->if_softc;
+
+       /* output processing */
+       if (m == NULL)
+               return EINVAL;
+
+       /* grab and chop off inner af type */
+       if (sizeof(int) > m->m_len) {
+               m = m_pullup(m, sizeof(int));
+               if (!m) {
+                       ifp->if_oerrors++;
+                       return ENOBUFS;
+               }
+       }
+       family = *mtod(m, int *);
+       bpf_mtap(ifp, m);
+       m_adj(m, sizeof(int));
+
+       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;
+#endif
+       default:
+               m_freem(m);
+               error = ENETDOWN;
+               break;
+       }
+
+       if (error)
+               ifp->if_oerrors++;
+       else {
+               ifp->if_opackets++;
+               ifp->if_obytes += len;
+       }
+
+       return error;
+}
+
 void
 gif_input(struct mbuf *m, int af, struct ifnet *ifp)
 {



Home | Main Index | Thread Index | Old Index