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

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

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