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