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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1997, 1998 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by the MASH Research
  16.  * Group at the University of California, Berkeley.
  17.  * 4. Neither the name of the University nor of the Research Group may be used
  18.  *    to endorse or promote products derived from this software without
  19.  *    specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33. #ifndef lint
  34. static const char rcsid[] =
  35.     "@(#) $Header: /cvsroot/nsnam/ns-2/emulate/tap.cc,v 1.15 2005/08/22 05:08:33 tomh Exp $ (UCB)";
  36. #endif
  37. #include "tap.h"
  38. static class TapAgentClass : public TclClass {
  39.  public:
  40. TapAgentClass() : TclClass("Agent/Tap") {}
  41. TclObject* create(int, const char*const*) {
  42. return (new TapAgent());
  43. }
  44. } class_tap_agent;
  45. TapAgent::TapAgent() : Agent(PT_LIVE), net_(NULL)
  46. {
  47. bind("maxpkt_", &maxpkt_);
  48. }
  49. //
  50. // link in a network to the agent.  Assumes net_ is non-zero
  51. //
  52. int
  53. TapAgent::linknet()
  54. {
  55. int mode = net_->mode();
  56. int rchan = net_->rchannel();
  57. int wchan = net_->schannel();
  58. unlink();
  59. if (mode == O_RDONLY || mode == O_RDWR) {
  60. // reading enabled?
  61. if (rchan < 0) {
  62. fprintf(stderr,
  63. "TapAgent(%s): network %s not open for reading (mode:%d)n",
  64.     name(), net_->name(), mode);
  65. return (TCL_ERROR);
  66. }
  67. link(rchan, TCL_READABLE);
  68. TDEBUG3("TapAgent(%s): linked sock %d as READABLEn",
  69. name(), rchan);
  70. } else if (mode != O_WRONLY) {
  71. if (mode == -1) {
  72. fprintf(stderr,
  73.    "TapAgent(%s): Network(%s) not opened properly.n",
  74. name(), net_->name());
  75. fprintf(stderr,
  76.    "(choose: readonly, readwrite, or writeonly)n");
  77. } else {
  78. fprintf(stderr,
  79.     "TapAgent(%s): unknown mode %d in Network(%s)n",
  80. name(), mode, net_->name());
  81. }
  82. return (TCL_ERROR);
  83. }
  84. if (mode == O_WRONLY || mode == O_RDWR) {
  85. // writing enabled?
  86. if (wchan < 0) {
  87. fprintf(stderr,
  88. "TapAgent(%s): network %s not open for writingn",
  89.     name(), net_->name());
  90. return (TCL_ERROR);
  91. }
  92. }
  93. return (TCL_OK);
  94. }
  95. int
  96. TapAgent::command(int argc, const char*const* argv)
  97. {
  98. Tcl& tcl = Tcl::instance();
  99. if (argc == 2) {
  100. if (strcmp(argv[1], "network") == 0) {
  101. tcl.result(name());
  102. return(TCL_OK);
  103. }
  104. if (argc == 3) {
  105. if (strcmp(argv[1], "network") == 0) {
  106. net_ = (Network *)TclObject::lookup(argv[2]);
  107. if (net_ != 0) {
  108. return(linknet());
  109. } else {
  110. fprintf(stderr,
  111. "TapAgent(%s): unknown network %sn",
  112.     name(), argv[2]);
  113. return (TCL_ERROR);
  114. }
  115. return(TCL_OK);
  116. }
  117. }
  118. return (Agent::command(argc, argv));
  119. }
  120. /*
  121.  * Receive a packet off the network and inject into the simulation.
  122.  */
  123. void
  124. TapAgent::recvpkt()
  125. {
  126. if (net_->mode() != O_RDWR && net_->mode() != O_RDONLY) {
  127. fprintf(stderr,
  128.   "TapAgent(%s): recvpkt called while in write-only mode!n",
  129.   name());
  130. return;
  131. }
  132. if (maxpkt_ <= 0) {
  133. fprintf(stderr,
  134.   "TapAgent(%s): recvpkt: maxpkt_ value too low (%d)n",
  135.   name(), maxpkt_);
  136. return;
  137. }
  138. // allocate packet and a data payload
  139. Packet* p = allocpkt(maxpkt_);
  140. // fill up payload
  141. sockaddr addr; // not really used (yet)
  142. double tstamp;
  143. int cc = net_->recv(p->accessdata(), maxpkt_, addr, tstamp);
  144. if (cc <= 0) {
  145. if (cc < 0) {
  146. perror("recv");
  147. }
  148. Packet::free(p);
  149. return;
  150. }
  151. TDEBUG4("%f: Tap(%s): recvpkt, cc:%dn", now(), name(), cc);
  152. // inject into simulator
  153. hdr_cmn* ch = HDR_CMN(p);
  154. ch->size() = cc;
  155. /*
  156.  * if the time-stamp on the pkt is sufficiently far in the future,
  157.  * put it in the scheduler instead of forwarding it immediately.
  158.  * This can happen if we are pulling packet from a trace file
  159.  * and we don't want them to be dispatched until later
  160.  *
  161.  * this agent assumes that the time stamps are in absolute
  162.  * time, so adjust it to relative time here
  163.  */
  164. double when = tstamp - now();
  165. if (when > 0.0) {
  166. TDEBUG5("%f: Tap(%s): DEFERRED PACKET %f secs, uid: "UID_PRINTF_FORMAT"n",
  167. now(), name(), when, p->uid_);
  168. ch->timestamp() = when;
  169. Scheduler::instance().schedule(target_, p, when);
  170. } else {
  171. TDEBUG4("%f: Tap(%s): recvpkt, writing to target: %sn",
  172. now(), name(), target_->name());
  173. ch->timestamp() = now();
  174. target_->recv(p);
  175. }
  176. return;
  177. }
  178. void
  179. TapAgent::dispatch(int)
  180. {
  181. /*
  182.  * Just process one packet.  We could put a loop here
  183.  * but instead we allow the dispatcher to call us back
  184.  * if there is a queue in the socket buffer; this allows
  185.  * other events to get a chance to slip in...
  186.  */
  187. #ifdef notdef
  188. Scheduler::instance().sync(); // sim clock gets set to now
  189. #endif
  190. recvpkt();
  191. }
  192. /*
  193.  * SIM -> Live
  194.  *
  195.  * Receive a packet from the simulation and inject into the network.
  196.  * if there is no network attached, call Connector::drop() to send
  197.  * to drop target
  198.  */
  199. void
  200. TapAgent::recv(Packet* p, Handler*)
  201. {
  202. (void) sendpkt(p);
  203. Packet::free(p);
  204. return;
  205. }
  206. int
  207. TapAgent::sendpkt(Packet* p)
  208. {
  209. if (net_->mode() != O_RDWR && net_->mode() != O_WRONLY) {
  210. fprintf(stderr,
  211.     "TapAgent(%s): sendpkt called while in read-only mode!n",
  212.     name());
  213. return (-1);
  214. }
  215. // send packet into the live network
  216. hdr_cmn* hc = HDR_CMN(p);
  217. if (net_ == NULL) {
  218. fprintf(stderr,
  219.          "TapAgent(%s): sendpkt attempted with NULL netn",
  220.  name());
  221. drop(p);
  222. return (-1);
  223. }
  224. if (net_->send(p->accessdata(), hc->size()) < 0) {
  225. fprintf(stderr,
  226.     "TapAgent(%s): sendpkt (%p, %d): %sn",
  227.     name(), p->accessdata(), hc->size(), strerror(errno));
  228. return (-1);
  229. }
  230. TDEBUG3("TapAgent(%s): sent packet (sz: %d)n",
  231. name(), hc->size());
  232. return 0;
  233. }