On 11/12/16(Sun) 19:24, Dimitris Papastamos wrote:
> Hi,
> 
> I converted the igmp stats to use percpu counters.  This work is
> basically the same as what dlg@ did for other parts of the stack.
> I looked at the diff and adjusted it for igmp.

ok mpi@

> 
> diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
> index 11446ce4188..c2a0a4839b4 100644
> --- a/sys/netinet/igmp.c
> +++ b/sys/netinet/igmp.c
> @@ -101,13 +101,14 @@ int *igmpctl_vars[IGMPCTL_MAXID] = IGMPCTL_VARS;
>  int          igmp_timers_are_running;
>  static struct router_info *rti_head;
>  static struct mbuf *router_alert;
> -struct igmpstat igmpstat;
> +struct cpumem *igmpcounters;
>  
>  void igmp_checktimer(struct ifnet *);
>  void igmp_sendpkt(struct in_multi *, int, in_addr_t);
>  int rti_fill(struct in_multi *);
>  struct router_info * rti_find(struct ifnet *);
>  void igmp_input_if(struct ifnet *, struct mbuf *, int);
> +int igmp_sysctl_igmpstat(void *, size_t *, void *);
>  
>  void
>  igmp_init(void)
> @@ -117,6 +118,7 @@ igmp_init(void)
>       igmp_timers_are_running = 0;
>       rti_head = 0;
>  
> +     igmpcounters = counters_alloc(igps_ncounters, M_COUNTERS);
>       router_alert = m_get(M_DONTWAIT, MT_DATA);
>       if (router_alert == NULL) {
>               printf("%s: no mbuf\n", __func__);
> @@ -217,7 +219,7 @@ igmp_input(struct mbuf *m, ...)
>       iphlen = va_arg(ap, int);
>       va_end(ap);
>  
> -     ++igmpstat.igps_rcv_total;
> +     igmpstat_inc(igps_rcv_total);
>  
>       ifp = if_get(m->m_pkthdr.ph_ifidx);
>       if (ifp == NULL) {
> @@ -248,14 +250,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>        * Validate lengths
>        */
>       if (igmplen < IGMP_MINLEN) {
> -             ++igmpstat.igps_rcv_tooshort;
> +             igmpstat_inc(igps_rcv_tooshort);
>               m_freem(m);
>               return;
>       }
>       minlen = iphlen + IGMP_MINLEN;
>       if ((m->m_flags & M_EXT || m->m_len < minlen) &&
>           (m = m_pullup(m, minlen)) == NULL) {
> -             ++igmpstat.igps_rcv_tooshort;
> +             igmpstat_inc(igps_rcv_tooshort);
>               return;
>       }
>  
> @@ -266,7 +268,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>       m->m_len -= iphlen;
>       igmp = mtod(m, struct igmp *);
>       if (in_cksum(m, igmplen)) {
> -             ++igmpstat.igps_rcv_badsum;
> +             igmpstat_inc(igps_rcv_badsum);
>               m_freem(m);
>               return;
>       }
> @@ -277,7 +279,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>       switch (igmp->igmp_type) {
>  
>       case IGMP_HOST_MEMBERSHIP_QUERY:
> -             ++igmpstat.igps_rcv_queries;
> +             igmpstat_inc(igps_rcv_queries);
>  
>               if (ifp->if_flags & IFF_LOOPBACK)
>                       break;
> @@ -292,7 +294,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>                       rti->rti_age = 0;
>  
>                       if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) {
> -                             ++igmpstat.igps_rcv_badqueries;
> +                             igmpstat_inc(igps_rcv_badqueries);
>                               m_freem(m);
>                               return;
>                       }
> @@ -317,7 +319,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>                       }
>               } else {
>                       if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
> -                             ++igmpstat.igps_rcv_badqueries;
> +                             igmpstat_inc(igps_rcv_badqueries);
>                               m_freem(m);
>                               return;
>                       }
> @@ -367,14 +369,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>               break;
>  
>       case IGMP_v1_HOST_MEMBERSHIP_REPORT:
> -             ++igmpstat.igps_rcv_reports;
> +             igmpstat_inc(igps_rcv_reports);
>  
>               if (ifp->if_flags & IFF_LOOPBACK)
>                       break;
>  
>               if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
>                   igmp->igmp_group.s_addr != ip->ip_dst.s_addr) {
> -                     ++igmpstat.igps_rcv_badreports;
> +                     igmpstat_inc(igps_rcv_badreports);
>                       m_freem(m);
>                       return;
>               }
> @@ -401,7 +403,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>               IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
>               if (inm != NULL) {
>                       inm->inm_timer = 0;
> -                     ++igmpstat.igps_rcv_ourreports;
> +                     igmpstat_inc(igps_rcv_ourreports);
>  
>                       switch (inm->inm_state) {
>                       case IGMP_IDLE_MEMBER:
> @@ -433,14 +435,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>                       break;
>  #endif
>  
> -             ++igmpstat.igps_rcv_reports;
> +             igmpstat_inc(igps_rcv_reports);
>  
>               if (ifp->if_flags & IFF_LOOPBACK)
>                       break;
>  
>               if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
>                   igmp->igmp_group.s_addr != ip->ip_dst.s_addr) {
> -                     ++igmpstat.igps_rcv_badreports;
> +                     igmpstat_inc(igps_rcv_badreports);
>                       m_freem(m);
>                       return;
>               }
> @@ -469,7 +471,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int 
> iphlen)
>               IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
>               if (inm != NULL) {
>                       inm->inm_timer = 0;
> -                     ++igmpstat.igps_rcv_ourreports;
> +                     igmpstat_inc(igps_rcv_ourreports);
>  
>                       switch (inm->inm_state) {
>                       case IGMP_DELAYING_MEMBER:
> @@ -667,7 +669,7 @@ igmp_sendpkt(struct in_multi *inm, int type, in_addr_t 
> addr)
>  
>       ip_output(m, router_alert, NULL, IP_MULTICASTOPTS, &imo, NULL, 0);
>  
> -     ++igmpstat.igps_snd_reports;
> +     igmpstat_inc(igps_snd_reports);
>  }
>  
>  /*
> @@ -685,8 +687,7 @@ igmp_sysctl(int *name, u_int namelen, void *oldp, size_t 
> *oldlenp,
>       case IGMPCTL_STATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &igmpstat, sizeof(igmpstat)));
> +             return (igmp_sysctl_igmpstat(oldp, oldlenp, newp));
>       default:
>               if (name[0] < IGMPCTL_MAXID)
>                       return (sysctl_int_arr(igmpctl_vars, name, namelen,
> @@ -695,3 +696,22 @@ igmp_sysctl(int *name, u_int namelen, void *oldp, size_t 
> *oldlenp,
>       }
>       /* NOTREACHED */
>  }
> +
> +int
> +igmp_sysctl_igmpstat(void *oldp, size_t *oldlenp, void *newp)
> +{
> +     uint64_t counters[igps_ncounters];
> +     struct igmpstat igmpstat;
> +     u_long *words = (u_long *)&igmpstat;
> +     int i;
> +
> +     KASSERT(sizeof(igmpstat) == (nitems(counters) * sizeof(u_long)));
> +
> +     counters_read(igmpcounters, counters, nitems(counters));
> +
> +     for (i = 0; i < nitems(counters); i++)
> +             words[i] = (u_long)counters[i];
> +
> +     return (sysctl_rdstruct(oldp, oldlenp, newp,
> +         &igmpstat, sizeof(igmpstat)));
> +}
> diff --git a/sys/netinet/igmp_var.h b/sys/netinet/igmp_var.h
> index ea066093ec4..290b1bef7d6 100644
> --- a/sys/netinet/igmp_var.h
> +++ b/sys/netinet/igmp_var.h
> @@ -78,7 +78,29 @@ struct igmpstat {
>  }
>  
>  #ifdef _KERNEL
> -extern struct igmpstat igmpstat;
> +
> +#include <sys/percpu.h>
> +
> +enum igmpstat_counters {
> +     igps_rcv_total,         /* total IGMP messages received */
> +     igps_rcv_tooshort,      /* received with too few bytes */
> +     igps_rcv_badsum,        /* received with bad checksum */
> +     igps_rcv_queries,       /* received membership queries */
> +     igps_rcv_badqueries,    /* received invalid queries */
> +     igps_rcv_reports,       /* received membership reports */
> +     igps_rcv_badreports,    /* received invalid reports */
> +     igps_rcv_ourreports,    /* received reports for our groups */
> +     igps_snd_reports,       /* sent membership reports */
> +     igps_ncounters
> +};
> +
> +extern struct cpumem *igmpcounters;
> +
> +static inline void
> +igmpstat_inc(enum igmpstat_counters c)
> +{
> +     counters_inc(igmpcounters, c);
> +}
>  
>  /*
>   * Macro to compute a random timer value between 1 and (IGMP_MAX_REPORTING_
> -- 
> 2.11.0
> 

Reply via email to