classifier-addr-mpls.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:31k
源码类别:

通讯编程

开发平台:

Visual C++

  1. // -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
  2. /*
  3.  * classifier-addr-mpls.cc
  4.  * Copyright (C) 2000 by the University of Southern California
  5.  * $Id: classifier-addr-mpls.cc,v 1.7 2005/08/25 18:58:09 johnh Exp $
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License,
  9.  * version 2, as published by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  * The copyright of this module includes the following
  22.  * linking-with-specific-other-licenses addition:
  23.  *
  24.  * In addition, as a special exception, the copyright holders of
  25.  * this module give you permission to combine (via static or
  26.  * dynamic linking) this module with free software programs or
  27.  * libraries that are released under the GNU LGPL and with code
  28.  * included in the standard release of ns-2 under the Apache 2.0
  29.  * license or under otherwise-compatible licenses with advertising
  30.  * requirements (or modified versions of such code, with unchanged
  31.  * license).  You may copy and distribute such a system following the
  32.  * terms of the GNU GPL for this module and the licenses of the
  33.  * other code concerned, provided that you include the source code of
  34.  * that other code when and as the GNU GPL requires distribution of
  35.  * source code.
  36.  *
  37.  * Note that people who make modified versions of this module
  38.  * are not obligated to grant this special exception for their
  39.  * modified versions; it is their choice whether to do so.  The GNU
  40.  * General Public License gives permission to release a modified
  41.  * version without this exception; this exception also makes it
  42.  * possible to release a modified version which carries forward this
  43.  * exception.
  44.  *
  45.  */
  46. //
  47. // Original source contributed by Gaeil Ahn. See below.
  48. //
  49. // $Header: /cvsroot/nsnam/ns-2/mpls/classifier-addr-mpls.cc,v 1.7 2005/08/25 18:58:09 johnh Exp $
  50. // XXX
  51. //
  52. // - Because MPLS header contains pointers, it cannot be used WITH multicast 
  53. //   routing which replicates packets
  54. // - Currently it works only with flat routing.
  55. /**************************************************************************
  56.  * Copyright (c) 2000 by Gaeil Ahn                                      *
  57.  * Everyone is permitted to copy and distribute this software.   *
  58.  * Please send mail to fog1@ce.cnu.ac.kr when you modify or distribute    *
  59.  * this sources.   *
  60.  **************************************************************************/
  61. /************************************************************
  62.  *                                                          *
  63.  *    File: File for packet switching in MPLS node          *
  64.  *    Author: Gaeil Ahn (fog1@ce.cnu.ac.kr), Dec. 1999      *
  65.  *                                                          *
  66.  ************************************************************/
  67. #include "packet.h"
  68. #include "trace.h"
  69. #include "classifier-addr-mpls.h"
  70. int hdr_mpls::offset_;
  71. static class shimhdreaderClass : public PacketHeaderClass {
  72. public:
  73. shimhdreaderClass() : PacketHeaderClass("PacketHeader/MPLS", 
  74. sizeof(hdr_mpls)) {
  75. bind_offset(&hdr_mpls::offset_);
  76. }
  77. } class_shimhdreader;
  78. static class MPLSAddrClassifierClass : public TclClass {
  79. public:
  80. MPLSAddrClassifierClass() : TclClass("Classifier/Addr/MPLS") {}
  81. virtual TclObject* create(int, const char*const*) {
  82. return (new MPLSAddressClassifier());
  83. }
  84. virtual void bind();
  85. virtual int method(int argc, const char*const* argv);
  86. } class_mpls_addr_classifier;
  87. void MPLSAddrClassifierClass::bind()
  88. {
  89. TclClass::bind();
  90. add_method("minimum-lspid");
  91. add_method("dont-care");
  92. add_method("ordered-control?");
  93. add_method("on-demand?");
  94. add_method("enable-ordered-control");
  95. add_method("enable-on-demand");
  96. }
  97. int MPLSAddrClassifierClass::method(int ac, const char*const* av)
  98. {
  99. Tcl& tcl = Tcl::instance();
  100. int argc = ac - 2;
  101. const char*const* argv = av + 2;
  102. if (argc == 2) {
  103. if (strcmp(argv[1], "minimum-lspid") == 0) {
  104. tcl.resultf("%d", MPLS_MINIMUM_LSPID);
  105. return (TCL_OK);
  106. } else if (strcmp(argv[1], "dont-care") == 0) {
  107. tcl.resultf("%d", MPLS_DONTCARE);
  108. return (TCL_OK);
  109. } if (strcmp(argv[1], "ordered-control?") == 0) {
  110. tcl.resultf("%d", 
  111.     MPLSAddressClassifier::ordered_control_);
  112. return (TCL_OK);
  113. } else if (strcmp(argv[1], "on-demand?") == 0) {
  114. tcl.resultf("%d", MPLSAddressClassifier::on_demand_);
  115. return (TCL_OK);
  116. } else if (strcmp(argv[1], "enable-ordered-control") == 0) {
  117. MPLSAddressClassifier::ordered_control_ = 1;
  118. return (TCL_OK);
  119. } else if (strcmp(argv[1], "enable-on-demand") == 0) {
  120. MPLSAddressClassifier::on_demand_ = 1;
  121. return (TCL_OK);
  122. }
  123. }
  124. return TclClass::method(ac, av);
  125. }
  126. int MPLSAddressClassifier::on_demand_ = 0;
  127. int MPLSAddressClassifier::ordered_control_ = 0;
  128. MPLSAddressClassifier::MPLSAddressClassifier() : 
  129. data_driven_(0), control_driven_(0)
  130. {
  131. PFT_.NB_ = 0;
  132. ERB_.NB_ = 0;
  133. LIB_.NB_ = 0;
  134. ttl_ = 32;
  135. }
  136. void MPLSAddressClassifier::delay_bind_init_all()
  137. {
  138. delay_bind_init_one("ttl_");
  139. delay_bind_init_one("trace_mpls_");   
  140. delay_bind_init_one("label_");
  141. delay_bind_init_one("enable_reroute_");
  142. delay_bind_init_one("reroute_option_");
  143. delay_bind_init_one("data_driven_");
  144. delay_bind_init_one("control_driven_");
  145. AddressClassifier::delay_bind_init_all();
  146. }
  147. // Arguments: varName, localName, tracer
  148. int MPLSAddressClassifier::delay_bind_dispatch(const char *vn, 
  149.        const char* ln, TclObject *t)
  150. {
  151. if (delay_bind(vn, ln, "ttl_", &ttl_, t))
  152. return TCL_OK;
  153. if (delay_bind(vn, ln, "trace_mpls_", &trace_mpls_, t)) 
  154. return TCL_OK;
  155. if (delay_bind(vn, ln, "label_", &label_, t)) 
  156. return TCL_OK;
  157. if (delay_bind(vn, ln, "enable_reroute_", &enable_reroute_, t))
  158. return TCL_OK;
  159. if (delay_bind(vn, ln, "reroute_option_", &reroute_option_, t))
  160. return TCL_OK;
  161. if (delay_bind(vn, ln, "data_driven_", &data_driven_, t))
  162. return TCL_OK;
  163. if (delay_bind(vn, ln, "control_driven_", &control_driven_, t))
  164. return TCL_OK;
  165. return AddressClassifier::delay_bind_dispatch(vn, ln, t);
  166. }
  167. int MPLSAddressClassifier::classify(Packet* p)
  168. {
  169. int nexthop = MPLSclassify(p);
  170. if ((enable_reroute_ == 1) && (size_ > 0) && 
  171.     (is_link_down(nexthop)))
  172. // Use alternative path if it exist
  173. nexthop = do_reroute(p);
  174. if (nexthop == MPLS_GOTO_L3)
  175. return AddressClassifier::classify(p);
  176. // XXX Do NOT return -1, which lets the classifier to process this 
  177. // packet twice!!
  178. return (nexthop == -1) ? Classifier::ONCE : nexthop;
  179. }
  180. int MPLSAddressClassifier::is_link_down(int node)
  181. {
  182. Tcl& tcl = Tcl::instance();   
  183. tcl.evalf("[%s set mpls_mod_] get-link-status %d", name(), node);
  184. return (strcmp(tcl.result(), "down") == 0) ? 1 : 0;
  185. }
  186. int MPLSAddressClassifier::do_reroute(Packet* p)
  187. {
  188. int oIface, oLabel, LIBptr;
  189. PI_.shimhdr_ = GetShimHeader(p);
  190. int iLabel = PI_.shimhdr_->label_;
  191. if (aPathLookup(PI_.dst_.addr_, PI_.phb_, oIface, oLabel, LIBptr) == 0)
  192. return convertL2toL2(iLabel, oIface, oLabel, LIBptr);
  193. else {
  194. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  195. trace("L", size_, iLabel, "Drop(linkFail)", -1, -1, -1);
  196. switch (reroute_option_) {
  197. case MPLS_DROPPACKET:
  198. return -1;
  199. case MPLS_L3FORWARDING:
  200. return MPLS_GOTO_L3;
  201. case MPLS_MAKENEWLSP:
  202. Tcl& tcl = Tcl::instance();   
  203. if (!control_driven_)
  204. tcl.evalf("%s ldp-trigger-by-switch %d", 
  205.   name(), PI_.dst_.addr_);
  206. return -1;
  207. }
  208. return -1;
  209. }
  210. }
  211. int MPLSAddressClassifier::convertL3toL2(int oIface, int oLabel, int LIBptr)
  212. {
  213. int iLabel= -1;
  214. int ptr;
  215.               
  216. while (oLabel >= 0) {
  217. /* penultimate hop */
  218. if (oLabel == 0)  {
  219. /* no operation */
  220. trace("U",size_, iLabel, "Push(penultimate)", 
  221.       oIface, oLabel, ttl_);
  222. } else {
  223. /* push operation in ingerss LSR */
  224. PI_.shimhdr_ = push(PI_.shimhdr_,oLabel);
  225. trace("U",size_, iLabel, "Push(ingress)", 
  226.       oIface, oLabel, ttl_);
  227. }
  228. if (LIBptr >= 0) {
  229. /* stack operation */
  230. iLabel = oLabel;
  231. ptr = LIBptr;
  232. LIBlookup(ptr, oIface, oLabel, LIBptr);
  233. } else
  234. break;
  235. }
  236. if (oLabel < 0) {
  237. if (size_ > 0)
  238. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  239. trace("U",size_, iLabel , "L3(errorLabel)", -1,-1, -1);
  240. return MPLS_GOTO_L3;
  241. }
  242. if (oIface < 0) {  
  243. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  244. trace("U", size_, iLabel, "L3(errorOIF)", -1 , -1, -1);
  245. return MPLS_GOTO_L3;
  246. } else
  247. // Guaranteed returned oIface is >= 0 or MPLS_GOTO_L3
  248. return oIface;
  249. }
  250. int MPLSAddressClassifier::convertL2toL2(int iLabel, int oIface, 
  251.  int oLabel, int LIBptr)
  252. {
  253. int  ttl = PI_.shimhdr_->ttl_;
  254. int  ptr;
  255. // push(stack) operation after swap or pop
  256. if (oLabel == 0) {
  257. // in penultimate hop
  258. PI_.shimhdr_ = pop(PI_.shimhdr_);
  259. trace("L", size_, iLabel, "Pop(penultimate)", 
  260.       oIface, oLabel, ttl);
  261. } else if (oLabel > 0) {
  262. // swap operation 
  263. swap(PI_.shimhdr_,oLabel);
  264. trace("L", size_, iLabel, "Swap", oIface, oLabel, ttl);
  265. } else {
  266. // Errored Label
  267. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  268. trace("L", size_, iLabel, "L3(errorLabel)", -1, -1, -1);
  269. return MPLS_GOTO_L3;
  270. }
  271. while (LIBptr >= 0) {
  272. // stack operation
  273. iLabel= oLabel;
  274. ptr = LIBptr;
  275. LIBlookup(ptr, oIface, oLabel, LIBptr);
  276. PI_.shimhdr_ = push(PI_.shimhdr_,oLabel);
  277. trace("L", size_, iLabel, "Push(tunnel)", 
  278.       oIface, oLabel, ttl_);
  279. }   
  280. if (oIface < 0) {  
  281. if (size_ > 0)
  282. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  283. trace("L",size_, iLabel , "L3(errorOIf)", -1 , -1, -1);
  284. return MPLS_GOTO_L3;
  285. }
  286. // Guaranteed returned oIface >= 0
  287. return oIface;
  288. }
  289. // Process unlabeled packet
  290. int MPLSAddressClassifier::processIP()
  291. {
  292. int oIface,oLabel,LIBptr;
  293. int iLabel = -1;
  294. // Insert code to manipulate PHB
  295. if (PFTlookup(PI_.dst_.addr_, PI_.phb_, oIface, oLabel, LIBptr) == 0)
  296. // Push operation
  297. return convertL3toL2(oIface,oLabel,LIBptr);
  298. // L3 forwarding
  299. // Traffic-driven, triggered by MPLS switch
  300. if (data_driven_) 
  301. Tcl::instance().evalf("%s ldp-trigger-by-switch %d", 
  302.       name(), PI_.dst_.addr_);
  303. trace("U", size_, iLabel, "L3", -1, -1, -1);               
  304. return MPLS_GOTO_L3;
  305. }
  306. // Process labeled packet
  307. int MPLSAddressClassifier::processLabelP()
  308. {
  309. int oIface,oLabel,LIBptr;
  310. int iLabel = PI_.shimhdr_->label_;
  311. PI_.shimhdr_ = checkTTL(PI_.shimhdr_);
  312. if (size_ == 0)
  313. // TTL check
  314. return MPLS_GOTO_L3;
  315. // Label swapping operation 
  316. if (LIBlookup(-1, iLabel, oIface, oLabel, LIBptr) == 0)
  317. return convertL2toL2(iLabel,oIface,oLabel,LIBptr);
  318. PI_.shimhdr_ = DelAllShimHeader(PI_.shimhdr_);
  319. trace("L",size_, iLabel,"L3(errorLabel)", -1, -1, -1);
  320. return ( MPLS_GOTO_L3 );
  321. }
  322. int MPLSAddressClassifier::MPLSclassify(Packet* p)
  323. {
  324. GetIPInfo(p, PI_.dst_, PI_.phb_, PI_.srcnode_);
  325. PI_.shimhdr_ = GetShimHeader(p);
  326.    
  327. // XXX Using header size to determine if this is a MPLS-labeled packet
  328. // is a very bad method. We should have some explicit flag that labels
  329. // every packet; this flag will only be set on for every MPLS-labeled
  330. // packet. This can be done by a bitmap field in the common header.
  331. if (size_ == 0) 
  332. // Unlabeled packet
  333. return processIP();
  334. // Labeled packet 
  335. int ret = processLabelP();
  336. if (ret == MPLS_GOTO_L3) {  
  337. PI_.shimhdr_ = GetShimHeader(p);
  338. return processIP();
  339. }
  340. return ret;   
  341. }
  342. hdr_mpls *MPLSAddressClassifier::checkTTL(hdr_mpls *shimhdr)
  343. {
  344. shimhdr->ttl_--;
  345. int ttl   = shimhdr->ttl_;
  346. int iLabel= shimhdr->label_;
  347.    
  348. if (ttl == 0) {
  349. shimhdr = DelAllShimHeader(shimhdr);
  350. trace("L", size_, iLabel, "L3(TTL=0)", -1, -1, ttl);
  351. }
  352. return shimhdr;
  353. }
  354. void MPLSAddressClassifier::GetIPInfo(Packet* p, ns_addr_t &dst,
  355.       int &phb, int &srcnode)
  356. {
  357. hdr_ip* iphdr = hdr_ip::access(p);
  358. dst = iphdr->dst_;
  359. srcnode = iphdr->src_.addr_;
  360. phb = MPLS_DEFAULT_PHB;
  361. }
  362. hdr_mpls *MPLSAddressClassifier::GetShimHeader(Packet* p)
  363. {
  364. hdr_mpls *shimhdr = hdr_mpls::access(p);
  365. size_ = 0;
  366. if ((shimhdr->label_ == 0) && (shimhdr->bflag_ == 0) && 
  367.     (shimhdr->ttl_ == 0)) {
  368. shimhdr->bflag_ = -1;
  369. shimhdr->label_ = -1;
  370. shimhdr->ttl_ = -1;
  371. shimhdr->top_    = shimhdr;
  372. shimhdr->nexthdr_= shimhdr;
  373. } else {
  374. while (shimhdr->top_ != shimhdr) { 
  375. shimhdr = shimhdr->top_;
  376. size_ += 4;
  377. }
  378. return shimhdr;
  379. }
  380. hdr_mpls *MPLSAddressClassifier::DelAllShimHeader(hdr_mpls *shimhdr)
  381. {
  382. while (shimhdr->bflag_ != -1)
  383. shimhdr = pop(shimhdr);
  384. return(shimhdr);
  385. }
  386. hdr_mpls *MPLSAddressClassifier::push(hdr_mpls *shimhdr, int oLabel)
  387. {
  388. hdr_mpls *newhdr;
  389. newhdr = (hdr_mpls *) malloc( sizeof(hdr_mpls) );
  390. newhdr->label_ = oLabel;
  391. newhdr->bflag_ = 1;
  392. newhdr->ttl_ = ttl_;
  393. newhdr->top_  = newhdr;
  394. newhdr->nexthdr_ = shimhdr;
  395. shimhdr->top_ = newhdr;
  396. size_ += 4;
  397.     
  398. return newhdr;
  399. }
  400. hdr_mpls *MPLSAddressClassifier::pop(hdr_mpls *shimhdr)
  401. {
  402. shimhdr = shimhdr->nexthdr_;
  403. free(shimhdr->top_);
  404. shimhdr->top_ = shimhdr;
  405. size_ -= 4;
  406. return shimhdr;
  407. }
  408. void MPLSAddressClassifier::install(int slot, NsObject *target) {
  409. Tcl& tcl = Tcl::instance();
  410. if ((slot >= 0) && (slot < nslot_) && 
  411.     (slot_[slot] != NULL)) {
  412. if (strcmp(slot_[slot]->name(), target->name()) != 0)
  413. tcl.evalf("%s routing-update %d %.15g",
  414.   name(), slot,
  415.   Scheduler::instance().clock());
  416. else
  417. tcl.evalf("%s routing-nochange %d %.15g",
  418.   name(), slot,
  419.   Scheduler::instance().clock());
  420. } else
  421. tcl.evalf("%s routing-new %d %.15g",
  422.   name(), slot,
  423.   Scheduler::instance().clock());
  424. Classifier::install(slot,target);
  425. }
  426. int MPLSAddressClassifier::command(int argc, const char*const* argv)
  427. {
  428. Tcl& tcl = Tcl::instance();
  429. if (argc == 2) {
  430. if (strcmp(argv[1], "control-driven?") == 0) {
  431. tcl.resultf("%d", control_driven_);
  432. return (TCL_OK);
  433. } else if (strcmp(argv[1], "data-driven?") == 0) {
  434. tcl.resultf("%d", data_driven_);
  435. return (TCL_OK);
  436. } else if (strcmp(argv[1], "enable-control-driven") == 0) {
  437. // XXX data-driven and control-driven triggers are
  438. // exclusive 
  439. control_driven_ = 1;
  440. data_driven_ = 0;
  441. return (TCL_OK);
  442. } else if (strcmp(argv[1], "enable-data-driven") == 0) {
  443. control_driven_ = 0;
  444. data_driven_ = 1;
  445. return (TCL_OK);
  446. }
  447. } else if (argc == 3) {      
  448. if (strcmp(argv[1], "PFTdump") == 0) {
  449. // <classifier> PFTdump nodeid*/
  450. PFTdump(argv[2]);
  451. return (TCL_OK);
  452. } else if (strcmp(argv[1], "ERBdump") == 0) {
  453. ERBdump(argv[2]);
  454. return (TCL_OK);
  455. } else if (strcmp(argv[1], "LIBdump") == 0) {
  456. LIBdump(argv[2]);
  457. return (TCL_OK);
  458. } else if (strcmp(argv[1], "get-fec-for-lspid") == 0) {
  459. // <classifier get-fec-for-lspid LSPid
  460. int LSPid  = atoi(argv[2]);
  461. int LIBptr = -1;
  462. int ERBnb;
  463. ERBnb = ERBlocate(LSPid, -1, LIBptr);
  464. if (ERBnb >= 0)
  465. tcl.resultf("%d", ERB_.Entry_[ERBnb].FEC_);
  466. else   
  467. tcl.result("-1");
  468. return (TCL_OK);
  469. } else if (argc == 4) {
  470. if (strcmp(argv[1], "exist-fec") == 0) {
  471. // <classifier> exist-fec <fec> <phb>
  472. int LIBptr;
  473. int PFTnb = PFTlocate(atoi(argv[2]), atoi(argv[3]),
  474.       LIBptr);         
  475. if (PFTnb > -1)
  476. tcl.result("1");
  477. else
  478. tcl.result("-1");
  479. return (TCL_OK);
  480. }
  481. int PFTnb = -1;
  482. int LIBptr = -1;
  483. int iLabel, oLabel, iIface, oIface;
  484. int fec   = atoi(argv[2]);
  485. int LSPid = atoi(argv[3]);
  486. int PHB   = LSPid;
  487. if (LSPid < 0)     // topology-based LSP
  488. PFTnb = PFTlocate(fec,PHB, LIBptr);
  489. else               // ER-LSP
  490. ERBlocate(LSPid,fec, LIBptr);
  491. if (strcmp(argv[1], "GetInIface") == 0) {
  492. // <classifier> GetInIface <FEC> <LSPid>
  493. if (LIBptr > -1) {
  494. LIBgetIncoming(LIBptr,iIface,iLabel);
  495. tcl.resultf("%d", iIface);
  496. } else
  497. tcl.result("-1");
  498. return (TCL_OK);
  499. } else if (strcmp(argv[1], "GetInLabel") == 0) {
  500. // <classifier> GetInLabel <FEC> <LSPid>
  501. if (LIBptr > -1) {
  502. LIBgetIncoming(LIBptr,iIface,iLabel);
  503. tcl.resultf("%d", iLabel);
  504. } else 
  505. tcl.result("-1");
  506. return (TCL_OK);
  507. } else if (strcmp(argv[1], "GetOutIface") == 0) {
  508. // <classifier> GetOutIface <FEC> <phb/LSPid>
  509. if (LIBptr > -1) {
  510. LIBlookup(LIBptr, oIface, oLabel, LIBptr);
  511. tcl.resultf("%d", oIface);
  512. } else
  513. tcl.result("-1");
  514. return (TCL_OK);
  515. } else if (strcmp(argv[1], "GetOutLabel") == 0) {
  516. // <classifier> GetOutLabel <FEC> <phb/LSPid>
  517. if (LIBptr > -1) {
  518. LIBlookup(LIBptr, oIface, oLabel, LIBptr);
  519. tcl.resultf("%d", oLabel);
  520. } else
  521. tcl.result("-1");
  522. return (TCL_OK);
  523. } else if (strcmp(argv[1], "install") == 0) { 
  524. int slot = atoi(argv[2]);
  525. //if ((slot >= 0) && (slot < nslot_) && 
  526. //  (slot_[slot] != NULL)) {
  527. // if (strcmp(slot_[slot]->name(),argv[3]) != 0)
  528. // tcl.evalf("%s routing-update %s %.15g",
  529. //   name(), argv[2],
  530. // Scheduler::instance().clock());
  531. // else
  532. //       tcl.evalf("%s routing-nochange %s %.15g",
  533. // name(), argv[2],
  534. // Scheduler::instance().clock());
  535. //} else
  536. // tcl.evalf("%s routing-new %s %.15g",
  537. //   name(), argv[2],
  538. //   Scheduler::instance().clock());
  539. // Then the control is passed on the the base
  540. // address classifier!
  541. //return AddressClassifier::command(argc, argv);
  542. //not a good idea since it would start an infinite loop incase MPLSAddressClassifier::install is defined; 
  543. //so call Classifier::install explicitly.
  544. NsObject* target = (NsObject*)TclObject::lookup(argv[3]);
  545. //Classifier::install(slot, target);
  546. install(slot,target);
  547. return (TCL_OK);
  548. }
  549. } else if (argc == 5) {      
  550. if (strcmp(argv[1], "ErLspBinding") == 0) {
  551. // <classifier> ErLspBinding <FEC> <PHB> <lspid>
  552. int addr   = atoi(argv[2]);
  553. int PHB    = atoi(argv[3]);
  554. int LSPid  = atoi(argv[4]);
  555. if ( !ErLspBinding(addr, PHB,-1, LSPid) )
  556. tcl.result("1");
  557. else     
  558. tcl.result("-1");
  559. return (TCL_OK);
  560. }
  561. } else if (argc == 6) {
  562. // <classifier> ErLspStacking fec0 erlspid0 fec erfecid
  563. if (strcmp(argv[1], "ErLspStacking") == 0) {
  564. int erfec0   = atoi(argv[2]);
  565. int erlspid0 = atoi(argv[3]);
  566. int erfec    = atoi(argv[4]);
  567. int erlspid  = atoi(argv[5]);
  568. if (ErLspStacking(erfec0,erlspid0,erfec,erlspid) == 0)
  569. tcl.result("1");
  570. else     
  571. tcl.result("-1");
  572. return (TCL_OK);
  573. } else if (strcmp(argv[1], "FlowAggregation") == 0) {
  574. // <classifier> FlowAggregation <fineFEC> <finePHB>
  575. //              <coarseFEC> <coarsePHB>
  576. int fineaddr   = atoi(argv[2]);
  577. int finePHB    = atoi(argv[3]);
  578. int coarseaddr = atoi(argv[4]);
  579. int coarsePHB  = atoi(argv[5]);
  580. if (FlowAggregation(fineaddr, finePHB, coarseaddr,
  581.     coarsePHB) == 0)
  582. tcl.result("1");
  583. else     
  584. tcl.result("-1");
  585. return (TCL_OK);
  586. } else if (strcmp(argv[1], "aPathBinding") == 0) {
  587. // <classifier> aPathBinding <FEC> <PHB> 
  588. // <erFEC> <LSPid>
  589. int FEC   = atoi(argv[2]);
  590. int PHB   = atoi(argv[3]);
  591. int erFEC = atoi(argv[4]);
  592. int LSPid = atoi(argv[5]);
  593. if (aPathBinding(FEC, PHB, erFEC, LSPid) == 0)
  594. tcl.result("1");
  595. else     
  596. tcl.result("-1");
  597. return (TCL_OK);
  598. }
  599. } else if (argc == 8) {      
  600. int addr  = atoi(argv[2]);
  601. int LSPid = atoi(argv[3]);
  602. int LIBptr;
  603. if (LSPid == MPLS_DEFAULT_PHB)  {
  604. // topology-based LSP
  605. int PHB   = LSPid;
  606. int PFTnb = PFTlocate(addr,PHB,LIBptr);
  607. if (strcmp(argv[1], "LSPrelease") == 0) {
  608. if (PFTnb >= 0) {
  609. // PFT entry exist
  610. LIBupdate(LIBptr, atoi(argv[4]), 
  611.   atoi(argv[5]), atoi(argv[6]),
  612.   atoi(argv[7]));
  613. if (LIBisdeleted(LIBptr) == 0)
  614. PFTdeleteLIBptr(LIBptr);
  615. }
  616. return (TCL_OK);
  617. } else if (strcmp(argv[1], "LSPsetup") == 0) {
  618. if (PFTnb < 0) {
  619. // PFT entry not exist
  620. int ptr = LIBinsert(atoi(argv[4]),
  621.     atoi(argv[5]),
  622.     atoi(argv[6]),
  623.     atoi(argv[7]));
  624. if (ptr > -1) {
  625. PFTinsert(addr, 
  626.   MPLS_DEFAULT_PHB,
  627.   ptr);
  628. return (TCL_OK);
  629. } else
  630. return (TCL_ERROR);
  631. }
  632. // PFTnb >= 0
  633. // PFT entry already exist
  634. if (LIBptr <= -1) {
  635. int ptr = LIBinsert(atoi(argv[4]),
  636.     atoi(argv[5]),
  637.     atoi(argv[6]),
  638.     atoi(argv[7]));
  639. if (ptr > -1) {
  640. PFTupdate(PFTnb, ptr);
  641. return (TCL_OK);
  642. } else
  643. return (TCL_ERROR);
  644. }
  645. // LIBptr > -1
  646. // Check whether or not altanative path setup
  647. if (!((enable_reroute_ == 1) &&
  648.       (LIB_.Entry_[LIBptr].oIface_ > -1) && 
  649.       (reroute_option_ == MPLS_MAKENEWLSP) &&
  650.       (atoi(argv[6]) > -1) && 
  651.       (is_link_down(LIB_.Entry_[LIBptr].oIface_))
  652.       )) { 
  653. LIBupdate(LIBptr, atoi(argv[4]),
  654.   atoi(argv[5]), atoi(argv[6]),
  655.   atoi(argv[7]));
  656. return (TCL_OK);
  657. }
  658. PFT_.Entry_[PFTnb].aPATHptr_ = 
  659. LIBinsert(atoi(argv[4]), atoi(argv[5]),
  660.   atoi(argv[6]),atoi(argv[7]));
  661. for (int i=0; i < LIB_.NB_; i++) {
  662. if (LIB_.Entry_[i].oIface_!=atoi(argv[2]))
  663. continue;
  664. for (int k=0; k<PFT_.NB_; k++) {
  665. if (PFT_.Entry_[k].LIBptr_ != i)
  666. continue;
  667. PFT_.Entry_[k].aPATHptr_ = 
  668.   PFT_.Entry_[PFTnb].aPATHptr_;
  669. }
  670. }
  671. return (TCL_OK);
  672. }
  673. } else {
  674. // ER-LSP
  675. int ERBnb = ERBlocate(LSPid,addr,LIBptr);
  676. if (strcmp(argv[1], "LSPrelease") == 0) {
  677. if ( ERBnb >= 0 ) {
  678. // ERB entry exist
  679. LIBupdate(LIBptr, atoi(argv[4]),
  680.   atoi(argv[5]), atoi(argv[6]),
  681.   atoi(argv[7]));
  682. if (LIBisdeleted(LIBptr) == 0) {
  683. ERBdelete(ERBnb);
  684. PFTdeleteLIBptr(LIBptr);
  685. }
  686. }
  687. return (TCL_OK);
  688. } else if (strcmp(argv[1], "LSPsetup") == 0) {
  689. if (ERBnb < 0) {
  690. // ERB entry not exist
  691. int ptr = LIBinsert(atoi(argv[4]),
  692.     atoi(argv[5]),
  693.     atoi(argv[6]),
  694.     atoi(argv[7]));
  695. if (ptr > -1) {
  696. ERBinsert(LSPid,addr,ptr);
  697. return (TCL_OK);
  698. } else
  699. return (TCL_ERROR);
  700. // ERBnb >= 0
  701. // ERB entry already exist
  702. if (LIBptr > -1)
  703. LIBupdate(LIBptr, atoi(argv[4]), atoi(argv[5]),
  704.   atoi(argv[6]), atoi(argv[7]));
  705. else {
  706. int ptr = 
  707. LIBinsert(atoi(argv[4]),atoi(argv[5]),
  708.   atoi(argv[6]),atoi(argv[7]));
  709. if (ptr > -1)
  710. ERBupdate(ERBnb, ptr);
  711. else
  712. return (TCL_ERROR);
  713. }
  714. return (TCL_OK);
  715. }
  716. }
  717. }
  718.   
  719. return (AddressClassifier::command(argc, argv));
  720. }
  721. //--------------------------------------------------
  722. // PFT(Partial Forwarding Table)
  723. //--------------------------------------------------
  724. void MPLSAddressClassifier::PFTinsert(int FEC, int PHB, int LIBptr)
  725. {
  726. PFT_.Entry_[PFT_.NB_].FEC_    = FEC;
  727. PFT_.Entry_[PFT_.NB_].PHB_    = PHB;
  728. PFT_.Entry_[PFT_.NB_].LIBptr_ = LIBptr;
  729. PFT_.Entry_[PFT_.NB_].aPATHptr_  = -1;
  730. PFT_.NB_++;
  731. }
  732. void MPLSAddressClassifier::PFTdelete(int entrynb)
  733. {
  734. PFT_.Entry_[entrynb].FEC_    = -1;
  735. PFT_.Entry_[entrynb].PHB_    = -1;
  736. PFT_.Entry_[entrynb].LIBptr_ = -1;
  737. }
  738. void MPLSAddressClassifier::PFTdeleteLIBptr(int LIBptr)
  739. {
  740. for (int i = 0; i < PFT_.NB_; i++) {
  741. if (PFT_.Entry_[i].LIBptr_ != LIBptr)
  742. continue; 
  743. PFT_.Entry_[i].FEC_    = -1;
  744. PFT_.Entry_[i].PHB_    = -1;
  745. PFT_.Entry_[i].LIBptr_ = -1;
  746. }  
  747. }
  748. void MPLSAddressClassifier::PFTupdate(int entrynb, int LIBptr)
  749. {
  750. PFT_.Entry_[entrynb].LIBptr_ = LIBptr;
  751. }
  752. int MPLSAddressClassifier::PFTlocate(int FEC, int PHB, int &LIBptr)
  753. {
  754. LIBptr = -1;
  755. if (FEC < 0) 
  756. return -1;
  757. for (int i = 0; i < PFT_.NB_; i++)
  758. if ((PFT_.Entry_[i].FEC_ == FEC) && (PFT_.Entry_[i].PHB_ == PHB)) {
  759. LIBptr = PFT_.Entry_[i].LIBptr_;
  760. return i;
  761. }
  762. return -1;
  763. }
  764. int MPLSAddressClassifier::PFTlookup(int FEC, int PHB, int &oIface, 
  765.      int &oLabel, int &LIBptr)
  766. {
  767. oIface = oLabel = LIBptr = -1;
  768. if (FEC < 0) 
  769. return -1;
  770. for (int i = 0; i < PFT_.NB_; i++)
  771. if ((PFT_.Entry_[i].FEC_ == FEC) && (PFT_.Entry_[i].PHB_ == PHB))
  772. return LIBlookup(PFT_.Entry_[i].LIBptr_,
  773.  oIface, oLabel, LIBptr);
  774. return -1;
  775. }
  776. void MPLSAddressClassifier::PFTdump(const char *id)
  777. {
  778. fflush(stdout);
  779. printf("      --) ___PFT dump___ [node: %s] (--n", id);
  780. printf("---------------------------------------------n");
  781. printf("     FEC       PHB       LIBptr  AltanativePathn");
  782. for (int i = 0; i < PFT_.NB_; i++) {
  783. if (PFT_.Entry_[i].FEC_ == -1) 
  784. continue;
  785. printf("     %d    ", PFT_.Entry_[i].FEC_);
  786. printf("     %d    ", PFT_.Entry_[i].PHB_);
  787. printf("     %d    ", PFT_.Entry_[i].LIBptr_);
  788. printf("     %dn", PFT_.Entry_[i].aPATHptr_);
  789. }
  790. printf("n");
  791. }
  792. //--------------------------------------------------
  793. // ER-LSP Table
  794. //--------------------------------------------------
  795. void MPLSAddressClassifier::ERBinsert(int LSPid, int FEC, int LIBptr)
  796. {
  797. ERB_.Entry_[ERB_.NB_].LSPid_  = LSPid;
  798. ERB_.Entry_[ERB_.NB_].FEC_    = FEC;
  799. ERB_.Entry_[ERB_.NB_].LIBptr_ = LIBptr;
  800. ERB_.NB_++;
  801. }
  802.  
  803. void MPLSAddressClassifier::ERBdelete(int entrynb)
  804. {
  805. ERB_.Entry_[entrynb].FEC_    = -1;
  806. ERB_.Entry_[entrynb].LSPid_  = -1;
  807. ERB_.Entry_[entrynb].LIBptr_ = -1;
  808. }
  809. void MPLSAddressClassifier::ERBupdate(int entrynb, int LIBptr)
  810. {
  811. ERB_.Entry_[entrynb].LIBptr_ = LIBptr;
  812. }
  813. int  MPLSAddressClassifier::ERBlocate(int LSPid, int FEC, int &LIBptr)
  814. {
  815. LIBptr = -1;
  816. for (int i = 0; i < ERB_.NB_; i++)
  817. if (ERB_.Entry_[i].LSPid_ == LSPid) {
  818. LIBptr = ERB_.Entry_[i].LIBptr_;
  819. return(i);
  820. }
  821. return -1;
  822. }
  823. void MPLSAddressClassifier::ERBdump(const char *id)
  824. {
  825. fflush(stdout);
  826. printf("      --) ___ERB dump___ [node: %s] (--n", id);
  827. printf("---------------------------------------------n");
  828. printf("     FEC       LSPid      LIBptrn");
  829. for (int i = 0; i < ERB_.NB_; i++) {
  830. if (ERB_.Entry_[i].FEC_ == -1) 
  831. continue;
  832. printf("     %d    ", ERB_.Entry_[i].FEC_);
  833. printf("     %d    ", ERB_.Entry_[i].LSPid_);
  834. printf("     %dn", ERB_.Entry_[i].LIBptr_);
  835. }
  836. printf("n");
  837. }
  838. //--------------------------------------------------
  839. // LIB (Label Information Base)
  840. //--------------------------------------------------
  841. int MPLSAddressClassifier::LIBinsert(int iIface, int iLabel, 
  842.      int oIface, int oLabel)
  843. {
  844. if (LIB_.NB_ == MPLS_MaxLIBEntryNB - 1) {
  845. fprintf(stderr, 
  846. "Error in LIBinstall: higher than MaxLIBEntryNBn");
  847. return -1;
  848. }
  849. LIB_.Entry_[LIB_.NB_].iIface_ = -1;
  850. LIB_.Entry_[LIB_.NB_].iLabel_ = -1;
  851. LIB_.Entry_[LIB_.NB_].oIface_ = -1;
  852. LIB_.Entry_[LIB_.NB_].oLabel_ = -1;
  853. if (iIface < 0) iIface = -1;
  854. if (iLabel < 0) iLabel = -1;
  855. if (oIface < 0) oIface = -1;
  856. if (oLabel < 0) oLabel = -1;
  857. LIB_.Entry_[LIB_.NB_].iIface_  = iIface;
  858. LIB_.Entry_[LIB_.NB_].iLabel_  = iLabel;
  859. LIB_.Entry_[LIB_.NB_].oIface_  = oIface;
  860. LIB_.Entry_[LIB_.NB_].oLabel_  = oLabel;
  861. LIB_.Entry_[LIB_.NB_].LIBptr_  = -1;
  862. LIB_.NB_++;
  863. return(LIB_.NB_-1);
  864. }
  865. int MPLSAddressClassifier::LIBisdeleted(int entrynb)
  866. {
  867. if ((LIB_.Entry_[entrynb].iIface_ == -1) &&
  868.     (LIB_.Entry_[entrynb].iLabel_ == -1) &&
  869.     (LIB_.Entry_[entrynb].oIface_ == -1) &&
  870.     (LIB_.Entry_[entrynb].oLabel_ == -1)) {
  871. LIB_.Entry_[entrynb].LIBptr_ = -1;
  872. // delete a entry referencing self in LIB
  873. for (int i = 0; i < LIB_.NB_; i++)
  874. if ((LIB_.Entry_[i].LIBptr_ == entrynb))
  875. LIB_.Entry_[i].LIBptr_ = -1;
  876. return 0;
  877. }
  878. return -1;
  879. }
  880. void MPLSAddressClassifier::LIBupdate(int entrynb, int iIface, int iLabel, 
  881.       int oIface, int oLabel)
  882. {
  883. if (iIface != MPLS_DONTCARE)
  884. LIB_.Entry_[entrynb].iIface_ = iIface;
  885. if (iLabel != MPLS_DONTCARE)    
  886. LIB_.Entry_[entrynb].iLabel_ = iLabel;
  887. if (oIface != MPLS_DONTCARE)
  888. LIB_.Entry_[entrynb].oIface_ = oIface;
  889. if (oLabel != MPLS_DONTCARE)
  890. LIB_.Entry_[entrynb].oLabel_ = oLabel;
  891. }
  892. int MPLSAddressClassifier::LIBlookup(int entrynb, int &oIface, 
  893.       int &oLabel, int &LIBptr)
  894. {
  895. oIface = oLabel = LIBptr = -1;
  896. if (entrynb < 0)
  897. return -1;
  898. oIface = LIB_.Entry_[entrynb].oIface_;
  899. oLabel = LIB_.Entry_[entrynb].oLabel_;
  900. LIBptr = LIB_.Entry_[entrynb].LIBptr_;
  901. return 0;
  902. }
  903. int MPLSAddressClassifier::LIBlookup(int iIface, int iLabel, int &oIface, 
  904.      int &oLabel, int &LIBptr)
  905. {
  906. oIface = oLabel = LIBptr = -1;
  907. if (iLabel < 0)
  908. return -1;
  909. for (int i = 0; i < LIB_.NB_; i++)
  910. if ((LIB_.Entry_[i].iLabel_ == iLabel)) {
  911. oIface = LIB_.Entry_[i].oIface_;
  912. oLabel = LIB_.Entry_[i].oLabel_;
  913. LIBptr = LIB_.Entry_[i].LIBptr_;
  914. return 0;
  915. return -1;
  916. }
  917. int MPLSAddressClassifier::LIBgetIncoming(int entrynb, int &iIface, 
  918.   int &iLabel)
  919. {
  920. if (entrynb < 0)
  921. return -1;
  922. iIface = LIB_.Entry_[entrynb].iIface_;
  923. iLabel = LIB_.Entry_[entrynb].iLabel_;
  924. return 0;
  925. }
  926. void MPLSAddressClassifier::LIBdump(const char *id)
  927. {
  928. fflush(stdout);
  929. printf("    ___LIB dump___ [node: %s]n", id);
  930. printf("---------------------------------------------n");
  931. printf("       #       iIface     iLabel      oIface     oLabel    LIBptrn");
  932. for (int i = 0; i < LIB_.NB_; i++) {
  933. if (!LIBisdeleted(i))
  934. continue;
  935. printf("     %d: ", i);
  936. printf("     %d    ", LIB_.Entry_[i].iIface_);
  937. printf("     %d  ", LIB_.Entry_[i].iLabel_);
  938. printf("     %d    ", LIB_.Entry_[i].oIface_);
  939. printf("     %d    ", LIB_.Entry_[i].oLabel_);
  940. printf("     %dn", LIB_.Entry_[i].LIBptr_);
  941. }
  942. printf("n");
  943. }
  944. //--------------------------------------------------
  945. // MPLS applications
  946. //--------------------------------------------------
  947. int MPLSAddressClassifier::ErLspStacking(int erFEC0,int erLSPid0, 
  948.  int erFEC, int erLSPid)
  949. {
  950. int erLIBptr0  =-1, erLIBptr  =-1;
  951. if ((ERBlocate(erLSPid0,erFEC0,erLIBptr0) < 0) || (erLIBptr0 < 0))
  952. return -1;
  953. if ((ERBlocate(erLSPid,erFEC,erLIBptr) < 0) || (erLIBptr < 0))
  954. return -1;
  955. LIB_.Entry_[erLIBptr0].LIBptr_ = erLIBptr;
  956. return 0;
  957. }
  958. int MPLSAddressClassifier::ErLspBinding(int FEC,int PHB, int erFEC, int LSPid)
  959. {
  960. int LIBptr=-1;
  961. int erLIBptr=-1;
  962. if ((ERBlocate(LSPid, erFEC, erLIBptr) < 0) || (erLIBptr < 0))
  963. return -1;
  964. int PFTnb = PFTlocate(FEC,PHB, LIBptr);
  965. if ((PFTnb < 0))
  966. PFTinsert(FEC,PHB, erLIBptr);
  967. else {
  968. if (LIBptr < 0)
  969. PFTupdate(PFTnb, LIBptr);
  970. else {  
  971. int i = LIBptr;
  972. while (i < 0) {
  973. LIBptr = i;;
  974. i = LIB_.Entry_[LIBptr].LIBptr_;
  975. }
  976. LIB_.Entry_[LIBptr].LIBptr_ = erLIBptr;
  977. }
  978. }
  979. return 0;
  980. }
  981. int MPLSAddressClassifier::FlowAggregation(int fineFEC, int finePHB, 
  982.    int coarseFEC, int coarsePHB)
  983. {
  984. int fLIBptr=-1;
  985. int cLIBptr=-1;
  986. if ((PFTlocate(coarseFEC,coarsePHB, cLIBptr) < 0) || (cLIBptr < 0))
  987. return -1;
  988. int PFTnb = PFTlocate(fineFEC,finePHB, fLIBptr);
  989. if ((PFTnb < 0))
  990. PFTinsert(fineFEC,finePHB, cLIBptr);
  991. else {
  992. if (fLIBptr < 0)
  993. PFTupdate(PFTnb, cLIBptr);
  994. else {
  995. int i=fLIBptr;
  996. while (i < 0) {
  997. fLIBptr = i;;
  998. i = LIB_.Entry_[fLIBptr].LIBptr_;
  999. }
  1000. LIB_.Entry_[fLIBptr].LIBptr_ = cLIBptr;
  1001. }
  1002. }
  1003.         return 0;
  1004. }
  1005. int MPLSAddressClassifier::aPathBinding(int FEC, int PHB, int erFEC, int LSPid)
  1006. {
  1007. int entrynb,tmp,erLIBptr;
  1008.       
  1009. entrynb = PFTlocate(FEC,PHB,tmp);
  1010. if ((entrynb < 0) || (ERBlocate(LSPid,erFEC,erLIBptr) < 0))
  1011. return -1;
  1012. PFT_.Entry_[entrynb].aPATHptr_ = erLIBptr;
  1013. return 0;
  1014. }
  1015. int MPLSAddressClassifier::aPathLookup(int FEC,int PHB, int &oIface,
  1016.        int &oLabel, int &LIBptr)
  1017. {
  1018. oIface = oLabel = LIBptr = -1;
  1019. if (FEC < 0) 
  1020. return -1;
  1021. for (int i = 0; i < PFT_.NB_; i++)
  1022. if ((PFT_.Entry_[i].FEC_ == FEC) && 
  1023.     (PFT_.Entry_[i].PHB_ == PHB))
  1024. return LIBlookup(PFT_.Entry_[i].aPATHptr_,
  1025.  oIface, oLabel, LIBptr);
  1026. return -1;
  1027. }
  1028. void MPLSAddressClassifier::trace(char *ptype, int psize, int ilabel, 
  1029.   char *op, int oiface, int olabel, int ttl)
  1030. {
  1031. if (trace_mpls_ != 1)
  1032. return;
  1033. Tcl::instance().evalf("%s trace-packet-switching " TIME_FORMAT 
  1034.       " %d %d %s %d %s %d %d %d %d",
  1035.       name(),
  1036.       Scheduler::instance().clock(),
  1037.       PI_.srcnode_,
  1038.       PI_.dst_.addr_,
  1039.       ptype,
  1040.       ilabel,
  1041.       op,
  1042.       oiface,
  1043.       olabel,
  1044.       ttl,
  1045.       psize);
  1046. }