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);