summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UPDATING7
-rw-r--r--sys/netinet/tcp_input.c29
-rw-r--r--sys/netinet/tcp_output.c28
-rw-r--r--sys/netinet/tcp_subr.c20
-rw-r--r--sys/netinet/tcp_var.h20
-rw-r--r--sys/sys/param.h2
6 files changed, 105 insertions, 1 deletions
diff --git a/UPDATING b/UPDATING
index 0323738..b4c302d 100644
--- a/UPDATING
+++ b/UPDATING
@@ -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
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 4dbc038..e2be41a 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -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
@@ -234,6 +237,24 @@ kmod_tcpstat_inc(int 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
*/
static void inline
@@ -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);
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index b7ec6f7..55d3c8e 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -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,9 +127,33 @@ 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
*/
static void inline
@@ -1134,6 +1159,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 7345661..00d266d 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -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;
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 3305b1a..4a43213 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -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 *
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 29114d3..7ccd3ea 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 900028 /* Master, propagated to newvers */
+#define __FreeBSD_version 900029 /* Master, propagated to newvers */
#ifdef _KERNEL
#define P_OSREL_SIGSEGV 700004
OpenPOWER on IntegriCloud