classifier.cc-recv() [ns2.35]
1 //without comments 2 3 int chooseECNSlot() 4 { 5 double maxProgress=0; 6 for(int i=0;i<=nslot_;i++) 7 { 8 if(slot_[i]!=NULL && window_i>2*count) 9 { 10 double ti=window_i/(2*count); 11 double iProg=umap[slot_[i]]+(window_i+ti/2)*ti; 12 for(int j=0;j<=nslot_;j++) 13 { 14 if(slot_[j]!=NULL && window_j>2*count) 15 { 16 double jProg=umap[slot_[j]]+(window_j+ti/2)*ti; 17 if(jProg>iProg) break; 18 } 19 if(j==nslot_) 20 { 21 return i; 22 } 23 } 24 } 25 }//for 26 return -1;//no flow satisfies the condition.(maybe should return the flow with max progress) 27 } 28 29 int PortClassifier::recv(Packet* p, Handler*h) 30 { 31 NsObject* node = find(p);//find调用classify,classify返回dport。 32 if (node == NULL) { 33 Packet::free(p); 34 return; 35 } 36 37 umap[node]++; 38 39 if(flag) 40 { 41 hdr_flags *hf=hdr_flags::access(pickPacketForECN(p)); 42 if(hf->ce()==1) 43 { 44 hf->ce()=0; 45 mark=chooseECNSlot(); 46 } 47 if (mark != -1 &&node==slot_[mark]) 48 { 49 hf->ce()=1; 50 mark = -1; 51 } 52 }//end of flag 53 54 node->recv(p,h); 55 } 56 57 void PortClassifier::install(int slot, NsObject* p)//install是用来向slot里赋值的。(连接agent & slot) 58 { 59 if (slot >= nslot_) 60 alloc(slot); 61 slot_[slot] = p; 62 63 if (slot >= maxslot_) 64 maxslot_ = slot; 65 66 count++; 67 if(count>=2) 68 flag=1; 69 70 } 71 72 73 74 ================================================================================================================================== 75 76 15.1.4 rewrite: 77 78 79 classifier-port.h里需要添加的: 80 (1)include处 81 #include <unordered_map> 还要using namespace std?或者不用?在底下定义的时候用std::unordered_map<NsObject*,double> umap 82 #include "flags.h"//里面有很多需要的变量和函数,如ce() 83 (2)3个变量 84 count=0; flag=0; mark=-1;//可以考虑用复杂些的变量名,防止别的需要include的文件里有重名的 85 count不止表示agent个数,同时它是server的个数! 86 flag用来标志receiver; 87 88 //【但是这样全局变量对吗?sender那边如果使用portclassifier时会累加上吗?不会的。这方法可以。亲测有效。】 89 //【如果不行就用遍历slot的方法。每次遍历一下看有多少agent。】 90 (3) 91 unordered_map<NsObject*,double> umap;//看看用不用指定std:: 92 93 94 95 ------------------------------------------------------------------------------------------------------------------------------ 96 //with comments 97 98 int chooseECNSlot()//根据umap里的统计来获取各流进度值。返回值是slot_的下标。 99 //这个函数还是改成专门筛选流的函数吧(筛选出需要窗口减半的流) 100 { 101 //该函数需要能访问到umap以及各流的window大小。 102 //注意:这里说的按进度排序不是按当前进度排序,而是按下次发生ECN的时刻的进度排序。 103 104 double maxProgress=0;//初始化最大进度值maxProgress 105 // mark=-1;//用来标记选中的流 106 // int flagMax=0; 107 for(int i=0;i<=nslot_;i++)//下标能否等于nslot? 108 { //其实遍历slot就行!slot_中有一些是empty,所以虽然知道共有count个agent,还是得完整遍历一遍slot_. 109 if(slot_[i]!=NULL && window_i>2*count)// 这是能“参赛”的流的入门条件。 110 {//在window大于2N的流里面找[下次ECN时刻]进度最大的。 111 //这里count就是server数目N。 112 //ASSUME flow with index[i] will be the maxProgress-flow at next ECN 113 double ti=window_i/(2*count);//the time gap from now when next ECN happens 114 int newProg=umap[slot_[i]]+(window_i+ti/2)*ti; 115 for(int j=0;j<=nslot_;j++) 116 { 117 if(slot_[j]!=NULL && window_j>2*count)//参赛门槛 118 { 119 double tj=window_j/(2*count); 120 tmpProg=umap[slot_[j]]+(window_j+tj/2)*tj; 121 if(tmpProg>newProg) break;//说明i不是下次ecn时进度最快的,假设不成立。 122 } 123 } 124 // if(umap[slot_[i]]>maxProgress) 125 // { 126 // maxProgress=umap[slot_[i]];//更新maxProgress 127 // mark=i;//标记下该流的node在slot_中对应的下标i; 128 // } 129 } 130 131 // else 132 // {//如果没有window>2N的流,就选当前进度最大的流?这是后话。 133 // } 134 135 }//for 136 137 // if(mark!=-1) 138 return mark;// 返回下标 139 // else//没有window>2N的流 140 // return mark2; 141 142 } 143 144 145 146 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 147 148 int PortClassifier::recv(Packet* p, Handler*h) 149 { 150 NsObject* node = find(p);//find调用classify,classify返回dport。 151 if (node == NULL) { 152 Packet::free(p); 153 return; 154 } 155 156 if(flag)//当前node是receiver时才执行下面的算法。 157 { 158 // mark=-1;//slot_下标的初始值置为-1? 159 umap[node]++;//需要在classifier.h中classifier类内部定义unordered_map umap<NsObject*,double>。 (但是注意,当umap里有流已传输完毕后要剔除出去,否则影响排序XXXX如果不用mark2的话那就不会影响到,因为首先是按window来看的,只有window足够大才会看进度。已经传输完成的流window应该变为0吧(如果没变要记得调整))。 160 hdr_flags *hf=hdr_flags::access(pickPacketForECN(p)); 161 if(hf->ce()==1)// 说明switch中发生了拥塞 162 { 163 hf->ce()=0;//首先清零。然后再根据算法分配ce。 164 mark=chooseECNSlot();//用chooseECNSlot()选出应当减半的流。 165 } 166 167 if (mark != -1 &&node==slot_[mark]) //这个recv()程序一开始就用到了find,把packet转换成了agent(这里是用node变量来表示的agent)。所以可以用这个node来和slot_[mark]直接比较。 168 //对每一个到来的packet都检查,直到发现是mark所标记的那个。可通过portclassifier里的classify返回dport。(参照slideshare P15,为什么通过classifier类,调用的却是portclassifier里的classify ?) 169 { 170 hf->ce()=1; 171 mark = -1;//任务完成,使mark失效。 172 } 173 }//end of flag 174 node->recv(p,h); 175 } 176 177 178 void PortClassifier::install(int slot, NsObject* p)//install是用来向slot里赋值的。(连接agent & slot) 179 { 180 if (slot >= nslot_) 181 alloc(slot); 182 slot_[slot] = p; 183 184 if (slot >= maxslot_) 185 maxslot_ = slot; 186 187 count++; 188 if(count>=2) flag=1; 189 190 } 191 192 193 194 ================================================================================================================================== 195 //below is original source code 196 197 void Classifier::recv(Packet* p, Handler*h)//original 198 { 199 NsObject* node = find(p); 200 if (node == NULL) { 201 /* 202 * XXX this should be "dropped" somehow. Right now, 203 * these events aren't traced. 204 */ 205 Packet::free(p); 206 return; 207 } 208 209 node->recv(p,h); 210 } 211 212 ///////////////////////////////////////////////////////////////////////////////////////////////////// 213 214 void Classifier::install(int slot, NsObject* p) 215 { 216 if (slot >= nslot_) 217 alloc(slot); 218 slot_[slot] = p; 219 if (slot >= maxslot_) 220 maxslot_ = slot; 221 } 222 223 //above is original source code 224 ===============================================================================================================
updated 15.1.8
1 void Classifier::recv(Packet* p, Handler*h)//original 2 { 3 NsObject* node = find(p); 4 if (node == NULL) { 5 /* 6 * XXX this should be "dropped" somehow. Right now, 7 * these events aren't traced. 8 */ 9 Packet::free(p); 10 return; 11 } 12 13 node->recv(p,h); 14 } 15 16 =============================================================================================================== 17 18 int chooseECNSlot() 19 //这个函数还是改成专门筛选流的函数(筛选出需要窗口减半的流) 20 {//在打ecn的地方引入调用这个函数,通过该函数来打ECN?或者通过该函数有针对性的回调打ecn的函数。 21 //该函数需要能访问到umap以及各流的window大小。 22 23 //sort(window)其实不用。用下面的方法只需遍历一次,O(N)复杂度即可。如果sort要O(NlogN)。 24 int maxProgress=0;//初始化最大进度值maxProgress 25 int mark=-1;//用来标记选中的流s 26 for(i=1;i<=n;i++)//其实遍历slot就行! 27 { 28 if(window>2*N)//在window大于2N的流里面找进度最大的。(如何获取该流的window?) 29 { 30 if(该流的进度值(umap.second)>maxProgress) 31 { 32 maxProgress=该进度值(umap.second);//更新maxProgress 33 mark=i;//标记下该流的node; 34 } 35 } 36 else 37 {//如果没有window>2N的流,就选当前进度最大的流。 38 39 } 40 } 41 if(mark!=-1) 42 return mark; 43 else//没有window>2N的流 44 return mark2; 45 46 } 47 48 49 50 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 15.1.4 rewrite: 52 53 #include "flags.h"//里面有很多需要的变量和函数,如ce() 54 void Classifier::recv(Packet* p, Handler*h) 55 { 56 NsObject* node = find(p);//find调用classify,classify返回dport。 57 if (node == NULL) { 58 Packet::free(p); 59 return; 60 } 61 umap[node]++;//需要在classifier.h中classifier类内部定义unordered_map umap<NsObject*,long long int>。 (但是注意,当umap里有流已传输完毕后要剔除出去,否则影响排序XXXX如果不用mark2的话那就不会影响到,因为首先是按window来看的,只有window足够大才会看进度。已经传输完成的流window应该变为0吧(如果没变要记得调整))。 62 63 hdr_flags *hf=hdr_flags::access(pickPacketForECN(p)); 64 if(hf->ce()==1)// 说明switch中发生了拥塞 65 { 66 hf->ce()=0;//首先清零。然后再根据算法分配ce。 67 int mark=function(筛选出需要窗口减半的流的slot下标);//该函数参照上面的chooseECNSlot 68 } 69 70 if (mark != -1 &&当前packet的dport==slot[mark])//对每一个到来的packet都检查,直到发现是mark所标记的那个。可通过portclassifier里的classify返回dport。(参照slideshare P15,为什么通过classifier类,调用的却是portclassifier里的classify ?) 71 { 72 hf->ce()=1; 73 mark = -1;//使mark失效。 74 } 75 node->recv(p,h); 76 }
http://www.slideshare.net/TBear76/20100403-classifiers