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

Reply via email to