0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/mm.h>
0014 #include <linux/module.h>
0015 #include <linux/skbuff.h>
0016 #include <linux/inet_diag.h>
0017
0018 #include <net/tcp.h>
0019
0020
0021
0022
0023 #define V_PARAM_SHIFT 1
0024 static const int beta = 3 << V_PARAM_SHIFT;
0025
0026
0027 struct veno {
0028 u8 doing_veno_now;
0029 u16 cntrtt;
0030 u32 minrtt;
0031 u32 basertt;
0032 u32 inc;
0033 u32 diff;
0034 };
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 static inline void veno_enable(struct sock *sk)
0046 {
0047 struct veno *veno = inet_csk_ca(sk);
0048
0049
0050 veno->doing_veno_now = 1;
0051
0052 veno->minrtt = 0x7fffffff;
0053 }
0054
0055 static inline void veno_disable(struct sock *sk)
0056 {
0057 struct veno *veno = inet_csk_ca(sk);
0058
0059
0060 veno->doing_veno_now = 0;
0061 }
0062
0063 static void tcp_veno_init(struct sock *sk)
0064 {
0065 struct veno *veno = inet_csk_ca(sk);
0066
0067 veno->basertt = 0x7fffffff;
0068 veno->inc = 1;
0069 veno_enable(sk);
0070 }
0071
0072
0073 static void tcp_veno_pkts_acked(struct sock *sk,
0074 const struct ack_sample *sample)
0075 {
0076 struct veno *veno = inet_csk_ca(sk);
0077 u32 vrtt;
0078
0079 if (sample->rtt_us < 0)
0080 return;
0081
0082
0083 vrtt = sample->rtt_us + 1;
0084
0085
0086 if (vrtt < veno->basertt)
0087 veno->basertt = vrtt;
0088
0089
0090
0091
0092 veno->minrtt = min(veno->minrtt, vrtt);
0093 veno->cntrtt++;
0094 }
0095
0096 static void tcp_veno_state(struct sock *sk, u8 ca_state)
0097 {
0098 if (ca_state == TCP_CA_Open)
0099 veno_enable(sk);
0100 else
0101 veno_disable(sk);
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
0114 {
0115 if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
0116 tcp_veno_init(sk);
0117 }
0118
0119 static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked)
0120 {
0121 struct tcp_sock *tp = tcp_sk(sk);
0122 struct veno *veno = inet_csk_ca(sk);
0123
0124 if (!veno->doing_veno_now) {
0125 tcp_reno_cong_avoid(sk, ack, acked);
0126 return;
0127 }
0128
0129
0130 if (!tcp_is_cwnd_limited(sk))
0131 return;
0132
0133
0134 if (veno->cntrtt <= 2) {
0135
0136
0137
0138 tcp_reno_cong_avoid(sk, ack, acked);
0139 } else {
0140 u64 target_cwnd;
0141 u32 rtt;
0142
0143
0144
0145
0146
0147 rtt = veno->minrtt;
0148
0149 target_cwnd = (u64)tcp_snd_cwnd(tp) * veno->basertt;
0150 target_cwnd <<= V_PARAM_SHIFT;
0151 do_div(target_cwnd, rtt);
0152
0153 veno->diff = (tcp_snd_cwnd(tp) << V_PARAM_SHIFT) - target_cwnd;
0154
0155 if (tcp_in_slow_start(tp)) {
0156
0157 acked = tcp_slow_start(tp, acked);
0158 if (!acked)
0159 goto done;
0160 }
0161
0162
0163 if (veno->diff < beta) {
0164
0165
0166
0167 tcp_cong_avoid_ai(tp, tcp_snd_cwnd(tp), acked);
0168 } else {
0169
0170
0171
0172 if (tp->snd_cwnd_cnt >= tcp_snd_cwnd(tp)) {
0173 if (veno->inc &&
0174 tcp_snd_cwnd(tp) < tp->snd_cwnd_clamp) {
0175 tcp_snd_cwnd_set(tp, tcp_snd_cwnd(tp) + 1);
0176 veno->inc = 0;
0177 } else
0178 veno->inc = 1;
0179 tp->snd_cwnd_cnt = 0;
0180 } else
0181 tp->snd_cwnd_cnt += acked;
0182 }
0183 done:
0184 if (tcp_snd_cwnd(tp) < 2)
0185 tcp_snd_cwnd_set(tp, 2);
0186 else if (tcp_snd_cwnd(tp) > tp->snd_cwnd_clamp)
0187 tcp_snd_cwnd_set(tp, tp->snd_cwnd_clamp);
0188 }
0189
0190
0191 veno->minrtt = 0x7fffffff;
0192 }
0193
0194
0195 static u32 tcp_veno_ssthresh(struct sock *sk)
0196 {
0197 const struct tcp_sock *tp = tcp_sk(sk);
0198 struct veno *veno = inet_csk_ca(sk);
0199
0200 if (veno->diff < beta)
0201
0202 return max(tcp_snd_cwnd(tp) * 4 / 5, 2U);
0203 else
0204
0205 return max(tcp_snd_cwnd(tp) >> 1U, 2U);
0206 }
0207
0208 static struct tcp_congestion_ops tcp_veno __read_mostly = {
0209 .init = tcp_veno_init,
0210 .ssthresh = tcp_veno_ssthresh,
0211 .undo_cwnd = tcp_reno_undo_cwnd,
0212 .cong_avoid = tcp_veno_cong_avoid,
0213 .pkts_acked = tcp_veno_pkts_acked,
0214 .set_state = tcp_veno_state,
0215 .cwnd_event = tcp_veno_cwnd_event,
0216
0217 .owner = THIS_MODULE,
0218 .name = "veno",
0219 };
0220
0221 static int __init tcp_veno_register(void)
0222 {
0223 BUILD_BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
0224 tcp_register_congestion_control(&tcp_veno);
0225 return 0;
0226 }
0227
0228 static void __exit tcp_veno_unregister(void)
0229 {
0230 tcp_unregister_congestion_control(&tcp_veno);
0231 }
0232
0233 module_init(tcp_veno_register);
0234 module_exit(tcp_veno_unregister);
0235
0236 MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
0237 MODULE_LICENSE("GPL");
0238 MODULE_DESCRIPTION("TCP Veno");