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
00040
00041
00042
00043
00044
00045
00046
00047 #ifndef lint
00048 static const char rcsid[] =
00049 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/classifier/classifier-bst.cc,v 1.15 2005/08/25 18:58:01 johnh Exp $";
00050 #endif
00051
00052 #include <assert.h>
00053 #include <stdlib.h>
00054
00055 #include "config.h"
00056 #include "packet.h"
00057 #include "ip.h"
00058 #include "classifier.h"
00059 #include "classifier-mcast.h"
00060 #include "address.h"
00061 #include "trace.h"
00062 #include "ump.h"
00063
00064 struct upstream_info {
00065 int dst;
00066 int node_id;
00067 char* oiflink;
00068 struct upstream_info* next;
00069 };
00070
00071 class MCastBSTClassifier : public MCastClassifier {
00072 public:
00073 MCastBSTClassifier();
00074 ~MCastBSTClassifier();
00075 static const char STARSYM[];
00076 protected:
00077 virtual int classify(Packet * p);
00078 upstream_info *oif2RP_;
00079 int32_t node_id_;
00080
00081 void insert_upstream_info(int dst);
00082 virtual void recv(Packet *p, Handler *h);
00083 void upstream_add(int dst, char *oif2RP, int node_id);
00084 upstream_info* upstream_find(int dst);
00085 };
00086
00087
00088 const char MCastBSTClassifier::STARSYM[]= "x";
00089
00090 static class MCastBSTClassifierClass : public TclClass {
00091 public:
00092 MCastBSTClassifierClass() : TclClass("Classifier/Multicast/BST") {}
00093 TclObject* create(int, const char*const*) {
00094 return (new MCastBSTClassifier());
00095 }
00096 } class_mcast_bidir_classifier;
00097
00098 MCastBSTClassifier::MCastBSTClassifier()
00099 {
00100 oif2RP_ = NULL;
00101 node_id_ = -1;
00102 }
00103
00104 MCastBSTClassifier::~MCastBSTClassifier()
00105 {
00106 clearAll();
00107 }
00108
00109 int MCastBSTClassifier::classify(Packet *pkt)
00110 {
00111 hdr_cmn* h = hdr_cmn::access(pkt);
00112 hdr_ip* ih = hdr_ip::access(pkt);
00113
00114 nsaddr_t src = ih->saddr();
00115 nsaddr_t dst = ih->daddr();
00116
00117 int iface = h->iface();
00118 Tcl& tcl = Tcl::instance();
00119
00120 hashnode* p = lookup(src, dst, iface);
00121
00122 if (p == 0)
00123 p = lookup_star(dst, iface);
00124
00125 if (p == 0) {
00126 if ((p = lookup(src, dst)) == 0)
00127 p = lookup_star(dst);
00128 if (p == 0) {
00129
00130 tcl.evalf("%s new-group %ld %ld %d cache-miss",
00131 name(), src, dst, iface);
00132
00133
00134
00135 int res= atoi(tcl.result());
00136
00137 if (res)
00138 insert_upstream_info(dst);
00139 return (res)? Classifier::TWICE : Classifier::ONCE;
00140 }
00141 if (p->iif == ANY_IFACE.value())
00142 return p->slot;
00143
00144 tcl.evalf("%s new-group %ld %ld %d wrong-iif",
00145 name(), src, dst, iface);
00146
00147 int res= atoi(tcl.result());
00148 return (res)? Classifier::TWICE : Classifier::ONCE;
00149 }
00150 return p->slot;
00151 }
00152
00153
00154 void MCastBSTClassifier::recv(Packet *p, Handler *h)
00155 {
00156 hdr_cmn* h_cmn = hdr_cmn::access(p);
00157 hdr_ip* ih = hdr_ip::access(p);
00158 hdr_ump* ump = hdr_ump::access(p);
00159 nsaddr_t dst = ih->daddr();
00160 Tcl& tcl = Tcl::instance();
00161 upstream_info *u_info;
00162
00163 if (node_id_ == -1) {
00164 tcl.evalf("[%s set node_] id", name());
00165 sscanf(tcl.result(), "%d", &node_id_);
00166 }
00167
00168 nsaddr_t src = ih->saddr();
00169
00170 NsObject *node = find(p);
00171 if (node == NULL) {
00172 Packet::free(p);
00173 return;
00174 }
00175
00176 if ((node_id_ != src) && (ump->isSet) && (ump->umpID_ != node_id_)) {
00177
00178
00179
00180
00181 int rpf_iface;
00182
00183 tcl.evalf("%s check-rpf-link %d %d", name(), node_id_, dst);
00184 sscanf(tcl.result(), "%d", &rpf_iface);
00185 if (rpf_iface != h_cmn->iface()) {
00186
00187
00188
00189 Packet::free(p);
00190 return;
00191
00192
00193
00194
00195
00196
00197
00198
00199 } else
00200 ump->isSet = 0;
00201 }
00202
00203 if (src == node_id_) {
00204 memset(ump, 0, sizeof(hdr_ump));
00205
00206
00207
00208 u_info = upstream_find(dst);
00209 if (!u_info) {
00210 printf("Error: Mcast info does not exist\n");
00211 exit(0);
00212 }
00213 ump->isSet = 1;
00214 ump->umpID_ = node_id_;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (ump->isSet) {
00228 u_info = upstream_find(dst);
00229 if (node_id_ == u_info->node_id)
00230
00231
00232 ump->isSet = 0;
00233 else {
00234 ump->umpID_ = u_info->node_id;
00235 ump->oif = strdup(u_info->oiflink);
00236 }
00237 } else {
00238 int match;
00239
00240 tcl.evalf("%s match-BST-iif %d %d", name(),
00241 h_cmn->iface(), dst);
00242 sscanf(tcl.result(), "%d", (int *)&match);
00243 if (!match) {
00244 Packet::free(p);
00245 return;
00246 }
00247 }
00248
00249 node->recv(p, h);
00250 }
00251
00252 void MCastBSTClassifier::upstream_add(int dst, char *link, int node_id)
00253 {
00254 struct upstream_info *next,
00255 *current;
00256
00257 if (oif2RP_) {
00258 next = oif2RP_;
00259 do {
00260 current = next;
00261 if (current->dst == dst) {
00262 free(current->oiflink);
00263 current->oiflink = strdup(link);
00264 current->node_id = node_id;
00265 return;
00266 }
00267 next = current->next;
00268 } while (next);
00269 next = new(struct upstream_info);
00270 next->dst = dst;
00271 next->oiflink = strdup(link);
00272 next->node_id = node_id;
00273 current->next = next;
00274 } else {
00275 oif2RP_ = new(struct upstream_info);
00276 oif2RP_->dst = dst;
00277 oif2RP_->oiflink = strdup(link);
00278 oif2RP_->node_id = node_id;
00279 oif2RP_->next = NULL;
00280 }
00281 }
00282
00283 upstream_info* MCastBSTClassifier::upstream_find(int dst)
00284 {
00285 upstream_info *index;
00286
00287 index = oif2RP_;
00288 while (index) {
00289 if (index->dst == dst)
00290 return index;
00291 index = index->next;
00292 }
00293 return NULL;
00294 }
00295
00296 void MCastBSTClassifier::insert_upstream_info(int dst)
00297 {
00298 char temp_str[100];
00299 int nodeID;
00300 Tcl& tcl = Tcl::instance();
00301
00302 tcl.evalf("%s info class", name());
00303 sscanf(tcl.result(), "%s", temp_str);
00304 tcl.evalf("%s upstream-link %d", name(), dst);
00305 sscanf(tcl.result(), "%s %d", temp_str, &nodeID);
00306 upstream_add(dst, temp_str, nodeID);
00307 }
00308