Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net Implement pktq_set_maxlen() and let sysctl net.inet....
details: https://anonhg.NetBSD.org/src/rev/a9399c1c45a2
branches: trunk
changeset: 329787:a9399c1c45a2
user: rmind <rmind%NetBSD.org@localhost>
date: Mon Jun 09 12:57:04 2014 +0000
description:
Implement pktq_set_maxlen() and let sysctl net.inet.{ip,ip6}.ifq.maxlen be
changed on the fly again.
diffstat:
sys/net/if.c | 31 ++++++++++++++++++++++---
sys/net/pktqueue.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
sys/net/pktqueue.h | 3 +-
3 files changed, 91 insertions(+), 7 deletions(-)
diffs (162 lines):
diff -r b78a723deeeb -r a9399c1c45a2 sys/net/if.c
--- a/sys/net/if.c Mon Jun 09 12:48:58 2014 +0000
+++ b/sys/net/if.c Mon Jun 09 12:57:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.278 2014/06/07 13:25:33 he Exp $ */
+/* $NetBSD: if.c,v 1.279 2014/06/09 12:57:04 rmind 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.278 2014/06/07 13:25:33 he Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.279 2014/06/09 12:57:04 rmind Exp $");
#include "opt_inet.h"
@@ -2341,6 +2341,20 @@
#if defined(INET) || defined(INET6)
static int
+sysctl_pktq_maxlen(SYSCTLFN_ARGS, pktqueue_t *pq)
+{
+ u_int nmaxlen = pktq_get_count(pq, PKTQ_MAXLEN);
+ struct sysctlnode node = *rnode;
+ int error;
+
+ node.sysctl_data = &nmaxlen;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+ return pktq_set_maxlen(pq, nmaxlen);
+}
+
+static int
sysctl_pktq_count(SYSCTLFN_ARGS, pktqueue_t *pq, u_int count_id)
{
int count = pktq_get_count(pq, count_id);
@@ -2357,12 +2371,21 @@
}
#if defined(INET)
-SYSCTL_NET_PKTQ(ip_pktq, maxlen, PKTQ_MAXLEN)
+static int
+sysctl_net_ip_pktq_maxlen(SYSCTLFN_ARGS)
+{
+ return sysctl_pktq_maxlen(SYSCTLFN_CALL(rnode), ip_pktq);
+}
SYSCTL_NET_PKTQ(ip_pktq, items, PKTQ_NITEMS)
SYSCTL_NET_PKTQ(ip_pktq, drops, PKTQ_DROPS)
#endif
+
#if defined(INET6)
-SYSCTL_NET_PKTQ(ip6_pktq, maxlen, PKTQ_MAXLEN)
+static int
+sysctl_net_ip6_pktq_maxlen(SYSCTLFN_ARGS)
+{
+ return sysctl_pktq_maxlen(SYSCTLFN_CALL(rnode), ip6_pktq);
+}
SYSCTL_NET_PKTQ(ip6_pktq, items, PKTQ_NITEMS)
SYSCTL_NET_PKTQ(ip6_pktq, drops, PKTQ_DROPS)
#endif
diff -r b78a723deeeb -r a9399c1c45a2 sys/net/pktqueue.c
--- a/sys/net/pktqueue.c Mon Jun 09 12:48:58 2014 +0000
+++ b/sys/net/pktqueue.c Mon Jun 09 12:57:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pktqueue.c,v 1.1 2014/06/05 23:48:16 rmind Exp $ */
+/* $NetBSD: pktqueue.c,v 1.2 2014/06/09 12:57:04 rmind Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.1 2014/06/05 23:48:16 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.2 2014/06/09 12:57:04 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -299,3 +299,63 @@
}
}
}
+
+/*
+ * pktq_set_maxlen: create per-CPU queues using a new size and replace
+ * the existing queues without losing any packets.
+ */
+int
+pktq_set_maxlen(pktqueue_t *pq, size_t maxlen)
+{
+ const u_int slotbytes = ncpu * sizeof(pcq_t *);
+ pcq_t **qs;
+
+ if (!maxlen || maxlen > PCQ_MAXLEN)
+ return EINVAL;
+ if (pq->pq_maxlen == maxlen)
+ return 0;
+
+ /* First, allocate the new queues and replace them. */
+ qs = kmem_zalloc(slotbytes, KM_SLEEP);
+ for (u_int i = 0; i < ncpu; i++) {
+ qs[i] = pcq_create(maxlen, KM_SLEEP);
+ }
+ mutex_enter(&pq->pq_lock);
+ for (u_int i = 0; i < ncpu; i++) {
+ /* Swap: store of a word is atomic. */
+ pcq_t *q = pq->pq_queue[i];
+ pq->pq_queue[i] = qs[i];
+ qs[i] = q;
+ }
+ pq->pq_maxlen = maxlen;
+ mutex_exit(&pq->pq_lock);
+
+ /*
+ * At this point, the new packets are flowing into the new
+ * queues. However, the old queues may have same packets
+ * present which are no longer being present. We are going
+ * to re-enqueue them. This may change the order of packet
+ * arrival, but it is not considered an issue.
+ *
+ * There may also in-flight interrupts calling pktq_dequeue()
+ * which reference the old queues. Issue a barrier to ensure
+ * that we are going to be the only pcq_get() callers on the
+ * old queues.
+ */
+ pktq_barrier(pq);
+
+ for (u_int i = 0; i < ncpu; i++) {
+ struct mbuf *m;
+
+ while ((m = pcq_get(qs[i])) != NULL) {
+ while (!pcq_put(pq->pq_queue[i], m)) {
+ kpause("pktqrenq", false, 1, NULL);
+ }
+ }
+ pcq_destroy(qs[i]);
+ }
+
+ /* Well, that was fun. */
+ kmem_free(qs, slotbytes);
+ return 0;
+}
diff -r b78a723deeeb -r a9399c1c45a2 sys/net/pktqueue.h
--- a/sys/net/pktqueue.h Mon Jun 09 12:48:58 2014 +0000
+++ b/sys/net/pktqueue.h Mon Jun 09 12:57:04 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pktqueue.h,v 1.1 2014/06/05 23:48:16 rmind Exp $ */
+/* $NetBSD: pktqueue.h,v 1.2 2014/06/09 12:57:04 rmind Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -49,6 +49,7 @@
struct mbuf * pktq_dequeue(pktqueue_t *);
void pktq_barrier(pktqueue_t *);
void pktq_flush(pktqueue_t *);
+int pktq_set_maxlen(pktqueue_t *, size_t);
uint32_t pktq_rps_hash(const struct mbuf *);
uint64_t pktq_get_count(pktqueue_t *, pktq_count_t);
Home |
Main Index |
Thread Index |
Old Index