this has the ifq count the statistics kept for output packets that
we currently count on an ifnet.

unlike the ifnet stats, these are all maintained by the ifq as a
matter of course except for the output errors counter. this means
drivers wont have to account for outgoing packets like they do now,
and they will be counted consistently with the number of bytes
transmitted.

errors can be updated by an interfaces start routine safely because
it is serialised by the ifq_serialiazer.

since most stats are protected by the mutex you can take the mutex
to read the stats consistently. unfortunately there's no mechanism
to serialise the read of the errors, but im not sure we care a lot.
we could just read it twice to see if it stays th same.

this only updates the stats at the moment. their values dont replace
or get rolled into the ifnet stats yet.

they are updated though. eg:

(gdb) print $1->arpcom.ac_if.if_snd
$2 = {ifq_if = 0x40011aae048, ifq_mtx = {mtx_owner = 0x0, mtx_wantipl = 12, 
    mtx_oldipl = 2}, ifq_ops = 0x1693920, ifq_q = 0x40011a93700, 
  ifq_len = 0, ifq_oactive = 0, ifq_packets = 0, ifq_bytes = 1908, 
  ifq_qdrops = 619139, ifq_errors = 0, ifq_mcasts = 0, ifq_task_mtx = {
    mtx_owner = 0x3, mtx_wantipl = 0, mtx_oldipl = 0}, ifq_task_list = {
    tqh_first = 0xc00000002, tqh_last = 0x0}, 
  ifq_serializer = 0x40011aae2d8, ifq_start = {t_entry = {tqe_next = 0x0, 
      tqe_prev = 0xffffffffffffffff}, t_func = 0xffffffffffffffff, 
    t_arg = 0x11fa4a0, t_flags = 1024}, ifq_restart = {t_entry = {
      tqe_next = 0x0, tqe_prev = 0x0}, t_func = 0, t_arg = 0x11fa500, 
    t_flags = 1024}, ifq_maxlen = 0}

i want to mvoe the stats here because ifnets will end up with
multiple send rings represented by ifq structures. rather than
serialise at the ifnet level for statistics, we can collect them
on the rings where we have to serialise anyway and aggregate them
for userland later. this in turn means we dont need to maintain
per-cpu stats for ifnets.

ok?

Index: ifq.c
===================================================================
RCS file: /cvs/src/sys/net/ifq.c,v
retrieving revision 1.4
diff -u -p -r1.4 ifq.c
--- ifq.c       29 Dec 2015 12:35:43 -0000      1.4
+++ ifq.c       20 Jan 2017 01:36:06 -0000
@@ -172,7 +172,7 @@ ifq_init(struct ifqueue *ifq, struct ifn
        ifq->ifq_if = ifp;
 
        mtx_init(&ifq->ifq_mtx, IPL_NET);
-       ifq->ifq_drops = 0;
+       ifq->ifq_qdrops = 0;
 
        /* default to priq */
        ifq->ifq_ops = &priq_ops;
@@ -214,7 +214,7 @@ ifq_attach(struct ifqueue *ifq, const st
 
        while ((m = ml_dequeue(&ml)) != NULL) {
                if (ifq->ifq_ops->ifqop_enq(ifq, m) != 0) {
-                       ifq->ifq_drops++;
+                       ifq->ifq_qdrops++;
                        ml_enqueue(&free_ml, m);
                } else
                        ifq->ifq_len++;
@@ -246,10 +246,15 @@ ifq_enqueue_try(struct ifqueue *ifq, str
 
        mtx_enter(&ifq->ifq_mtx);
        rv = ifq->ifq_ops->ifqop_enq(ifq, m);
-       if (rv == 0)
+       if (rv == 0) {
                ifq->ifq_len++;
-       else
-               ifq->ifq_drops++;
+
+               ifq->ifq_packets++;
+               ifq->ifq_bytes += m->m_pkthdr.len;
+               if (ISSET(m->m_flags, M_MCAST))
+                       ifq->ifq_mcasts++;
+       } else
+               ifq->ifq_qdrops++;
        mtx_leave(&ifq->ifq_mtx);
 
        return (rv);
@@ -330,7 +335,7 @@ ifq_purge(struct ifqueue *ifq)
        ifq->ifq_ops->ifqop_purge(ifq, &ml);
        rv = ifq->ifq_len;
        ifq->ifq_len = 0;
-       ifq->ifq_drops += rv;
+       ifq->ifq_qdrops += rv;
        mtx_leave(&ifq->ifq_mtx);
 
        KASSERT(rv == ml_len(&ml));
Index: ifq.h
===================================================================
RCS file: /cvs/src/sys/net/ifq.h,v
retrieving revision 1.5
diff -u -p -r1.5 ifq.h
--- ifq.h       20 Jan 2016 17:27:16 -0000      1.5
+++ ifq.h       20 Jan 2017 01:36:06 -0000
@@ -28,11 +28,17 @@ struct ifqueue {
 
        /* mbuf handling */
        struct mutex             ifq_mtx;
-       uint64_t                 ifq_drops;
        const struct ifq_ops    *ifq_ops;
        void                    *ifq_q;
        unsigned int             ifq_len;
        unsigned int             ifq_oactive;
+
+       /* statistics */
+       uint64_t                 ifq_packets;
+       uint64_t                 ifq_bytes;
+       uint64_t                 ifq_qdrops;
+       uint64_t                 ifq_errors;
+       uint64_t                 ifq_mcasts;
 
        /* work serialisation */
        struct mutex             ifq_task_mtx;

Reply via email to