]> err.no Git - linux-2.6/blob - net/ipv4/tcp_yeah.h
[TCP] YeAH-TCP: algorithm implementation
[linux-2.6] / net / ipv4 / tcp_yeah.h
1 #include <linux/mm.h>
2 #include <linux/module.h>
3 #include <linux/skbuff.h>
4 #include <linux/inet_diag.h>
5
6 #include <net/tcp.h>
7
8 /* Vegas variables */
9 struct vegas {
10         u32     beg_snd_nxt;    /* right edge during last RTT */
11         u32     beg_snd_una;    /* left edge  during last RTT */
12         u32     beg_snd_cwnd;   /* saves the size of the cwnd */
13         u8      doing_vegas_now;/* if true, do vegas for this RTT */
14         u16     cntRTT;         /* # of RTTs measured within last RTT */
15         u32     minRTT;         /* min of RTTs measured within last RTT (in usec) */
16         u32     baseRTT;        /* the min of all Vegas RTT measurements seen (in usec) */
17 };
18
19 /* There are several situations when we must "re-start" Vegas:
20  *
21  *  o when a connection is established
22  *  o after an RTO
23  *  o after fast recovery
24  *  o when we send a packet and there is no outstanding
25  *    unacknowledged data (restarting an idle connection)
26  *
27  * In these circumstances we cannot do a Vegas calculation at the
28  * end of the first RTT, because any calculation we do is using
29  * stale info -- both the saved cwnd and congestion feedback are
30  * stale.
31  *
32  * Instead we must wait until the completion of an RTT during
33  * which we actually receive ACKs.
34  */
35 static inline void vegas_enable(struct sock *sk)
36 {
37         const struct tcp_sock *tp = tcp_sk(sk);
38         struct vegas *vegas = inet_csk_ca(sk);
39
40         /* Begin taking Vegas samples next time we send something. */
41         vegas->doing_vegas_now = 1;
42
43         /* Set the beginning of the next send window. */
44         vegas->beg_snd_nxt = tp->snd_nxt;
45
46         vegas->cntRTT = 0;
47         vegas->minRTT = 0x7fffffff;
48 }
49
50 /* Stop taking Vegas samples for now. */
51 static inline void vegas_disable(struct sock *sk)
52 {
53         struct vegas *vegas = inet_csk_ca(sk);
54
55         vegas->doing_vegas_now = 0;
56 }
57
58 static void tcp_vegas_init(struct sock *sk)
59 {
60         struct vegas *vegas = inet_csk_ca(sk);
61
62         vegas->baseRTT = 0x7fffffff;
63         vegas_enable(sk);
64 }
65
66 static void tcp_vegas_state(struct sock *sk, u8 ca_state)
67 {
68
69         if (ca_state == TCP_CA_Open)
70                 vegas_enable(sk);
71         else
72                 vegas_disable(sk);
73 }
74
75 /* Do RTT sampling needed for Vegas.
76  * Basically we:
77  *   o min-filter RTT samples from within an RTT to get the current
78  *     propagation delay + queuing delay (we are min-filtering to try to
79  *     avoid the effects of delayed ACKs)
80  *   o min-filter RTT samples from a much longer window (forever for now)
81  *     to find the propagation delay (baseRTT)
82  */
83 static void tcp_vegas_rtt_calc(struct sock *sk, u32 usrtt)
84 {
85         struct vegas *vegas = inet_csk_ca(sk);
86         u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
87
88         /* Filter to find propagation delay: */
89         if (vrtt < vegas->baseRTT)
90                 vegas->baseRTT = vrtt;
91
92         /* Find the min RTT during the last RTT to find
93          * the current prop. delay + queuing delay:
94          */
95         vegas->minRTT = min(vegas->minRTT, vrtt);
96         vegas->cntRTT++;
97 }
98
99 /*
100  * If the connection is idle and we are restarting,
101  * then we don't want to do any Vegas calculations
102  * until we get fresh RTT samples.  So when we
103  * restart, we reset our Vegas state to a clean
104  * slate. After we get acks for this flight of
105  * packets, _then_ we can make Vegas calculations
106  * again.
107  */
108 static void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event)
109 {
110         if (event == CA_EVENT_CWND_RESTART ||
111             event == CA_EVENT_TX_START)
112                 tcp_vegas_init(sk);
113 }
114
115 /* Extract info for Tcp socket info provided via netlink. */
116 static void tcp_vegas_get_info(struct sock *sk, u32 ext,
117                                struct sk_buff *skb)
118 {
119         const struct vegas *ca = inet_csk_ca(sk);
120         if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
121                 struct tcpvegas_info *info;
122
123                 info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
124                                           sizeof(*info)));
125
126                 info->tcpv_enabled = ca->doing_vegas_now;
127                 info->tcpv_rttcnt = ca->cntRTT;
128                 info->tcpv_rtt = ca->baseRTT;
129                 info->tcpv_minrtt = ca->minRTT;
130         rtattr_failure: ;
131         }
132 }
133
134