svn commit: r195239 - projects/tcp_cc_8.x/sys/netinet
Lawrence Stewart
lstewart at FreeBSD.org
Wed Jul 1 13:30:02 UTC 2009
Author: lstewart
Date: Wed Jul 1 13:30:01 2009
New Revision: 195239
URL: http://svn.freebsd.org/changeset/base/195239
Log:
Create a set of CC related hook function wrappers around the algorithm specific
hook function calls. These wrappers provide a place to do various asserts and
place code that is algorithm agnostic. There is scope to move more code into
some of these wrappers than has been done so far. It may also be beneficial to
optimise for the case where the system default algorithm is in use for the
connection and there are no other algorithms available e.g. don't indirect
through the tcpcb and call the default algorithm's function directly. Not sure
what savings could be made if any, but probably worth exploring.
Modified:
projects/tcp_cc_8.x/sys/netinet/cc.c
projects/tcp_cc_8.x/sys/netinet/tcp_input.c
projects/tcp_cc_8.x/sys/netinet/tcp_output.c
projects/tcp_cc_8.x/sys/netinet/tcp_timer.c
Modified: projects/tcp_cc_8.x/sys/netinet/cc.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc.c Wed Jul 1 13:22:08 2009 (r195238)
+++ projects/tcp_cc_8.x/sys/netinet/cc.c Wed Jul 1 13:30:01 2009 (r195239)
@@ -204,6 +204,12 @@ cc_deregister_algo(struct cc_algo *remov
* Check all active control blocks and change any that are
* using this algorithm back to newreno. If the algorithm that
* was in use requires cleanup code to be run, call it.
+ *
+ * New connections already part way through being initialised
+ * with the CC algo we're removing will not race with this code
+ * because the INP_INFO_WLOCK is held during initialisation.
+ * We therefore don't enter the loop below until the connection
+ * list has stabilised.
*/
INP_INFO_RLOCK(&V_tcbinfo);
LIST_FOREACH(inp, &V_tcb, inp_list) {
Modified: projects/tcp_cc_8.x/sys/netinet/tcp_input.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_input.c Wed Jul 1 13:22:08 2009 (r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_input.c Wed Jul 1 13:30:01 2009 (r195239)
@@ -214,6 +214,59 @@ static void tcp_pulloutofband(struct so
struct tcphdr *, struct mbuf *, int);
static void tcp_xmit_timer(struct tcpcb *, int);
static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
+static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th);
+static void inline cc_cwnd_init(struct tcpcb *tp);
+static void inline cc_pre_fr(struct tcpcb *tp, struct tcphdr *th);
+static void inline cc_post_fr(struct tcpcb *tp, struct tcphdr *th);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_ack_received(struct tcpcb *tp, struct tcphdr *th)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (!IN_FASTRECOVERY(tp) && CC_ALGO(tp)->ack_received != NULL)
+ CC_ALGO(tp)->ack_received(tp, th);
+}
+
+static void inline
+cc_cwnd_init(struct tcpcb *tp)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ /*
+ * XXXLS: Should rename this hook and do
+ * ssthresh init in there as well
+ */
+
+ if (CC_ALGO(tp)->cwnd_init != NULL)
+ CC_ALGO(tp)->cwnd_init(tp);
+}
+
+static void inline
+cc_pre_fr(struct tcpcb *tp, struct tcphdr *th)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (CC_ALGO(tp)->pre_fr != NULL)
+ CC_ALGO(tp)->pre_fr(tp, th);
+
+ ENTER_FASTRECOVERY(tp);
+ tp->snd_recover = tp->snd_max;
+ if (tp->t_flags & TF_ECN_PERMIT)
+ tp->t_flags |= TF_ECN_SND_CWR;
+}
+
+static void inline
+cc_post_fr(struct tcpcb *tp, struct tcphdr *th)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (CC_ALGO(tp)->post_fr != NULL)
+ CC_ALGO(tp)->post_fr(tp, th);
+}
/* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */
#ifdef INET6
@@ -1160,17 +1213,7 @@ tcp_do_segment(struct mbuf *m, struct tc
if ((thflags & TH_ECE) &&
SEQ_LEQ(th->th_ack, tp->snd_recover)) {
TCPSTAT_INC(tcps_ecn_rcwnd);
- /*
- * If the current CC algo has
- * defined a hook for tasks to run
- * before entering FR, call it.
- */
- if (CC_ALGO(tp)->pre_fr != NULL)
- CC_ALGO(tp)->pre_fr(tp, th);
- ENTER_FASTRECOVERY(tp);
- tp->snd_recover = tp->snd_max;
- if (tp->t_flags & TF_ECN_PERMIT)
- tp->t_flags |= TF_ECN_SND_CWR;
+ cc_pre_fr(tp, th);
}
}
@@ -2105,17 +2148,7 @@ tcp_do_segment(struct mbuf *m, struct tc
}
}
- /*
- * If the current CC algo has
- * defined a hook for tasks to run
- * before entering FR, call it.
- */
- if (CC_ALGO(tp)->pre_fr != NULL)
- CC_ALGO(tp)->pre_fr(tp, th);
- ENTER_FASTRECOVERY(tp);
- tp->snd_recover = tp->snd_max;
- if (tp->t_flags & TF_ECN_PERMIT)
- tp->t_flags |= TF_ECN_SND_CWR;
+ cc_pre_fr(tp, th);
tcp_timer_activate(tp, TT_REXMT, 0);
tp->t_rtttime = 0;
if (tp->t_flags & TF_SACK_PERMIT) {
@@ -2186,10 +2219,8 @@ tcp_do_segment(struct mbuf *m, struct tc
tcp_sack_partialack(tp, th);
else
tcp_newreno_partial_ack(tp, th);
- } else {
- if (CC_ALGO(tp)->post_fr != NULL)
- CC_ALGO(tp)->post_fr(tp, th);
- }
+ } else
+ cc_post_fr(tp, th);
}
tp->t_dupacks = 0;
/*
@@ -2292,10 +2323,8 @@ process_ACK:
* The specifics of how this is achieved are up to the
* congestion control algorithm in use for this connection.
*/
- if (!IN_FASTRECOVERY(tp)) {
- if (CC_ALGO(tp)->ack_received != NULL)
- CC_ALGO(tp)->ack_received(tp, th);
- }
+ cc_ack_received(tp, th);
+
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
@@ -3274,9 +3303,7 @@ tcp_mss(struct tcpcb *tp, int offer)
if (metrics.rmx_bandwidth)
tp->snd_bandwidth = metrics.rmx_bandwidth;
- /* Set the initial cwnd value. */
- if (CC_ALGO(tp)->cwnd_init != NULL)
- CC_ALGO(tp)->cwnd_init(tp);
+ cc_cwnd_init(tp);
/* Check the interface for TSO capabilities. */
if (mtuflags & CSUM_TSO)
Modified: projects/tcp_cc_8.x/sys/netinet/tcp_output.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_output.c Wed Jul 1 13:22:08 2009 (r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_output.c Wed Jul 1 13:30:01 2009 (r195239)
@@ -125,6 +125,19 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_inet
CTLFLAG_RW, tcp_autosndbuf_max, 0,
"Max size of automatic send buffer");
+static void inline cc_after_idle(struct tcpcb *tp);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_after_idle(struct tcpcb *tp)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (CC_ALGO(tp)->after_idle != NULL)
+ CC_ALGO(tp)->after_idle(tp);
+}
/*
* Tcp output routine: figure out what should be sent and send it.
@@ -169,11 +182,8 @@ tcp_output(struct tcpcb *tp)
* to send, then transmit; otherwise, investigate further.
*/
idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
- if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur) {
- /* reset cwnd after a period of idleness */
- if (CC_ALGO(tp)->after_idle != NULL)
- CC_ALGO(tp)->after_idle(tp);
- }
+ if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur)
+ cc_after_idle(tp);
tp->t_flags &= ~TF_LASTIDLE;
if (idle) {
if (tp->t_flags & TF_MORETOCOME) {
Modified: projects/tcp_cc_8.x/sys/netinet/tcp_timer.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_timer.c Wed Jul 1 13:22:08 2009 (r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_timer.c Wed Jul 1 13:30:01 2009 (r195239)
@@ -118,6 +118,24 @@ int tcp_maxpersistidle;
/* max idle time in persist */
int tcp_maxidle;
+static void inline cc_after_timeout(struct tcpcb *tp);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_after_timeout(struct tcpcb *tp)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (CC_ALGO(tp)->after_timeout != NULL)
+ CC_ALGO(tp)->after_timeout(tp);
+
+ tp->t_dupacks = 0;
+ EXIT_FASTRECOVERY(tp);
+ tp->t_bytes_acked = 0;
+}
+
/*
* Tcp protocol timeout routine called every 500 ms.
* Updates timestamps used for TCP
@@ -555,12 +573,8 @@ tcp_timer_rexmt(void * xtp)
*/
tp->t_rtttime = 0;
- if (CC_ALGO(tp)->after_timeout != NULL)
- CC_ALGO(tp)->after_timeout(tp);
+ cc_after_timeout(tp);
- tp->t_dupacks = 0;
- EXIT_FASTRECOVERY(tp);
- tp->t_bytes_acked = 0;
(void) tcp_output(tp);
out:
More information about the svn-src-projects
mailing list