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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (C) 1999 by the University of Southern California
  4.  * $Id: classifier-bst.cc,v 1.15 2005/08/25 18:58:01 johnh Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. #ifndef lint
  46. static const char rcsid[] =
  47.     "@(#) $Header: /cvsroot/nsnam/ns-2/classifier/classifier-bst.cc,v 1.15 2005/08/25 18:58:01 johnh Exp $";
  48. #endif
  49. #include <assert.h>
  50. #include <stdlib.h>
  51. #include "config.h"
  52. #include "packet.h"
  53. #include "ip.h"
  54. #include "classifier.h"
  55. #include "classifier-mcast.h"
  56. #include "address.h"
  57. #include "trace.h"
  58. #include "ump.h"
  59. struct upstream_info {
  60. int dst;
  61. int node_id;
  62. char* oiflink;
  63. struct upstream_info* next;
  64. };
  65. class MCastBSTClassifier : public MCastClassifier {
  66. public:
  67. MCastBSTClassifier();
  68. ~MCastBSTClassifier();
  69. static const char STARSYM[]; //"source" field for shared trees
  70. protected:
  71. virtual int classify(Packet * p);
  72. upstream_info *oif2RP_;
  73. int32_t node_id_;
  74. void insert_upstream_info(int dst);
  75. virtual void recv(Packet *p, Handler *h);
  76. void upstream_add(int dst, char *oif2RP, int node_id);
  77. upstream_info* upstream_find(int dst);
  78. };
  79. const char MCastBSTClassifier::STARSYM[]= "x"; //"source" field for shared trees
  80. static class MCastBSTClassifierClass : public TclClass {
  81. public:
  82. MCastBSTClassifierClass() : TclClass("Classifier/Multicast/BST") {}
  83. TclObject* create(int, const char*const*) {
  84. return (new MCastBSTClassifier());
  85. }
  86. } class_mcast_bidir_classifier;
  87. MCastBSTClassifier::MCastBSTClassifier()
  88. {
  89. oif2RP_ = NULL;
  90. node_id_ = -1;
  91. }
  92. MCastBSTClassifier::~MCastBSTClassifier()
  93. {
  94. clearAll();
  95. }
  96. int MCastBSTClassifier::classify(Packet *pkt)
  97. {
  98. hdr_cmn* h = hdr_cmn::access(pkt);
  99. hdr_ip* ih = hdr_ip::access(pkt);
  100. nsaddr_t src = ih->saddr(); /*XXX*/
  101. nsaddr_t dst = ih->daddr();
  102. int iface = h->iface();
  103. Tcl& tcl = Tcl::instance();
  104. hashnode* p = lookup(src, dst, iface);
  105. //printf("%s, src %d, dst %d, iface %d, p %dn", name(), src, dst, iface, p);
  106.   if (p == 0)
  107.           p = lookup_star(dst, iface);
  108. if (p == 0) {
  109. if ((p = lookup(src, dst)) == 0)
  110. p = lookup_star(dst);
  111. if (p == 0) {
  112.    // Didn't find an entry.
  113. tcl.evalf("%s new-group %ld %ld %d cache-miss", 
  114.   name(), src, dst, iface);
  115. // XXX see McastProto.tcl for the return values 0 -
  116. // once, 1 - twice 
  117. //printf("cache-miss result= %sn", tcl.result());
  118. int res= atoi(tcl.result());
  119. if (res)
  120. insert_upstream_info(dst);
  121. return (res)? Classifier::TWICE : Classifier::ONCE;
  122. }
  123. if (p->iif == ANY_IFACE.value()) // || iface == UNKN_IFACE.value())
  124. return p->slot;
  125. tcl.evalf("%s new-group %ld %ld %d wrong-iif", 
  126.   name(), src, dst, iface);
  127. //printf("wrong-iif result= %sn", tcl.result());
  128. int res= atoi(tcl.result());
  129. return (res)? Classifier::TWICE : Classifier::ONCE;
  130. }
  131. return p->slot;
  132. }
  133. void MCastBSTClassifier::recv(Packet *p, Handler *h) 
  134. {
  135. hdr_cmn* h_cmn = hdr_cmn::access(p);
  136. hdr_ip* ih = hdr_ip::access(p);
  137.   hdr_ump* ump = hdr_ump::access(p);
  138. nsaddr_t dst = ih->daddr();
  139. Tcl& tcl = Tcl::instance();
  140. upstream_info *u_info;
  141. if (node_id_ == -1) {
  142. tcl.evalf("[%s set node_] id", name());
  143. sscanf(tcl.result(), "%d", &node_id_);
  144. } // if
  145. nsaddr_t src = ih->saddr(); /*XXX*/
  146. NsObject *node = find(p);
  147. if (node == NULL) {
  148. Packet::free(p);
  149. return;
  150. } // if
  151. if ((node_id_ != src) && (ump->isSet) && (ump->umpID_ != node_id_)) {
  152. // If this node is not the next hop upstream router,
  153. // and if there are no receivers connected to it, then 
  154. // we should immediately drop the packet before we
  155. // trigger a chace miss
  156. int rpf_iface;
  157. tcl.evalf("%s check-rpf-link %d %d", name(), node_id_, dst);
  158. sscanf(tcl.result(), "%d", &rpf_iface);
  159. if (rpf_iface != h_cmn->iface()) {
  160. // The RPF check has failed so we have to drop
  161. // the packet.  Otherwise, we will create
  162. // duplicate packets on the net.
  163.    Packet::free(p);
  164.    return;
  165. // The following code demonstrates how we
  166. // could generate duplicates if RPF check is
  167. // ignord.  Do not reset the UMP and then we
  168. // will have even more duplicates.  Remember
  169. // to comment out the previous two lines
  170. //   ih->flowid()++;
  171. } else 
  172. ump->isSet = 0;
  173. } // if
  174. if (src == node_id_) {
  175. memset(ump, 0, sizeof(hdr_ump)); // Initialize UMP to 0
  176. // We need to set the UMP option.  We need to find the
  177. // next hop router to the source and place it in the
  178. // UMP option.
  179. u_info = upstream_find(dst);
  180. if (!u_info) {
  181. printf("Error: Mcast info does not existn");
  182. exit(0);
  183. } // if
  184. ump->isSet = 1;
  185. ump->umpID_ = node_id_;
  186. } // if
  187. //  if (ump->isSet) {
  188. //  if (ump->umpID_ != node_id_) {
  189. //  // By now we are sure that the packet has
  190. //  // arrived on an RPF link.  So the UMP portion 
  191. //  // of the packet should be cleared before it
  192. //  // is sent downstream
  193. //  ump->isSet = 0;
  194. //  } // if
  195. //  } // if
  196. if (ump->isSet) {
  197. u_info = upstream_find(dst);
  198. if (node_id_ == u_info->node_id)
  199. // If the next hop is the node itself, then we
  200. // are at the RP.
  201. ump->isSet = 0;
  202. else {
  203. ump->umpID_ = u_info->node_id;
  204. ump->oif = strdup(u_info->oiflink);
  205. } // else
  206. } else {
  207. int match;
  208. tcl.evalf("%s match-BST-iif %d %d", name(),
  209.   h_cmn->iface(), dst);  
  210. sscanf(tcl.result(), "%d", (int *)&match);
  211. if (!match) {
  212. Packet::free(p);
  213. return;
  214. } // else
  215. } // else
  216. node->recv(p, h);
  217. } // MCastBSTClassifier::recv
  218. void MCastBSTClassifier::upstream_add(int dst, char *link, int node_id)
  219. {
  220. struct upstream_info *next,
  221. *current;
  222. if (oif2RP_) {
  223. next = oif2RP_;
  224. do {
  225. current = next;
  226. if (current->dst == dst) {
  227. free(current->oiflink);
  228. current->oiflink = strdup(link);
  229. current->node_id = node_id;
  230. return;
  231. } // if
  232. next = current->next;
  233. } while (next);
  234. next = new(struct upstream_info);
  235. next->dst = dst;
  236. next->oiflink = strdup(link);
  237. next->node_id = node_id;
  238. current->next = next;
  239. } else {
  240. oif2RP_ = new(struct upstream_info);
  241. oif2RP_->dst = dst;
  242. oif2RP_->oiflink = strdup(link);
  243. oif2RP_->node_id = node_id;
  244. oif2RP_->next = NULL;
  245. } // else
  246. } // MCastBSTClassifier::upstream_add
  247. upstream_info* MCastBSTClassifier::upstream_find(int dst)
  248. {
  249. upstream_info *index;
  250. index = oif2RP_;
  251. while (index) {
  252. if (index->dst == dst)
  253. return index;
  254. index = index->next;
  255. } // while
  256. return NULL;
  257. } // MCastBSTClassifier::upstream_find
  258. void MCastBSTClassifier::insert_upstream_info(int dst) 
  259. {
  260. char temp_str[100];
  261. int nodeID;
  262. Tcl& tcl = Tcl::instance();
  263. tcl.evalf("%s info class", name());
  264. sscanf(tcl.result(), "%s", temp_str);
  265. tcl.evalf("%s upstream-link %d", name(), dst);
  266. sscanf(tcl.result(), "%s %d", temp_str, &nodeID);
  267. upstream_add(dst, temp_str, nodeID);
  268. } // MCastBSTClassifier::insert_upstream_info