Could someone who uses divert socket confirm that this diff works fine? ok?
Index: netinet/ip_divert.c =================================================================== RCS file: /d/cvs/src/sys/netinet/ip_divert.c,v retrieving revision 1.43 diff -u -p -r1.43 ip_divert.c --- netinet/ip_divert.c 29 Jan 2017 19:58:47 -0000 1.43 +++ netinet/ip_divert.c 6 Feb 2017 23:15:49 -0000 @@ -42,7 +42,7 @@ #include <net/pfvar.h> struct inpcbtable divbtable; -struct divstat divstat; +struct cpumem *divcounters; #ifndef DIVERT_SENDSPACE #define DIVERT_SENDSPACE (65536 + 100) @@ -69,6 +69,7 @@ void divert_init(void) { in_pcbinit(&divbtable, divbhashsize); + divcounters = counters_alloc(divs_ncounters); } int @@ -96,7 +97,7 @@ divert_output(struct inpcb *inp, struct goto fail; if ((m = m_pullup(m, sizeof(struct ip))) == NULL) { /* m_pullup() has freed the mbuf, so just return. */ - divstat.divs_errors++; + divstat_inc(divs_errors); return (ENOBUFS); } ip = mtod(m, struct ip *); @@ -157,12 +158,12 @@ divert_output(struct inpcb *inp, struct error = EHOSTUNREACH; } - divstat.divs_opackets++; + divstat_inc(divs_opackets); return (error); fail: m_freem(m); - divstat.divs_errors++; + divstat_inc(divs_errors); return (error ? error : EINVAL); } @@ -174,11 +175,11 @@ divert_packet(struct mbuf *m, int dir, u struct sockaddr_in addr; inp = NULL; - divstat.divs_ipackets++; + divstat_inc(divs_ipackets); if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) { - divstat.divs_errors++; + divstat_inc(divs_errors); return (0); } @@ -220,7 +221,7 @@ divert_packet(struct mbuf *m, int dir, u if (inp) { sa = inp->inp_socket; if (sbappendaddr(&sa->so_rcv, sintosa(&addr), m, NULL) == 0) { - divstat.divs_fullsock++; + divstat_inc(divs_fullsock); m_freem(m); return (0); } else @@ -228,7 +229,7 @@ divert_packet(struct mbuf *m, int dir, u } if (sa == NULL) { - divstat.divs_noport++; + divstat_inc(divs_noport); m_freem(m); } return (0); @@ -331,6 +332,25 @@ release: return (error); } +int +divert_sysctl_divstat(void *oldp, size_t *oldlenp, void *newp) +{ + uint64_t counters[divs_ncounters]; + struct divstat divstat; + u_long *words = (u_long *)&divstat; + int i; + + CTASSERT(sizeof(divstat) == (nitems(counters) * sizeof(u_long))); + + counters_read(divcounters, counters, nitems(counters)); + + for (i = 0; i < nitems(counters); i++) + words[i] = (u_long)counters[i]; + + return (sysctl_rdstruct(oldp, oldlenp, newp, + &divstat, sizeof(divstat))); +} + /* * Sysctl for divert variables. */ @@ -350,10 +370,7 @@ divert_sysctl(int *name, u_int namelen, return (sysctl_int(oldp, oldlenp, newp, newlen, &divert_recvspace)); case DIVERTCTL_STATS: - if (newp != NULL) - return (EPERM); - return (sysctl_struct(oldp, oldlenp, newp, newlen, - &divstat, sizeof(divstat))); + return (divert_sysctl_divstat(oldp, oldlenp, newp)); default: if (name[0] < DIVERTCTL_MAXID) return sysctl_int_arr(divertctl_vars, name, namelen, Index: netinet/ip_divert.h =================================================================== RCS file: /d/cvs/src/sys/netinet/ip_divert.h,v retrieving revision 1.7 diff -u -p -r1.7 ip_divert.h --- netinet/ip_divert.h 25 Jan 2017 17:34:31 -0000 1.7 +++ netinet/ip_divert.h 6 Feb 2017 13:57:37 -0000 @@ -50,8 +50,27 @@ struct divstat { } #ifdef _KERNEL + +#include <sys/percpu.h> + +enum divstat_counters { + divs_ipackets, + divs_noport, + divs_fullsock, + divs_opackets, + divs_errors, + divs_ncounters, +}; + +extern struct cpumem *divcounters; + +static inline void +divstat_inc(enum divstat_counters c) +{ + counters_inc(divcounters, c); +} + extern struct inpcbtable divbtable; -extern struct divstat divstat; void divert_init(void); void divert_input(struct mbuf *, int, int); Index: netinet6/ip6_divert.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/ip6_divert.c,v retrieving revision 1.44 diff -u -p -r1.44 ip6_divert.c --- netinet6/ip6_divert.c 29 Jan 2017 19:58:47 -0000 1.44 +++ netinet6/ip6_divert.c 6 Feb 2017 23:16:07 -0000 @@ -43,7 +43,7 @@ #include <net/pfvar.h> struct inpcbtable divb6table; -struct div6stat div6stat; +struct cpumem *div6counters; #ifndef DIVERT_SENDSPACE #define DIVERT_SENDSPACE (65536 + 100) @@ -71,6 +71,7 @@ void divert6_init(void) { in_pcbinit(&divb6table, divb6hashsize); + div6counters = counters_alloc(div6s_ncounters); } int @@ -95,7 +96,7 @@ divert6_output(struct inpcb *inp, struct goto fail; if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { /* m_pullup() has freed the mbuf, so just return. */ - div6stat.divs_errors++; + div6stat_inc(div6s_errors); return (ENOBUFS); } ip6 = mtod(m, struct ip6_hdr *); @@ -159,11 +160,11 @@ divert6_output(struct inpcb *inp, struct IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL); } - div6stat.divs_opackets++; + div6stat_inc(div6s_opackets); return (error); fail: - div6stat.divs_errors++; + div6stat_inc(div6s_errors); m_freem(m); return (error ? error : EINVAL); } @@ -176,11 +177,11 @@ divert6_packet(struct mbuf *m, int dir, struct sockaddr_in6 addr; inp = NULL; - div6stat.divs_ipackets++; + div6stat_inc(div6s_ipackets); if (m->m_len < sizeof(struct ip6_hdr) && (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { - div6stat.divs_errors++; + div6stat_inc(div6s_errors); return (0); } @@ -221,7 +222,7 @@ divert6_packet(struct mbuf *m, int dir, if (inp) { sa = inp->inp_socket; if (sbappendaddr(&sa->so_rcv, sin6tosa(&addr), m, NULL) == 0) { - div6stat.divs_fullsock++; + div6stat_inc(div6s_fullsock); m_freem(m); return (0); } else @@ -229,7 +230,7 @@ divert6_packet(struct mbuf *m, int dir, } if (sa == NULL) { - div6stat.divs_noport++; + div6stat_inc(div6s_noport); m_freem(m); } return (0); @@ -332,6 +333,25 @@ release: return (error); } +int +divert6_sysctl_div6stat(void *oldp, size_t *oldlenp, void *newp) +{ + uint64_t counters[div6s_ncounters]; + struct div6stat div6stat; + u_long *words = (u_long *)&div6stat; + int i; + + CTASSERT(sizeof(div6stat) == (nitems(counters) * sizeof(u_long))); + + counters_read(div6counters, counters, nitems(counters)); + + for (i = 0; i < nitems(counters); i++) + words[i] = (u_long)counters[i]; + + return (sysctl_rdstruct(oldp, oldlenp, newp, + &div6stat, sizeof(div6stat))); +} + /* * Sysctl for divert variables. */ @@ -351,10 +371,7 @@ divert6_sysctl(int *name, u_int namelen, return (sysctl_int(oldp, oldlenp, newp, newlen, &divert6_recvspace)); case DIVERT6CTL_STATS: - if (newp != NULL) - return (EPERM); - return (sysctl_struct(oldp, oldlenp, newp, newlen, - &div6stat, sizeof(div6stat))); + return (divert6_sysctl_div6stat(oldp, oldlenp, newp)); default: if (name[0] < DIVERT6CTL_MAXID) return sysctl_int_arr(divert6ctl_vars, name, namelen, Index: netinet6/ip6_divert.h =================================================================== RCS file: /d/cvs/src/sys/netinet6/ip6_divert.h,v retrieving revision 1.5 diff -u -p -r1.5 ip6_divert.h --- netinet6/ip6_divert.h 10 Jul 2014 03:17:59 -0000 1.5 +++ netinet6/ip6_divert.h 6 Feb 2017 14:02:32 -0000 @@ -50,8 +50,27 @@ struct div6stat { } #ifdef _KERNEL + +#include <sys/percpu.h> + +enum div6stat_counters { + div6s_ipackets, + div6s_noport, + div6s_fullsock, + div6s_opackets, + div6s_errors, + div6s_ncounters, +}; + +extern struct cpumem *div6counters; + +static inline void +div6stat_inc(enum div6stat_counters c) +{ + counters_inc(div6counters, c); +} + extern struct inpcbtable divb6table; -extern struct div6stat div6stat; void divert6_init(void); int divert6_input(struct mbuf **, int *, int); -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE