classifier-bst.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * Copyright (C) 1999 by the University of Southern California
00005  * $Id: classifier-bst.cc,v 1.15 2005/08/25 18:58:01 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 #ifndef lint
00048 static const char rcsid[] =
00049     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/classifier/classifier-bst.cc,v 1.15 2005/08/25 18:58:01 johnh Exp $";
00050 #endif
00051 
00052 #include <assert.h>
00053 #include <stdlib.h>
00054 
00055 #include "config.h"
00056 #include "packet.h"
00057 #include "ip.h"
00058 #include "classifier.h"
00059 #include "classifier-mcast.h"
00060 #include "address.h"
00061 #include "trace.h"
00062 #include "ump.h"
00063 
00064 struct upstream_info {
00065     int dst;
00066     int node_id;
00067     char* oiflink;
00068     struct upstream_info* next;
00069 };
00070 
00071 class MCastBSTClassifier : public MCastClassifier {
00072 public:
00073     MCastBSTClassifier();
00074     ~MCastBSTClassifier();
00075     static const char STARSYM[]; //"source" field for shared trees
00076 protected:
00077     virtual int classify(Packet * p);
00078     upstream_info *oif2RP_;
00079     int32_t node_id_;
00080 
00081     void insert_upstream_info(int dst);
00082     virtual void recv(Packet *p, Handler *h);
00083     void upstream_add(int dst, char *oif2RP, int node_id);
00084     upstream_info* upstream_find(int dst);
00085 };
00086 
00087 
00088 const char MCastBSTClassifier::STARSYM[]= "x"; //"source" field for shared trees
00089 
00090 static class MCastBSTClassifierClass : public TclClass {
00091 public:
00092     MCastBSTClassifierClass() : TclClass("Classifier/Multicast/BST") {}
00093     TclObject* create(int, const char*const*) {
00094         return (new MCastBSTClassifier());
00095     }
00096 } class_mcast_bidir_classifier;
00097 
00098 MCastBSTClassifier::MCastBSTClassifier()
00099 {
00100     oif2RP_ = NULL;
00101     node_id_ = -1;
00102 }
00103 
00104 MCastBSTClassifier::~MCastBSTClassifier()
00105 {
00106     clearAll();
00107 }
00108 
00109 int MCastBSTClassifier::classify(Packet *pkt)
00110 {
00111     hdr_cmn* h = hdr_cmn::access(pkt);
00112     hdr_ip* ih = hdr_ip::access(pkt);
00113 
00114     nsaddr_t src = ih->saddr(); /*XXX*/
00115     nsaddr_t dst = ih->daddr();
00116 
00117     int iface = h->iface();
00118     Tcl& tcl = Tcl::instance();
00119 
00120     hashnode* p = lookup(src, dst, iface);
00121     //printf("%s, src %d, dst %d, iface %d, p %d\n", name(), src, dst, iface, p);
00122     if (p == 0)
00123             p = lookup_star(dst, iface);
00124         
00125     if (p == 0) {
00126         if ((p = lookup(src, dst)) == 0)
00127             p = lookup_star(dst);
00128         if (p == 0) {
00129             // Didn't find an entry.
00130             tcl.evalf("%s new-group %ld %ld %d cache-miss", 
00131                   name(), src, dst, iface);
00132             // XXX see McastProto.tcl for the return values 0 -
00133             // once, 1 - twice 
00134             //printf("cache-miss result= %s\n", tcl.result());
00135             int res= atoi(tcl.result());
00136 
00137             if (res)
00138                 insert_upstream_info(dst);
00139             return (res)? Classifier::TWICE : Classifier::ONCE;
00140         }
00141         if (p->iif == ANY_IFACE.value()) // || iface == UNKN_IFACE.value())
00142             return p->slot;
00143 
00144         tcl.evalf("%s new-group %ld %ld %d wrong-iif", 
00145               name(), src, dst, iface);
00146         //printf("wrong-iif result= %s\n", tcl.result());
00147         int res= atoi(tcl.result());
00148         return (res)? Classifier::TWICE : Classifier::ONCE;
00149     }
00150     return p->slot;
00151 }
00152 
00153 
00154 void MCastBSTClassifier::recv(Packet *p, Handler *h) 
00155 {
00156     hdr_cmn* h_cmn = hdr_cmn::access(p);
00157     hdr_ip* ih = hdr_ip::access(p);
00158     hdr_ump* ump = hdr_ump::access(p);
00159     nsaddr_t dst = ih->daddr();
00160     Tcl& tcl = Tcl::instance();
00161     upstream_info *u_info;
00162 
00163     if (node_id_ == -1) {
00164         tcl.evalf("[%s set node_] id", name());
00165         sscanf(tcl.result(), "%d", &node_id_);
00166     } // if
00167 
00168     nsaddr_t src = ih->saddr(); /*XXX*/
00169 
00170     NsObject *node = find(p);
00171     if (node == NULL) {
00172         Packet::free(p);
00173         return;
00174     } // if
00175 
00176     if ((node_id_ != src) && (ump->isSet) && (ump->umpID_ != node_id_)) {
00177         // If this node is not the next hop upstream router,
00178         // and if there are no receivers connected to it, then 
00179         // we should immediately drop the packet before we
00180         // trigger a chace miss
00181         int rpf_iface;
00182 
00183         tcl.evalf("%s check-rpf-link %d %d", name(), node_id_, dst);
00184         sscanf(tcl.result(), "%d", &rpf_iface);
00185         if (rpf_iface != h_cmn->iface()) {
00186             // The RPF check has failed so we have to drop
00187             // the packet.  Otherwise, we will create
00188             // duplicate packets on the net.
00189             Packet::free(p);
00190             return;
00191 
00192             // The following code demonstrates how we
00193             // could generate duplicates if RPF check is
00194             // ignord.  Do not reset the UMP and then we
00195             // will have even more duplicates.  Remember
00196             // to comment out the previous two lines
00197 
00198 //              ih->flowid()++;
00199         } else 
00200             ump->isSet = 0;
00201     } // if
00202 
00203     if (src == node_id_) {
00204         memset(ump, 0, sizeof(hdr_ump)); // Initialize UMP to 0
00205         // We need to set the UMP option.  We need to find the
00206         // next hop router to the source and place it in the
00207         // UMP option.
00208         u_info = upstream_find(dst);
00209         if (!u_info) {
00210             printf("Error: Mcast info does not exist\n");
00211             exit(0);
00212         } // if
00213         ump->isSet = 1;
00214         ump->umpID_ = node_id_;
00215     } // if
00216 
00217 //  if (ump->isSet) {
00218 //      if (ump->umpID_ != node_id_) {
00219 //          // By now we are sure that the packet has
00220 //          // arrived on an RPF link.  So the UMP portion 
00221 //          // of the packet should be cleared before it
00222 //          // is sent downstream
00223 //          ump->isSet = 0;
00224 //      } // if
00225 //  } // if
00226 
00227     if (ump->isSet) {
00228         u_info = upstream_find(dst);
00229         if (node_id_ == u_info->node_id)
00230             // If the next hop is the node itself, then we
00231             // are at the RP.
00232             ump->isSet = 0;
00233         else {
00234             ump->umpID_ = u_info->node_id;
00235             ump->oif = strdup(u_info->oiflink);
00236         } // else
00237     } else {
00238         int match;
00239         
00240         tcl.evalf("%s match-BST-iif %d %d", name(),
00241               h_cmn->iface(), dst);  
00242         sscanf(tcl.result(), "%d", (int *)&match);
00243         if (!match) {
00244             Packet::free(p);
00245             return;
00246         } // else
00247     } // else
00248 
00249     node->recv(p, h);
00250 } // MCastBSTClassifier::recv
00251 
00252 void MCastBSTClassifier::upstream_add(int dst, char *link, int node_id)
00253 {
00254     struct upstream_info *next,
00255         *current;
00256 
00257     if (oif2RP_) {
00258         next = oif2RP_;
00259         do {
00260             current = next;
00261             if (current->dst == dst) {
00262                 free(current->oiflink);
00263                 current->oiflink = strdup(link);
00264                 current->node_id = node_id;
00265                 return;
00266             } // if
00267             next = current->next;
00268         } while (next);
00269         next = new(struct upstream_info);
00270         next->dst = dst;
00271         next->oiflink = strdup(link);
00272         next->node_id = node_id;
00273         current->next = next;
00274     } else {
00275         oif2RP_ = new(struct upstream_info);
00276         oif2RP_->dst = dst;
00277         oif2RP_->oiflink = strdup(link);
00278         oif2RP_->node_id = node_id;
00279         oif2RP_->next = NULL;
00280     } // else
00281 } // MCastBSTClassifier::upstream_add
00282 
00283 upstream_info* MCastBSTClassifier::upstream_find(int dst)
00284 {
00285     upstream_info *index;
00286 
00287     index = oif2RP_;
00288     while (index) {
00289         if (index->dst == dst)
00290             return index;
00291         index = index->next;
00292     } // while
00293     return NULL;
00294 } // MCastBSTClassifier::upstream_find
00295 
00296 void MCastBSTClassifier::insert_upstream_info(int dst) 
00297 {
00298     char temp_str[100];
00299     int nodeID;
00300     Tcl& tcl = Tcl::instance();
00301 
00302     tcl.evalf("%s info class", name());
00303     sscanf(tcl.result(), "%s", temp_str);
00304     tcl.evalf("%s upstream-link %d", name(), dst);
00305     sscanf(tcl.result(), "%s %d", temp_str, &nodeID);
00306     upstream_add(dst, temp_str, nodeID);
00307 } // MCastBSTClassifier::insert_upstream_info
00308 

Generated on Tue Mar 6 16:47:43 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6