I failed to find a nice place where to initialize the counters.  The
code that uses counters is reachable even if gif(4) isn't compiled in.

I can think of 3 obvious ways to call the init function.

1. call ipip_init() through .pr_init.  The idea would be to call
   ipip_init() once per protosw entry that needs it, so the function
   should return early if it was already run.

2. call ipip_init() from ip_init(), after all ip_init() is always
   compiled in.

3. call ipip_init() from init_main.c.

The diff implements option 3, but what do you folks prefer?
Thoughts / ok?


Index: kern/init_main.c
===================================================================
RCS file: /d/cvs/src/sys/kern/init_main.c,v
retrieving revision 1.267
diff -u -p -r1.267 init_main.c
--- kern/init_main.c    6 Mar 2017 10:48:16 -0000       1.267
+++ kern/init_main.c    7 Mar 2017 14:20:17 -0000
@@ -147,6 +147,7 @@ void        taskq_init(void);
 void   timeout_proc_init(void);
 void   pool_gc_pages(void *);
 void   percpu_init(void);
+void   ipip_init(void);
 
 extern char sigcode[], esigcode[], sigcoderet[];
 #ifdef SYSCALL_DEBUG
@@ -364,6 +365,9 @@ main(void *framep)
 
        /* Per CPU memory allocation */
        percpu_init();
+
+       /* IP-in-IP memory allocation */
+       ipip_init();
 
        /* Initialize the file systems. */
 #if defined(NFSSERVER) || defined(NFSCLIENT)
Index: netinet/ip_ipip.c
===================================================================
RCS file: /d/cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.71
diff -u -p -r1.71 ip_ipip.c
--- netinet/ip_ipip.c   29 Jan 2017 19:58:47 -0000      1.71
+++ netinet/ip_ipip.c   7 Mar 2017 14:20:17 -0000
@@ -84,7 +84,14 @@
  */
 int ipip_allow = 0;
 
-struct ipipstat ipipstat;
+struct cpumem *ipipcounters;
+
+void
+ipip_init(void)
+{
+       if (ipipcounters == NULL)
+               ipipcounters = counters_alloc(ipips_ncounters);
+}
 
 /*
  * Really only a wrapper for ipip_input(), for use with pr_input.
@@ -95,7 +102,7 @@ ip4_input(struct mbuf **mp, int *offp, i
        /* If we do not accept IP-in-IP explicitly, drop.  */
        if (!ipip_allow && ((*mp)->m_flags & (M_AUTH|M_CONF)) == 0) {
                DPRINTF(("ip4_input(): dropped due to policy\n"));
-               ipipstat.ipips_pdrops++;
+               ipipstat_inc(ipips_pdrops);
                m_freem(*mp);
                return IPPROTO_DONE;
        }
