Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net/lagg handle LACPDU and MarkerDU in thread context



details:   https://anonhg.NetBSD.org/src/rev/9a9a60e3d027
branches:  trunk
changeset: 364598:9a9a60e3d027
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Thu Mar 31 02:04:50 2022 +0000

description:
handle LACPDU and MarkerDU in thread context

Those handler move from softint to thread context to
improve throughput in high load, because they hold LACP_LOCK.

pointed out by k-goda@IIJ

diffstat:

 sys/net/lagg/if_lagg_lacp.c |  99 +++++++++++++++++++++++++++++++++++++++++---
 sys/net/lagg/if_lagg_lacp.h |   4 +-
 2 files changed, 95 insertions(+), 8 deletions(-)

diffs (225 lines):

diff -r 4b81ff8cb291 -r 9a9a60e3d027 sys/net/lagg/if_lagg_lacp.c
--- a/sys/net/lagg/if_lagg_lacp.c       Thu Mar 31 02:00:27 2022 +0000
+++ b/sys/net/lagg/if_lagg_lacp.c       Thu Mar 31 02:04:50 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_lagg_lacp.c,v 1.17 2022/03/31 02:00:27 yamaguchi Exp $      */
+/*     $NetBSD: if_lagg_lacp.c,v 1.18 2022/03/31 02:04:50 yamaguchi Exp $      */
 
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.17 2022/03/31 02:00:27 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.18 2022/03/31 02:04:50 yamaguchi Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_lagg.h"
@@ -42,6 +42,7 @@
 
 #include <sys/evcnt.h>
 #include <sys/kmem.h>
+#include <sys/pcq.h>
 #include <sys/pslist.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
@@ -163,13 +164,18 @@
                                 lsc_aggregators;
        struct workqueue        *lsc_workq;
        struct lagg_work         lsc_work_tick;
+       struct lagg_work         lsc_work_rcvdu;
        callout_t                lsc_tick;
+       pcq_t                   *lsc_du_q;
 
        char                     lsc_evgroup[32];
        struct evcnt             lsc_mgethdr_failed;
        struct evcnt             lsc_mpullup_failed;
        struct evcnt             lsc_badlacpdu;
        struct evcnt             lsc_badmarkerdu;
+       struct evcnt             lsc_norcvif;
+       struct evcnt             lsc_nolaggport;
+       struct evcnt             lsc_duq_nospc;
 
        bool                     lsc_optimistic;
        bool                     lsc_stop_lacpdu;
@@ -277,6 +283,7 @@
 static void    lacp_sm_ptx_schedule(struct lacp_port *);
 static void    lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t);
 
+static void    lacp_rcvdu_work(struct lagg_work *, void *);
 static void    lacp_marker_work(struct lagg_work *, void *);
 static void    lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *,
                    const struct lacpdu_peerinfo *,
@@ -463,6 +470,12 @@
        if (lsc == NULL)
                return ENOMEM;
 
+       lsc->lsc_du_q = pcq_create(LACP_RCVDU_LIMIT, KM_NOSLEEP);
+       if (lsc->lsc_du_q == NULL) {
+               error = ENOMEM;
+               goto free_lsc;
+       }
+
        mutex_init(&lsc->lsc_lock, MUTEX_DEFAULT, IPL_SOFTNET);
        lsc->lsc_softc = sc;
        lsc->lsc_key = htons(if_get_index(&sc->sc_if));
@@ -473,6 +486,8 @@
        TAILQ_INIT(&lsc->lsc_aggregators);
 
        lagg_work_set(&lsc->lsc_work_tick, lacp_tick_work, lsc);
+       lagg_work_set(&lsc->lsc_work_rcvdu, lacp_rcvdu_work, lsc);
+
        snprintf(xnamebuf, sizeof(xnamebuf), "%s.lacp",
            sc->sc_if.if_xname);
        lsc->lsc_workq = lagg_workq_create(xnamebuf,
@@ -494,14 +509,18 @@
        lacp_evcnt_attach(lsc, &lsc->lsc_mpullup_failed, "m_pullup failed");
        lacp_evcnt_attach(lsc, &lsc->lsc_badlacpdu, "Bad LACPDU recieved");
        lacp_evcnt_attach(lsc, &lsc->lsc_badmarkerdu, "Bad MarkerDU recieved");
+       lacp_evcnt_attach(lsc, &lsc->lsc_norcvif, "No received interface");
+       lacp_evcnt_attach(lsc, &lsc->lsc_nolaggport, "No lagg context");
+       lacp_evcnt_attach(lsc, &lsc->lsc_duq_nospc, "No space left on queues");
 
        if_link_state_change(&sc->sc_if, LINK_STATE_DOWN);
 
        *lscp = (struct lagg_proto_softc *)lsc;
        return 0;
-
 destroy_lock:
        mutex_destroy(&lsc->lsc_lock);
+       pcq_destroy(lsc->lsc_du_q);
+free_lsc:
        kmem_free(lsc, sizeof(*lsc));
 
        return error;
@@ -519,13 +538,18 @@
 
        lacp_down(xlsc);
 
+       lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_rcvdu);
        evcnt_detach(&lsc->lsc_mgethdr_failed);
        evcnt_detach(&lsc->lsc_mpullup_failed);
        evcnt_detach(&lsc->lsc_badlacpdu);
        evcnt_detach(&lsc->lsc_badmarkerdu);
