On 09/11/16(Wed) 14:55, David Gwynne wrote:
> since counters are an array of uint64_t values, this uses an enum
> to list the indexes into such an array.
> 
> we still export an ipstat struct to userland (which you can see
> with netstat -sp ip). the export cheats a bit because we know that
> the struct is a collection of u_longs, so we just iterate over the
> coutners and the struct as an array and assign values.

What about introducing a new type for counters instead of using M_PCB?

This way we can easily track how much memory we use for per-CPU
counters.

> ok?

ok mpi@

> 
> Index: net/if_bridge.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_bridge.c,v
> retrieving revision 1.287
> diff -u -p -r1.287 if_bridge.c
> --- net/if_bridge.c   3 Oct 2016 15:53:09 -0000       1.287
> +++ net/if_bridge.c   9 Nov 2016 04:45:23 -0000
> @@ -1603,25 +1603,25 @@ bridge_ip(struct bridge_softc *sc, int d
>               /* Copy minimal header, and drop invalids */
>               if (m->m_len < sizeof(struct ip) &&
>                   (m = m_pullup(m, sizeof(struct ip))) == NULL) {
> -                     ipstat.ips_toosmall++;
> +                     ipstat_inc(ips_toosmall);
>                       return (NULL);
>               }
>               ip = mtod(m, struct ip *);
>  
>               if (ip->ip_v != IPVERSION) {
> -                     ipstat.ips_badvers++;
> +                     ipstat_inc(ips_badvers);
>                       goto dropit;
>               }
>  
>               hlen = ip->ip_hl << 2;  /* get whole header length */
>               if (hlen < sizeof(struct ip)) {
> -                     ipstat.ips_badhlen++;
> +                     ipstat_inc(ips_badhlen);
>                       goto dropit;
>               }
>  
>               if (hlen > m->m_len) {
>                       if ((m = m_pullup(m, hlen)) == NULL) {
> -                             ipstat.ips_badhlen++;
> +                             ipstat_inc(ips_badhlen);
>                               return (NULL);
>                       }
>                       ip = mtod(m, struct ip *);
> @@ -1629,13 +1629,13 @@ bridge_ip(struct bridge_softc *sc, int d
>  
>               if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
>                       if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
> -                             ipstat.ips_badsum++;
> +                             ipstat_inc(ips_badsum);
>                               goto dropit;
>                       }
>  
> -                     ipstat.ips_inswcsum++;
> +                     ipstat_inc(ips_inswcsum);
>                       if (in_cksum(m, hlen) != 0) {
> -                             ipstat.ips_badsum++;
> +                             ipstat_inc(ips_badsum);
>                               goto dropit;
>                       }
>               }
> @@ -1678,7 +1678,7 @@ bridge_ip(struct bridge_softc *sc, int d
>               if (0 && (ifp->if_capabilities & IFCAP_CSUM_IPv4))
>                       m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
>               else {
> -                     ipstat.ips_outswcsum++;
> +                     ipstat_inc(ips_outswcsum);
>                       ip->ip_sum = in_cksum(m, hlen);
>               }
>  
> @@ -1848,7 +1848,7 @@ bridge_fragment(struct bridge_softc *sc,
>       }
>  
>       if (error == 0)
> -             ipstat.ips_fragmented++;
> +             ipstat_inc(ips_fragmented);
>  
>       return;
>   dropit:
> Index: net/if_etherip.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_etherip.c,v
> retrieving revision 1.7
> diff -u -p -r1.7 if_etherip.c
> --- net/if_etherip.c  13 Apr 2016 11:41:15 -0000      1.7
> +++ net/if_etherip.c  9 Nov 2016 04:45:23 -0000
> @@ -430,7 +430,7 @@ ip_etherip_input(struct mbuf *m, ...)
>  
>       if (ip->ip_p != IPPROTO_ETHERIP) {
>               m_freem(m);
> -             ipstat.ips_noproto++;
> +             ipstat_inc(ips_noproto);
>               return;
>       }
>  
> Index: net/pf.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf.c,v
> retrieving revision 1.996
> diff -u -p -r1.996 pf.c
> --- net/pf.c  28 Oct 2016 07:54:19 -0000      1.996
> +++ net/pf.c  9 Nov 2016 04:45:23 -0000
> @@ -5825,7 +5825,7 @@ pf_route(struct mbuf **m, struct pf_pdes
>       if (!r->rt) {
>               rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
>               if (rt == NULL) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       goto bad;
>               }
>  
> @@ -5859,7 +5859,7 @@ pf_route(struct mbuf **m, struct pf_pdes
>  
>               rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
>               if (rt == NULL) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       goto bad;
>               }
>       }
> @@ -5887,7 +5887,7 @@ pf_route(struct mbuf **m, struct pf_pdes
>               if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
>                       m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
>               else {
> -                     ipstat.ips_outswcsum++;
> +                     ipstat_inc(ips_outswcsum);
>                       ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
>               }
>               error = ifp->if_output(ifp, m0, sintosa(dst), rt);
> @@ -5899,7 +5899,7 @@ pf_route(struct mbuf **m, struct pf_pdes
>        * Must be able to put at least 8 bytes per fragment.
>        */
>       if (ip->ip_off & htons(IP_DF)) {
> -             ipstat.ips_cantfrag++;
> +             ipstat_inc(ips_cantfrag);
>               if (r->rt != PF_DUPTO) {
>                       icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
>                           ifp->if_mtu);
> @@ -5925,7 +5925,7 @@ pf_route(struct mbuf **m, struct pf_pdes
>       }
>  
>       if (error == 0)
> -             ipstat.ips_fragmented++;
> +             ipstat_inc(ips_fragmented);
>  
>  done:
>       if (r->rt != PF_DUPTO)
> Index: netinet/ip_icmp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
> retrieving revision 1.152
> diff -u -p -r1.152 ip_icmp.c
> --- netinet/ip_icmp.c 22 Aug 2016 15:37:23 -0000      1.152
> +++ netinet/ip_icmp.c 9 Nov 2016 04:45:23 -0000
> @@ -751,7 +751,7 @@ icmp_reflect(struct mbuf *m, struct mbuf
>               /* keep packet in the original virtual instance */
>               rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid);
>               if (rt == NULL) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       m_freem(m);
>                       return (EHOSTUNREACH);
>               }
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.282
> diff -u -p -r1.282 ip_input.c
> --- netinet/ip_input.c        22 Sep 2016 10:12:25 -0000      1.282
> +++ netinet/ip_input.c        9 Nov 2016 04:45:23 -0000
> @@ -120,7 +120,9 @@ struct niqueue ipintrq = NIQUEUE_INITIAL
>  struct pool ipqent_pool;
>  struct pool ipq_pool;
>  
> -struct ipstat ipstat;
> +struct cpumem *ipcounters;
> +
> +int ip_sysctl_ipstat(void *, size_t *, void *);
>  
>  static struct mbuf_queue     ipsend_mq;
>  
> @@ -132,7 +134,7 @@ void      ip_forward(struct mbuf *, struct if
>  int  ip_input_ipsec_fwd_check(struct mbuf *, int);
>  int  ip_input_ipsec_ours_check(struct mbuf *, int);
>  #endif /* IPSEC */
> -
> +     
>  static void ip_send_dispatch(void *);
>  static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch, 
> &ipsend_mq);
>  /*
> @@ -166,6 +168,8 @@ ip_init(void)
>       const u_int16_t defrootonlyports_tcp[] = DEFROOTONLYPORTS_TCP;
>       const u_int16_t defrootonlyports_udp[] = DEFROOTONLYPORTS_UDP;
>  
> +     ipcounters = counters_alloc(ips_ncounters, M_PCB);
> +
>       pool_init(&ipqent_pool, sizeof(struct ipqent), 0,
>           IPL_SOFTNET, 0, "ipqe",  NULL);
>       pool_init(&ipq_pool, sizeof(struct ipq), 0,
> @@ -247,25 +251,25 @@ ipv4_input(struct mbuf *m)
>       if (ifp == NULL)
>               goto bad;
>  
> -     ipstat.ips_total++;
> +     ipstat_inc(ips_total);
>       if (m->m_len < sizeof (struct ip) &&
>           (m = m_pullup(m, sizeof (struct ip))) == NULL) {
> -             ipstat.ips_toosmall++;
> +             ipstat_inc(ips_toosmall);
>               goto out;
>       }
>       ip = mtod(m, struct ip *);
>       if (ip->ip_v != IPVERSION) {
> -             ipstat.ips_badvers++;
> +             ipstat_inc(ips_badvers);
>               goto bad;
>       }
>       hlen = ip->ip_hl << 2;
>       if (hlen < sizeof(struct ip)) { /* minimum header length */
> -             ipstat.ips_badhlen++;
> +             ipstat_inc(ips_badhlen);
>               goto bad;
>       }
>       if (hlen > m->m_len) {
>               if ((m = m_pullup(m, hlen)) == NULL) {
> -                     ipstat.ips_badhlen++;
> +                     ipstat_inc(ips_badhlen);
>                       goto out;
>               }
>               ip = mtod(m, struct ip *);
> @@ -275,20 +279,20 @@ ipv4_input(struct mbuf *m)
>       if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
>           (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
>               if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
> -                     ipstat.ips_badaddr++;
> +                     ipstat_inc(ips_badaddr);
>                       goto bad;
>               }
>       }
>  
>       if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
>               if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
> -                     ipstat.ips_badsum++;
> +                     ipstat_inc(ips_badsum);
>                       goto bad;
>               }
>  
> -             ipstat.ips_inswcsum++;
> +             ipstat_inc(ips_inswcsum);
>               if (in_cksum(m, hlen) != 0) {
> -                     ipstat.ips_badsum++;
> +                     ipstat_inc(ips_badsum);
>                       goto bad;
>               }
>       }
> @@ -300,7 +304,7 @@ ipv4_input(struct mbuf *m)
>        * Convert fields to host representation.
>        */
>       if (len < hlen) {
> -             ipstat.ips_badlen++;
> +             ipstat_inc(ips_badlen);
>               goto bad;
>       }
>  
> @@ -311,7 +315,7 @@ ipv4_input(struct mbuf *m)
>        * Drop packet if shorter than we expect.
>        */
>       if (m->m_pkthdr.len < len) {
> -             ipstat.ips_tooshort++;
> +             ipstat_inc(ips_tooshort);
>               goto bad;
>       }
>       if (m->m_pkthdr.len > len) {
> @@ -370,7 +374,7 @@ ipv4_input(struct mbuf *m)
>               if (ipmforwarding && ip_mrouter) {
>                       if (m->m_flags & M_EXT) {
>                               if ((m = m_pullup(m, hlen)) == NULL) {
> -                                     ipstat.ips_toosmall++;
> +                                     ipstat_inc(ips_toosmall);
>                                       goto out;
>                               }
>                               ip = mtod(m, struct ip *);
> @@ -391,7 +395,7 @@ ipv4_input(struct mbuf *m)
>                       rv = ip_mforward(m, ifp);
>                       KERNEL_UNLOCK();
>                       if (rv != 0) {
> -                             ipstat.ips_cantforward++;
> +                             ipstat_inc(ips_cantforward);
>                               goto bad;
>                       }
>  
> @@ -404,7 +408,7 @@ ipv4_input(struct mbuf *m)
>                               ip_ours(m);
>                               goto out;
>                       }
> -                     ipstat.ips_forward++;
> +                     ipstat_inc(ips_forward);
>               }
>  #endif
>               /*
> @@ -412,9 +416,9 @@ ipv4_input(struct mbuf *m)
>                * arrival interface.
>                */
>               if (!in_hasmulti(&ip->ip_dst, ifp)) {
> -                     ipstat.ips_notmember++;
> +                     ipstat_inc(ips_notmember);
>                       if (!IN_LOCAL_GROUP(ip->ip_dst.s_addr))
> -                             ipstat.ips_cantforward++;
> +                             ipstat_inc(ips_cantforward);
>                       goto bad;
>               }
>               ip_ours(m);
> @@ -436,7 +440,7 @@ ipv4_input(struct mbuf *m)
>        * Not for us; forward if possible and desirable.
>        */
>       if (ipforwarding == 0) {
> -             ipstat.ips_cantforward++;
> +             ipstat_inc(ips_cantforward);
>               goto bad;
>       }
>  #ifdef IPSEC
> @@ -445,7 +449,7 @@ ipv4_input(struct mbuf *m)
>               rv = ip_input_ipsec_fwd_check(m, hlen);
>               KERNEL_UNLOCK();
>               if (rv != 0) {
> -                     ipstat.ips_cantforward++;
> +                     ipstat_inc(ips_cantforward);
>                       goto bad;
>               }
>               /*
> @@ -493,7 +497,7 @@ ip_ours(struct mbuf *m)
>       if (ip->ip_off &~ htons(IP_DF | IP_RF)) {
>               if (m->m_flags & M_EXT) {               /* XXX */
>                       if ((m = m_pullup(m, hlen)) == NULL) {
> -                             ipstat.ips_toosmall++;
> +                             ipstat_inc(ips_toosmall);
>                               return;
>                       }
>                       ip = mtod(m, struct ip *);
> @@ -526,7 +530,7 @@ found:
>                        */
>                       if (ntohs(ip->ip_len) == 0 ||
>                           (ntohs(ip->ip_len) & 0x7) != 0) {
> -                             ipstat.ips_badfrags++;
> +                             ipstat_inc(ips_badfrags);
>                               goto bad;
>                       }
>               }
> @@ -538,16 +542,16 @@ found:
>                * attempt reassembly; if it succeeds, proceed.
>                */
>               if (mff || ip->ip_off) {
> -                     ipstat.ips_fragments++;
> +                     ipstat_inc(ips_fragments);
>                       if (ip_frags + 1 > ip_maxqueue) {
>                               ip_flush();
> -                             ipstat.ips_rcvmemdrop++;
> +                             ipstat_inc(ips_rcvmemdrop);
>                               goto bad;
>                       }
>  
>                       ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
>                       if (ipqe == NULL) {
> -                             ipstat.ips_rcvmemdrop++;
> +                             ipstat_inc(ips_rcvmemdrop);
>                               goto bad;
>                       }
>                       ip_frags++;
> @@ -558,7 +562,7 @@ found:
>                       if (m == NULL) {
>                               return;
>                       }
> -                     ipstat.ips_reassembled++;
> +                     ipstat_inc(ips_reassembled);
>                       ip = mtod(m, struct ip *);
>                       hlen = ip->ip_hl << 2;
>                       ip->ip_len = htons(ntohs(ip->ip_len) + hlen);
> @@ -570,7 +574,7 @@ found:
>  #ifdef IPSEC
>       if (ipsec_in_use) {
>               if (ip_input_ipsec_ours_check(m, hlen) != 0) {
> -                     ipstat.ips_cantforward++;
> +                     ipstat_inc(ips_cantforward);
>                       goto bad;
>               }
>       }
> @@ -580,7 +584,7 @@ found:
>       /*
>        * Switch out to protocol's input routine.
>        */
> -     ipstat.ips_delivered++;
> +     ipstat_inc(ips_delivered);
>       (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen, NULL, 0);
>       return;
>  bad:
> @@ -896,7 +900,7 @@ insert:
>       q = LIST_FIRST(&fp->ipq_fragq);
>       ip = q->ipqe_ip;
>       if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
> -             ipstat.ips_toolong++;
> +             ipstat_inc(ips_toolong);
>               ip_freef(fp);
>               return (0);
>       }
> @@ -938,7 +942,7 @@ insert:
>       return (m);
>  
>  dropfrag:
> -     ipstat.ips_fragdropped++;
> +     ipstat_inc(ips_fragdropped);
>       m_freem(m);
>       pool_put(&ipqent_pool, ipqe);
>       ip_frags--;
> @@ -979,7 +983,7 @@ ip_slowtimo(void)
>       for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) {
>               nfp = LIST_NEXT(fp, ipq_q);
>               if (--fp->ipq_ttl == 0) {
> -                     ipstat.ips_fragtimeout++;
> +                     ipstat_inc(ips_fragtimeout);
>                       ip_freef(fp);
>               }
>       }
> @@ -993,7 +997,7 @@ void
>  ip_drain(void)
>  {
>       while (!LIST_EMPTY(&ipq)) {
> -             ipstat.ips_fragdropped++;
> +             ipstat_inc(ips_fragdropped);
>               ip_freef(LIST_FIRST(&ipq));
>       }
>  }
> @@ -1008,7 +1012,7 @@ ip_flush(void)
>  
>       /* ipq already locked */
>       while (!LIST_EMPTY(&ipq) && ip_frags > ip_maxqueue * 3 / 4 && --max) {
> -             ipstat.ips_fragdropped++;
> +             ipstat_inc(ips_fragdropped);
>               ip_freef(LIST_FIRST(&ipq));
>       }
>  }
> @@ -1263,7 +1267,7 @@ ip_dooptions(struct mbuf *m, struct ifne
>  bad:
>       KERNEL_UNLOCK();
>       icmp_error(m, type, code, 0, 0);
> -     ipstat.ips_badoptions++;
> +     ipstat_inc(ips_badoptions);
>       return (1);
>  }
>  
> @@ -1413,7 +1417,7 @@ ip_forward(struct mbuf *m, struct ifnet 
>  
>       dest = 0;
>       if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
> -             ipstat.ips_cantforward++;
> +             ipstat_inc(ips_cantforward);
>               m_freem(m);
>               goto freecopy;
>       }
> @@ -1494,11 +1498,11 @@ ip_forward(struct mbuf *m, struct ifnet 
>           NULL, NULL, 0);
>       rt = ro.ro_rt;
>       if (error)
> -             ipstat.ips_cantforward++;
> +             ipstat_inc(ips_cantforward);
>       else {
> -             ipstat.ips_forward++;
> +             ipstat_inc(ips_forward);
>               if (type)
> -                     ipstat.ips_redirectsent++;
> +                     ipstat_inc(ips_redirectsent);
>               else
>                       goto freecopy;
>       }
> @@ -1538,7 +1542,7 @@ ip_forward(struct mbuf *m, struct ifnet 
>                       }
>               }
>  #endif /*IPSEC*/
> -             ipstat.ips_cantfrag++;
> +             ipstat_inc(ips_cantfrag);
>               break;
>  
>       case EACCES:
> @@ -1632,8 +1636,7 @@ ip_sysctl(int *name, u_int namelen, void
>               return (sysctl_niq(name + 1, namelen - 1,
>                   oldp, oldlenp, newp, newlen, &ipintrq));
>       case IPCTL_STATS:
> -             return (sysctl_rdstruct(oldp, oldlenp, newp,
> -                 &ipstat, sizeof(ipstat)));
> +             return (ip_sysctl_ipstat(oldp, oldlenp, newp));
>  #ifdef MROUTING
>       case IPCTL_MRTSTATS:
>               return (sysctl_rdstruct(oldp, oldlenp, newp,
> @@ -1662,6 +1665,24 @@ ip_sysctl(int *name, u_int namelen, void
>               return (EOPNOTSUPP);
>       }
>       /* NOTREACHED */
> +}
> +
> +int
> +ip_sysctl_ipstat(void *oldp, size_t *oldlenp, void *newp)
> +{
> +     uint64_t counters[ips_ncounters];
> +     struct ipstat ipstat;
> +     u_long *words = (u_long *)&ipstat;
> +     int i;
> +
> +     KASSERT(sizeof(ipstat) == (nitems(counters) * sizeof(u_long)));
> +
> +     counters_read(ipcounters, counters, nitems(counters));
> +
> +     for (i = 0; i < nitems(counters); i++)
> +             words[i] = (u_long)counters[i];
> +
> +     return (sysctl_rdstruct(oldp, oldlenp, newp, &ipstat, sizeof(ipstat)));
>  }
>  
>  void
> Index: netinet/ip_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.327
> diff -u -p -r1.327 ip_output.c
> --- netinet/ip_output.c       4 Sep 2016 17:18:56 -0000       1.327
> +++ netinet/ip_output.c       9 Nov 2016 04:45:23 -0000
> @@ -133,7 +133,7 @@ ip_output(struct mbuf *m0, struct mbuf *
>               ip->ip_off &= htons(IP_DF);
>               ip->ip_id = htons(ip_randomid());
>               ip->ip_hl = hlen >> 2;
> -             ipstat.ips_localout++;
> +             ipstat_inc(ips_localout);
>       } else {
>               hlen = ip->ip_hl << 2;
>       }
> @@ -204,7 +204,7 @@ reroute:
>                           &ip->ip_src.s_addr, ro->ro_tableid);
>  
>               if (ro->ro_rt == NULL) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       error = EHOSTUNREACH;
>                       goto bad;
>               }
> @@ -284,7 +284,7 @@ reroute:
>                * output
>                */
>               if (!ifp) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       error = EHOSTUNREACH;
>                       goto bad;
>               }
> @@ -298,7 +298,7 @@ reroute:
>                     (ifp->if_flags & IFF_MULTICAST) == 0) ||
>                    ((m->m_flags & M_BCAST) &&
>                     (ifp->if_flags & IFF_BROADCAST) == 0)) && (tdb == NULL)) {
> -                     ipstat.ips_noroute++;
> +                     ipstat_inc(ips_noroute);
>                       error = ENETUNREACH;
>                       goto bad;
>               }
> @@ -464,7 +464,7 @@ sendit:
>                   (ifp->if_bridgeport == NULL))
>                       m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
>               else {
> -                     ipstat.ips_outswcsum++;
> +                     ipstat_inc(ips_outswcsum);
>                       ip->ip_sum = in_cksum(m, hlen);
>               }
>  
> @@ -495,7 +495,7 @@ sendit:
>                   (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
>                       ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
>               }
> -             ipstat.ips_cantfrag++;
> +             ipstat_inc(ips_cantfrag);
>               goto bad;
>       }
>  
> @@ -515,7 +515,7 @@ sendit:
>       }
>  
>       if (error == 0)
> -             ipstat.ips_fragmented++;
> +             ipstat_inc(ips_fragmented);
>  
>  done:
>       if (ro == &iproute && ro->ro_rt)
> @@ -676,7 +676,7 @@ ip_fragment(struct mbuf *m, struct ifnet
>       for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
>               MGETHDR(m, M_DONTWAIT, MT_HEADER);
>               if (m == NULL) {
> -                     ipstat.ips_odropped++;
> +                     ipstat_inc(ips_odropped);
>                       error = ENOBUFS;
>                       goto sendorfree;
>               }
> @@ -705,7 +705,7 @@ ip_fragment(struct mbuf *m, struct ifnet
>               mhip->ip_len = htons((u_int16_t)(len + mhlen));
>               m->m_next = m_copym(m0, off, len, M_NOWAIT);
>               if (m->m_next == 0) {
> -                     ipstat.ips_odropped++;
> +                     ipstat_inc(ips_odropped);
>                       error = ENOBUFS;
>                       goto sendorfree;
>               }
> @@ -718,10 +718,10 @@ ip_fragment(struct mbuf *m, struct ifnet
>                   (ifp->if_bridgeport == NULL))
>                       m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
>               else {
> -                     ipstat.ips_outswcsum++;
> +                     ipstat_inc(ips_outswcsum);
>                       mhip->ip_sum = in_cksum(m, mhlen);
>               }
> -             ipstat.ips_ofragments++;
> +             ipstat_inc(ips_ofragments);
>               fragments++;
>       }
>       /*
> @@ -739,7 +739,7 @@ ip_fragment(struct mbuf *m, struct ifnet
>           (ifp->if_bridgeport == NULL))
>               m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
>       else {
> -             ipstat.ips_outswcsum++;
> +             ipstat_inc(ips_outswcsum);
>               ip->ip_sum = in_cksum(m, hlen);
>       }
>  sendorfree:
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.62
> diff -u -p -r1.62 ip_var.h
> --- netinet/ip_var.h  15 Apr 2016 11:18:40 -0000      1.62
> +++ netinet/ip_var.h  9 Nov 2016 04:45:23 -0000
> @@ -96,6 +96,53 @@ struct ipoption {
>  
>  #ifdef _KERNEL
>  
> +#include <sys/percpu.h>
> +
> +enum ipstat_counters {
> +     ips_total,              /* total packets received */
> +     ips_badsum,             /* checksum bad */
> +     ips_tooshort,           /* packet too short */
> +     ips_toosmall,           /* not enough data */
> +     ips_badhlen,            /* ip header length < data size */
> +     ips_badlen,             /* ip length < ip header length */
> +     ips_fragments,          /* fragments received */
> +     ips_fragdropped,        /* frags dropped (dups, out of space) */
> +     ips_fragtimeout,        /* fragments timed out */
> +     ips_forward,            /* packets forwarded */
> +     ips_cantforward,        /* packets rcvd for unreachable dest */
> +     ips_redirectsent,       /* packets forwarded on same net */
> +     ips_noproto,            /* unknown or unsupported protocol */
> +     ips_delivered,          /* datagrams delivered to upper level*/
> +     ips_localout,           /* total ip packets generated here */
> +     ips_odropped,           /* lost packets due to nobufs, etc. */
> +     ips_reassembled,        /* total packets reassembled ok */
> +     ips_fragmented,         /* datagrams successfully fragmented */
> +     ips_ofragments,         /* output fragments created */
> +     ips_cantfrag,           /* don't fragment flag was set, etc. */
> +     ips_badoptions,         /* error in option processing */
> +     ips_noroute,            /* packets discarded due to no route */
> +     ips_badvers,            /* ip version != 4 */
> +     ips_rawout,             /* total raw ip packets generated */
> +     ips_badfrags,           /* malformed fragments (bad length) */
> +     ips_rcvmemdrop,         /* frags dropped for lack of memory */
> +     ips_toolong,            /* ip length > max ip packet size */
> +     ips_nogif,              /* no match gif found */
> +     ips_badaddr,            /* invalid address on header */
> +     ips_inswcsum,           /* software checksummed on input */
> +     ips_outswcsum,          /* software checksummed on output */
> +     ips_notmember,          /* multicasts for unregistered groups */
> +
> +     ips_ncounters
> +};
> +
> +extern struct cpumem *ipcounters;
> +
> +static inline void
> +ipstat_inc(enum ipstat_counters c)
> +{
> +     counters_inc(ipcounters, c);
> +}
> +
>  /*
>   * Structure attached to inpcb.ip_moptions and
>   * passed to ip_output when IP multicast options are in use.
> Index: netinet/raw_ip.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/raw_ip.c,v
> retrieving revision 1.86
> diff -u -p -r1.86 raw_ip.c
> --- netinet/raw_ip.c  7 Mar 2016 18:44:00 -0000       1.86
> +++ netinet/raw_ip.c  9 Nov 2016 04:45:23 -0000
> @@ -126,6 +126,8 @@ rip_input(struct mbuf *m, ...)
>       struct ip *ip = mtod(m, struct ip *);
>       struct inpcb *inp, *last = NULL;
>       struct mbuf *opts = NULL;
> +     struct counters_ref ref;
> +     uint64_t *counters;
>  
>       ripsrc.sin_addr = ip->ip_src;
>       TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
> @@ -195,8 +197,11 @@ rip_input(struct mbuf *m, ...)
>                       icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 
> 0);
>               else
>                       m_freem(m);
> -             ipstat.ips_noproto++;
> -             ipstat.ips_delivered--;
> +
> +             counters = counters_enter(&ref, ipcounters);
> +             counters[ips_noproto]++;
> +             counters[ips_delivered]--;
> +             counters_leave(&ref, ipcounters);
>       }
>  }
>  
> @@ -267,7 +272,7 @@ rip_output(struct mbuf *m, ...)
>               }
>               /* XXX prevent ip_output from overwriting header fields */
>               flags |= IP_RAWOUTPUT;
> -             ipstat.ips_rawout++;
> +             ipstat_inc(ips_rawout);
>       }
>  #ifdef INET6
>       /*
> Index: sys/percpu.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/percpu.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 percpu.h
> --- sys/percpu.h      24 Oct 2016 23:58:33 -0000      1.3
> +++ sys/percpu.h      9 Nov 2016 04:45:23 -0000
> @@ -138,6 +138,40 @@ counters_leave(struct counters_ref *ref,
>       cpumem_leave(cm, ref->c);
>  }
>  
> +static inline void
> +counters_inc(struct cpumem *cm, unsigned int c)
> +{
> +     struct counters_ref ref;
> +     uint64_t *counters;
> +
> +     counters = counters_enter(&ref, cm);
> +     counters[c]++;
> +     counters_leave(&ref, cm);
> +}
> +
> +static inline void
> +counters_add(struct cpumem *cm, unsigned int c, uint64_t v)
> +{
> +     struct counters_ref ref;
> +     uint64_t *counters;
> +
> +     counters = counters_enter(&ref, cm);
> +     counters[c] += v;
> +     counters_leave(&ref, cm);
> +}
> +
> +static inline void
> +counters_pkt(struct cpumem *cm, unsigned int c, unsigned int b, uint64_t v)
> +{
> +     struct counters_ref ref;
> +     uint64_t *counters;
> +
> +     counters = counters_enter(&ref, cm);
> +     counters[c]++;
> +     counters[b] += v;
> +     counters_leave(&ref, cm);
> +}
> +
>  #ifdef MULTIPROCESSOR
>  #define COUNTERS_BOOT_MEMORY(_name, _n)                                      
> \
>       CPUMEM_BOOT_MEMORY(_name, ((_n) + 1) * sizeof(uint64_t))
> 

Reply via email to