Redo r294869. The array of counters for TCP states doesn't belong to
struct tcpstat, because the structure can be zeroed out by netstat(1) -z, and of course running connection counts shouldn't be touched. Place running connection counts into separate array, and provide separate read-only sysctl oid for it.
This commit is contained in:
parent
b5b7b142a7
commit
bf840a1707
@ -47,6 +47,7 @@ struct tcp_index {
|
|||||||
static uint64_t tcp_tick;
|
static uint64_t tcp_tick;
|
||||||
static uint64_t tcp_stats_tick;
|
static uint64_t tcp_stats_tick;
|
||||||
static struct tcpstat tcpstat;
|
static struct tcpstat tcpstat;
|
||||||
|
static uint64_t tcps_states[TCP_NSTATES];
|
||||||
static struct xinpgen *xinpgen;
|
static struct xinpgen *xinpgen;
|
||||||
static size_t xinpgen_len;
|
static size_t xinpgen_len;
|
||||||
static u_int tcp_total;
|
static u_int tcp_total;
|
||||||
@ -78,6 +79,17 @@ fetch_tcp_stats(void)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len = sizeof(tcps_states);
|
||||||
|
if (sysctlbyname("net.inet.tcp.states", &tcps_states, &len, NULL,
|
||||||
|
0) == -1) {
|
||||||
|
syslog(LOG_ERR, "net.inet.tcp.states: %m");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (len != sizeof(tcps_states)) {
|
||||||
|
syslog(LOG_ERR, "net.inet.tcp.states: wrong size");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
tcp_stats_tick = get_ticks();
|
tcp_stats_tick = get_ticks();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -231,8 +243,8 @@ op_tcp(struct snmp_context *ctx __unused, struct snmp_value *value,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LEAF_tcpCurrEstab:
|
case LEAF_tcpCurrEstab:
|
||||||
value->v.uint32 = tcpstat.tcps_states[TCPS_ESTABLISHED] +
|
value->v.uint32 = tcps_states[TCPS_ESTABLISHED] +
|
||||||
tcpstat.tcps_states[TCPS_CLOSE_WAIT];
|
tcps_states[TCPS_CLOSE_WAIT];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LEAF_tcpInSegs:
|
case LEAF_tcpInSegs:
|
||||||
|
@ -235,16 +235,39 @@ VNET_DEFINE(struct inpcbhead, tcb);
|
|||||||
VNET_DEFINE(struct inpcbinfo, tcbinfo);
|
VNET_DEFINE(struct inpcbinfo, tcbinfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP statistics are stored in an "array" of counter(9)s.
|
* TCP statistics are stored in an array of counter(9)s, which size matches
|
||||||
|
* size of struct tcpstat. TCP running connection count is a regular array.
|
||||||
*/
|
*/
|
||||||
VNET_PCPUSTAT_DEFINE(struct tcpstat, tcpstat);
|
VNET_PCPUSTAT_DEFINE(struct tcpstat, tcpstat);
|
||||||
VNET_PCPUSTAT_SYSINIT(tcpstat);
|
|
||||||
SYSCTL_VNET_PCPUSTAT(_net_inet_tcp, TCPCTL_STATS, stats, struct tcpstat,
|
SYSCTL_VNET_PCPUSTAT(_net_inet_tcp, TCPCTL_STATS, stats, struct tcpstat,
|
||||||
tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
|
tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
|
||||||
|
VNET_DEFINE(counter_u64_t, tcps_states[TCP_NSTATES]);
|
||||||
|
SYSCTL_COUNTER_U64_ARRAY(_net_inet_tcp, TCPCTL_STATES, states, CTLFLAG_RD |
|
||||||
|
CTLFLAG_VNET, &VNET_NAME(tcps_states), TCP_NSTATES,
|
||||||
|
"TCP connection counts by TCP state");
|
||||||
|
|
||||||
|
static void
|
||||||
|
tcp_vnet_init(const void *unused)
|
||||||
|
{
|
||||||
|
|
||||||
|
COUNTER_ARRAY_ALLOC(VNET(tcps_states), TCP_NSTATES, M_WAITOK);
|
||||||
|
VNET_PCPUSTAT_ALLOC(tcpstat, M_WAITOK);
|
||||||
|
}
|
||||||
|
VNET_SYSINIT(tcp_vnet_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||||
|
tcp_vnet_init, NULL);
|
||||||
|
|
||||||
#ifdef VIMAGE
|
#ifdef VIMAGE
|
||||||
VNET_PCPUSTAT_SYSUNINIT(tcpstat);
|
static void
|
||||||
|
tcp_vnet_uninit(const void *unused)
|
||||||
|
{
|
||||||
|
|
||||||
|
COUNTER_ARRAY_FREE(VNET(tcps_states), TCP_NSTATES);
|
||||||
|
VNET_PCPUSTAT_FREE(tcpstat);
|
||||||
|
}
|
||||||
|
VNET_SYSUNINIT(tcp_vnet_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||||
|
tcp_vnet_uninit, NULL);
|
||||||
#endif /* VIMAGE */
|
#endif /* VIMAGE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel module interface for updating tcpstat. The argument is an index
|
* Kernel module interface for updating tcpstat. The argument is an index
|
||||||
* into tcpstat treated as an array.
|
* into tcpstat treated as an array.
|
||||||
|
@ -1542,7 +1542,7 @@ tcp_close(struct tcpcb *tp)
|
|||||||
#endif
|
#endif
|
||||||
in_pcbdrop(inp);
|
in_pcbdrop(inp);
|
||||||
TCPSTAT_INC(tcps_closed);
|
TCPSTAT_INC(tcps_closed);
|
||||||
TCPSTAT_DEC(tcps_states[tp->t_state]);
|
TCPSTATES_DEC(tp->t_state);
|
||||||
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
|
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
|
||||||
so = inp->inp_socket;
|
so = inp->inp_socket;
|
||||||
soisdisconnected(so);
|
soisdisconnected(so);
|
||||||
@ -1665,7 +1665,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
|
|||||||
*/
|
*/
|
||||||
if (req->oldptr == NULL) {
|
if (req->oldptr == NULL) {
|
||||||
n = V_tcbinfo.ipi_count +
|
n = V_tcbinfo.ipi_count +
|
||||||
TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
|
counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
|
||||||
n += imax(n / 8, 10);
|
n += imax(n / 8, 10);
|
||||||
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xtcpcb);
|
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xtcpcb);
|
||||||
return (0);
|
return (0);
|
||||||
@ -1682,7 +1682,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
|
|||||||
n = V_tcbinfo.ipi_count;
|
n = V_tcbinfo.ipi_count;
|
||||||
INP_LIST_RUNLOCK(&V_tcbinfo);
|
INP_LIST_RUNLOCK(&V_tcbinfo);
|
||||||
|
|
||||||
m = TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
|
m = counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
|
||||||
|
|
||||||
error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
|
error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
|
||||||
+ (n + m) * sizeof(struct xtcpcb));
|
+ (n + m) * sizeof(struct xtcpcb));
|
||||||
@ -2986,8 +2986,8 @@ tcp_state_change(struct tcpcb *tp, int newstate)
|
|||||||
int pstate = tp->t_state;
|
int pstate = tp->t_state;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TCPSTAT_DEC(tcps_states[tp->t_state]);
|
TCPSTATES_DEC(tp->t_state);
|
||||||
TCPSTAT_INC(tcps_states[newstate]);
|
TCPSTATES_INC(newstate);
|
||||||
tp->t_state = newstate;
|
tp->t_state = newstate;
|
||||||
TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
|
TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,7 @@ syncache_insert(struct syncache *sc, struct syncache_head *sch)
|
|||||||
|
|
||||||
SCH_UNLOCK(sch);
|
SCH_UNLOCK(sch);
|
||||||
|
|
||||||
TCPSTAT_INC(tcps_states[TCPS_SYN_RECEIVED]);
|
TCPSTATES_INC(TCPS_SYN_RECEIVED);
|
||||||
TCPSTAT_INC(tcps_sc_added);
|
TCPSTAT_INC(tcps_sc_added);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
|
|||||||
|
|
||||||
SCH_LOCK_ASSERT(sch);
|
SCH_LOCK_ASSERT(sch);
|
||||||
|
|
||||||
TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
|
TCPSTATES_DEC(TCPS_SYN_RECEIVED);
|
||||||
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
||||||
sch->sch_length--;
|
sch->sch_length--;
|
||||||
|
|
||||||
@ -1003,7 +1003,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
* sonewconn->tcp_usr_attach in TCPS_CLOSED state, then
|
* sonewconn->tcp_usr_attach in TCPS_CLOSED state, then
|
||||||
* syncache_socket() will change it to TCPS_SYN_RECEIVED.
|
* syncache_socket() will change it to TCPS_SYN_RECEIVED.
|
||||||
*/
|
*/
|
||||||
TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
|
TCPSTATES_DEC(TCPS_SYN_RECEIVED);
|
||||||
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
||||||
sch->sch_length--;
|
sch->sch_length--;
|
||||||
#ifdef TCP_OFFLOAD
|
#ifdef TCP_OFFLOAD
|
||||||
|
@ -660,7 +660,7 @@ tcp_tw_2msl_stop(struct tcptw *tw, int reuse)
|
|||||||
|
|
||||||
if (!reuse)
|
if (!reuse)
|
||||||
uma_zfree(V_tcptw_zone, tw);
|
uma_zfree(V_tcptw_zone, tw);
|
||||||
TCPSTAT_DEC(tcps_states[TCPS_TIME_WAIT]);
|
TCPSTATES_DEC(TCPS_TIME_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tcptw *
|
struct tcptw *
|
||||||
|
@ -1883,7 +1883,7 @@ tcp_attach(struct socket *so)
|
|||||||
tp->t_state = TCPS_CLOSED;
|
tp->t_state = TCPS_CLOSED;
|
||||||
INP_WUNLOCK(inp);
|
INP_WUNLOCK(inp);
|
||||||
INP_INFO_RUNLOCK(&V_tcbinfo);
|
INP_INFO_RUNLOCK(&V_tcbinfo);
|
||||||
TCPSTAT_INC(tcps_states[TCPS_CLOSED]);
|
TCPSTATES_INC(TCPS_CLOSED);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,9 +588,6 @@ struct tcpstat {
|
|||||||
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
|
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
|
||||||
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
|
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
|
||||||
|
|
||||||
/* Running connection count. */
|
|
||||||
uint64_t tcps_states[TCP_NSTATES];
|
|
||||||
|
|
||||||
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
|
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -609,9 +606,6 @@ VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
|
|||||||
#define TCPSTAT_ADD(name, val) \
|
#define TCPSTAT_ADD(name, val) \
|
||||||
VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val))
|
VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val))
|
||||||
#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
|
#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
|
||||||
#define TCPSTAT_DEC(name) TCPSTAT_ADD(name, -1)
|
|
||||||
#define TCPSTAT_FETCH(name) VNET_PCPUSTAT_FETCH(struct tcpstat, tcpstat, \
|
|
||||||
name)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel module consumers must use this accessor macro.
|
* Kernel module consumers must use this accessor macro.
|
||||||
@ -620,6 +614,13 @@ void kmod_tcpstat_inc(int statnum);
|
|||||||
#define KMOD_TCPSTAT_INC(name) \
|
#define KMOD_TCPSTAT_INC(name) \
|
||||||
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(uint64_t))
|
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(uint64_t))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Running TCP connection count by state.
|
||||||
|
*/
|
||||||
|
VNET_DECLARE(counter_u64_t, tcps_states[TCP_NSTATES]);
|
||||||
|
#define TCPSTATES_INC(state) counter_u64_add(VNET(tcps_states)[state], 1)
|
||||||
|
#define TCPSTATES_DEC(state) counter_u64_add(VNET(tcps_states)[state], -1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP specific helper hook point identifiers.
|
* TCP specific helper hook point identifiers.
|
||||||
*/
|
*/
|
||||||
@ -678,6 +679,7 @@ struct xtcpcb {
|
|||||||
#define TCPCTL_V6MSSDFLT 13 /* MSS default for IPv6 */
|
#define TCPCTL_V6MSSDFLT 13 /* MSS default for IPv6 */
|
||||||
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
|
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
|
||||||
#define TCPCTL_DROP 15 /* drop tcp connection */
|
#define TCPCTL_DROP 15 /* drop tcp connection */
|
||||||
|
#define TCPCTL_STATES 16 /* connection counts by TCP state */
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
#ifdef SYSCTL_DECL
|
#ifdef SYSCTL_DECL
|
||||||
|
Loading…
Reference in New Issue
Block a user