update_dctcp_alpha

 1  /*
 2 +  * Update dctcp alpha based on the ecn bit in the received packet.
 3 +  * This procedure is called only when dctcp_ is 1.
 4 +  */
 5 + void FullTcpAgent::update_dctcp_alpha(Packet *pkt)
 6 + {
 7 +     int ecnbit = hdr_flags::access(pkt)->ecnecho();
 8 +     int ackno = hdr_tcp::access(pkt)->ackno();
 9 +     int acked_bytes = ackno - highest_ack_; 
10 + 
11 +     if (acked_bytes <= 0) 
12 +         acked_bytes = size_;    
13 +     dctcp_total += acked_bytes;
14 +     if (ecnbit) {
15 +         dctcp_marked += acked_bytes;
16 +     }
17 + 
18 +     /* Check for barrier indicating its time to recalculate alpha.
19 +      * This code basically updated alpha roughly once per RTT.
20 +      */
21 +     if (ackno > dctcp_alpha_update_seq) {
22 +         double temp_alpha;
23 +         dctcp_alpha_update_seq = dctcp_maxseq;
24 +         if (dctcp_total > 0) 
25 +             temp_alpha = ((double) dctcp_marked) / dctcp_total;
26 +         else 
27 +             temp_alpha = 0.0;
28 + 
29 +         dctcp_alpha_ = (1 - dctcp_g_) * dctcp_alpha_ + dctcp_g_ * temp_alpha;
30 +         dctcp_marked = 0;
31 +         dctcp_total = 0;
32 +     }
33 + }

 =====================================================================================================

 1 int chooseECNSlot()
 2 {
 3     double maxProgress=0;
 4     for(int i=0;i<=nslot_;i++)
 5     { 
 6         if(slot_[i]!=NULL && window_i>2*count)
 7         {
 8             double ti=window_i/(2*count);
 9             double iProg=umap[slot_[i]]+(window_i+ti/2)*ti;
10             for(int j=0;j<=nslot_;j++)
11             {
12                 if(slot_[j]!=NULL && window_j>2*count)
13                 {
14                     double jProg=umap[slot_[j]]+(window_j+ti/2)*ti;
15                     if(jProg>iProg) break;
16                 }
17                 if(j==nslot_) 
18                 {
19                     return i;
20                 }
21             }
22         }
23     }//for
24     return -1;//no flow satisfies the condition.(maybe should return the flow with max progress)
25 }
26 
27 int PortClassifier::recv(Packet* p, Handler*h)
28 {
29     NsObject* node = find(p);//find调用classify,classify返回dport。
30     if (node == NULL) {
31         Packet::free(p);
32         return;
33     }
34     
35     umap[node]++;
36     
37     if(flag)
38     {        
39         hdr_flags *hf=hdr_flags::access(pickPacketForECN(p));
40         if(hf->ce()==1)
41         {
42             hf->ce()=0;
43             mark=chooseECNSlot();
44         }
45         if (mark != -1 &&node==slot_[mark]) 
46         {
47             hf->ce()=1;
48             mark = -1;
49         }
50     }//end of flag
51     
52     node->recv(p,h);
53 }
54       
55 void PortClassifier::install(int slot, NsObject* p)//install是用来向slot里赋值的。(连接agent & slot)
56 {
57     if (slot >= nslot_)
58         alloc(slot);
59     slot_[slot] = p;
60     
61     if (slot >= maxslot_)
62         maxslot_ = slot;
63         
64     count++;
65     if(count>=2) 
66         flag=1;
67     
68 }   
69 ==================================================================================================================================
70 
71 classifier-port.h里需要添加的:
72 (1)include处
73 #include <unordered_map> 还要using namespace std?或者不用?在底下定义的时候用std::unordered_map<NsObject*,double> umap
74 #include "flags.h"//里面有很多需要的变量和函数,如ce()
75 (2)3个变量
76 count=0; flag=0; mark=-1;//可以考虑用复杂些的变量名,防止别的需要include的文件里有重名的
77 count不止表示agent个数,同时它是server的个数!
78 flag用来标志receiver;
79 
80 //【但是这样全局变量对吗?sender那边如果使用portclassifier时会累加上吗?不会的。这方法可以。亲测有效。】
81 //【如果不行就用遍历slot的方法。每次遍历一下看有多少agent。】
82 (3)
83 unordered_map<NsObject*,double> umap;//看看用不用指定std::

=====================================================================================================

 =====================================================================================================

 =====================================================================================================

