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