Module Name:    src
Committed By:   ozaki-r
Date:           Wed Sep 30 07:12:32 UTC 2015

Modified Files:
        src/sys/net: if.h if_llatbl.c if_llatbl.h

Log Message:
Make GATEWAY (fastforward) work again

With GATEWAY (fastforward), the whole forwarding processing runs in
hardware interrupt context. So we cannot use rwlock for lltable and
llentry in that case.

This change replaces rwlock with mutex(IPL_NET) for lltable and llentry
when GATEWAY is enabled. We need to tweak locking only around rtree
in lltable_free. Other than that, what we need to do is to change macros
for locks.

I hope fastforward runs in softint some day in the future...


To generate a diff of this commit:
cvs rdiff -u -r1.191 -r1.192 src/sys/net/if.h
cvs rdiff -u -r1.5 -r1.6 src/sys/net/if_llatbl.c
cvs rdiff -u -r1.2 -r1.3 src/sys/net/if_llatbl.h

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.h
diff -u src/sys/net/if.h:1.191 src/sys/net/if.h:1.192
--- src/sys/net/if.h:1.191	Mon Aug 31 08:02:44 2015
+++ src/sys/net/if.h	Wed Sep 30 07:12:32 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.191 2015/08/31 08:02:44 ozaki-r Exp $	*/
+/*	$NetBSD: if.h,v 1.192 2015/09/30 07:12:32 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -123,6 +123,7 @@
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
+#include "opt_gateway.h"
 #endif
 
 struct mbuf;
@@ -213,7 +214,11 @@ struct ifnet_lock;
 #include <sys/condvar.h>
 #include <sys/percpu.h>
 #include <sys/callout.h>
+#ifdef GATEWAY
+#include <sys/mutex.h>
+#else
 #include <sys/rwlock.h>
+#endif
 
 struct ifnet_lock {
 	kmutex_t il_lock;	/* Protects the critical section. */
@@ -347,7 +352,11 @@ typedef struct ifnet {
 #ifdef _KERNEL /* XXX kvm(3) */
 	struct callout *if_slowtimo_ch;
 #endif
+#ifdef GATEWAY
+	struct kmutex	*if_afdata_lock;
+#else
 	struct krwlock	*if_afdata_lock;
+#endif
 } ifnet_t;
  
 #define	if_mtu		if_data.ifi_mtu
@@ -437,6 +446,31 @@ typedef struct ifnet {
 	"\23TSO6"		\
 	"\24LRO"		\
 
+#ifdef GATEWAY
+#define	IF_AFDATA_LOCK_INIT(ifp)	\
+	do { \
+		(ifp)->if_afdata_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); \
+	} while (0)
+
+#define	IF_AFDATA_WLOCK(ifp)	mutex_enter((ifp)->if_afdata_lock)
+#define	IF_AFDATA_RLOCK(ifp)	mutex_enter((ifp)->if_afdata_lock)
+#define	IF_AFDATA_WUNLOCK(ifp)	mutex_exit((ifp)->if_afdata_lock)
+#define	IF_AFDATA_RUNLOCK(ifp)	mutex_exit((ifp)->if_afdata_lock)
+#define	IF_AFDATA_LOCK(ifp)	IF_AFDATA_WLOCK(ifp)
+#define	IF_AFDATA_UNLOCK(ifp)	IF_AFDATA_WUNLOCK(ifp)
+#define	IF_AFDATA_TRYLOCK(ifp)	mutex_tryenter((ifp)->if_afdata_lock)
+#define	IF_AFDATA_DESTROY(ifp)	mutex_destroy((ifp)->if_afdata_lock)
+
+#define	IF_AFDATA_LOCK_ASSERT(ifp)	\
+	KASSERT(mutex_owned((ifp)->if_afdata_lock))
+#define	IF_AFDATA_RLOCK_ASSERT(ifp)	\
+	KASSERT(mutex_owned((ifp)->if_afdata_lock))
+#define	IF_AFDATA_WLOCK_ASSERT(ifp)	\
+	KASSERT(mutex_owned((ifp)->if_afdata_lock))
+#define	IF_AFDATA_UNLOCK_ASSERT(ifp)	\
+	KASSERT(!mutex_owned((ifp)->if_afdata_lock))
+
+#else /* GATEWAY */
 #define	IF_AFDATA_LOCK_INIT(ifp)	\
 	do {(ifp)->if_afdata_lock = rw_obj_alloc();} while (0)
 