update 15.1.12

  1 int chooseECNSlot()
  2 {
  3     int maxValue=-1;
  4     int maxDport=-1;
  5     int secondMaxValue=-1;
  6     int secondMaxDport=-1;
  7     for(int i=0;i<packetsBetweenECN.size();i++)
  8     {        
  9         if(packetsBetweenECN[i].progress>maxValue)
 10         {
 11             maxValue=packetsBetweenECN[i].progress;
 12             maxDport=packetsBetweenECN[i].dport;
 13         }        
 14     }
 15     for(int i=0;i<packetsBetweenECN.size();i++)
 16     {        
 17         if(packetsBetweenECN[i].dport!=maxDport && packetsBetweenECN[i].progress>secondMaxValue)
 18         {
 19             secondMaxValue=packetsBetweenECN[i].progress;
 20             secondMaxDport=packetsBetweenECN[i].dport;
 21         }        
 22     }
 23     long long int progressOfMaxWindow;    
 24     for(int i=0;i<array.size();i++)
 25     {
 26         if(array[i].dport==maxDport)
 27         {
 28             progressOfMaxWindow=array[i].progress;
 29         }
 30     }
 31     int flag_2=0;
 32     for(int i=0;i<array.size();i++)
 33     {
 34         if(array[i].dport!=maxDport && array[i].progress<=progressOfMaxWindow)
 35             {
 36                 flag_2=1;
 37                 break;
 38             }
 39     }
 40     if(flag_2==1)
 41         return maxDport;
 42     else
 43         return secondMaxDport;
 44         
 45     //return -1;//no flow satisfies the condition.(maybe should return the flow with max progress)
 46 }
 47 
 48 int PortClassifier::recv(Packet* p, Handler*h)
 49 {
 50     NsObject* node = find(p);//find调用classify,classify返回dport。
 51     if (node == NULL) {
 52         Packet::free(p);
 53         return;
 54     }
 55     
 56     //umap[node]++;
 57     
 58     //update total sum of packets
 59     indexNode tmp;
 60     int dportOfP=classify(p);
 61     tmp.dport=dportOfP;
 62     tmp.progress=1;
 63     
 64     if(array.size()==0)
 65     {
 66         array.push_back(tmp);        
 67     }
 68     else
 69     {
 70         int flag_new=0;
 71         for(int i=0;i<array.size();i++)
 72         {
 73             if(array[i].dport==dportOfP)
 74             {
 75                 array[i].progress++;
 76                 flag_new=1;
 77                 break;
 78             }
 79         }
 80         if(flag_new==0)
 81         {
 82             array.push_back(tmp);            
 83         }
 84     }
 85     
 86     //update packetsBetweenECN
 87     if(packetsBetweenECN.size()==0)
 88     {
 89         packetsBetweenECN.push_back(tmp);
 90     }
 91     else
 92     {
 93         int flag_new=0;
 94         for(int i=0;i<packetsBetweenECN.size();i++)
 95         {
 96             if(packetsBetweenECN[i].dport==dportOfP)
 97             {
 98                 packetsBetweenECN[i].progress++;
 99                 flag_new=1;
100                 break;
101             }
102         }
103         if(flag_new==0)
104         {
105             packetsBetweenECN.push_back(tmp);            
106         }
107     }
108     
109     //change the behaviour of receiver
110     
111     hdr_flags *hf=hdr_flags::access(pickPacketForECN(p));
112     
113     if(flag)
114     {            
115         if(hf->ce()==1)
116         {
117             hf->ce()=0;
118             mark=chooseECNSlot();
119         }
120         if (mark != -1 &&node==slot_[mark]) 
121         {
122             hf->ce()=1;
123             mark = -1;
124         }
125     }//end of flag
126     if(hf->cwr())
127     {
128         packetsBetweenECN.clear();
129     }
130     
131     node->recv(p,h);
132 }
133      
134 void PortClassifier::install(int slot, NsObject* p)//install是用来向slot里赋值的。(连接agent & slot)
135 {
136     if (slot >= nslot_)
137         alloc(slot);
138     slot_[slot] = p;
139     
140     if (slot >= maxslot_)
141         maxslot_ = slot;
142         
143     count++;
144     if(count>=2) 
145         flag=1;
146 }   
147 /////////////////////////////////////////////////////////
148 
149 struct indexNode
150 {
151     int dport;
152     long long int progress;
153 };
154 vector<indexNode> array;//totalSum
155 vector<indexNode> packetsBetweenECN;
156 
157 
158 
159 ===============================================================================================================================================
160 ===============================================================================================================================================
161 ===============================================================================================================================================
162 
163 
164 
165 classifier-port.h里需要添加的:
166 (1)include处
167 //#include <unordered_map> 还要using namespace std?或者不用?在底下定义的时候用std::unordered_map<NsObject*,double> umap
168 #include "flags.h"//里面有很多需要的变量和函数,如ce()
169 (2)3个变量
170 count=0; flag=0; mark=-1;//可以考虑用复杂些的变量名,防止别的需要include的文件里有重名的
171 count不止表示agent个数,同时它是server的个数!
172 flag用来标志receiver;
173 
174 //【但是这样全局变量对吗?sender那边如果使用portclassifier时会累加上吗?不会的。这方法可以。亲测有效。】
175 //【如果不行就用遍历slot的方法。每次遍历一下看有多少agent。】
176 (3)
177 //unordered_map<NsObject*,double> umap;//看看用不用指定std::

 ====================================================================

notes:

