Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

classifier.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1996 Regents of the University of California.
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the MASH Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Research Group may be
00019  *    used to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  * 
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 #ifndef lint
00036 static const char rcsid[] =
00037     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/classifier/classifier.cc,v 1.41 2002/03/21 01:46:02 johnh Exp $";
00038 #endif
00039 
00040 #include <stdlib.h>
00041 #include "config.h"
00042 #include "classifier.h"
00043 #include "packet.h"
00044 
00045 static class ClassifierClass : public TclClass {
00046 public:
00047         ClassifierClass() : TclClass("Classifier") {}
00048         TclObject* create(int, const char*const*) {
00049                 return (new Classifier());
00050         }
00051 } class_classifier;
00052 
00053 
00054 Classifier::Classifier() : 
00055         slot_(0), nslot_(0), maxslot_(-1), shift_(0), mask_(0xffffffff), nsize_(0)
00056 {
00057         default_target_ = 0;
00058 
00059         bind("offset_", &offset_);
00060         bind("shift_", &shift_);
00061         bind("mask_", &mask_);
00062 }
00063 
00064 int Classifier::classify(Packet *p)
00065 {
00066         return (mshift(*((int*) p->access(offset_))));
00067 }
00068 
00069 Classifier::~Classifier()
00070 {
00071         delete [] slot_;
00072 }
00073 
00074 void Classifier::set_table_size(int nn)
00075 {
00076         nsize_ = nn;
00077 }
00078 
00079 void Classifier::alloc(int slot)
00080 {
00081         NsObject** old = slot_;
00082         int n = nslot_;
00083         if (old == 0) 
00084                 if (nsize_ != 0) {
00085                         //printf("classifier %x set to %d....%dth visit\n", this, nsize_, i++);
00086                         nslot_ = nsize_;
00087                 }
00088                 else {
00089                         //printf("classifier %x set to 32....%dth visit\n", this, j++);
00090                         nslot_ = 32;
00091                 }
00092         while (nslot_ <= slot) 
00093                 nslot_ <<= 1;
00094         slot_ = new NsObject*[nslot_];
00095         memset(slot_, 0, nslot_ * sizeof(NsObject*));
00096         for (int i = 0; i < n; ++i)
00097                 slot_[i] = old[i];
00098         delete [] old;
00099 }
00100 
00101 
00102 void Classifier::install(int slot, NsObject* p)
00103 {
00104         if (slot >= nslot_)
00105                 alloc(slot);
00106         slot_[slot] = p;
00107         if (slot >= maxslot_)
00108                 maxslot_ = slot;
00109 }
00110 
00111 void Classifier::clear(int slot)
00112 {
00113         slot_[slot] = 0;
00114         if (slot == maxslot_) {
00115                 while (--maxslot_ >= 0 && slot_[maxslot_] == 0)
00116                         ;
00117         }
00118 }
00119 
00120 int Classifier::getnxt(NsObject *nullagent)
00121 {
00122         int i;
00123         for (i=0; i < nslot_; i++)
00124                 if (slot_[i]==0 || slot_[i]==nullagent)
00125                         return i;
00126         i=nslot_;
00127         alloc(nslot_);
00128         return i;
00129 }
00130 
00131 /*
00132  * objects only ever see "packet" events, which come either
00133  * from an incoming link or a local agent (i.e., packet source).
00134  */
00135 void Classifier::recv(Packet* p, Handler*h)
00136 {
00137         NsObject* node = find(p);
00138         if (node == NULL) {
00139                 /*
00140                  * XXX this should be "dropped" somehow.  Right now,
00141                  * these events aren't traced.
00142                  */
00143                 Packet::free(p);
00144                 return;
00145         }
00146         node->recv(p,h);
00147 }
00148 
00149 /*
00150  * perform the mapping from packet to object
00151  * perform upcall if no mapping
00152  */
00153 
00154 NsObject* Classifier::find(Packet* p)
00155 {
00156         NsObject* node = NULL;
00157         int cl = classify(p);
00158         if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0) { 
00159                 if (default_target_) 
00160                         return default_target_;
00161                 /*
00162                  * Sigh.  Can't pass the pkt out to tcl because it's
00163                  * not an object.
00164                  */
00165                 Tcl::instance().evalf("%s no-slot %ld", name(), cl);
00166                 if (cl == TWICE) {
00167                         /*
00168                          * Try again.  Maybe callback patched up the table.
00169                          */
00170                         cl = classify(p);
00171                         if (cl < 0 || cl >= nslot_ || (node = slot_[cl]) == 0)
00172                                 return (NULL);
00173                 }
00174         }
00175         return (node);
00176 }
00177 
00178 int Classifier::install_next(NsObject *node) {
00179         int slot = maxslot_ + 1;
00180         install(slot, node);
00181         return (slot);
00182 }
00183 
00184 int Classifier::command(int argc, const char*const* argv)
00185 {
00186         Tcl& tcl = Tcl::instance();
00187         if(argc == 2) {
00188                 if (strcmp(argv[1], "defaulttarget") == 0) {
00189                         if (default_target_ != 0)
00190                                 tcl.result(default_target_->name());
00191                         return (TCL_OK);
00192                 }
00193         } else if (argc == 3) {
00194                 /*
00195                  * $classifier alloc-port nullagent
00196                  */
00197                 if (strcmp(argv[1],"alloc-port") == 0) {
00198                         int slot;
00199                         NsObject* nullagent =
00200                                 (NsObject*)TclObject::lookup(argv[2]);
00201                         slot = getnxt(nullagent);
00202                         tcl.resultf("%u",slot);
00203                         return(TCL_OK);
00204                 }
00205                 /*
00206                  * $classifier clear $slot
00207                  */
00208                 if (strcmp(argv[1], "clear") == 0) {
00209                         int slot = atoi(argv[2]);
00210                         clear(slot);
00211                         return (TCL_OK);
00212                 }
00213                 /*
00214                  * $classifier installNext $node
00215                  */
00216                 if (strcmp(argv[1], "installNext") == 0) {
00217                         //int slot = maxslot_ + 1;
00218                         NsObject* node = (NsObject*)TclObject::lookup(argv[2]);
00219                         if (node == NULL) {
00220                                 tcl.resultf("Classifier::installNext attempt "
00221                     "to install non-object %s into classifier", argv[2]);
00222                                 return TCL_ERROR;
00223                         };
00224                         int slot = install_next(node);
00225                         tcl.resultf("%u", slot);
00226                         return TCL_OK;
00227                 }
00228                 /*
00229                  * $classifier slot snum
00230                  * returns the name of the object in slot # snum
00231                  */
00232                 if (strcmp(argv[1], "slot") == 0) {
00233                         int slot = atoi(argv[2]);
00234                         if (slot >= 0 && slot < nslot_ && slot_[slot] != NULL) {
00235                                 tcl.resultf("%s", slot_[slot]->name());
00236                                 return TCL_OK;
00237                         }
00238                         tcl.resultf("Classifier: no object at slot %d", slot);
00239                         return (TCL_ERROR);
00240                 }
00241                 /*
00242                  * $classifier findslot $node
00243                  * finds the slot containing $node
00244                  */
00245                 if (strcmp(argv[1], "findslot") == 0) {
00246                         int slot = 0;
00247                         NsObject* node = (NsObject*)TclObject::lookup(argv[2]);
00248                         if (node == NULL) {
00249                                 return (TCL_ERROR);
00250                         }
00251                         while (slot < nslot_) {
00252                                 // check if the slot is empty (xuanc, 1/14/02) 
00253                                 // fix contributed by Frank A. Zdarsky 
00254                                 // <frank.zdarsky@kom.tu-darmstadt.de>
00255                                 if (slot_[slot] && 
00256                                     strcmp(slot_[slot]->name(), argv[2]) == 0){
00257                                         tcl.resultf("%u", slot);
00258                                         return (TCL_OK);
00259                                 }
00260                                 slot++;
00261                         }
00262                         tcl.result("-1");
00263                         return (TCL_OK);
00264                 }
00265                 if (strcmp(argv[1], "defaulttarget") == 0) {
00266                         default_target_=(NsObject*)TclObject::lookup(argv[2]);
00267                         if (default_target_ == 0)
00268                                 return TCL_ERROR;
00269                         return TCL_OK;
00270                 }
00271         } else if (argc == 4) {
00272                 /*
00273                  * $classifier install $slot $node
00274                  */
00275                 if (strcmp(argv[1], "install") == 0) {
00276                         int slot = atoi(argv[2]);
00277                         NsObject* node = (NsObject*)TclObject::lookup(argv[3]);
00278                         install(slot, node);
00279                         return (TCL_OK);
00280                 }
00281         }
00282         return (NsObject::command(argc, argv));
00283 }

Generated on Tue Apr 20 12:14:12 2004 for NS2.26SourcesOriginal by doxygen 1.3.3