Index: ifq.c =================================================================== RCS file: /cvs/src/sys/net/ifq.c,v retrieving revision 1.40 diff -u -p -r1.40 ifq.c --- ifq.c 17 Jun 2020 06:45:22 -0000 1.40 +++ ifq.c 23 Jun 2020 00:20:52 -0000 @@ -17,6 +17,7 @@ */ #include "bpfilter.h" +#include "kstat.h" #include #include @@ -32,6 +33,10 @@ #include #endif +#if NKSTAT > 0 +#include +#endif + /* * priq glue */ @@ -122,7 +127,11 @@ ifq_is_serialized(struct ifqueue *ifq) void ifq_start(struct ifqueue *ifq) { - if (ifq_len(ifq) >= min(ifq->ifq_if->if_txmit, ifq->ifq_maxlen)) { + struct ifnet *ifp = ifq->ifq_if; + + if (ISSET(ifp->if_xflags, IFXF_MPSAFE) && + ifq_len(ifq) >= min(ifp->if_txmit, ifq->ifq_maxlen)) { + atomic_inc_int(&ifq->ifq_dispatch); task_del(ifq->ifq_softnet, &ifq->ifq_bundle); ifq_run_start(ifq); } else @@ -157,6 +166,7 @@ ifq_bundle_task(void *p) { struct ifqueue *ifq = p; + atomic_inc_int(&ifq->ifq_defers); ifq_run_start(ifq); } @@ -188,11 +198,48 @@ ifq_barrier_task(void *p) * ifqueue mbuf queue API */ +#if NKSTAT > 0 +struct ifq_kstat_data { + struct kstat_kv kd_packets; + struct kstat_kv kd_bytes; + struct kstat_kv kd_qdrops; + struct kstat_kv kd_errors; + struct kstat_kv kd_qlen; + struct kstat_kv kd_maxqlen; + struct kstat_kv kd_oactive; + + struct kstat_kv kd_dispatch; + struct kstat_kv kd_defers; +}; + +static const struct ifq_kstat_data ifq_kstat_tpl = { + KSTAT_KV_UNIT_INITIALIZER("packets", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("bytes", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("qdrops", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("errors", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("qlen", + KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("maxqlen", + KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), + KSTAT_KV_INITIALIZER("oactive", KSTAT_KV_T_BOOL), + + KSTAT_KV_INITIALIZER("dispatch", KSTAT_KV_T_COUNTER32), + KSTAT_KV_INITIALIZER("defers", KSTAT_KV_T_COUNTER32), +}; + +static int ifq_kstat_copy(struct kstat *, void *); +#endif + void ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx) { ifq->ifq_if = ifp; - ifq->ifq_softnet = net_tq(ifp->if_index); /* + idx */ + ifq->ifq_softnet = ISSET(ifp->if_xflags, IFXF_MPSAFE) ? + net_tq(ifp->if_index /* + idx */) : systq; ifq->ifq_softc = NULL; mtx_init(&ifq->ifq_mtx, IPL_NET); @@ -222,6 +269,18 @@ ifq_init(struct ifqueue *ifq, struct ifn ifq_set_maxlen(ifq, IFQ_MAXLEN); ifq->ifq_idx = idx; + +#if NKSTAT > 0 + /* XXX xname vs driver name and unit */ + ifq->ifq_kstat = kstat_create(ifp->if_xname, 0, + "txq", ifq->ifq_idx, KSTAT_T_KV, 0); + KASSERT(ifq->ifq_kstat != NULL); + kstat_set_mutex(ifq->ifq_kstat, &ifq->ifq_mtx); + ifq->ifq_kstat->ks_softc = ifq; + ifq->ifq_kstat->ks_datalen = sizeof(ifq_kstat_tpl); + ifq->ifq_kstat->ks_copy = ifq_kstat_copy; + kstat_install(ifq->ifq_kstat); +#endif } void @@ -265,6 +324,10 @@ ifq_destroy(struct ifqueue *ifq) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); +#if NKSTAT > 0 + kstat_destroy(ifq->ifq_kstat); +#endif + NET_ASSERT_UNLOCKED(); if (!task_del(ifq->ifq_softnet, &ifq->ifq_bundle)) taskq_barrier(ifq->ifq_softnet); @@ -289,6 +352,29 @@ ifq_add_data(struct ifqueue *ifq, struct mtx_leave(&ifq->ifq_mtx); } +#if NKSTAT > 0 +static int +ifq_kstat_copy(struct kstat *ks, void *dst) +{ + struct ifqueue *ifq = ks->ks_softc; + struct ifq_kstat_data *kd = dst; + + *kd = ifq_kstat_tpl; + kd->kd_packets.kv_v.v_u64 = ifq->ifq_packets; + kd->kd_bytes.kv_v.v_u64 = ifq->ifq_bytes; + kd->kd_qdrops.kv_v.v_u64 = ifq->ifq_qdrops; + kd->kd_errors.kv_v.v_u64 = ifq->ifq_errors; + kd->kd_qlen.kv_v.v_u32 = ifq->ifq_len; + kd->kd_maxqlen.kv_v.v_u32 = ifq->ifq_maxlen; + kd->kd_oactive.kv_v.v_bool = ifq->ifq_oactive; + + kd->kd_dispatch.kv_v.v_u32 = ifq->ifq_dispatch; + kd->kd_defers.kv_v.v_u32 = ifq->ifq_defers; + + return (0); +} +#endif + int ifq_enqueue(struct ifqueue *ifq, struct mbuf *m) { @@ -505,6 +591,31 @@ ifq_mfreeml(struct ifqueue *ifq, struct * ifiq */ +#if NKSTAT > 0 +struct ifiq_kstat_data { + struct kstat_kv kd_packets; + struct kstat_kv kd_bytes; + struct kstat_kv kd_qdrops; + struct kstat_kv kd_errors; + struct kstat_kv kd_qlen; +}; + +static const struct ifiq_kstat_data ifiq_kstat_tpl = { + KSTAT_KV_UNIT_INITIALIZER("packets", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("bytes", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("qdrops", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("errors", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("qlen", + KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), +}; + +static int ifiq_kstat_copy(struct kstat *, void *); +#endif + static void ifiq_process(void *); void @@ -525,11 +636,27 @@ ifiq_init(struct ifiqueue *ifiq, struct ifiq->ifiq_errors = 0; ifiq->ifiq_idx = idx; + +#if NKSTAT > 0 + /* XXX xname vs driver name and unit */ + ifiq->ifiq_kstat = kstat_create(ifp->if_xname, 0, + "rxq", ifiq->ifiq_idx, KSTAT_T_KV, 0); + KASSERT(ifiq->ifiq_kstat != NULL); + kstat_set_mutex(ifiq->ifiq_kstat, &ifiq->ifiq_mtx); + ifiq->ifiq_kstat->ks_softc = ifiq; + ifiq->ifiq_kstat->ks_datalen = sizeof(ifiq_kstat_tpl); + ifiq->ifiq_kstat->ks_copy = ifiq_kstat_copy; + kstat_install(ifiq->ifiq_kstat); +#endif } void ifiq_destroy(struct ifiqueue *ifiq) { +#if NKSTAT > 0 + kstat_destroy(ifiq->ifiq_kstat); +#endif + NET_ASSERT_UNLOCKED(); if (!task_del(ifiq->ifiq_softnet, &ifiq->ifiq_task)) taskq_barrier(ifiq->ifiq_softnet); @@ -616,6 +743,24 @@ ifiq_add_data(struct ifiqueue *ifiq, str data->ifi_iqdrops += ifiq->ifiq_qdrops; mtx_leave(&ifiq->ifiq_mtx); } + +#if NKSTAT > 0 +static int +ifiq_kstat_copy(struct kstat *ks, void *dst) +{ + struct ifiqueue *ifiq = ks->ks_softc; + struct ifiq_kstat_data *kd = dst; + + *kd = ifiq_kstat_tpl; + kd->kd_packets.kv_v.v_u64 = ifiq->ifiq_packets; + kd->kd_bytes.kv_v.v_u64 = ifiq->ifiq_bytes; + kd->kd_qdrops.kv_v.v_u64 = ifiq->ifiq_qdrops; + kd->kd_errors.kv_v.v_u64 = ifiq->ifiq_errors; + kd->kd_qlen.kv_v.v_u32 = ml_len(&ifiq->ifiq_ml); + + return (0); +} +#endif int ifiq_enqueue(struct ifiqueue *ifiq, struct mbuf *m) Index: ifq.h =================================================================== RCS file: /cvs/src/sys/net/ifq.h,v retrieving revision 1.31 diff -u -p -r1.31 ifq.h --- ifq.h 22 May 2020 07:02:24 -0000 1.31 +++ ifq.h 23 Jun 2020 00:20:52 -0000 @@ -20,6 +20,7 @@ #define _NET_IFQ_H_ struct ifnet; +struct kstat; struct ifq_ops; @@ -54,6 +55,11 @@ struct ifqueue { uint64_t ifq_errors; uint64_t ifq_mcasts; + unsigned int ifq_dispatch; + unsigned int ifq_defers; + + struct kstat *ifq_kstat; + /* work serialisation */ struct mutex ifq_task_mtx; struct task_list ifq_task_list; @@ -91,6 +97,8 @@ struct ifiqueue { uint64_t ifiq_errors; uint64_t ifiq_mcasts; uint64_t ifiq_noproto; + + struct kstat *ifiq_kstat; /* properties */ unsigned int ifiq_idx;