00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <agent.h>
00040 #include <random.h>
00041 #include <trace.h>
00042
00043 #include <ll.h>
00044 #include <priqueue.h>
00045 #include <tora/tora_packet.h>
00046 #include <tora/tora.h>
00047
00048 #define CURRENT_TIME Scheduler::instance().clock()
00049
00050
00051
00052
00053 TORADest::TORADest(nsaddr_t id, Agent *a) : height(id)
00054 {
00055 index = id;
00056
00057 rt_req = 0;
00058 time_upd = 0.0;
00059
00060 time_rt_req = 0.0;
00061 time_tx_qry = 0.0;
00062
00063 LIST_INIT(&nblist);
00064 num_active = num_down = num_up = 0;
00065
00066 agent = (toraAgent*) a;
00067 }
00068
00069
00070 void
00071 TORADest::dump()
00072 {
00073 TORANeighbor *tn = nb_find_next_hop();
00074
00075 fprintf(stdout, "\tDEST: %d, RT Req: %x, Time UPD: %f\n",
00076 index, rt_req, time_upd);
00077 fprintf(stdout, "\t\ttau: %f, oid: %d, r: %d, delta: %d, id: %d\n",
00078 height.tau, height.oid, height.r, height.delta, height.id);
00079 fprintf(stdout, "\t\tActive: %d, Down: %d, Up: %d, Next Hop: %d\n\n",
00080 num_active, num_down, num_up, tn ? tn->index : -1);
00081
00082 for(tn = nblist.lh_first; tn; tn = tn->link.le_next)
00083 tn->dump();
00084 }
00085
00086
00087
00088
00089 TORANeighbor*
00090 TORADest::nb_add(nsaddr_t id)
00091 {
00092 TORANeighbor *tn = new TORANeighbor(id, agent);
00093 assert(tn);
00094
00095 LIST_INSERT_HEAD(&nblist, tn, link);
00096
00097 num_active += 1;
00098 if(tn->index == index) {
00099 tn->height.Zero();
00100 tn->lnk_stat = LINK_DN;
00101 num_down += 1;
00102 }
00103
00104 return tn;
00105 }
00106
00107
00108 int
00109 TORADest::nb_del(nsaddr_t id)
00110 {
00111 TORANeighbor *tn = nblist.lh_first;
00112
00113 for( ; tn; tn = tn->link.le_next) {
00114 if(tn->index == id) {
00115
00116 num_active -= 1;
00117
00118 if(tn->lnk_stat == LINK_DN)
00119 num_down -=1;
00120 if(tn->lnk_stat == LINK_UP)
00121 num_up -= 1;
00122
00123
00124 LIST_REMOVE(tn, link);
00125 delete tn;
00126
00127
00128
00129
00130
00131 if(num_down == 0) {
00132 if(num_up > 0) {
00133 update_height(CURRENT_TIME,
00134 index,
00135 0,
00136 0,
00137 index);
00138 } else {
00139 update_height(-1,
00140 -1,
00141 -1,
00142 -1,
00143 index);
00144
00145 }
00146
00147 agent->logNbDeletedLastDN(this);
00148
00149 return 1;
00150
00151 }
00152 return 0;
00153 }
00154 }
00155 return 0;
00156 }
00157
00158
00159 TORANeighbor*
00160 TORADest::nb_find(nsaddr_t id)
00161 {
00162 TORANeighbor *tn = nblist.lh_first;
00163 for( ; tn; tn = tn->link.le_next) {
00164 if(tn->index == id)
00165 return tn;
00166 }
00167 return 0;
00168 }
00169
00170
00171 TORANeighbor*
00172 TORADest::nb_find_next_hop()
00173 {
00174 TORANeighbor *tn = nblist.lh_first;
00175 TORANeighbor *tn_min = 0;
00176
00177 for( ; tn; tn = tn->link.le_next) {
00178 if(tn->height.isNull())
00179 continue;
00180
00181 if(tn->lnk_stat != LINK_DN)
00182 continue;
00183
00184 if(tn_min == 0 || tn_min->height.compare(&tn->height) < 0) {
00185 tn_min = tn;
00186 }
00187 }
00188 assert(tn_min == 0 || tn_min->lnk_stat == LINK_DN);
00189 return tn_min;
00190 }
00191
00192
00193
00194
00195
00196
00197 TORANeighbor*
00198 TORADest::nb_find_min_height(int R)
00199 {
00200 TORANeighbor *tn = nblist.lh_first;
00201 TORANeighbor *tn_min = 0;
00202
00203 for( ; tn; tn = tn->link.le_next) {
00204 if(tn->height.r == R) {
00205 if(tn_min == 0 ||
00206 tn_min->height.compare(&tn->height) < 0)
00207 tn_min = tn;
00208 }
00209 }
00210 return tn_min;
00211 }
00212
00213
00214
00215
00216
00217
00218 TORANeighbor*
00219 TORADest::nb_find_min_nonnull_height(Height *h)
00220 {
00221 TORANeighbor *tn = nblist.lh_first;
00222 TORANeighbor *tn_min = 0;
00223
00224 assert(h);
00225
00226 for( ; tn; tn = tn->link.le_next) {
00227 if(tn->height.isNull() == 0 &&
00228 tn->height.tau == h->tau &&
00229 tn->height.oid == h->oid &&
00230 tn->height.r == h->r) {
00231 if(tn_min == 0 ||
00232 tn_min->height.compare(&tn->height) < 0)
00233 tn_min = tn;
00234 }
00235 }
00236 return tn_min;
00237 }
00238
00239
00240
00241
00242
00243
00244 TORANeighbor*
00245 TORADest::nb_find_max_height()
00246 {
00247 TORANeighbor *tn = nblist.lh_first;
00248 TORANeighbor *tn_max = 0;
00249
00250 for( ; tn; tn = tn->link.le_next) {
00251 if(tn->height.isNull() == 0) {
00252 if(tn_max == 0 ||
00253 tn_max->height.compare(&tn->height) > 0)
00254 tn_max = tn;
00255 }
00256 }
00257 return tn_max;
00258 }
00259
00260
00261
00262
00263 int
00264 TORADest::nb_check_same_ref()
00265 {
00266 TORANeighbor *tn = nblist.lh_first;
00267 TORANeighbor *tref = 0;
00268
00269 for( ; tn; tn = tn->link.le_next) {
00270 if(tn->height.isNull() == 0) {
00271 if(tref == 0)
00272 tref = tn;
00273 else if(tref->height.tau != tn->height.tau ||
00274 tref->height.oid != tn->height.oid ||
00275 tref->height.r != tn->height.r)
00276 return 0;
00277 }
00278 }
00279 return 1;
00280 }
00281
00282
00283 void
00284 TORADest::update_height_nb(TORANeighbor *tn, struct hdr_tora_upd *uh)
00285 {
00286 Height h(uh->tu_id);
00287
00288 h.tau = uh->tu_tau;
00289 h.oid = uh->tu_oid;
00290 h.r = uh->tu_r;
00291 h.delta = uh->tu_delta;
00292
00293 tn->height.update(&h);
00294
00295
00296
00297
00298 if(tn->lnk_stat == LINK_DN)
00299 num_down -= 1;
00300 if(tn->lnk_stat == LINK_UP)
00301 num_up -= 1;
00302
00303 tn->update_link_status(&height);
00304
00305
00306
00307
00308 if(tn->lnk_stat == LINK_DN)
00309 num_down += 1;
00310 if(tn->lnk_stat == LINK_UP)
00311 num_up += 1;
00312 }
00313
00314
00315
00316
00317
00318
00319 void
00320 TORADest::update_height(double TAU, nsaddr_t OID, int R, int DELTA, nsaddr_t ID)
00321 {
00322 TORANeighbor *tn = nblist.lh_first;
00323
00324 height.tau = TAU;
00325 height.oid = OID;
00326 height.r = R;
00327 height.delta = DELTA;
00328 height.id = ID;
00329
00330 #ifdef LOGGING
00331 agent->log_dst_state_change(this);
00332 #endif
00333 num_active = num_down = num_up = 0;
00334
00335 for( ; tn; tn = tn->link.le_next) {
00336
00337 tn->update_link_status(&height);
00338
00339 num_active += 1;
00340
00341 if(tn->lnk_stat == LINK_DN)
00342 num_down += 1;
00343 if(tn->lnk_stat == LINK_UP)
00344 num_up += 1;
00345 }
00346 }
00347