- 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.

- Bump __FreeBSD_version and add a note to UPDATING regarding to ABI changes
  introduced by this commit and r216753.

In collaboration with:	David Hayes <dahayes at swin edu au> and
				Grenville Armitage <garmitage at swin edu au>
Sponsored by:	FreeBSD Foundation
Reviewed by:	bz, others along the way
MFC after:	3 months
This commit is contained in:
Lawrence Stewart 2010-12-28 12:13:30 +00:00
parent 20a95cd6fc
commit 39bc9de532
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216758
6 changed files with 105 additions and 1 deletions

View File

@ -22,6 +22,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
machines to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
20101228:
The TCP stack has been modified to allow Khelp modules to interact with
it via helper hook points and store per-connection data in the TCP
control block. Bump __FreeBSD_version to 900029. User space tools that
rely on the size of struct tcpcb in tcp_var.h (e.g. sockstat) need to
be recompiled.
20101114:
Generic IEEE 802.3 annex 31B full duplex flow control support has been
added to mii(4) and bge(4), bce(4), msk(4), nfe(4) and stge(4) along

View File

@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/hhook.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h> /* for proc0 declaration */
@ -218,6 +219,8 @@ static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th,
uint16_t type);
static void inline cc_conn_init(struct tcpcb *tp);
static void inline cc_post_recovery(struct tcpcb *tp, struct tcphdr *th);
static void inline hhook_run_tcp_est_in(struct tcpcb *tp,
struct tcphdr *th, struct tcpopt *to);
/*
* Kernel module interface for updating tcpstat. The argument is an index
@ -233,6 +236,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
*/
@ -1486,6 +1507,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
ticks - tp->t_rtttime);
}
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);
@ -2199,6 +2224,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);

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/domain.h>
#include <sys/hhook.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mbuf.h>
@ -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
*/
@ -1134,6 +1159,9 @@ tcp_output(struct tcpcb *tp)
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.

View File

@ -41,7 +41,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/callout.h>
#include <sys/hhook.h>
#include <sys/kernel.h>
#include <sys/khelp.h>
#include <sys/sysctl.h>
#include <sys/jail.h>
#include <sys/malloc.h>
@ -214,6 +216,8 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, soreceive_stream, CTLFLAG_RDTUN,
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,
@ -239,6 +243,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);
@ -278,6 +283,13 @@ tcp_init(void)
{
int hashsize;
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)) {
@ -661,6 +673,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
@ -894,6 +912,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;

View File

@ -201,6 +201,7 @@ struct tcpcb {
int t_bytes_acked; /* # bytes acked during current RTT */
struct cc_algo *cc_algo; /* congestion control algorithm */
struct cc_var *ccv;
struct osd *osd; /* storage for Khelp module data */
int t_ispare; /* explicit pad for 64bit alignment */
void *t_pspare2[4]; /* 4 TBD */
@ -501,6 +502,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
/*
@ -608,6 +625,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 *

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 900028 /* Master, propagated to newvers */
#define __FreeBSD_version 900029 /* Master, propagated to newvers */
#ifdef _KERNEL
#define P_OSREL_SIGSEGV 700004