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 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/classifier/classifier-mcast.cc,v 1.31 2001/12/20 00:15:33 haldar Exp $";
00038 #endif
00039
00040 #include <stdlib.h>
00041 #include "config.h"
00042 #include "packet.h"
00043 #include "ip.h"
00044 #include "classifier.h"
00045 #include "classifier-mcast.h"
00046
00047 const char MCastClassifier::STARSYM[]= "x";
00048
00049 static class MCastClassifierClass : public TclClass {
00050 public:
00051 MCastClassifierClass() : TclClass("Classifier/Multicast") {}
00052 TclObject* create(int, const char*const*) {
00053 return (new MCastClassifier());
00054 }
00055 } class_mcast_classifier;
00056
00057 MCastClassifier::MCastClassifier()
00058 {
00059 memset(ht_, 0, sizeof(ht_));
00060 memset(ht_star_, 0, sizeof(ht_star_));
00061 }
00062
00063 MCastClassifier::~MCastClassifier()
00064 {
00065 clearAll();
00066 }
00067
00068 void MCastClassifier::clearHash(hashnode* h[], int size)
00069 {
00070 for (int i = 0; i < size; ++i) {
00071 hashnode* p = h[i];
00072 while (p != 0) {
00073 hashnode* n = p->next;
00074 delete p;
00075 p = n;
00076 }
00077 }
00078 memset(h, 0, size * sizeof(hashnode*));
00079 }
00080
00081 void MCastClassifier::clearAll()
00082 {
00083 clearHash(ht_, HASHSIZE);
00084 clearHash(ht_star_, HASHSIZE);
00085 }
00086
00087 MCastClassifier::hashnode*
00088 MCastClassifier::lookup(nsaddr_t src, nsaddr_t dst, int iface) const
00089 {
00090 int h = hash(src, dst);
00091 hashnode* p;
00092 for (p = ht_[h]; p != 0; p = p->next) {
00093 if (p->src == src && p->dst == dst)
00094 if (p->iif == iface ||
00095
00096 iface == ANY_IFACE.value())
00097 break;
00098 }
00099 return (p);
00100 }
00101
00102 MCastClassifier::hashnode*
00103 MCastClassifier::lookup_star(nsaddr_t dst, int iface) const
00104 {
00105 int h = hash(0, dst);
00106 hashnode* p;
00107 for (p = ht_star_[h]; p != 0; p = p->next) {
00108 if (p->dst == dst &&
00109 (iface == ANY_IFACE.value() || p->iif == iface))
00110 break;
00111 }
00112 return (p);
00113 }
00114
00115 int MCastClassifier::classify(Packet *pkt)
00116 {
00117 hdr_cmn* h = hdr_cmn::access(pkt);
00118 hdr_ip* ih = hdr_ip::access(pkt);
00119
00120 nsaddr_t src = ih->saddr();
00121 nsaddr_t dst = ih->daddr();
00122
00123 int iface = h->iface();
00124 Tcl& tcl = Tcl::instance();
00125
00126 hashnode* p = lookup(src, dst, iface);
00127
00128 if (p == 0)
00129 p = lookup_star(dst, iface);
00130
00131 if (p == 0) {
00132 if ((p = lookup(src, dst)) == 0)
00133 p = lookup_star(dst);
00134 if (p == 0) {
00135
00136 tcl.evalf("%s new-group %ld %ld %d cache-miss",
00137 name(), src, dst, iface);
00138
00139
00140
00141 int res= atoi(tcl.result());
00142
00143 return (res)? Classifier::TWICE : Classifier::ONCE;
00144 }
00145 if (p->iif == ANY_IFACE.value())
00146 return p->slot;
00147
00148 tcl.evalf("%s new-group %ld %ld %d wrong-iif",
00149 name(), src, dst, iface);
00150
00151 int res= atoi(tcl.result());
00152 return (res)? Classifier::TWICE : Classifier::ONCE;
00153 }
00154 return p->slot;
00155 }
00156
00157 int MCastClassifier::findslot()
00158 {
00159 int i;
00160 for (i = 0; i < nslot_; ++i)
00161 if (slot_[i] == 0)
00162 break;
00163 return (i);
00164 }
00165
00166 void MCastClassifier::set_hash(hashnode* ht[], nsaddr_t src, nsaddr_t dst,
00167 int slot, int iface)
00168 {
00169 int h = hash(src, dst);
00170 hashnode* p = new hashnode;
00171 p->src = src;
00172 p->dst = dst;
00173 p->slot = slot;
00174 p->iif = iface;
00175 p->next = ht[h];
00176 ht[h] = p;
00177 }
00178
00179 int MCastClassifier::command(int argc, const char*const* argv)
00180 {
00181 if (argc == 6) {
00182 if (strcmp(argv[1], "set-hash") == 0) {
00183
00184
00185
00186
00187
00188 nsaddr_t src = strtol(argv[2], (char**)0, 0);
00189 nsaddr_t dst = strtol(argv[3], (char**)0, 0);
00190 int slot = atoi(argv[4]);
00191 int iface = (strcmp(argv[5], ANY_IFACE.name())==0) ? ANY_IFACE.value()
00192 : (strcmp(argv[5], UNKN_IFACE.name())==0) ? UNKN_IFACE.value()
00193 : atoi(argv[5]);
00194 if (strcmp(STARSYM, argv[2]) == 0) {
00195
00196 set_hash(ht_star_, 0, dst, slot, iface);
00197 } else {
00198
00199 set_hash(ht_, src, dst, slot, iface);
00200 }
00201 return (TCL_OK);
00202 }
00203 if (strcmp(argv[1], "change-iface") == 0) {
00204
00205 nsaddr_t src = strtol(argv[2], (char**)0, 0);
00206 nsaddr_t dst = strtol(argv[3], (char**)0, 0);
00207 int oldiface = atoi(argv[4]);
00208 int newiface = atoi(argv[5]);
00209 if (strcmp(STARSYM, argv[2]) == 0) {
00210 change_iface(dst, oldiface, newiface);
00211 } else {
00212 change_iface(src, dst, oldiface, newiface);
00213 }
00214 return (TCL_OK);
00215 }
00216 } else if (argc == 5) {
00217 if (strcmp(argv[1], "lookup") == 0) {
00218
00219
00220 Tcl &tcl = Tcl::instance();
00221 nsaddr_t src = strtol(argv[2], (char**)0, 0);
00222 nsaddr_t dst = strtol(argv[3], (char**)0, 0);
00223 int iface = atoi(argv[4]);
00224
00225 hashnode* p= (strcmp(STARSYM, argv[2]) == 0) ? lookup_star(dst, iface)
00226 : lookup(src, dst, iface);
00227 if ((p == 0) || (slot_[p->slot] == 0))
00228 tcl.resultf("");
00229 else
00230 tcl.resultf("%s", slot_[p->slot]->name());
00231 return (TCL_OK);
00232 }
00233 } else if (argc == 4) {
00234 if (strcmp(argv[1], "lookup-iface") == 0) {
00235
00236
00237 Tcl &tcl = Tcl::instance();
00238 nsaddr_t src = strtol(argv[2], (char**)0, 0);
00239 nsaddr_t dst = strtol(argv[3], (char**)0, 0);
00240 hashnode* p= (strcmp(argv[2], STARSYM) == 0) ? lookup_star(dst)
00241 : lookup(src, dst);
00242 if (p == 0)
00243 tcl.resultf("");
00244 else
00245 tcl.resultf("%d", p->iif);
00246 return (TCL_OK);
00247 }
00248 } else if (argc == 2) {
00249 if (strcmp(argv[1], "clearAll") == 0) {
00250 clearAll();
00251 return (TCL_OK);
00252 }
00253 }
00254 return (Classifier::command(argc, argv));
00255 }
00256
00257
00258
00259 void MCastClassifier::change_iface(nsaddr_t src, nsaddr_t dst, int oldiface, int newiface)
00260 {
00261
00262 hashnode* p = lookup(src, dst, oldiface);
00263 if (p) p->iif = newiface;
00264 }
00265
00266 void MCastClassifier::change_iface(nsaddr_t dst, int oldiface, int newiface)
00267 {
00268 hashnode* p = lookup_star(dst, oldiface);
00269 if (p) p->iif = newiface;
00270 }
00271