+       evcnt_detach(&lsc->lsc_norcvif);
+       evcnt_detach(&lsc->lsc_nolaggport);
+       evcnt_detach(&lsc->lsc_duq_nospc);
        lagg_workq_destroy(lsc->lsc_workq);
        pserialize_destroy(lsc->lsc_psz);
        mutex_destroy(&lsc->lsc_lock);
+       pcq_destroy(lsc->lsc_du_q);
        kmem_free(lsc, sizeof(*lsc));
 }
 
@@ -1223,12 +1247,17 @@
 
                m_copydata(m, sizeof(struct ether_header),
                    sizeof(subtype), &subtype);
+
                switch (subtype) {
                case SLOWPROTOCOLS_SUBTYPE_LACP:
-                       (void)lacp_pdu_input(lsc, lacpp, m);
-                       return NULL;
                case SLOWPROTOCOLS_SUBTYPE_MARKER:
-                       (void)lacp_marker_input(lsc, lacpp, m);
+                       if (pcq_put(lsc->lsc_du_q, (void *)m)) {
+                               lagg_workq_add(lsc->lsc_workq,
+                                   &lsc->lsc_work_rcvdu);
+                       } else {
+                               m_freem(m);
+                               lsc->lsc_duq_nospc.ev_count++;
+                       }
                        return NULL;
                }
        }
@@ -1242,6 +1271,62 @@
        return m;
 }
 
+static void
+lacp_rcvdu_work(struct lagg_work *lw __unused, void *xlsc)
+{
+       struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
+       struct ifnet *ifp;
+       struct psref psref_lp;
+       struct lagg_port *lp;
+       struct mbuf *m;
+       uint8_t subtype;
+       int bound, s;
+
+       bound = curlwp_bind();
+
+       for (;;) {
+               m = pcq_get(lsc->lsc_du_q);
+               if (m == NULL)
+                       break;
+
+               ifp = m_get_rcvif(m, &s);
+               if (ifp == NULL) {
+                       m_freem(m);
+                       lsc->lsc_norcvif.ev_count++;
+                       continue;
+               }
+
+               lp = atomic_load_consume(&ifp->if_lagg);
+               if (lp == NULL) {
+                       m_put_rcvif(ifp, &s);
+                       m_freem(m);
+                       lsc->lsc_norcvif.ev_count++;
+                       continue;
+               }
+
+               lagg_port_getref(lp, &psref_lp);
+               m_put_rcvif(ifp, &s);
+
+               m_copydata(m, sizeof(struct ether_header),
+                   sizeof(subtype), &subtype);
+
+               switch (subtype) {
+               case SLOWPROTOCOLS_SUBTYPE_LACP:
+                       (void)lacp_pdu_input(lsc,
+                           lp->lp_proto_ctx, m);
+                       break;
+               case SLOWPROTOCOLS_SUBTYPE_MARKER:
+                       (void)lacp_marker_input(lsc,
+                           lp->lp_proto_ctx, m);
+                       break;
+               }
+
+               lagg_port_putref(lp, &psref_lp);
+       }
+
+       curlwp_bindx(bound);
+}
+
 static bool
 lacp_port_need_to_tell(struct lacp_port *lacpp)
 {
@@ -1262,7 +1347,7 @@
                return false;
 
        if (ppsratecheck(&lacpp->lp_last_lacpdu, &lacpp->lp_lacpdu_sent,
-           (3 / LACP_FAST_PERIODIC_TIME)) == 0)
+           (LACP_SENDDU_PPS / LACP_FAST_PERIODIC_TIME)) == 0)
                return false;
 
        return true;
diff -r 4b81ff8cb291 -r 9a9a60e3d027 sys/net/lagg/if_lagg_lacp.h
--- a/sys/net/lagg/if_lagg_lacp.h       Thu Mar 31 02:00:27 2022 +0000
+++ b/sys/net/lagg/if_lagg_lacp.h       Thu Mar 31 02:04:50 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_lagg_lacp.h,v 1.3 2021/11/30 01:17:02 yamaguchi Exp $       */
+/*     $NetBSD: if_lagg_lacp.h,v 1.4 2022/03/31 02:04:50 yamaguchi Exp $       */
 
 /*
  * Copyright (c) 2021 Internet Initiative Japan Inc.
@@ -41,6 +41,8 @@
 #define LACP_MAX_PORTS         16
 #define LACP_SYSTEM_PRIO       0x8000U
 #define LACP_PORT_PRIO         LAGG_PORT_PRIO
+#define LACP_SENDDU_PPS                3
+#define LACP_RCVDU_LIMIT       (LACP_SENDDU_PPS * LACP_MAX_PORTS)
 
 #define LACP_PARTNER_ADMIN_OPTIMISTIC  (LACP_STATE_SYNC | \
                                        LACP_STATE_AGGREGATION | \



Home | Main Index | Thread Index | Old Index