@@ -129,7 +136,7 @@ ipip_input(struct mbuf **mp, int *offp, 
        u_int8_t v;
        sa_family_t af;
 
-       ipipstat.ipips_ipackets++;
+       ipipstat_inc(ipips_ipackets);
 
        m_copydata(m, 0, 1, &v);
 
@@ -143,7 +150,7 @@ ipip_input(struct mbuf **mp, int *offp, 
                break;
 #endif
        default:
-               ipipstat.ipips_family++;
+               ipipstat_inc(ipips_family);
                m_freem(m);
                return IPPROTO_DONE;
        }
@@ -152,7 +159,7 @@ ipip_input(struct mbuf **mp, int *offp, 
        if (m->m_len < hlen) {
                if ((m = m_pullup(m, hlen)) == NULL) {
                        DPRINTF(("ipip_input(): m_pullup() failed\n"));
-                       ipipstat.ipips_hdrops++;
+                       ipipstat_inc(ipips_hdrops);
                        return IPPROTO_DONE;
                }
        }
@@ -179,7 +186,7 @@ ipip_input(struct mbuf **mp, int *offp, 
 
        /* Sanity check */
        if (m->m_pkthdr.len < sizeof(struct ip)) {
-               ipipstat.ipips_hdrops++;
+               ipipstat_inc(ipips_hdrops);
                m_freem(m);
                return IPPROTO_DONE;
        }
@@ -195,7 +202,7 @@ ipip_input(struct mbuf **mp, int *offp, 
                break;
 #endif
        default:
-               ipipstat.ipips_family++;
+               ipipstat_inc(ipips_family);
                m_freem(m);
                return IPPROTO_DONE;
        }
@@ -206,7 +213,7 @@ ipip_input(struct mbuf **mp, int *offp, 
        if (m->m_len < hlen) {
                if ((m = m_pullup(m, hlen)) == NULL) {
                        DPRINTF(("ipip_input(): m_pullup() failed\n"));
-                       ipipstat.ipips_hdrops++;
+                       ipipstat_inc(ipips_hdrops);
                        return IPPROTO_DONE;
                }
        }
@@ -229,7 +236,7 @@ ipip_input(struct mbuf **mp, int *offp, 
                    ECN_ALLOWED_IPSEC : ECN_ALLOWED;
                if (!ip_ecn_egress(mode, &otos, &ipo->ip_tos)) {
                        DPRINTF(("ipip_input(): ip_ecn_egress() failed"));
-                       ipipstat.ipips_pdrops++;
+                       ipipstat_inc(ipips_pdrops);
                        m_freem(m);
                        return IPPROTO_DONE;
                }
@@ -249,7 +256,7 @@ ipip_input(struct mbuf **mp, int *offp, 
                itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
                if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) {
                        DPRINTF(("ipip_input(): ip_ecn_egress() failed"));
-                       ipipstat.ipips_pdrops++;
+                       ipipstat_inc(ipips_pdrops);
                        m_freem(m);
                        return IPPROTO_DONE;
                }
@@ -291,7 +298,7 @@ ipip_input(struct mbuf **mp, int *offp, 
                rt = rtalloc((struct sockaddr *)&ss, 0,
                    m->m_pkthdr.ph_rtableid);
                if ((rt != NULL) && (rt->rt_flags & RTF_LOCAL)) {
-                       ipipstat.ipips_spoof++;
+                       ipipstat_inc(ipips_spoof);
                        m_freem(m);
                        rtfree(rt);
                        return IPPROTO_DONE;
@@ -302,7 +309,7 @@ ipip_input(struct mbuf **mp, int *offp, 
        }
 
        /* Statistics */
-       ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
+       ipipstat_add(ipips_ibytes, m->m_pkthdr.len - iphlen);
 
        /*
         * Interface pointer stays the same; if no IPsec processing has
@@ -336,7 +343,7 @@ ipip_input(struct mbuf **mp, int *offp, 
 #endif
 
        if (niq_enqueue(ifq, m) != 0) {
-               ipipstat.ipips_qfull++;
+               ipipstat_inc(ipips_qfull);
                DPRINTF(("ipip_input(): packet dropped because of full "
                    "queue\n"));
        }
@@ -375,7 +382,7 @@ ipip_output(struct mbuf *m, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi)));
 
-                       ipipstat.ipips_unspec++;
+                       ipipstat_inc(ipips_unspec);
                        m_freem(m);
                        *mp = NULL;
                        return EINVAL;
@@ -384,7 +391,7 @@ ipip_output(struct mbuf *m, struct tdb *
                M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
                if (m == NULL) {
                        DPRINTF(("ipip_output(): M_PREPEND failed\n"));
-                       ipipstat.ipips_hdrops++;
+                       ipipstat_inc(ipips_hdrops);
                        *mp = NULL;
                        return ENOBUFS;
                }
@@ -441,7 +448,7 @@ ipip_output(struct mbuf *m, struct tdb *
                else {
                        m_freem(m);
                        *mp = NULL;
-                       ipipstat.ipips_family++;
+                       ipipstat_inc(ipips_family);
                        return EAFNOSUPPORT;
                }
 
@@ -461,7 +468,7 @@ ipip_output(struct mbuf *m, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi)));
 
-                       ipipstat.ipips_unspec++;
+                       ipipstat_inc(ipips_unspec);
                        m_freem(m);
                        *mp = NULL;
                        return ENOBUFS;
@@ -480,7 +487,7 @@ ipip_output(struct mbuf *m, struct tdb *
                M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
                if (m == NULL) {
                        DPRINTF(("ipip_output(): M_PREPEND failed\n"));
-                       ipipstat.ipips_hdrops++;
+                       ipipstat_inc(ipips_hdrops);
                        *mp = NULL;
                        return ENOBUFS;
                }
@@ -518,7 +525,7 @@ ipip_output(struct mbuf *m, struct tdb *
                        } else {
                                m_freem(m);
                                *mp = NULL;
-                               ipipstat.ipips_family++;
+                               ipipstat_inc(ipips_family);
                                return EAFNOSUPPORT;
                        }
 
@@ -533,11 +540,11 @@ ipip_output(struct mbuf *m, struct tdb *
                    tdb->tdb_dst.sa.sa_family));
                m_freem(m);
                *mp = NULL;
-               ipipstat.ipips_family++;
+               ipipstat_inc(ipips_family);
                return EAFNOSUPPORT;
        }
 
-       ipipstat.ipips_opackets++;
+       ipipstat_inc(ipips_opackets);
        *mp = m;
 
        if (tdb->tdb_dst.sa.sa_family == AF_INET) {
@@ -545,7 +552,7 @@ ipip_output(struct mbuf *m, struct tdb *
                        tdb->tdb_cur_bytes +=
                            m->m_pkthdr.len - sizeof(struct ip);
 
-               ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
+               ipipstat_add(ipips_obytes, m->m_pkthdr.len - sizeof(struct ip));
        }
 
 #ifdef INET6
@@ -554,8 +561,8 @@ ipip_output(struct mbuf *m, struct tdb *
                        tdb->tdb_cur_bytes +=
                            m->m_pkthdr.len - sizeof(struct ip6_hdr);
 
-               ipipstat.ipips_obytes +=
-                   m->m_pkthdr.len - sizeof(struct ip6_hdr);
+               ipipstat_add(ipips_obytes,
+                   m->m_pkthdr.len - sizeof(struct ip6_hdr));
        }
 #endif /* INET6 */
 
@@ -592,6 +599,17 @@ ipe4_input(struct mbuf *m, int hlen, int
 #endif /* IPSEC */
 
 int
+ipip_sysctl_ipipstat(void *oldp, size_t *oldlenp, void *newp)
+{
+       struct ipipstat ipipstat;
+
+       CTASSERT(sizeof(ipipstat) == (ipips_ncounters * sizeof(uint64_t)));
+       counters_read(ipipcounters, (uint64_t *)&ipipstat, ipips_ncounters);
+       return (sysctl_rdstruct(oldp, oldlenp, newp,
+           &ipipstat, sizeof(ipipstat)));
+}
+
+int
 ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
@@ -603,10 +621,7 @@ ipip_sysctl(int *name, u_int namelen, vo
        case IPIPCTL_ALLOW:
                return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
        case IPIPCTL_STATS:
-               if (newp != NULL)
-                       return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &ipipstat, sizeof(ipipstat)));
+               return (ipip_sysctl_ipipstat(oldp, oldlenp, newp));
        default:
                return (ENOPROTOOPT);
        }
Index: netinet/ip_ipip.h
===================================================================
RCS file: /d/cvs/src/sys/netinet/ip_ipip.h,v
retrieving revision 1.7
diff -u -p -r1.7 ip_ipip.h
--- netinet/ip_ipip.h   20 Feb 2017 17:04:25 -0000      1.7
+++ netinet/ip_ipip.h   7 Mar 2017 14:20:17 -0000
@@ -73,9 +73,39 @@ struct ipipstat {
 }
 
 #ifdef _KERNEL
+
+#include <sys/percpu.h>
+
+enum ipipstat_counters {
+       ipips_ipackets,
+       ipips_opackets,
+       ipips_hdrops,
+       ipips_qfull,
+       ipips_ibytes,
+       ipips_obytes,
+       ipips_pdrops,
+       ipips_spoof,
+       ipips_family,
+       ipips_unspec,
+       ipips_ncounters
+};
+
+extern struct cpumem *ipipcounters;
+
+static inline void
+ipipstat_inc(enum ipipstat_counters c)
+{
+       counters_inc(ipipcounters, c);
+}
+
+static inline void
+ipipstat_add(enum ipipstat_counters c, uint64_t v)
+{
+       counters_add(ipipcounters, c, v);
+}
+
 int    ipip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 
 extern int ipip_allow;
-extern struct ipipstat ipipstat;
 #endif /* _KERNEL */
 #endif /* _NETINET_IPIP_H_ */


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to