ns2.35-classifier.cc
line143:recv()
1 /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ 2 /* 3 * Copyright (c) 1996 Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the MASH Research 17 * Group at the University of California Berkeley. 18 * 4. Neither the name of the University nor of the Research Group may be 19 * used to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef lint 36 static const char rcsid[] = 37 "@(#) $Header: /cvsroot/nsnam/ns-2/classifier/classifier.cc,v 1.44 2010/03/08 05:54:49 tom_henderson Exp $"; 38 #endif 39 40 #include <stdlib.h> 41 #include "config.h" 42 #include "classifier.h" 43 #include "packet.h" 44 #include "link/cell_header.h" 45 46 static class ClassifierClass : public TclClass { 47 public: 48 ClassifierClass() : TclClass("Classifier") {} 49 TclObject* create(int, const char*const*) { 50 return (new Classifier()); 51 } 52 } class_classifier; 53 54 55 Classifier::Classifier() : 56 slot_(0), nslot_(0), maxslot_(-1), shift_(0), mask_(0xffffffff), nsize_(0) 57 { 58 default_target_ = 0; 59 60 bind("offset_", &offset_); 61 bind("shift_", &shift_); 62 bind("mask_", &mask_); 63 } 64 65 int Classifier::classify(Packet *p) 66 { 67 return (mshift(*((int*) p->access(offset_)))); 68 } 69 70 Classifier::~Classifier() 71 { 72 delete [] slot_; 73 } 74 75 void Classifier::set_table_size(int nn) 76 { 77 nsize_ = nn; 78 } 79 80 void Classifier::alloc(int slot) 81 { 82 NsObject** old = slot_; 83 int n = nslot_; 84 if (old == 0) 85 { 86 if (nsize_ != 0) { 87 //printf("classifier %x set to %d....%dth visit\n", this, nsize_, i++); 88 nslot_ = nsize_; 89 } 90 else { 91 //printf("classifier %x set to 32....%dth visit\n", this, j++); 92 nslot_ = 32; 93 } 94 } 95 while (nslot_ <= slot) 96 nslot_ <<= 1; 97 slot_ = new NsObject*[nslot_]; 98 memset(slot_, 0, nslot_ * sizeof(NsObject*)); 99 for (int i = 0; i < n; ++i) 100 slot_[i] = old[i]; 101 delete [] old; 102 } 103 104 105 void Classifier::install(int slot, NsObject* p) 106 { 107 if (slot >= nslot_) 108 alloc(slot); 109 slot_[slot] = p; 110 if (slot >= maxslot_) 111 maxslot_ = slot; 112 } 113 114 void Classifier::clear(int slot) 115 { 116 slot_[slot] = 0; 117 if (slot == maxslot_) { 118 while (--maxslot_ >= 0 && slot_[maxslot_] == 0) 119 ; 120 } 121 } 122 123 int Classifier::allocPort (NsObject *nullagent) 124 { 125 return getnxt (nullagent); 126 } 127 128 int Classifier::getnxt(NsObject *nullagent) 129 { 130 int i; 131 for (i=0; i < nslot_; i++) 132 if (slot_[i]==0 || slot_[i]==nullagent) 133 return i; 134 i=nslot_; 135 alloc(nslot_); 136 return i; 137 } 138 139 /* 140 * objects only ever see "packet" events, which come either 141 * from an incoming link or a local agent (i.e., packet source). 142 */ 143 void Classifier::recv(Packet* p, Handler*h) 144 { 145 NsObject* node = find(p); 146 if (node == NULL) { 147 /* 148 * XXX this should be "dropped" somehow. Right now, 149 * these events aren't traced. 150 */ 151 Packet::free(p); 152 return; 153 } 154 node->recv(p,h); 155 } 156 157 /* 158 * perform the mapping from packet to object 159 * perform upcall if no mapping 160 */ 161 162 NsObject* Classifier::find(Packet* p) 163 { 164 NsObject* node = NULL; 165 int cl = classify(p); 166 if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0) { 167 if (default_target_) 168 return default_target_; 169 /* 170 * Sigh. Can't pass the pkt out to tcl because it's 171 * not an object. 172 */ 173 Tcl::instance().evalf("%s no-slot %ld", name(), cl); 174 if (cl == TWICE) { 175 /* 176 * Try again. Maybe callback patched up the table. 177 */ 178 cl = classify(p); 179 if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0) 180 return (NULL); 181 } 182 } 183 return (node); 184 } 185 186 int Classifier::install_next(NsObject *node) { 187 int slot = maxslot_ + 1; 188 install(slot, node); 189 return (slot); 190 } 191 192 int Classifier::command(int argc, const char*const* argv) 193 { 194 Tcl& tcl = Tcl::instance(); 195 if(argc == 2) { 196 if (strcmp(argv[1], "defaulttarget") == 0) { 197 if (default_target_ != 0) 198 tcl.result(default_target_->name()); 199 return (TCL_OK); 200 } 201 } else if (argc == 3) { 202 /* 203 * $classifier alloc-port nullagent 204 */ 205 if (strcmp(argv[1],"alloc-port") == 0) { 206 int slot; 207 NsObject* nullagent = 208 (NsObject*)TclObject::lookup(argv[2]); 209 slot = getnxt(nullagent); 210 tcl.resultf("%u",slot); 211 return(TCL_OK); 212 } 213 /* 214 * $classifier clear $slot 215 */ 216 if (strcmp(argv[1], "clear") == 0) { 217 int slot = atoi(argv[2]); 218 clear(slot); 219 return (TCL_OK); 220 } 221 /* 222 * $classifier installNext $node 223 */ 224 if (strcmp(argv[1], "installNext") == 0) { 225 //int slot = maxslot_ + 1; 226 NsObject* node = (NsObject*)TclObject::lookup(argv[2]); 227 if (node == NULL) { 228 tcl.resultf("Classifier::installNext attempt " 229 "to install non-object %s into classifier", argv[2]); 230 return TCL_ERROR; 231 }; 232 int slot = install_next(node); 233 tcl.resultf("%u", slot); 234 return TCL_OK; 235 } 236 /* 237 * $classifier slot snum 238 * returns the name of the object in slot # snum 239 */ 240 if (strcmp(argv[1], "slot") == 0) { 241 int slot = atoi(argv[2]); 242 if (slot >= 0 && slot < nslot_ && slot_[slot] != NULL) { 243 tcl.resultf("%s", slot_[slot]->name()); 244 return TCL_OK; 245 } 246 tcl.resultf("Classifier: no object at slot %d", slot); 247 return (TCL_ERROR); 248 } 249 /* 250 * $classifier findslot $node 251 * finds the slot containing $node 252 */ 253 if (strcmp(argv[1], "findslot") == 0) { 254 int slot = 0; 255 NsObject* node = (NsObject*)TclObject::lookup(argv[2]); 256 if (node == NULL) { 257 return (TCL_ERROR); 258 } 259 while (slot < nslot_) { 260 // check if the slot is empty (xuanc, 1/14/02) 261 // fix contributed by Frank A. Zdarsky 262 // <frank.zdarsky@kom.tu-darmstadt.de> 263 if (slot_[slot] && 264 strcmp(slot_[slot]->name(), argv[2]) == 0){ 265 tcl.resultf("%u", slot); 266 return (TCL_OK); 267 } 268 slot++; 269 } 270 tcl.result("-1"); 271 return (TCL_OK); 272 } 273 if (strcmp(argv[1], "defaulttarget") == 0) { 274 default_target_=(NsObject*)TclObject::lookup(argv[2]); 275 if (default_target_ == 0) 276 return TCL_ERROR; 277 return TCL_OK; 278 } 279 } else if (argc == 4) { 280 /* 281 * $classifier install $slot $node 282 */ 283 if (strcmp(argv[1], "install") == 0) { 284 int slot = atoi(argv[2]); 285 NsObject* node = (NsObject*)TclObject::lookup(argv[3]); 286 install(slot, node); 287 return (TCL_OK); 288 } 289 } 290 return (NsObject::command(argc, argv)); 291 } 292 293 void Classifier::set_table_size(int, int) 294 {}