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。注释掉后也会有所不同。