@@ -457,7 +491,7 @@ typedef struct ifnet {
 	KASSERT(rw_write_held((ifp)->if_afdata_lock))
 #define	IF_AFDATA_UNLOCK_ASSERT(ifp)	\
 	KASSERT(!rw_lock_head((ifp)->if_afdata_lock))
-
+#endif /* GATEWAY */
 
 #define IFQ_LOCK(_ifq)		if ((_ifq)->ifq_lock) mutex_enter((_ifq)->ifq_lock)
 #define IFQ_UNLOCK(_ifq)	if ((_ifq)->ifq_lock) mutex_exit((_ifq)->ifq_lock)

Index: src/sys/net/if_llatbl.c
diff -u src/sys/net/if_llatbl.c:1.5 src/sys/net/if_llatbl.c:1.6
--- src/sys/net/if_llatbl.c:1.5	Mon Sep 28 07:55:26 2015
+++ src/sys/net/if_llatbl.c	Wed Sep 30 07:12:32 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_llatbl.c,v 1.5 2015/09/28 07:55:26 ozaki-r Exp $	*/
+/*	$NetBSD: if_llatbl.c,v 1.6 2015/09/30 07:12:32 ozaki-r Exp $	*/
 /*
  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
@@ -377,8 +377,20 @@ lltable_free(struct lltable *llt)
 			LLE_REMREF(lle);
 #if defined(__NetBSD__)
 		/* XXX should have callback? */
-		if (lle->la_rt != NULL)
-			rtfree(lle->la_rt);
+		if (lle->la_rt != NULL) {
+			struct rtentry *rt = lle->la_rt;
+			lle->la_rt = NULL;
+#ifdef GATEWAY
+			/* XXX cannot call rtfree with holding mutex(IPL_NET) */
+			LLE_ADDREF(lle);
+			LLE_WUNLOCK(lle);
+#endif
+			rtfree(rt);
+#ifdef GATEWAY
+			LLE_WLOCK(lle);
+			LLE_REMREF(lle);
+#endif
+		}
 #endif
 		llentry_free(lle);
 	}

Index: src/sys/net/if_llatbl.h
diff -u src/sys/net/if_llatbl.h:1.2 src/sys/net/if_llatbl.h:1.3
--- src/sys/net/if_llatbl.h:1.2	Mon Aug 31 08:05:20 2015
+++ src/sys/net/if_llatbl.h	Wed Sep 30 07:12:32 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_llatbl.h,v 1.2 2015/08/31 08:05:20 ozaki-r Exp $	*/
+/*	$NetBSD: if_llatbl.h,v 1.3 2015/09/30 07:12:32 ozaki-r Exp $	*/
 /*
  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
@@ -32,7 +32,15 @@
 #ifndef	_NET_IF_LLATBL_H_
 #define	_NET_IF_LLATBL_H_
 
+#if defined(_KERNEL_OPT)
+#include "opt_gateway.h"
+#endif
+
 #include <sys/rwlock.h>
+#ifdef GATEWAY
+#include <sys/mutex.h>
+#endif
+
 #include <netinet/in.h>
 
 struct ifnet;
@@ -85,7 +93,11 @@ struct llentry {
 
 	LIST_ENTRY(llentry)	lle_chain;	/* chain of deleted items */
 	struct callout		lle_timer;
+#ifdef GATEWAY
+	kmutex_t		lle_lock;
+#else
 	krwlock_t		lle_lock;
+#endif
 
 #ifdef __NetBSD__
 #define	la_timer	lle_timer
@@ -101,6 +113,31 @@ struct llentry {
 #define LLE_LOCK_TRACE(n)
 #endif
 
+#ifdef GATEWAY
+#define	LLE_WLOCK(lle)		do { \
+					LLE_LOCK_TRACE(WL); \
+					mutex_enter(&(lle)->lle_lock); \
+				} while (0)
+#define	LLE_RLOCK(lle)		do { \
+					LLE_LOCK_TRACE(RL); \
+					mutex_enter(&(lle)->lle_lock); \
+				} while (0)
+#define	LLE_WUNLOCK(lle)	do { \
+					LLE_LOCK_TRACE(WU); \
+					mutex_exit(&(lle)->lle_lock); \
+				} while (0)
+#define	LLE_RUNLOCK(lle)	do { \
+					LLE_LOCK_TRACE(RU); \
+					mutex_exit(&(lle)->lle_lock); \
+				} while (0)
+#define	LLE_DOWNGRADE(lle)	do {} while (0)
+#define	LLE_TRY_UPGRADE(lle)	do {} while (0)
+#define	LLE_LOCK_INIT(lle)	mutex_init(&(lle)->lle_lock, MUTEX_DEFAULT, \
+				    IPL_NET)
+#define	LLE_LOCK_DESTROY(lle)	mutex_destroy(&(lle)->lle_lock)
+#define	LLE_WLOCK_ASSERT(lle)	KASSERT(mutex_owned(&(lle)->lle_lock))
+
+#else /* GATEWAY */
 #define	LLE_WLOCK(lle)		do { \
 					LLE_LOCK_TRACE(WL); \
 					rw_enter(&(lle)->lle_lock, RW_WRITER); \
@@ -126,6 +163,7 @@ struct llentry {
 #endif
 #define	LLE_LOCK_DESTROY(lle)	rw_destroy(&(lle)->lle_lock)
 #define	LLE_WLOCK_ASSERT(lle)	KASSERT(rw_write_held(&(lle)->lle_lock))
+#endif /* GATEWAY */
 
 #define LLE_IS_VALID(lle)	(((lle) != NULL) && ((lle) != (void *)-1))
 

Reply via email to