Module Name: src
Committed By: knakahara
Date: Mon Jul 4 04:43:46 UTC 2016
Modified Files:
src/sys/net: if_gif.c
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.118 -r1.119 src/sys/net/if_gif.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if_gif.c
diff -u src/sys/net/if_gif.c:1.118 src/sys/net/if_gif.c:1.119
--- src/sys/net/if_gif.c:1.118 Mon Jul 4 04:40:13 2016
+++ src/sys/net/if_gif.c Mon Jul 4 04:43:46 2016
@@ -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 void gifattach0(struct gif_softc
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 @@ gifattach0(struct gif_softc *sc)
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 @@ gif_output(struct ifnet *ifp, struct mbu
{
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 @@ gif_output(struct ifnet *ifp, struct mbu
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 @@ gif_start(struct ifnet *ifp)
}
}
+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)
{