GENIEducation/SampleAssignments/TcpAssignment/ForInstructors: tcp_exp_answer_v2.c

File tcp_exp_answer_v2.c, 3.6 KB (added by sedwards@bbn.com, 10 years ago)
Line 
1#include <net/tcp.h>
2#include <linux/module.h>
3
4int sysctl_tcp_max_ssthresh = 0;
5
6/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */
7void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w)
8{
9        if (tp->snd_cwnd_cnt >= w) {
10                if (tp->snd_cwnd < tp->snd_cwnd_clamp)
11                        tp->snd_cwnd++;
12                tp->snd_cwnd_cnt = 0;
13        } else {
14                tp->snd_cwnd_cnt++;
15        }
16}
17
18static void exp_slow_start(struct tcp_sock *tp)
19{
20    /* Handle cwnd manipulation for slow start here */
21        int cnt; /* increase in packets */
22        unsigned int delta = 0;
23        u32 snd_cwnd = tp->snd_cwnd;
24
25        if (unlikely(!snd_cwnd)) {
26                printk("snd_cwnd is nul, please report this bug.\n");
27                snd_cwnd = 1U;
28        }
29
30        if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)
31                cnt = sysctl_tcp_max_ssthresh >> 1;     /* limited slow start */
32        else
33                cnt = snd_cwnd * 2;     /* changed by Shufeng - exponential factor 3 increase */
34
35        tp->snd_cwnd_cnt += cnt;
36        while (tp->snd_cwnd_cnt >= snd_cwnd) {
37                tp->snd_cwnd_cnt -= snd_cwnd;
38                delta++;
39        }
40        tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp);
41}
42
43static void exp_cong_avoid(struct sock *sk, u32 adk, u32 in_flight)
44{
45    /* Handle cwnd manipulation for congestion avoidance here */
46        struct tcp_sock *tp = tcp_sk(sk);
47
48        if (!tcp_is_cwnd_limited(sk, in_flight))
49                return;
50
51        /* In "safe" area, increase. */
52        if (tp->snd_cwnd <= tp->snd_ssthresh)
53                exp_slow_start(tp);
54        /* In dangerous area, increase slowly. */
55        else
56                tcp_cong_avoid_ai(tp, tp->snd_cwnd);
57}
58
59static u32 exp_ssthresh(struct sock *sk)
60{
61    /* Compute the appropriate value of ssthresh here */
62        const struct tcp_sock *tp = tcp_sk(sk);
63        return max(tp->snd_cwnd*3/4, 2U); //changed by Shufeng
64}
65
66
67//See  http://lwn.net/Articles/128681/ for more information
68/*
69 * The start() method initializes the algorithm when a new batch of data
70 * is being transmitted; this can happen for new sockets, or when one
71 * has been idle for a while.
72 *
73 * The ssthresh() method calculates the "slow start threshold"; when the
74 * congestion window is below that threshold, the connection is in slow
75 * start mode rather than full congestion avoidance mode. This method is
76 * called when congestion occurs.
77 *
78 * The actual initial window may be set by min_cwnd() to be less than
79 * the threshold value as a starting point for the slow start algorithm.
80 *
81 * When an acknowledgment arrives from the remote end, the cong_avoid()
82 * method is invoked; it may respond to successful packet delivery by
83 * enlarging the congestion window.
84 *
85 * rtt_sample() tells the algorithm about a measured round-trip time -
86 * the time taken between sending a packet and receiving the
87 * corresponding acknowledgment.
88 *
89 * set_state() indicates that the TCP state of the socket has changed.
90 *
91 * Various events of interest can be communicated to the algorithm via
92 * cwnd_event().
93 *
94 * Sometimes, transient situations can cause the congestion window to be
95 * reduced; the undo_cwnd() method can be called when such a situation
96 * is detected to restore a larger window.
97 *
98 * The get_info() method can be used to make congestion avoidance
99 * information available to user space.
100 */
101static struct tcp_congestion_ops tcp_exp __read_mostly = {
102    .init       = NULL,
103    .ssthresh   = exp_ssthresh,
104    .cong_avoid = exp_cong_avoid,
105    .min_cwnd   = tcp_reno_min_cwnd,
106   
107    .owner      = THIS_MODULE,
108    .name       = "exp"
109};
110
111static int __init exp_register(void)
112{
113        return tcp_register_congestion_control(&tcp_exp);
114}
115
116static void __exit exp_unregister(void)
117{
118        tcp_unregister_congestion_control(&tcp_exp);
119}
120
121module_init(exp_register);
122module_exit(exp_unregister);
123
124MODULE_AUTHOR("Shufeng Huang");
125MODULE_LICENSE("GPL");
126MODULE_DESCRIPTION("Experimental TCP");