Module Name: src
Committed By: thorpej
Date: Fri Sep 2 05:50:36 UTC 2022
Modified Files:
src/sys/net: if.c pktqueue.c pktqueue.h
Log Message:
Re-factor how pktq_barrier() is issued by if_detach().
Rather than excplicitly referencing ip_pktq and ip6_pktq in if_detach(),
instead add all pktqueues to a global list. This list is then used in
the new pktq_ifdetach() function to issue a barrier on all pktqueues.
Note that the performance of this list is not critical; it will seldom
be accessed (then pktqueues are created/destroyed and when network
interfaces are detached), and so a simple synchronization strategy using
a rwlock is sufficient.
To generate a diff of this commit:
cvs rdiff -u -r1.522 -r1.523 src/sys/net/if.c
cvs rdiff -u -r1.19 -r1.20 src/sys/net/pktqueue.c
cvs rdiff -u -r1.7 -r1.8 src/sys/net/pktqueue.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.c
diff -u src/sys/net/if.c:1.522 src/sys/net/if.c:1.523
--- src/sys/net/if.c:1.522 Fri Sep 2 04:34:58 2022
+++ src/sys/net/if.c Fri Sep 2 05:50:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.522 2022/09/02 04:34:58 thorpej Exp $ */
+/* $NetBSD: if.c,v 1.523 2022/09/02 05:50:36 thorpej Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.522 2022/09/02 04:34:58 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.523 2022/09/02 05:50:36 thorpej Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -1412,17 +1412,13 @@ if_detach(struct ifnet *ifp)
}
/*
- * IP queues have to be processed separately: net-queue barrier
- * ensures that the packets are dequeued while a cross-call will
- * ensure that the interrupts have completed. FIXME: not quite..
+ * Ensure that all packets on protocol input pktqueues have been
+ * processed, or, at least, removed from the queues.
+ *
+ * A cross-call will ensure that the interrupts have completed.
+ * FIXME: not quite..
*/
-#ifdef INET
- pktq_barrier(ip_pktq);
-#endif
-#ifdef INET6
- if (in6_present)
- pktq_barrier(ip6_pktq);
-#endif
+ pktq_ifdetach();
xc_barrier(0);
/*
Index: src/sys/net/pktqueue.c
diff -u src/sys/net/pktqueue.c:1.19 src/sys/net/pktqueue.c:1.20
--- src/sys/net/pktqueue.c:1.19 Fri Sep 2 03:50:00 2022
+++ src/sys/net/pktqueue.c Fri Sep 2 05:50:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: pktqueue.c,v 1.19 2022/09/02 03:50:00 thorpej Exp $ */
+/* $NetBSD: pktqueue.c,v 1.20 2022/09/02 05:50:36 thorpej Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.19 2022/09/02 03:50:00 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.20 2022/09/02 05:50:36 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -53,6 +53,9 @@ __KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v
#include <sys/proc.h>
#include <sys/percpu.h>
#include <sys/xcall.h>
+#include <sys/once.h>
+#include <sys/queue.h>
+#include <sys/rwlock.h>
#include <net/pktqueue.h>
#include <net/rss_config.h>
@@ -80,8 +83,11 @@ struct pktqueue {
percpu_t * pq_counters;
void * pq_sih;
- /* Finally, per-CPU queues. */
+ /* The per-CPU queues. */
struct percpu * pq_pcq; /* struct pcq * */
+
+ /* The linkage on the list of all pktqueues. */
+ LIST_ENTRY(pktqueue) pq_list;
};
/* The counters of the packet queue. */
@@ -97,6 +103,28 @@ typedef struct {
/* Special marker value used by pktq_barrier() mechanism. */
#define PKTQ_MARKER ((void *)(~0ULL))
+/*
+ * This is a list of all pktqueues. This list is used by
+ * pktq_ifdetach() to issue a barrier on every pktqueue.
+ *
+ * The r/w lock is acquired for writing in pktq_create() and
+ * pktq_destroy(), and for reading in pktq_ifdetach().
+ *
+ * This list is not performance critical, and will seldom be
+ * accessed.
+ */
+static LIST_HEAD(, pktqueue) pktqueue_list __read_mostly;
+static krwlock_t pktqueue_list_lock __read_mostly;
+static once_t pktqueue_list_init_once __read_mostly;
+
+static int
+pktqueue_list_init(void)
+{
+ LIST_INIT(&pktqueue_list);
+ rw_init(&pktqueue_list_lock);
+ return 0;
+}
+
static void
pktq_init_cpu(void *vqp, void *vpq, struct cpu_info *ci)
{
@@ -141,6 +169,8 @@ pktq_create(size_t maxlen, void (*intrh)
percpu_t *pc;
void *sih;
+ RUN_ONCE(&pktqueue_list_init_once, pktqueue_list_init);
+
pc = percpu_alloc(sizeof(pktq_counters_t));
if ((sih = softint_establish(sflags, intrh, sc)) == NULL) {
percpu_free(pc, sizeof(pktq_counters_t));
@@ -155,6 +185,10 @@ pktq_create(size_t maxlen, void (*intrh)
pq->pq_pcq = percpu_create(sizeof(struct pcq *),
pktq_init_cpu, pktq_fini_cpu, pq);
+ rw_enter(&pktqueue_list_lock, RW_WRITER);
+ LIST_INSERT_HEAD(&pktqueue_list, pq, pq_list);
+ rw_exit(&pktqueue_list_lock);
+
return pq;
}
@@ -162,6 +196,12 @@ void
pktq_destroy(pktqueue_t *pq)
{
+ KASSERT(pktqueue_list_init_once.o_status == ONCE_DONE);
+
+ rw_enter(&pktqueue_list_lock, RW_WRITER);
+ LIST_REMOVE(pq, pq_list);
+ rw_exit(&pktqueue_list_lock);
+
percpu_free(pq->pq_pcq, sizeof(struct pcq *));
percpu_free(pq->pq_counters, sizeof(pktq_counters_t));
softint_disestablish(pq->pq_sih);
@@ -472,6 +512,25 @@ pktq_barrier(pktqueue_t *pq)
}
/*
+ * pktq_ifdetach: issue a barrier on all pktqueues when a network
+ * interface is detached.
+ */
+void
+pktq_ifdetach(void)
+{
+ pktqueue_t *pq;
+
+ /* Just in case no pktqueues have been created yet... */
+ RUN_ONCE(&pktqueue_list_init_once, pktqueue_list_init);
+
+ rw_enter(&pktqueue_list_lock, RW_READER);
+ LIST_FOREACH(pq, &pktqueue_list, pq_list) {
+ pktq_barrier(pq);
+ }
+ rw_exit(&pktqueue_list_lock);
+}
+
+/*
* pktq_flush: free mbufs in all queues.
*
* => The caller must ensure there are no concurrent writers or flush calls.
Index: src/sys/net/pktqueue.h
diff -u src/sys/net/pktqueue.h:1.7 src/sys/net/pktqueue.h:1.8
--- src/sys/net/pktqueue.h:1.7 Fri Sep 2 03:50:00 2022
+++ src/sys/net/pktqueue.h Fri Sep 2 05:50:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: pktqueue.h,v 1.7 2022/09/02 03:50:00 thorpej Exp $ */
+/* $NetBSD: pktqueue.h,v 1.8 2022/09/02 05:50:36 thorpej Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -53,6 +53,7 @@ void pktq_destroy(pktqueue_t *);
bool pktq_enqueue(pktqueue_t *, struct mbuf *, const u_int);
struct mbuf * pktq_dequeue(pktqueue_t *);
void pktq_barrier(pktqueue_t *);
+void pktq_ifdetach(void);
void pktq_flush(pktqueue_t *);
int pktq_set_maxlen(pktqueue_t *, size_t);