On Thu, Mar 09, 2017 at 03:49:21PM +0100, Jeremie Courreges-Anglas wrote:
> Martin Pieuchot <m...@openbsd.org> writes:
>
> > On 08/03/17(Wed) 12:03, Jeremie Courreges-Anglas wrote:
> >> [...]
> >> So here's a refreshed diff that initializes the counters directly from
> >> ip_init(). I remove the ipip_init() wrapper to make it clear that
> >> ip_init() is responsible for the job.
> >>
> >> (Still) ok?
> >
> > I'm against adding more "#if PEUDOIF" in the stack everywhere and it
> > makes no sense to move more globals outside of ip_ipip.c.
>
> The previous diff was just plain wrong.
>
> > If you really don't want to use .pr_init, then call ipip_input() from
> > ip_input().
>
> Actually I'm fine with .pr_init. There are other protosw entries that
> reach the counters but one shouldn't remove entries carelessly anyway.
>
> Is this better?
>
Definitely. OK dhill@
>
> Index: netinet/in_proto.c
> ===================================================================
> RCS file: /d/cvs/src/sys/netinet/in_proto.c,v
> retrieving revision 1.74
> diff -u -p -r1.74 in_proto.c
> --- netinet/in_proto.c 2 Mar 2017 08:58:24 -0000 1.74
> +++ netinet/in_proto.c 8 Mar 2017 11:56:45 -0000
> @@ -239,7 +239,8 @@ struct protosw inetsw[] = {
> .pr_output = rip_output,
> .pr_ctloutput = rip_ctloutput,
> .pr_usrreq = rip_usrreq,
> - .pr_sysctl = ipip_sysctl
> + .pr_sysctl = ipip_sysctl,
> + .pr_init = ipip_init
> },
> {
> .pr_type = SOCK_RAW,
> @@ -284,7 +285,8 @@ struct protosw inetsw[] = {
> .pr_output = rip_output,
> .pr_ctloutput = rip_ctloutput,
> .pr_usrreq = rip_usrreq,
> - .pr_sysctl = ipip_sysctl
> + .pr_sysctl = ipip_sysctl,
> + .pr_init = ipip_init
> },
> #ifdef INET6
> {
> 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 8 Mar 2017 11:59:04 -0000
> @@ -84,7 +84,13 @@
> */
> int ipip_allow = 0;
>
> -struct ipipstat ipipstat;
> +struct cpumem *ipipcounters;
> +
> +void
> +ipip_init(void)
> +{
> + ipipcounters = counters_alloc(ipips_ncounters);
> +}
>
> /*
> * Really only a wrapper for ipip_input(), for use with pr_input.
> @@ -95,7 +101,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 +135,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 +149,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 +158,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 +185,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 +201,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 +212,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 +235,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 +255,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 +297,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 +308,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 +342,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 +381,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 +390,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 +447,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 +467,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 +486,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 +524,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 +539,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 +551,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 +560,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 +598,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 +620,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 8 Mar 2017 11:57:46 -0000
> @@ -73,9 +73,40 @@ 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);
> +}
> +
> +void ipip_init(void);
> 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
>