别忘了在PortClassifier类定义里加上一行函数声明: void install(int slot, NsObject* p);
recv函数的返回值改为void, 不是int。头文件和实现文件里都要改过来。

对于 ‘pickPacketForECN’ was not declared in this scope,添加了red.h头文件还是不行。大概是需要声明?

//把red.h里的pickPacketForECN()给public了,原本是protected。

//把之前加在classifier-port.h里的类的定义中的recv()函数给改成了public,之前是protected的。

在red.h中定义portclassifier类为友元,并在red.h中include了classifier-port.h 。

error: mobile/dumb-agent.[h,cc] 中有recv(),error说‘virtual void PortClassifier::recv(Packet*, Handler*)’ is protected
dumb-agent里class DumbAgent 是派生的agent类的,而agent本身也有recv函数。portclassifier里之前是没有定义recv函数的。莫非是因为这个干扰到了dumbAgent的recv的使用?我在portclassifier里先把recv注释掉试试。经实验,这样的话可以通过编译,但ns在使用时会segmentation fault,无法正常使用。

刚才调的时候还是使用时有问题,跑例子时就会segment fault。于是我把修改过的classifier-port.[cc,h]这两个文件放到nomad/dctcp-code文件夹备份起来,然后在ns库里删除掉,用原本未经修改过的这两个文件的原件替换进来。这样的话跑例子时就又正常了。看来我得小心翼翼一步一步的改。

最基本的检测ns能不能用,就是直接输入ns,看出不出%

现在是只把install加进去是没有问题,但是加上recv就会有问题。

 这会编译能通过,但是在运行例子的时候竟然吞吐量没有变化。不知哪里出了问题。

另外我在用到pickpacketsforecn时直接把它省略了,因为我发现它是直接返回packet的。不知会不会有问题。

需要在脚本里用red而不是fifo。因为我程序里就是靠red打的标记。

在tcl脚本里将DropTail改成RED之后能在吞吐量上看到明显变化。只不过可能由于我算法考虑的不周全,吞吐量反而下降了很多。不过好在能有效果了。下面仔细分析算法的问题,跟踪查找问题并改正。

另外进一步考虑的话可以看red里上下限对齐。参考dctcp的做法。因为传统red里打ce是基于概率的,不是严格按照比例的。

另外,需要看是否发生丢包,直接在trace里就能看到。

考虑一下临界情况,比如当一个流传输完毕时,是否应该从排序候选人中剔除,如果不剔除会出现什么情况。

我似乎没有考虑到ce连续出现的情况。莫非是这个问题?对每一个ce为1的包都做处理。不过receiver好像不会理会多个ecnecho,不会说一直不停的减半。

我应该考虑改一下代码,对于连续的ce只接受一次。

为什么对返回最大窗口还是次大窗口流的代码做修改后(比如改为每次都返回最大窗口的流),吞吐量没有任何变化?莫非chooseECN函数没起作用?

怎么好像我的程序起的作用很少呢。我把recv里的if(flag)去掉后仍得到相同的吞吐量。

 加了个waitingCWR变量,这样的话在遇到ce和遇到cwr之间只对一个包打ce,这样就不对连续的包打了。不过这样的话也有弊端。比如当ce=1时说明已经在拥挤了,已经倾向于丢包了,那么这时的ecnecho也是容易丢的。所以发一连串ce的话能保证肯定能把ce这个信息传到server端,只发一个的话就容易丢。

非常悲哀的发现。当我把portclassifier::recv()里自己添加的算法注释掉后,运行示例没有任何区别!坑爹啊。。不过也还好,至少说明吞吐量下降不是我算法的错,因为我的算法压根还没生效,摔。。。

--那么问题来了。既然我都注释掉那些ce操作之后,吞吐量还是那种 838,849,31,42,51,31,37,42,32,35,那么,为什么是这个数而不是838,9xx,9xx,........,104 ?

--原因是,当在nx和nc之间的链路上使用DropTail时,就会是8xx,9xx,9xx。。。104. 而如果用的是RED的话,就会是838,849,31,42这种。是不同队列算法导致的这个差异。

但是我的算法还是没起作用啊。分析一下原因。portclassifier是不是用错了。

====================================================================================================================

1.14

会不会在tcl脚本里用的agent不是FullTCP?

果然用的不是TCP/FullTcp。在tcl里改过来之后,运行tcl脚本就会出现一堆bug。

 但是我好像没有改agent相关的内容啊。我是直接改得中间的classifier啊。

 现在先把classifier的两个程序替换成original code,试试是不是fulltcp本身的问题。

老师分析的没错。仅仅把DropTail换成RED不能差别这么大,估计是tcl脚本里一些细节导致的,比如loss module那块。

于是我把loss module那块注释掉,果然有变化!

这样的话出现4种状态:注释前的RED,注释前的DropTail,注释后的。。。。

还有一个是76行的,singledup。注释掉后也会有所不同。

原文地址:https://www.cnblogs.com/forcheryl/p/4212765.html