From: Mohamed Alrshah <mohamed.a...@gmail.com>

---
 net/ipv4/Kconfig       |  15 ++++
 net/ipv4/Makefile      |   1 +
 net/ipv4/tcp_agilesd.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+)
 create mode 100755 net/ipv4/tcp_agilesd.c

diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 91a25579..22d824b1 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -677,6 +677,17 @@ config TCP_CONG_BBR
        bufferbloat, policers, or AQM schemes that do not provide a delay
        signal. It requires the fq ("Fair Queue") pacing packet scheduler.
 
+config TCP_CONG_AGILESD
+        tristate "Agile-SD Congestion control"
+        default n
+        ---help---
+        
+        This is version 1.0 of Agile-SD TCP. It is a sender-side only. 
+        It contributes the Agility Factor (AF) to shorten the epoch time 
+        and to make TCP independent from RTT. AF reduces the sensitivity 
+        to packet losses, which in turn Agile-SD to achieve better throughput 
+        over high-speed networks.
+
 choice
        prompt "Default TCP congestion control"
        default DEFAULT_CUBIC
@@ -713,6 +724,9 @@ choice
 
        config DEFAULT_BBR
                bool "BBR" if TCP_CONG_BBR=y
+               
+        config DEFAULT_AGILESD
+               bool "AGILESD" if TCP_CONG_AGILESD=y
 
        config DEFAULT_RENO
                bool "Reno"
@@ -738,6 +752,7 @@ config DEFAULT_TCP_CONG
        default "dctcp" if DEFAULT_DCTCP
        default "cdg" if DEFAULT_CDG
        default "bbr" if DEFAULT_BBR
+       default "agilesd" if DEFAULT_AGILESD
        default "cubic"
 
 config TCP_MD5SIG
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index f83de23a..33d398b5 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
 obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o
 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o
+obj-$(CONFIG_TCP_CONG_AGILESD) += tcp_agilesd.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
 obj-$(CONFIG_TCP_CONG_CDG) += tcp_cdg.o
 obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
diff --git a/net/ipv4/tcp_agilesd.c b/net/ipv4/tcp_agilesd.c
new file mode 100755
index 00000000..fd040ff2
--- /dev/null
+++ b/net/ipv4/tcp_agilesd.c
@@ -0,0 +1,221 @@
+/* agilesd is a Loss-Based Congestion Control Algorithm for TCP v1.0.
+ * agilesd has been created by Mohamed A. Alrshah,
+ * at Faculty of Computer Science and Information Technology,
+ * Universiti Putra Malaysia.
+ * agilesd is based on the article, which is published in 2015 as below:
+ * 
+ * Alrshah, M.A., Othman, M., Ali, B. and Hanapi, Z.M., 2015. 
+ * Agile-SD: a Linux-based TCP congestion control algorithm for supporting 
high-speed and short-distance networks. 
+ * Journal of Network and Computer Applications, 55, pp.181-190. 
+ */
+
+/* These includes are very important to operate the algorithm under NS2. */
+//#define NS_PROTOCOL "tcp_agilesd.c"
+//#include "../ns-linux-c.h"
+//#include "../ns-linux-util.h"
+//#include <math.h>
+/* These includes are very important to operate the algorithm under NS2. */
+
+/* These includes are very important to operate the algorithm under Linux OS. 
*/
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/math64.h>
+#include <net/tcp.h>
+//#include <linux/skbuff.h>    // optional
+//#include <linux/inet_diag.h> // optional
+/* These includes are very important to operate the algorithm under Linux OS. 
*/
+
+#define SCALE   1000                   /* Scale factor to avoid fractions */
+#define Double_SCALE 1000000   /* Double_SCALE must be equal to SCALE^2 */
+#define beta    900                            /* beta for multiplicative 
decrease */
+
+static int initial_ssthresh __read_mostly;
+//static int beta __read_mostly = 900; /*the initial value of beta is equal to 
90%*/
+
+module_param(initial_ssthresh, int, 0644);
+MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+//module_param(beta, int, 0444);
+//MODULE_PARM_DESC(beta, "beta for multiplicative decrease");
+
+/* agilesd Parameters */
+struct agilesdtcp {
+       u32             loss_cwnd;                      // congestion window at 
last loss.
+       u32             frac_tracer;            // This is to trace the 
fractions of the increment.
+       u32     degraded_loss_cwnd;     // loss_cwnd after degradation.
+       enum    dystate{SS=0, CA=1} agilesd_tcp_status;
+};
+
+static inline void agilesdtcp_reset(struct sock *sk)
+{
+       /*After timeout loss cntRTT and baseRTT must be reset to the initial 
values as below */
+}
+
+/* This function is called after the first acknowledgment is received and 
before the congestion
+ * control algorithm will be called for the first time. If the congestion 
control algorithm has
+ * private data, it should initialize its private date here. */
+static void agilesdtcp_init(struct sock *sk)
+{
+       struct agilesdtcp *ca = inet_csk_ca(sk);
+
+       // If the value of initial_ssthresh is not set, snd_ssthresh will be 
initialized by a large value.
+       if (initial_ssthresh)
+               tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
+       else
+               tcp_sk(sk)->snd_ssthresh = 0x7fffffff;
+
+       ca->loss_cwnd           = 0;
+       ca->frac_tracer         = 0;
+       ca->agilesd_tcp_status  = SS;
+}
+
+/* This function is called whenever an ack is received and the congestion 
window can be increased.
+ * This is equivalent to opencwnd in tcp.cc.
+ * ack is the number of bytes that are acknowledged in the latest 
acknowledgment;
+ * rtt is the the rtt measured by the latest acknowledgment;
+ * in_flight is the packet in flight before the latest acknowledgment;
+ * good_ack is an indicator whether the current situation is normal (no 
duplicate ack, no loss and no SACK). */
+static void agilesdtcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)     
                                //For Linux Kernel Use.
