From ae8a8673fa5e15cab60c7bf413c9fd154415ac2b Mon Sep 17 00:00:00 2001 From: lstewart Date: Sat, 28 May 2011 08:13:39 +0000 Subject: [PATCH] MFC r216758,217252: - Add some helper hook points to the TCP stack. The hooks allow Khelp modules to access inbound/outbound events and associated data for established TCP connections. The hooks only run if at least one hook function is registered for the hook point, ensuring the impact on the stack is effectively nil when no TCP Khelp modules are loaded. struct tcp_hhook_data is passed as contextual data to any registered Khelp module hook functions. - Add an OSD (Object Specific Data) pointer to struct tcpcb to allow Khelp modules to associate per-connection data with the TCP control block. - Tweak the MFCed code to preserve the ABI of the 8-STABLE branch with respect to "struct tcpcb" by consuming some of the padding within the struct. - Bump __FreeBSD_version to 802506. In collaboration with: David Hayes and Grenville Armitage Sponsored by: FreeBSD Foundation Reviewed by: bz, others along the way git-svn-id: svn://svn.freebsd.org/base/stable/8@222408 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/netinet/tcp_input.c | 29 +++++++++++++++++++++++++++++ sys/netinet/tcp_output.c | 28 ++++++++++++++++++++++++++++ sys/netinet/tcp_subr.c | 21 +++++++++++++++++++++ sys/netinet/tcp_var.h | 22 +++++++++++++++++++++- sys/sys/param.h | 2 +- 5 files changed, 100 insertions(+), 2 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index d84362e91..7e1c214f0 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include /* for proc0 declaration */ @@ -219,6 +220,8 @@ static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th, static void inline cc_conn_init(struct tcpcb *tp); static void inline cc_post_recovery(struct tcpcb *tp, struct tcphdr *th); static void inline tcp_fields_to_host(struct tcphdr *); +static void inline hhook_run_tcp_est_in(struct tcpcb *tp, + struct tcphdr *th, struct tcpopt *to); #ifdef TCP_SIGNATURE static void inline tcp_fields_to_net(struct tcphdr *); static int inline tcp_signature_verify_input(struct mbuf *, int, int, @@ -239,6 +242,24 @@ kmod_tcpstat_inc(int statnum) (*((u_long *)&V_tcpstat + statnum))++; } +/* + * Wrapper for the TCP established input helper hook. + */ +static void inline +hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to) +{ + struct tcp_hhook_data hhook_data; + + if (V_tcp_hhh[HHOOK_TCP_EST_IN]->hhh_nhooks > 0) { + hhook_data.tp = tp; + hhook_data.th = th; + hhook_data.to = to; + + hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_IN], &hhook_data, + tp->osd); + } +} + /* * CC wrapper hook functions */ @@ -1583,6 +1604,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, } tcp_xmit_bandwidth_limit(tp, th->th_ack); acked = BYTES_THIS_ACK(tp, th); + + /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */ + hhook_run_tcp_est_in(tp, th, &to); + TCPSTAT_INC(tcps_rcvackpack); TCPSTAT_ADD(tcps_rcvackbyte, acked); sbdrop(&so->so_snd, acked); @@ -2297,6 +2322,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, ((to.to_flags & TOF_SACK) || !TAILQ_EMPTY(&tp->snd_holes))) tcp_sack_doack(tp, &to, th->th_ack); + + /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */ + hhook_run_tcp_est_in(tp, th, &to); + if (SEQ_LEQ(th->th_ack, tp->snd_una)) { if (tlen == 0 && tiwin == tp->snd_wnd) { TCPSTAT_INC(tcps_rcvdupack); diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index b815a6cc6..8bd56c9dd 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -126,8 +127,32 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW, &VNET_NAME(tcp_autosndbuf_max), 0, "Max size of automatic send buffer"); +static void inline hhook_run_tcp_est_out(struct tcpcb *tp, + struct tcphdr *th, struct tcpopt *to, + long len, int tso); static void inline cc_after_idle(struct tcpcb *tp); +/* + * Wrapper for the TCP established ouput helper hook. + */ +static void inline +hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th, + struct tcpopt *to, long len, int tso) +{ + struct tcp_hhook_data hhook_data; + + if (V_tcp_hhh[HHOOK_TCP_EST_OUT]->hhh_nhooks > 0) { + hhook_data.tp = tp; + hhook_data.th = th; + hhook_data.to = to; + hhook_data.len = len; + hhook_data.tso = tso; + + hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_OUT], &hhook_data, + tp->osd); + } +} + /* * CC wrapper hook functions */ @@ -1119,6 +1144,9 @@ timer: tp->snd_max = tp->snd_nxt + len; } + /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */ + hhook_run_tcp_est_out(tp, th, &to, len, tso); + #ifdef TCPDEBUG /* * Trace. diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index b5501739c..120e7df2e 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -41,7 +41,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -266,6 +268,8 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW, VNET_DEFINE(uma_zone_t, sack_hole_zone); #define V_sack_hole_zone VNET(sack_hole_zone) +VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]); + static struct inpcb *tcp_notify(struct inpcb *, int); static void tcp_isn_tick(void *); static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, @@ -291,6 +295,7 @@ struct tcpcb_mem { struct tcpcb tcb; struct tcp_timer tt; struct cc_var ccv; + struct osd osd; }; static VNET_DEFINE(uma_zone_t, tcpcb_zone); @@ -336,6 +341,14 @@ tcp_init(void) V_tcbinfo.ipi_vnet = curvnet; #endif V_tcbinfo.ipi_listhead = &V_tcb; + + if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, + &V_tcp_hhh[HHOOK_TCP_EST_IN], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) + printf("%s: WARNING: unable to register helper hook\n", __func__); + if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, + &V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) + printf("%s: WARNING: unable to register helper hook\n", __func__); + hashsize = TCBHASHSIZE; TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", &hashsize); if (!powerof2(hashsize)) { @@ -726,6 +739,12 @@ tcp_newtcpcb(struct inpcb *inp) return (NULL); } + tp->osd = &tm->osd; + if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { + uma_zfree(V_tcpcb_zone, tm); + return (NULL); + } + #ifdef VIMAGE tp->t_vnet = inp->inp_vnet; #endif @@ -952,6 +971,8 @@ tcp_discardcb(struct tcpcb *tp) if (CC_ALGO(tp)->cb_destroy != NULL) CC_ALGO(tp)->cb_destroy(tp->ccv); + khelp_destroy_osd(tp->osd); + CC_ALGO(tp) = NULL; inp->inp_ppcb = NULL; tp->t_inpcb = NULL; diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 9c5013506..c764f69d0 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -200,8 +200,9 @@ struct tcpcb { struct cc_algo *cc_algo; /* congestion control algorithm */ struct cc_var *ccv; /* congestion control specific vars */ + struct osd *osd; /* storage for Khelp module data */ - void *t_pspare2[4]; /* 4 TBD */ + void *t_pspare2[3]; /* 3 TBD */ uint64_t _pad[10]; /* 7 UTO, 3 TBD (1-2 CC/RTT?) */ uint64_t t_sndrexmitpack;/* retransmit packets sent */ @@ -509,6 +510,22 @@ struct tcpstat { void kmod_tcpstat_inc(int statnum); #define KMOD_TCPSTAT_INC(name) \ kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(u_long)) + +/* + * TCP specific helper hook point identifiers. + */ +#define HHOOK_TCP_EST_IN 0 +#define HHOOK_TCP_EST_OUT 1 +#define HHOOK_TCP_LAST HHOOK_TCP_EST_OUT + +struct tcp_hhook_data { + struct tcpcb *tp; + struct tcphdr *th; + struct tcpopt *to; + long len; + int tso; + tcp_seq curack; +}; #endif /* @@ -607,6 +624,9 @@ VNET_DECLARE(int, tcp_ecn_maxretries); #define V_tcp_do_ecn VNET(tcp_do_ecn) #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries) +VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]); +#define V_tcp_hhh VNET(tcp_hhh) + int tcp_addoptions(struct tcpopt *, u_char *); int tcp_ccalgounload(struct cc_algo *unload_algo); struct tcpcb * diff --git a/sys/sys/param.h b/sys/sys/param.h index 7f036bdde..2363dcb42 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 802505 /* Master, propagated to newvers */ +#define __FreeBSD_version 802506 /* Master, propagated to newvers */ #ifdef _KERNEL #define P_OSREL_SIGSEGV 700004 -- 2.45.0