2 #include <linux/module.h>
3 #include <linux/skbuff.h>
4 #include <linux/inet_diag.h>
11 u32 beg_snd_nxt
; /* right edge during last RTT */
12 u32 beg_snd_una
; /* left edge during last RTT */
13 u32 beg_snd_cwnd
; /* saves the size of the cwnd */
14 u8 doing_vegas_now
;/* if true, do vegas for this RTT */
15 u16 cntRTT
; /* # of RTTs measured within last RTT */
16 u32 minRTT
; /* min of RTTs measured within last RTT (in usec) */
17 u32 baseRTT
; /* the min of all Vegas RTT measurements seen (in usec) */
20 /* There are several situations when we must "re-start" Vegas:
22 * o when a connection is established
24 * o after fast recovery
25 * o when we send a packet and there is no outstanding
26 * unacknowledged data (restarting an idle connection)
28 * In these circumstances we cannot do a Vegas calculation at the
29 * end of the first RTT, because any calculation we do is using
30 * stale info -- both the saved cwnd and congestion feedback are
33 * Instead we must wait until the completion of an RTT during
34 * which we actually receive ACKs.
36 static inline void vegas_enable(struct sock
*sk
)
38 const struct tcp_sock
*tp
= tcp_sk(sk
);
39 struct vegas
*vegas
= inet_csk_ca(sk
);
41 /* Begin taking Vegas samples next time we send something. */
42 vegas
->doing_vegas_now
= 1;
44 /* Set the beginning of the next send window. */
45 vegas
->beg_snd_nxt
= tp
->snd_nxt
;
48 vegas
->minRTT
= 0x7fffffff;
51 /* Stop taking Vegas samples for now. */
52 static inline void vegas_disable(struct sock
*sk
)
54 struct vegas
*vegas
= inet_csk_ca(sk
);
56 vegas
->doing_vegas_now
= 0;
59 static void tcp_vegas_init(struct sock
*sk
)
61 struct vegas
*vegas
= inet_csk_ca(sk
);
63 vegas
->baseRTT
= 0x7fffffff;
67 static void tcp_vegas_state(struct sock
*sk
, u8 ca_state
)
70 if (ca_state
== TCP_CA_Open
)
76 /* Do RTT sampling needed for Vegas.
78 * o min-filter RTT samples from within an RTT to get the current
79 * propagation delay + queuing delay (we are min-filtering to try to
80 * avoid the effects of delayed ACKs)
81 * o min-filter RTT samples from a much longer window (forever for now)
82 * to find the propagation delay (baseRTT)
84 static void tcp_vegas_rtt_calc(struct sock
*sk
, u32 usrtt
)
86 struct vegas
*vegas
= inet_csk_ca(sk
);
87 u32 vrtt
= usrtt
+ 1; /* Never allow zero rtt or baseRTT */
89 /* Filter to find propagation delay: */
90 if (vrtt
< vegas
->baseRTT
)
91 vegas
->baseRTT
= vrtt
;
93 /* Find the min RTT during the last RTT to find
94 * the current prop. delay + queuing delay:
96 vegas
->minRTT
= min(vegas
->minRTT
, vrtt
);
101 * If the connection is idle and we are restarting,
102 * then we don't want to do any Vegas calculations
103 * until we get fresh RTT samples. So when we
104 * restart, we reset our Vegas state to a clean
105 * slate. After we get acks for this flight of
106 * packets, _then_ we can make Vegas calculations
109 static void tcp_vegas_cwnd_event(struct sock
*sk
, enum tcp_ca_event event
)
111 if (event
== CA_EVENT_CWND_RESTART
||
112 event
== CA_EVENT_TX_START
)
116 /* Extract info for Tcp socket info provided via netlink. */
117 static void tcp_vegas_get_info(struct sock
*sk
, u32 ext
,
120 const struct vegas
*ca
= inet_csk_ca(sk
);
121 if (ext
& (1 << (INET_DIAG_VEGASINFO
- 1))) {
122 struct tcpvegas_info
*info
;
124 info
= RTA_DATA(__RTA_PUT(skb
, INET_DIAG_VEGASINFO
,
127 info
->tcpv_enabled
= ca
->doing_vegas_now
;
128 info
->tcpv_rttcnt
= ca
->cntRTT
;
129 info
->tcpv_rtt
= ca
->baseRTT
;
130 info
->tcpv_minrtt
= ca
->minRTT
;