+//static void agilesdtcp_cong_avoid(struct sock *sk, u32 ack, u32 seq_rtt, u32 
in_flight, int data_acked)      //For NS2 Use.
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct agilesdtcp *ca = inet_csk_ca(sk);
+       u32 inc_factor;
+       u32 ca_inc;
+       u32 current_gap, total_gap;
+       /* The value of inc_factor is limited by lower_fl and upper_fl.
+        * The lower_fl must be always = 1. The greater the upper_fl the higher 
the aggressiveness.
+        * But, if upper_fl set to 1, agilesd will work exactly as newreno.
+        * We have already designed an equation to calculate the optimum 
upper_fl based on the given beta.
+        * This equation will be revealed once its article is published*/
+       u32 lower_fl = 1 * SCALE;
+       u32 upper_fl = 3 * SCALE;
+
+       //if (!tcp_is_cwnd_limited(sk, in_flight)) return;      //For NS-2 Use, 
if the in flight packets not >= cwnd do nothing//
+       if (!tcp_is_cwnd_limited(sk)) return;                   // For Linux 
Kernel Use.
+       
+       if (tp->snd_cwnd < tp->snd_ssthresh){
+               ca->agilesd_tcp_status = SS;
+               //tcp_slow_start(tp);                           //For NS-2 Use
+               tcp_slow_start(tp, in_flight);                  // For Linux 
Kernel Use.
+       }
+       else {
+               ca->agilesd_tcp_status = CA;
+
+               if (ca->loss_cwnd > ca->degraded_loss_cwnd)
+                       total_gap = ca->loss_cwnd - ca->degraded_loss_cwnd;
+               else
+                       total_gap = 1;
+
+               if (ca->loss_cwnd >  tp->snd_cwnd)
+                       current_gap = ca->loss_cwnd - tp->snd_cwnd;
+               else
+                       current_gap = 0;
+
+               inc_factor = min(max(((upper_fl * current_gap) / total_gap), 
lower_fl), upper_fl);
+
+               ca_inc = ((inc_factor * SCALE) / tp->snd_cwnd); /* SCALE is 
used to avoid fractions*/
+
+               ca->frac_tracer += ca_inc;                      /* This in 
order to take the fraction increase into account */
+               if (ca->frac_tracer >= Double_SCALE)    /* To take factor scale 
into account */
+               {
+                       tp->snd_cwnd += 1;
+                       ca->frac_tracer -= Double_SCALE;
+               }
+       }
+}
+
+/* This function is called when the TCP flow detects a loss.
+ * It returns the slow start threshold of a flow, after a packet loss is 
detected. */
+static u32 agilesdtcp_recalc_ssthresh(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       struct agilesdtcp *ca = inet_csk_ca(sk);
+
+       ca->loss_cwnd = tp->snd_cwnd;
+
+       if (ca->agilesd_tcp_status == CA)
+               ca->degraded_loss_cwnd = max((tp->snd_cwnd * beta) / SCALE, 2U);
+       else
+               ca->degraded_loss_cwnd = max((tp->snd_cwnd * beta) / SCALE, 2U);
+
+       ca->frac_tracer = 0;
+
+       return ca->degraded_loss_cwnd;
+}
+
+/* This function is called when the TCP flow detects a loss.
+ * It returns the congestion window of a flow, after a packet loss is detected;
+ * (for many algorithms, this will be equal to ssthresh). When a loss is 
detected,
+ * min_cwnd is called after ssthresh. But some others algorithms might set 
min_cwnd
+ * to be smaller than ssthresh. If this is the case, there will be a slow 
start after loss recovery. */
+//static u32 agilesdtcp_min_cwnd(const struct sock *sk)
+//{
+//     return tcp_sk(sk)->snd_ssthresh;
+//}
+
+static u32 agilesdtcp_undo_cwnd(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       const struct agilesdtcp *ca = inet_csk_ca(sk);
+       return max(tp->snd_cwnd, ca->loss_cwnd);
+}
+
+/* This function is called when the congestion state of the TCP is changed.
+ * newstate is the state code for the state that TCP is going to be in.
+ * The possible states are listed below:
+ * The current congestion control state, which can be one of the followings:
+ * TCP_CA_Open: normal state
+ * TCP_CA_Recovery: Loss Recovery after a Fast Transmission
+ * TCP_CA_Loss: Loss Recovery after a  Timeout
+ * (The following two states are not effective in TCP-Linux but is effective 
in Linux)
+ * TCP_CA_Disorder: duplicate packets detected, but haven't reach the 
threshold. So TCP  shall assume that  packet reordering is happening.
+ * TCP_CA_CWR: the state that congestion window is decreasing (after local 
congestion in NIC, or ECN and etc).
+ * It is to notify the congestion control algorithm and is used by some
+ * algorithms which turn off their special control during loss recovery. */
+static void agilesdtcp_state(struct sock *sk, u8 new_state)
+{
+       if (new_state == TCP_CA_Loss)
+               agilesdtcp_reset(inet_csk_ca(sk));
+}
+
+/* This function is called when there is an acknowledgment that acknowledges 
some new packets.
+ * num_acked is the number of packets that are acknowledged by this 
acknowledgments. */
+//static void agilesdtcp_acked(struct sock *sk, u32 num_acked, ktime_t rtt_us) 
                        //For NS2 Use.
