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

classifier-mcast.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-1997 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-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"; //"source" field for shared trees
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                             //p->iif == UNKN_IFACE.value() ||
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         //printf("%s, src %d, dst %d, iface %d, p %d\n", name(), src, dst, iface, p);
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                         // Didn't find an entry.
00136                         tcl.evalf("%s new-group %ld %ld %d cache-miss", 
00137                                   name(), src, dst, iface);
00138                         // XXX see McastProto.tcl for the return values 0 -
00139                         // once, 1 - twice 
00140                         //printf("cache-miss result= %s\n", tcl.result());
00141                         int res= atoi(tcl.result());
00142 
00143                         return (res)? Classifier::TWICE : Classifier::ONCE;
00144                 }
00145                 if (p->iif == ANY_IFACE.value()) // || iface == UNKN_IFACE.value())
00146                         return p->slot;
00147 
00148                 tcl.evalf("%s new-group %ld %ld %d wrong-iif", 
00149                           name(), src, dst, iface);
00150                 //printf("wrong-iif result= %s\n", tcl.result());
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                         // $classifier set-hash $src $group $slot $iif
00184                         //      $iif can be:(1) <number>
00185                         //                  (2) "*" - matches any interface
00186                         //                  (3) "?" - interface is unknown (usually this means that
00187                         //                             the packet came from a local agent)
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                             // install a <x,G> entry: give 0 as src, but can be anything
00196                             set_hash(ht_star_, 0, dst, slot, iface);
00197                         } else {
00198                             //install a <S,G> entry
00199                             set_hash(ht_, src, dst, slot, iface);
00200                         }
00201                         return (TCL_OK);
00202                 }
00203                 if (strcmp(argv[1], "change-iface") == 0) {
00204                         // $classifier change-iface $src $dst $olfiif $newiif
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                         // $classifier lookup $src $group $iface
00219                         // returns name of the object (replicator)
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                         // $classifier lookup-iface $src $group 
00236                         // returns incoming iface
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 /* interface look up for the interface code*/
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 

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