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.32 2005/09/26 07:38:08 lacage 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 %d %d %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 %d %d %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 Mar 6 16:47:43 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6