+static void agilesdtcp_acked(struct sock *sk, u32 num_acked, s32 rtt_us)       
                //For Linux Kernel Use.
+{
+
+}
+
+static struct tcp_congestion_ops agilesdtcp __read_mostly = {
+       .init           = agilesdtcp_init,
+       .ssthresh       = agilesdtcp_recalc_ssthresh,   //REQUIRED
+       .cong_avoid     = agilesdtcp_cong_avoid,        //REQUIRED
+       .set_state      = agilesdtcp_state,
+       .undo_cwnd      = agilesdtcp_undo_cwnd,
+       .pkts_acked     = agilesdtcp_acked,
+       .owner          = THIS_MODULE,
+       .name           = "agilesd",                    //REQUIRED
+       //.min_cwnd     = agilesdtcp_min_cwnd,          //NOT REQUIRED
+};
+
+static int __init agilesdtcp_register(void)
+{
+       BUILD_BUG_ON(sizeof(struct agilesdtcp) > ICSK_CA_PRIV_SIZE);
+       return tcp_register_congestion_control(&agilesdtcp);
+}
+
+static void __exit agilesdtcp_unregister(void)
+{
+       tcp_unregister_congestion_control(&agilesdtcp);
+}
+
+module_init(agilesdtcp_register);
+module_exit(agilesdtcp_unregister);
+
+MODULE_AUTHOR("Mohamed A. Alrshah <mohamed.a.alrs...@ieee.org>");
+MODULE_AUTHOR("Mohamed Othman");
+MODULE_AUTHOR("Borhanuddin Ali");
+MODULE_AUTHOR("Zurina Hanapi");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("agilesd is a Loss-Based Congestion Control Algorithm for 
TCP v1.0. By Mohamed A. Alrshah");
+MODULE_VERSION("1.0");
-- 
2.12.3

Reply via email to