classifier-addr-mpls.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  * classifier-addr-mpls.cc
00005  * Copyright (C) 2000 by the University of Southern California
00006  * $Id: classifier-addr-mpls.cc,v 1.7 2005/08/25 18:58:09 johnh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 //
00049 // Original source contributed by Gaeil Ahn. See below.
00050 //
00051 // $Header: /nfs/jade/vint/CVSROOT/ns-2/mpls/classifier-addr-mpls.cc,v 1.7 2005/08/25 18:58:09 johnh Exp $
00052 
00053 // XXX
00054 //
00055 // - Because MPLS header contains pointers, it cannot be used WITH multicast 
00056 //   routing which replicates packets
00057 // - Currently it works only with flat routing.
00058 
00059 /**************************************************************************
00060  * Copyright (c) 2000 by Gaeil Ahn                                        *
00061  * Everyone is permitted to copy and distribute this software.        *
00062  * Please send mail to fog1@ce.cnu.ac.kr when you modify or distribute    *
00063  * this sources.                              *
00064  **************************************************************************/
00065 
00066 /************************************************************
00067  *                                                          *
00068  *    File: File for packet switching in MPLS node          *
00069  *    Author: Gaeil Ahn (fog1@ce.cnu.ac.kr), Dec. 1999      *
00070  *                                                          *
00071  ************************************************************/
00072 
00073 #include "packet.h"
00074 #include "trace.h"
00075 #include "classifier-addr-mpls.h"
00076 
00077 int hdr_mpls::offset_;
00078 
00079 static class shimhdreaderClass : public PacketHeaderClass {
00080 public:
00081     shimhdreaderClass() : PacketHeaderClass("PacketHeader/MPLS", 
00082                         sizeof(hdr_mpls)) {
00083         bind_offset(&hdr_mpls::offset_);
00084     }
00085 } class_shimhdreader;
00086 
00087 static class MPLSAddrClassifierClass : public TclClass {
00088 public:
00089     MPLSAddrClassifierClass() : TclClass("Classifier/Addr/MPLS") {}
00090     virtual TclObject* create(int, const char*const*) {
00091         return (new MPLSAddressClassifier());
00092     }
00093     virtual void bind();
00094     virtual int method(int argc, const char*const* argv);
00095 } class_mpls_addr_classifier;
00096 
00097 void MPLSAddrClassifierClass::bind()
00098 {
00099     TclClass::bind();
00100     add_method("minimum-lspid");
00101     add_method("dont-care");
00102     add_method("ordered-control?");
00103     add_method("on-demand?");
00104     add_method("enable-ordered-control");
00105     add_method("enable-on-demand");
00106 }
00107 
00108 int MPLSAddrClassifierClass::method(int ac, const char*const* av)
00109 {
00110     Tcl& tcl = Tcl::instance();
00111     int argc = ac - 2;
00112     const char*const* argv = av + 2;
00113 
00114     if (argc == 2) {
00115         if (strcmp(argv[1], "minimum-lspid") == 0) {
00116             tcl.resultf("%d", MPLS_MINIMUM_LSPID);
00117             return (TCL_OK);
00118         } else if (strcmp(argv[1], "dont-care") == 0) {
00119             tcl.resultf("%d", MPLS_DONTCARE);
00120             return (TCL_OK);
00121         } if (strcmp(argv[1], "ordered-control?") == 0) {
00122             tcl.resultf("%d", 
00123                     MPLSAddressClassifier::ordered_control_);
00124             return (TCL_OK);
00125         } else if (strcmp(argv[1], "on-demand?") == 0) {
00126             tcl.resultf("%d", MPLSAddressClassifier::on_demand_);
00127             return (TCL_OK);
00128         } else if (strcmp(argv[1], "enable-ordered-control") == 0) {
00129             MPLSAddressClassifier::ordered_control_ = 1;
00130             return (TCL_OK);
00131         } else if (strcmp(argv[1], "enable-on-demand") == 0) {
00132             MPLSAddressClassifier::on_demand_ = 1;
00133             return (TCL_OK);
00134         }
00135     }
00136     return TclClass::method(ac, av);
00137 }
00138 
00139 int MPLSAddressClassifier::on_demand_ = 0;
00140 int MPLSAddressClassifier::ordered_control_ = 0;
00141 
00142 MPLSAddressClassifier::MPLSAddressClassifier() : 
00143     data_driven_(0), control_driven_(0)
00144 {
00145     PFT_.NB_ = 0;
00146     ERB_.NB_ = 0;
00147     LIB_.NB_ = 0;
00148     ttl_ = 32;
00149 }
00150 
00151 void MPLSAddressClassifier::delay_bind_init_all()
00152 {
00153     delay_bind_init_one("ttl_");
00154     delay_bind_init_one("trace_mpls_");   
00155     delay_bind_init_one("label_");
00156     delay_bind_init_one("enable_reroute_");
00157     delay_bind_init_one("reroute_option_");
00158     delay_bind_init_one("data_driven_");
00159     delay_bind_init_one("control_driven_");
00160     AddressClassifier::delay_bind_init_all();
00161 }
00162 
00163 // Arguments: varName, localName, tracer
00164 int MPLSAddressClassifier::delay_bind_dispatch(const char *vn, 
00165                            const char* ln, TclObject *t)
00166 {
00167     if (delay_bind(vn, ln, "ttl_", &ttl_, t))
00168         return TCL_OK;
00169     if (delay_bind(vn, ln, "trace_mpls_", &trace_mpls_, t)) 
00170         return TCL_OK;
00171     if (delay_bind(vn, ln, "label_", &label_, t)) 
00172         return TCL_OK;
00173     if (delay_bind(vn, ln, "enable_reroute_", &enable_reroute_, t))
00174         return TCL_OK;
00175     if (delay_bind(vn, ln, "reroute_option_", &reroute_option_, t))
00176         return TCL_OK;
00177     if (delay_bind(vn, ln, "data_driven_", &data_driven_, t))
00178         return TCL_OK;
00179     if (delay_bind(vn, ln, "control_driven_", &control_driven_, t))
00180         return TCL_OK;
00181     return AddressClassifier::delay_bind_dispatch(vn, ln, t);
00182 }
00183 
00184 int MPLSAddressClassifier::classify(Packet* p)
00185 {
00186     int nexthop = MPLSclassify(p);
00187 
00188     if ((enable_reroute_ == 1) && (size_ > 0) && 
00189         (is_link_down(nexthop)))
00190         // Use alternative path if it exist
00191         nexthop = do_reroute(p);
00192     if (nexthop == MPLS_GOTO_L3)
00193         return AddressClassifier::classify(p);
00194     // XXX Do NOT return -1, which lets the classifier to process this 
00195     // packet twice!!
00196     return (nexthop == -1) ? Classifier::ONCE : nexthop;
00197 }
00198 
00199 int MPLSAddressClassifier::is_link_down(int node)
00200 {
00201     Tcl& tcl = Tcl::instance();   
00202     tcl.evalf("[%s set mpls_mod_] get-link-status %d", name(), node);
00203     return (strcmp(tcl.result(), "down") == 0) ? 1 : 0;
00204 }
00205 
00206 int MPLSAddressClassifier::do_reroute(Packet* p)
00207 {
00208     int oIface, oLabel, LIBptr;
00209     PI_.shimhdr_ = GetShimHeader(p);
00210     int iLabel = PI_.shimhdr_->label_;
00211 
00212     if (aPathLookup(PI_.dst_.addr_, PI_.phb_, oIface, oLabel, LIBptr) == 0)
00213         return convertL2toL2(iLabel, oIface, oLabel, LIBptr);
00214     else {
00215         PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00216         trace("L", size_, iLabel, "Drop(linkFail)", -1, -1, -1);
00217         switch (reroute_option_) {
00218         case MPLS_DROPPACKET:
00219             return -1;
00220         case MPLS_L3FORWARDING:
00221             return MPLS_GOTO_L3;
00222         case MPLS_MAKENEWLSP:
00223             Tcl& tcl = Tcl::instance();   
00224             if (!control_driven_)
00225                 tcl.evalf("%s ldp-trigger-by-switch %d", 
00226                       name(), PI_.dst_.addr_);
00227             return -1;
00228         }
00229         return -1;
00230     }
00231 }
00232 
00233 int MPLSAddressClassifier::convertL3toL2(int oIface, int oLabel, int LIBptr)
00234 {
00235     int iLabel= -1;
00236     int ptr;
00237               
00238     while (oLabel >= 0) {
00239         /* penultimate hop */
00240         if (oLabel == 0)  {
00241             /* no operation */
00242             trace("U",size_, iLabel, "Push(penultimate)", 
00243                   oIface, oLabel, ttl_);
00244         } else {
00245             /* push operation in ingerss LSR */
00246             PI_.shimhdr_ = push(PI_.shimhdr_,oLabel);
00247             trace("U",size_, iLabel, "Push(ingress)", 
00248                   oIface, oLabel, ttl_);
00249         }
00250         if (LIBptr >= 0) {
00251             /* stack operation */
00252             iLabel = oLabel;
00253             ptr = LIBptr;
00254             LIBlookup(ptr, oIface, oLabel, LIBptr);
00255         } else
00256             break;
00257     }
00258 
00259     if (oLabel < 0) {
00260         if (size_ > 0)
00261             PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00262         trace("U",size_, iLabel , "L3(errorLabel)", -1,-1, -1);
00263         return MPLS_GOTO_L3;
00264     }
00265     if (oIface < 0) {  
00266         PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00267         trace("U", size_, iLabel, "L3(errorOIF)", -1 , -1, -1);
00268         return MPLS_GOTO_L3;
00269     } else
00270         // Guaranteed returned oIface is >= 0 or MPLS_GOTO_L3
00271         return oIface;
00272 }
00273 
00274 int MPLSAddressClassifier::convertL2toL2(int iLabel, int oIface, 
00275                      int oLabel, int LIBptr)
00276 {
00277     int  ttl = PI_.shimhdr_->ttl_;
00278     int  ptr;
00279 
00280     // push(stack) operation after swap or pop
00281     if (oLabel == 0) {
00282         // in penultimate hop
00283         PI_.shimhdr_ = pop(PI_.shimhdr_);
00284         trace("L", size_, iLabel, "Pop(penultimate)", 
00285               oIface, oLabel, ttl);
00286     } else if (oLabel > 0) {
00287         // swap operation 
00288         swap(PI_.shimhdr_,oLabel);
00289         trace("L", size_, iLabel, "Swap", oIface, oLabel, ttl);
00290     } else {
00291         // Errored Label
00292         PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00293         trace("L", size_, iLabel, "L3(errorLabel)", -1, -1, -1);
00294         return MPLS_GOTO_L3;
00295     }
00296     while (LIBptr >= 0) {
00297         // stack operation
00298         iLabel= oLabel;
00299         ptr = LIBptr;
00300         LIBlookup(ptr, oIface, oLabel, LIBptr);
00301         PI_.shimhdr_ = push(PI_.shimhdr_,oLabel);
00302         trace("L", size_, iLabel, "Push(tunnel)", 
00303               oIface, oLabel, ttl_);
00304     }   
00305     if (oIface < 0) {  
00306         if (size_ > 0)
00307             PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00308         trace("L",size_, iLabel , "L3(errorOIf)", -1 , -1, -1);
00309         return MPLS_GOTO_L3;
00310     }
00311     // Guaranteed returned oIface >= 0
00312     return oIface;
00313 }
00314 
00315 // Process unlabeled packet
00316 int MPLSAddressClassifier::processIP()
00317 {
00318     int oIface,oLabel,LIBptr;
00319     int iLabel = -1;
00320 
00321     // Insert code to manipulate PHB
00322     if (PFTlookup(PI_.dst_.addr_, PI_.phb_, oIface, oLabel, LIBptr) == 0)
00323         // Push operation
00324         return convertL3toL2(oIface,oLabel,LIBptr);
00325 
00326     // L3 forwarding
00327     // Traffic-driven, triggered by MPLS switch
00328     if (data_driven_) 
00329         Tcl::instance().evalf("%s ldp-trigger-by-switch %d", 
00330                       name(), PI_.dst_.addr_);
00331     trace("U", size_, iLabel, "L3", -1, -1, -1);               
00332     return MPLS_GOTO_L3;
00333 }
00334 
00335 // Process labeled packet
00336 int MPLSAddressClassifier::processLabelP()
00337 {
00338     int oIface,oLabel,LIBptr;
00339     int iLabel = PI_.shimhdr_->label_;
00340 
00341     PI_.shimhdr_ = checkTTL(PI_.shimhdr_);
00342 
00343     if (size_ == 0)
00344         // TTL check
00345         return MPLS_GOTO_L3;
00346 
00347     // Label swapping operation 
00348     if (LIBlookup(-1, iLabel, oIface, oLabel, LIBptr) == 0)
00349         return convertL2toL2(iLabel,oIface,oLabel,LIBptr);
00350 
00351     PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
00352     trace("L",size_, iLabel,"L3(errorLabel)", -1, -1, -1);
00353     return ( MPLS_GOTO_L3 );
00354 }
00355 
00356 int MPLSAddressClassifier::MPLSclassify(Packet* p)
00357 {
00358     GetIPInfo(p, PI_.dst_, PI_.phb_, PI_.srcnode_);
00359     PI_.shimhdr_ = GetShimHeader(p);
00360    
00361     // XXX Using header size to determine if this is a MPLS-labeled packet
00362     // is a very bad method. We should have some explicit flag that labels
00363     // every packet; this flag will only be set on for every MPLS-labeled
00364     // packet. This can be done by a bitmap field in the common header.
00365     if (size_ == 0) 
00366         // Unlabeled packet
00367         return processIP();
00368 
00369     // Labeled packet 
00370     int ret = processLabelP();
00371     if (ret == MPLS_GOTO_L3) {  
00372         PI_.shimhdr_ = GetShimHeader(p);
00373         return processIP();
00374     }
00375     return ret;   
00376 }
00377 
00378 hdr_mpls *MPLSAddressClassifier::checkTTL(hdr_mpls *shimhdr)
00379 {
00380     shimhdr->ttl_--;
00381     int ttl   = shimhdr->ttl_;
00382     int iLabel= shimhdr->label_;
00383    
00384     if (ttl == 0) {
00385         shimhdr = DelAllShimHeader(shimhdr);
00386         trace("L", size_, iLabel, "L3(TTL=0)", -1, -1, ttl);
00387     }
00388     return shimhdr;
00389 }
00390 
00391 void MPLSAddressClassifier::GetIPInfo(Packet* p, ns_addr_t &dst,
00392                       int &phb, int &srcnode)
00393 {
00394     hdr_ip* iphdr = hdr_ip::access(p);
00395     dst = iphdr->dst_;
00396     srcnode = iphdr->src_.addr_;
00397     phb = MPLS_DEFAULT_PHB;
00398 }
00399 
00400 hdr_mpls *MPLSAddressClassifier::GetShimHeader(Packet* p)
00401 {
00402     hdr_mpls *shimhdr = hdr_mpls::access(p);
00403     size_ = 0;
00404     if ((shimhdr->label_ == 0) && (shimhdr->bflag_ == 0) && 
00405         (shimhdr->ttl_ == 0)) {
00406         shimhdr->bflag_ = -1;
00407         shimhdr->label_ = -1;
00408         shimhdr->ttl_ = -1;
00409         shimhdr->top_    = shimhdr;
00410         shimhdr->nexthdr_= shimhdr;
00411     } else {
00412         while (shimhdr->top_ != shimhdr) { 
00413             shimhdr = shimhdr->top_;
00414             size_ += 4;
00415         }
00416     } 
00417     return shimhdr;
00418 }
00419 
00420 hdr_mpls *MPLSAddressClassifier::DelAllShimHeader(hdr_mpls *shimhdr)
00421 {
00422     while (shimhdr->bflag_ != -1)
00423         shimhdr = pop(shimhdr);
00424     return(shimhdr);
00425 }
00426 
00427 hdr_mpls *MPLSAddressClassifier::push(hdr_mpls *shimhdr, int oLabel)
00428 {
00429     hdr_mpls *newhdr;
00430 
00431     newhdr = (hdr_mpls *) malloc( sizeof(hdr_mpls) );
00432     newhdr->label_ = oLabel;
00433     newhdr->bflag_ = 1;
00434     newhdr->ttl_ = ttl_;
00435     newhdr->top_  = newhdr;
00436     newhdr->nexthdr_ = shimhdr;
00437 
00438     shimhdr->top_ = newhdr;
00439     size_ += 4;
00440     
00441     return newhdr;
00442 }
00443 
00444 hdr_mpls *MPLSAddressClassifier::pop(hdr_mpls *shimhdr)
00445 {
00446     shimhdr = shimhdr->nexthdr_;
00447     free(shimhdr->top_);
00448     shimhdr->top_ = shimhdr;
00449     size_ -= 4;
00450     return shimhdr;
00451 }
00452 
00453 void MPLSAddressClassifier::install(int slot, NsObject *target) {
00454     Tcl& tcl = Tcl::instance();
00455     if ((slot >= 0) && (slot < nslot_) && 
00456         (slot_[slot] != NULL)) {
00457         if (strcmp(slot_[slot]->name(), target->name()) != 0)
00458             tcl.evalf("%s routing-update %d %.15g",
00459                   name(), slot,
00460                   Scheduler::instance().clock());
00461         else
00462             tcl.evalf("%s routing-nochange %d %.15g",
00463                   name(), slot,
00464                   Scheduler::instance().clock());
00465     } else
00466         tcl.evalf("%s routing-new %d %.15g",
00467               name(), slot,
00468               Scheduler::instance().clock());
00469     Classifier::install(slot,target);
00470 }
00471 
00472 int MPLSAddressClassifier::command(int argc, const char*const* argv)
00473 {
00474     Tcl& tcl = Tcl::instance();
00475     if (argc == 2) {
00476         if (strcmp(argv[1], "control-driven?") == 0) {
00477             tcl.resultf("%d", control_driven_);
00478             return (TCL_OK);
00479         } else if (strcmp(argv[1], "data-driven?") == 0) {
00480             tcl.resultf("%d", data_driven_);
00481             return (TCL_OK);
00482         } else if (strcmp(argv[1], "enable-control-driven") == 0) {
00483             // XXX data-driven and control-driven triggers are
00484             // exclusive 
00485             control_driven_ = 1;
00486             data_driven_ = 0;
00487             return (TCL_OK);
00488         } else if (strcmp(argv[1], "enable-data-driven") == 0) {
00489             control_driven_ = 0;
00490             data_driven_ = 1;
00491             return (TCL_OK);
00492         }
00493     } else if (argc == 3) {      
00494         if (strcmp(argv[1], "PFTdump") == 0) {
00495             // <classifier> PFTdump nodeid*/
00496             PFTdump(argv[2]);
00497             return (TCL_OK);
00498         } else if (strcmp(argv[1], "ERBdump") == 0) {
00499             ERBdump(argv[2]);
00500             return (TCL_OK);
00501         } else if (strcmp(argv[1], "LIBdump") == 0) {
00502             LIBdump(argv[2]);
00503             return (TCL_OK);
00504         } else if (strcmp(argv[1], "get-fec-for-lspid") == 0) {
00505             // <classifier get-fec-for-lspid LSPid
00506             int LSPid  = atoi(argv[2]);
00507             int LIBptr = -1;
00508             int ERBnb;
00509             ERBnb = ERBlocate(LSPid, -1, LIBptr);
00510             if (ERBnb >= 0)
00511                 tcl.resultf("%d", ERB_.Entry_[ERBnb].FEC_);
00512             else   
00513                 tcl.result("-1");
00514             return (TCL_OK);
00515         } 
00516     } else if (argc == 4) {
00517         if (strcmp(argv[1], "exist-fec") == 0) {
00518             // <classifier> exist-fec <fec> <phb>
00519             int LIBptr;
00520             int PFTnb = PFTlocate(atoi(argv[2]), atoi(argv[3]),
00521                           LIBptr);         
00522             if (PFTnb > -1)
00523                 tcl.result("1");
00524             else
00525                 tcl.result("-1");
00526             return (TCL_OK);
00527         }
00528         int PFTnb = -1;
00529         int LIBptr = -1;
00530         int iLabel, oLabel, iIface, oIface;
00531         int fec   = atoi(argv[2]);
00532         int LSPid = atoi(argv[3]);
00533         int PHB   = LSPid;
00534         if (LSPid < 0)     // topology-based LSP
00535             PFTnb = PFTlocate(fec,PHB, LIBptr);
00536         else               // ER-LSP
00537             ERBlocate(LSPid,fec, LIBptr);
00538 
00539         if (strcmp(argv[1], "GetInIface") == 0) {
00540             // <classifier> GetInIface <FEC> <LSPid>
00541             if (LIBptr > -1) {
00542                 LIBgetIncoming(LIBptr,iIface,iLabel);
00543                 tcl.resultf("%d", iIface);
00544             } else
00545                 tcl.result("-1");
00546             return (TCL_OK);
00547         } else if (strcmp(argv[1], "GetInLabel") == 0) {
00548             // <classifier> GetInLabel <FEC> <LSPid>
00549             if (LIBptr > -1) {
00550                 LIBgetIncoming(LIBptr,iIface,iLabel);
00551                 tcl.resultf("%d", iLabel);
00552             } else 
00553                 tcl.result("-1");
00554             return (TCL_OK);
00555         } else if (strcmp(argv[1], "GetOutIface") == 0) {
00556             // <classifier> GetOutIface <FEC> <phb/LSPid>
00557             if (LIBptr > -1) {
00558                 LIBlookup(LIBptr, oIface, oLabel, LIBptr);
00559                 tcl.resultf("%d", oIface);
00560             } else
00561                 tcl.result("-1");
00562             return (TCL_OK);
00563         } else if (strcmp(argv[1], "GetOutLabel") == 0) {
00564             // <classifier> GetOutLabel <FEC> <phb/LSPid>
00565             if (LIBptr > -1) {
00566                 LIBlookup(LIBptr, oIface, oLabel, LIBptr);
00567                 tcl.resultf("%d", oLabel);
00568             } else
00569                 tcl.result("-1");
00570             return (TCL_OK);
00571         } else if (strcmp(argv[1], "install") == 0) { 
00572             int slot = atoi(argv[2]);
00573             //if ((slot >= 0) && (slot < nslot_) && 
00574             //  (slot_[slot] != NULL)) {
00575             //  if (strcmp(slot_[slot]->name(),argv[3]) != 0)
00576             //      tcl.evalf("%s routing-update %s %.15g",
00577             //            name(), argv[2],
00578             //          Scheduler::instance().clock());
00579             //  else
00580             //        tcl.evalf("%s routing-nochange %s %.15g",
00581             //          name(), argv[2],
00582             //          Scheduler::instance().clock());
00583             //} else
00584             //  tcl.evalf("%s routing-new %s %.15g",
00585             //        name(), argv[2],
00586             //        Scheduler::instance().clock());
00587             // Then the control is passed on the the base
00588             // address classifier!
00589             //return AddressClassifier::command(argc, argv);
00590             //not a good idea since it would start an infinite loop incase MPLSAddressClassifier::install is defined; 
00591             //so call Classifier::install explicitly.
00592             NsObject* target = (NsObject*)TclObject::lookup(argv[3]);
00593             //Classifier::install(slot, target);
00594 
00595             install(slot,target);
00596             return (TCL_OK);
00597         }
00598     } else if (argc == 5) {      
00599         if (strcmp(argv[1], "ErLspBinding") == 0) {
00600             // <classifier> ErLspBinding <FEC> <PHB> <lspid>
00601             int addr   = atoi(argv[2]);
00602             int PHB    = atoi(argv[3]);
00603             int LSPid  = atoi(argv[4]);
00604             if ( !ErLspBinding(addr, PHB,-1, LSPid) )
00605                 tcl.result("1");
00606             else     
00607                 tcl.result("-1");
00608             return (TCL_OK);
00609         }
00610     } else if (argc == 6) {
00611         // <classifier> ErLspStacking fec0 erlspid0 fec erfecid
00612         if (strcmp(argv[1], "ErLspStacking") == 0) {
00613             int erfec0   = atoi(argv[2]);
00614             int erlspid0 = atoi(argv[3]);
00615             int erfec    = atoi(argv[4]);
00616             int erlspid  = atoi(argv[5]);
00617             if (ErLspStacking(erfec0,erlspid0,erfec,erlspid) == 0)
00618                 tcl.result("1");
00619             else     
00620                 tcl.result("-1");
00621             return (TCL_OK);
00622         } else if (strcmp(argv[1], "FlowAggregation") == 0) {
00623             // <classifier> FlowAggregation <fineFEC> <finePHB>
00624             //              <coarseFEC> <coarsePHB>
00625             int fineaddr   = atoi(argv[2]);
00626             int finePHB    = atoi(argv[3]);
00627             int coarseaddr = atoi(argv[4]);
00628             int coarsePHB  = atoi(argv[5]);
00629             if (FlowAggregation(fineaddr, finePHB, coarseaddr,
00630                         coarsePHB) == 0)
00631                 tcl.result("1");
00632             else     
00633                 tcl.result("-1");
00634             return (TCL_OK);
00635         } else if (strcmp(argv[1], "aPathBinding") == 0) {
00636             // <classifier> aPathBinding <FEC> <PHB> 
00637             // <erFEC> <LSPid>
00638             int FEC   = atoi(argv[2]);
00639             int PHB   = atoi(argv[3]);
00640             int erFEC = atoi(argv[4]);
00641             int LSPid = atoi(argv[5]);
00642             if (aPathBinding(FEC, PHB, erFEC, LSPid) == 0)
00643                 tcl.result("1");
00644             else     
00645                 tcl.result("-1");
00646             return (TCL_OK);
00647         }
00648     } else if (argc == 8) {      
00649         int addr  = atoi(argv[2]);
00650         int LSPid = atoi(argv[3]);
00651         int LIBptr;
00652         if (LSPid == MPLS_DEFAULT_PHB)  {
00653             // topology-based LSP
00654             int PHB   = LSPid;
00655             int PFTnb = PFTlocate(addr,PHB,LIBptr);
00656             if (strcmp(argv[1], "LSPrelease") == 0) {
00657                 if (PFTnb >= 0) {
00658                     // PFT entry exist
00659                     LIBupdate(LIBptr, atoi(argv[4]), 
00660                           atoi(argv[5]), atoi(argv[6]),
00661                           atoi(argv[7]));
00662                     if (LIBisdeleted(LIBptr) == 0)
00663                         PFTdeleteLIBptr(LIBptr);
00664                 }
00665                 return (TCL_OK);
00666             } else if (strcmp(argv[1], "LSPsetup") == 0) {
00667                 if (PFTnb < 0) {
00668                     // PFT entry not exist
00669                     int ptr = LIBinsert(atoi(argv[4]),
00670                                 atoi(argv[5]),
00671                                 atoi(argv[6]),
00672                                 atoi(argv[7]));
00673                     if (ptr > -1) {
00674                         PFTinsert(addr, 
00675                               MPLS_DEFAULT_PHB,
00676                               ptr);
00677                         return (TCL_OK);
00678                     } else
00679                         return (TCL_ERROR);
00680                 }
00681                 // PFTnb >= 0
00682                 // PFT entry already exist
00683                 if (LIBptr <= -1) {
00684                     int ptr = LIBinsert(atoi(argv[4]),
00685                                 atoi(argv[5]),
00686                                 atoi(argv[6]),
00687                                 atoi(argv[7]));
00688                     if (ptr > -1) {
00689                         PFTupdate(PFTnb, ptr);
00690                         return (TCL_OK);
00691                     } else
00692                         return (TCL_ERROR); 
00693                 }
00694                 // LIBptr > -1
00695                 // Check whether or not altanative path setup
00696                 if (!((enable_reroute_ == 1) &&
00697                       (LIB_.Entry_[LIBptr].oIface_ > -1) && 
00698                       (reroute_option_ == MPLS_MAKENEWLSP) &&
00699                       (atoi(argv[6]) > -1) && 
00700                       (is_link_down(LIB_.Entry_[LIBptr].oIface_))
00701                       )) { 
00702                     LIBupdate(LIBptr, atoi(argv[4]),
00703                           atoi(argv[5]), atoi(argv[6]),
00704                           atoi(argv[7]));
00705                     return (TCL_OK);
00706                 }
00707                 PFT_.Entry_[PFTnb].aPATHptr_ = 
00708                     LIBinsert(atoi(argv[4]), atoi(argv[5]),
00709                           atoi(argv[6]),atoi(argv[7]));
00710                 for (int i=0; i < LIB_.NB_; i++) {
00711                     if (LIB_.Entry_[i].oIface_!=atoi(argv[2]))
00712                         continue;
00713                     for (int k=0; k<PFT_.NB_; k++) {
00714                         if (PFT_.Entry_[k].LIBptr_ != i)
00715                             continue;
00716                         PFT_.Entry_[k].aPATHptr_ = 
00717                           PFT_.Entry_[PFTnb].aPATHptr_;
00718                     }
00719                 }
00720                 return (TCL_OK);
00721             }
00722         } else {
00723             // ER-LSP
00724             int ERBnb = ERBlocate(LSPid,addr,LIBptr);
00725             if (strcmp(argv[1], "LSPrelease") == 0) {
00726                 if ( ERBnb >= 0 ) {
00727                     // ERB entry exist
00728                     LIBupdate(LIBptr, atoi(argv[4]),
00729                           atoi(argv[5]), atoi(argv[6]),
00730                           atoi(argv[7]));
00731                     if (LIBisdeleted(LIBptr) == 0) {
00732                         ERBdelete(ERBnb);
00733                         PFTdeleteLIBptr(LIBptr);
00734                     }
00735                 }
00736                 return (TCL_OK);
00737             } else if (strcmp(argv[1], "LSPsetup") == 0) {
00738                 if (ERBnb < 0) {
00739                     // ERB entry not exist
00740                     int ptr = LIBinsert(atoi(argv[4]),
00741                                 atoi(argv[5]),
00742                                 atoi(argv[6]),
00743                                 atoi(argv[7]));
00744                     if (ptr > -1) {
00745                         ERBinsert(LSPid,addr,ptr);
00746                         return (TCL_OK);
00747                     } else
00748                         return (TCL_ERROR);
00749                 } 
00750                 // ERBnb >= 0
00751                 // ERB entry already exist
00752                 if (LIBptr > -1)
00753                     LIBupdate(LIBptr, atoi(argv[4]), atoi(argv[5]),
00754                           atoi(argv[6]), atoi(argv[7]));
00755                 else {
00756                     int ptr = 
00757                         LIBinsert(atoi(argv[4]),atoi(argv[5]),
00758                               atoi(argv[6]),atoi(argv[7]));
00759                     if (ptr > -1)
00760                         ERBupdate(ERBnb, ptr);
00761                     else
00762                         return (TCL_ERROR);
00763                 }
00764                 return (TCL_OK);
00765             }
00766         }
00767     }
00768   
00769     return (AddressClassifier::command(argc, argv));
00770 }
00771 
00772 //--------------------------------------------------
00773 // PFT(Partial Forwarding Table)
00774 //--------------------------------------------------
00775 
00776 void MPLSAddressClassifier::PFTinsert(int FEC, int PHB, int LIBptr)
00777 {
00778     PFT_.Entry_[PFT_.NB_].FEC_    = FEC;
00779     PFT_.Entry_[PFT_.NB_].PHB_    = PHB;
00780     PFT_.Entry_[PFT_.NB_].LIBptr_ = LIBptr;
00781     PFT_.Entry_[PFT_.NB_].aPATHptr_  = -1;
00782     PFT_.NB_++;
00783 }
00784 
00785 void MPLSAddressClassifier::PFTdelete(int entrynb)
00786 {
00787     PFT_.Entry_[entrynb].FEC_    = -1;
00788     PFT_.Entry_[entrynb].PHB_    = -1;
00789     PFT_.Entry_[entrynb].LIBptr_ = -1;
00790 }
00791 
00792 void MPLSAddressClassifier::PFTdeleteLIBptr(int LIBptr)
00793 {
00794     for (int i = 0; i < PFT_.NB_; i++) {
00795         if (PFT_.Entry_[i].LIBptr_ != LIBptr)
00796             continue; 
00797         PFT_.Entry_[i].FEC_    = -1;
00798         PFT_.Entry_[i].PHB_    = -1;
00799         PFT_.Entry_[i].LIBptr_ = -1;
00800     }  
00801 }
00802 
00803 void MPLSAddressClassifier::PFTupdate(int entrynb, int LIBptr)
00804 {
00805     PFT_.Entry_[entrynb].LIBptr_ = LIBptr;
00806 }
00807 
00808 int MPLSAddressClassifier::PFTlocate(int FEC, int PHB, int &LIBptr)
00809 {
00810     LIBptr = -1;
00811     if (FEC < 0) 
00812         return -1;
00813     for (int i = 0; i < PFT_.NB_; i++)
00814         if ((PFT_.Entry_[i].FEC_ == FEC) && (PFT_.Entry_[i].PHB_ == PHB)) {
00815             LIBptr = PFT_.Entry_[i].LIBptr_;
00816             return i;
00817         }
00818     return -1;
00819 }
00820 
00821 int MPLSAddressClassifier::PFTlookup(int FEC, int PHB, int &oIface, 
00822                      int &oLabel, int &LIBptr)
00823 {
00824     oIface = oLabel = LIBptr = -1;
00825     if (FEC < 0) 
00826         return -1;
00827     for (int i = 0; i < PFT_.NB_; i++)
00828         if ((PFT_.Entry_[i].FEC_ == FEC) && (PFT_.Entry_[i].PHB_ == PHB))
00829             return LIBlookup(PFT_.Entry_[i].LIBptr_,
00830                      oIface, oLabel, LIBptr);
00831     return -1;
00832 }
00833 
00834 void MPLSAddressClassifier::PFTdump(const char *id)
00835 {
00836     fflush(stdout);
00837     printf("      --) ___PFT dump___ [node: %s] (--\n", id);
00838     printf("---------------------------------------------\n");
00839     printf("     FEC       PHB       LIBptr  AltanativePath\n");
00840     for (int i = 0; i < PFT_.NB_; i++) {
00841         if (PFT_.Entry_[i].FEC_ == -1) 
00842             continue;
00843         printf("     %d    ", PFT_.Entry_[i].FEC_);
00844         printf("     %d    ", PFT_.Entry_[i].PHB_);
00845         printf("     %d    ", PFT_.Entry_[i].LIBptr_);
00846         printf("     %d\n", PFT_.Entry_[i].aPATHptr_);
00847     }
00848     printf("\n");
00849 }
00850 
00851 //--------------------------------------------------
00852 // ER-LSP Table
00853 //--------------------------------------------------
00854 
00855 void MPLSAddressClassifier::ERBinsert(int LSPid, int FEC, int LIBptr)
00856 {
00857     ERB_.Entry_[ERB_.NB_].LSPid_  = LSPid;
00858     ERB_.Entry_[ERB_.NB_].FEC_    = FEC;
00859     ERB_.Entry_[ERB_.NB_].LIBptr_ = LIBptr;
00860     ERB_.NB_++;
00861 }
00862  
00863 void MPLSAddressClassifier::ERBdelete(int entrynb)
00864 {
00865     ERB_.Entry_[entrynb].FEC_    = -1;
00866     ERB_.Entry_[entrynb].LSPid_  = -1;
00867     ERB_.Entry_[entrynb].LIBptr_ = -1;
00868 }
00869 
00870 void MPLSAddressClassifier::ERBupdate(int entrynb, int LIBptr)
00871 {
00872     ERB_.Entry_[entrynb].LIBptr_ = LIBptr;
00873 }
00874 
00875 int  MPLSAddressClassifier::ERBlocate(int LSPid, int FEC, int &LIBptr)
00876 {
00877     LIBptr = -1;
00878     for (int i = 0; i < ERB_.NB_; i++)
00879         if (ERB_.Entry_[i].LSPid_ == LSPid) {
00880             LIBptr = ERB_.Entry_[i].LIBptr_;
00881             return(i);
00882         }
00883     return -1;
00884 }
00885 
00886 void MPLSAddressClassifier::ERBdump(const char *id)
00887 {
00888     fflush(stdout);
00889     printf("      --) ___ERB dump___ [node: %s] (--\n", id);
00890     printf("---------------------------------------------\n");
00891     printf("     FEC       LSPid      LIBptr\n");
00892     for (int i = 0; i < ERB_.NB_; i++) {
00893         if (ERB_.Entry_[i].FEC_ == -1) 
00894             continue;
00895         printf("     %d    ", ERB_.Entry_[i].FEC_);
00896         printf("     %d    ", ERB_.Entry_[i].LSPid_);
00897         printf("     %d\n", ERB_.Entry_[i].LIBptr_);
00898     }
00899     printf("\n");
00900 }
00901 
00902 //--------------------------------------------------
00903 // LIB (Label Information Base)
00904 //--------------------------------------------------
00905 int MPLSAddressClassifier::LIBinsert(int iIface, int iLabel, 
00906                      int oIface, int oLabel)
00907 {
00908     if (LIB_.NB_ == MPLS_MaxLIBEntryNB - 1) {
00909         fprintf(stderr, 
00910             "Error in LIBinstall: higher than MaxLIBEntryNB\n");
00911         return -1;
00912     }
00913 
00914     LIB_.Entry_[LIB_.NB_].iIface_ = -1;
00915     LIB_.Entry_[LIB_.NB_].iLabel_ = -1;
00916     LIB_.Entry_[LIB_.NB_].oIface_ = -1;
00917     LIB_.Entry_[LIB_.NB_].oLabel_ = -1;
00918 
00919     if (iIface < 0) iIface = -1;
00920     if (iLabel < 0) iLabel = -1;
00921     if (oIface < 0) oIface = -1;
00922     if (oLabel < 0) oLabel = -1;
00923 
00924     LIB_.Entry_[LIB_.NB_].iIface_  = iIface;
00925     LIB_.Entry_[LIB_.NB_].iLabel_  = iLabel;
00926     LIB_.Entry_[LIB_.NB_].oIface_  = oIface;
00927     LIB_.Entry_[LIB_.NB_].oLabel_  = oLabel;
00928     LIB_.Entry_[LIB_.NB_].LIBptr_  = -1;
00929 
00930     LIB_.NB_++;
00931     return(LIB_.NB_-1);
00932 }
00933 
00934 int MPLSAddressClassifier::LIBisdeleted(int entrynb)
00935 {
00936     if ((LIB_.Entry_[entrynb].iIface_ == -1) &&
00937         (LIB_.Entry_[entrynb].iLabel_ == -1) &&
00938         (LIB_.Entry_[entrynb].oIface_ == -1) &&
00939         (LIB_.Entry_[entrynb].oLabel_ == -1)) {
00940 
00941         LIB_.Entry_[entrynb].LIBptr_ = -1;
00942         // delete a entry referencing self in LIB
00943         for (int i = 0; i < LIB_.NB_; i++)
00944             if ((LIB_.Entry_[i].LIBptr_ == entrynb))
00945                 LIB_.Entry_[i].LIBptr_ = -1;
00946         return 0;
00947     }
00948     return -1;
00949 }
00950 
00951 void MPLSAddressClassifier::LIBupdate(int entrynb, int iIface, int iLabel, 
00952                       int oIface, int oLabel)
00953 {
00954     if (iIface != MPLS_DONTCARE)
00955         LIB_.Entry_[entrynb].iIface_ = iIface;
00956     if (iLabel != MPLS_DONTCARE)    
00957         LIB_.Entry_[entrynb].iLabel_ = iLabel;
00958     if (oIface != MPLS_DONTCARE)
00959         LIB_.Entry_[entrynb].oIface_ = oIface;
00960     if (oLabel != MPLS_DONTCARE)
00961         LIB_.Entry_[entrynb].oLabel_ = oLabel;
00962 }
00963 
00964 int MPLSAddressClassifier::LIBlookup(int entrynb, int &oIface, 
00965                       int &oLabel, int &LIBptr)
00966 {
00967     oIface = oLabel = LIBptr = -1;
00968 
00969     if (entrynb < 0)
00970         return -1;
00971     oIface = LIB_.Entry_[entrynb].oIface_;
00972     oLabel = LIB_.Entry_[entrynb].oLabel_;
00973     LIBptr = LIB_.Entry_[entrynb].LIBptr_;
00974     return 0;
00975 }
00976 
00977 int MPLSAddressClassifier::LIBlookup(int iIface, int iLabel, int &oIface, 
00978                      int &oLabel, int &LIBptr)
00979 {
00980     oIface = oLabel = LIBptr = -1;
00981     if (iLabel < 0)
00982         return -1;
00983     for (int i = 0; i < LIB_.NB_; i++)
00984         if ((LIB_.Entry_[i].iLabel_ == iLabel)) {
00985             oIface = LIB_.Entry_[i].oIface_;
00986             oLabel = LIB_.Entry_[i].oLabel_;
00987             LIBptr = LIB_.Entry_[i].LIBptr_;
00988             return 0;
00989         } 
00990     return -1;
00991 }
00992 
00993 int MPLSAddressClassifier::LIBgetIncoming(int entrynb, int &iIface, 
00994                       int &iLabel)
00995 {
00996     if (entrynb < 0)
00997         return -1;
00998     iIface = LIB_.Entry_[entrynb].iIface_;
00999     iLabel = LIB_.Entry_[entrynb].iLabel_;
01000     return 0;
01001 }
01002 
01003 void MPLSAddressClassifier::LIBdump(const char *id)
01004 {
01005     fflush(stdout);
01006     printf("    ___LIB dump___ [node: %s]\n", id);
01007     printf("---------------------------------------------\n");
01008     printf("       #       iIface     iLabel      oIface     oLabel    LIBptr\n");
01009     for (int i = 0; i < LIB_.NB_; i++) {
01010         if (!LIBisdeleted(i))
01011             continue;
01012         printf("     %d: ", i);
01013         printf("     %d    ", LIB_.Entry_[i].iIface_);
01014         printf("     %d  ", LIB_.Entry_[i].iLabel_);
01015         printf("     %d    ", LIB_.Entry_[i].oIface_);
01016         printf("     %d    ", LIB_.Entry_[i].oLabel_);
01017         printf("     %d\n", LIB_.Entry_[i].LIBptr_);
01018     }
01019     printf("\n");
01020 }
01021 
01022 //--------------------------------------------------
01023 // MPLS applications
01024 //--------------------------------------------------
01025 
01026 int MPLSAddressClassifier::ErLspStacking(int erFEC0,int erLSPid0, 
01027                      int erFEC, int erLSPid)
01028 {
01029     int erLIBptr0  =-1, erLIBptr  =-1;
01030 
01031     if ((ERBlocate(erLSPid0,erFEC0,erLIBptr0) < 0) || (erLIBptr0 < 0))
01032         return -1;
01033     if ((ERBlocate(erLSPid,erFEC,erLIBptr) < 0) || (erLIBptr < 0))
01034         return -1;
01035     LIB_.Entry_[erLIBptr0].LIBptr_ = erLIBptr;
01036     return 0;
01037 }
01038 
01039 int MPLSAddressClassifier::ErLspBinding(int FEC,int PHB, int erFEC, int LSPid)
01040 {
01041     int LIBptr=-1;
01042     int erLIBptr=-1;
01043 
01044     if ((ERBlocate(LSPid, erFEC, erLIBptr) < 0) || (erLIBptr < 0))
01045         return -1;
01046 
01047     int PFTnb = PFTlocate(FEC,PHB, LIBptr);
01048     if ((PFTnb < 0))
01049         PFTinsert(FEC,PHB, erLIBptr);
01050     else {
01051         if (LIBptr < 0)
01052             PFTupdate(PFTnb, LIBptr);
01053         else {  
01054             int i = LIBptr;
01055             while (i < 0) {
01056                 LIBptr = i;;
01057                 i = LIB_.Entry_[LIBptr].LIBptr_;
01058             }
01059             LIB_.Entry_[LIBptr].LIBptr_ = erLIBptr;
01060         }
01061     }
01062     return 0;
01063 }
01064 
01065 int MPLSAddressClassifier::FlowAggregation(int fineFEC, int finePHB, 
01066                        int coarseFEC, int coarsePHB)
01067 {
01068     int fLIBptr=-1;
01069     int cLIBptr=-1;
01070 
01071     if ((PFTlocate(coarseFEC,coarsePHB, cLIBptr) < 0) || (cLIBptr < 0))
01072         return -1;
01073 
01074     int PFTnb = PFTlocate(fineFEC,finePHB, fLIBptr);
01075     if ((PFTnb < 0))
01076         PFTinsert(fineFEC,finePHB, cLIBptr);
01077     else {
01078         if (fLIBptr < 0)
01079             PFTupdate(PFTnb, cLIBptr);
01080         else {
01081             int i=fLIBptr;
01082             while (i < 0) {
01083                 fLIBptr = i;;
01084                 i = LIB_.Entry_[fLIBptr].LIBptr_;
01085             }
01086             LIB_.Entry_[fLIBptr].LIBptr_ = cLIBptr;
01087         }
01088     }
01089         return 0;
01090 }
01091 
01092 int MPLSAddressClassifier::aPathBinding(int FEC, int PHB, int erFEC, int LSPid)
01093 {
01094     int entrynb,tmp,erLIBptr;   
01095       
01096     entrynb = PFTlocate(FEC,PHB,tmp);
01097     if ((entrynb < 0) || (ERBlocate(LSPid,erFEC,erLIBptr) < 0))
01098         return -1;
01099     PFT_.Entry_[entrynb].aPATHptr_ = erLIBptr;
01100     return 0;
01101 }
01102 
01103 int MPLSAddressClassifier::aPathLookup(int FEC,int PHB, int &oIface,
01104                        int &oLabel, int &LIBptr)
01105 {
01106     oIface = oLabel = LIBptr = -1;
01107 
01108     if (FEC < 0) 
01109         return -1;
01110     for (int i = 0; i < PFT_.NB_; i++)
01111         if ((PFT_.Entry_[i].FEC_ == FEC) && 
01112             (PFT_.Entry_[i].PHB_ == PHB))
01113             return LIBlookup(PFT_.Entry_[i].aPATHptr_,
01114                      oIface, oLabel, LIBptr);
01115     return -1;
01116 }
01117 
01118 void MPLSAddressClassifier::trace(char *ptype, int psize, int ilabel, 
01119                   char *op, int oiface, int olabel, int ttl)
01120 {
01121     if (trace_mpls_ != 1)
01122         return;
01123     Tcl::instance().evalf("%s trace-packet-switching " TIME_FORMAT 
01124                   " %d %d %s %d %s %d %d %d %d",
01125                   name(),
01126                   Scheduler::instance().clock(),
01127                   PI_.srcnode_,
01128                   PI_.dst_.addr_,
01129                   ptype,
01130                   ilabel,
01131                   op,
01132                   oiface,
01133                   olabel,
01134                   ttl,
01135                   psize);
01136 }

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