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

通讯编程

开发平台:

Visual C++

  1. /*-*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
  2.  *
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * $Header: /cvsroot/nsnam/ns-2/mac/arp.cc,v 1.12 2005/04/26 18:56:35 haldar Exp $
  35.  */
  36. /* 
  37.  * Ported from CMU/Monarch's code, nov'98 -Padma.
  38.  *
  39.  * basic arp cache and MAC addr resolution
  40.  *
  41.  * Note: code in this file violates the convention that addresses of
  42.  * type Af_INET stored in nsaddr_t variables are stored in 24/8 format.
  43.  * Many variables in nsaddr_t's in this file store ip addrs as simple ints.
  44.  */
  45. #include <errno.h>
  46. #include "delay.h"
  47. //#include "debug.h"
  48. #include "mac.h"
  49. #include "arp.h"
  50. #include "topography.h"
  51. #include "cmu-trace.h"
  52. #include "mobilenode.h"
  53. #include "ll.h"
  54. #include "packet.h"
  55. #include <address.h>
  56. // #define DEBUG
  57. static class ARPTableClass : public TclClass {
  58. public:
  59.         ARPTableClass() : TclClass("ARPTable") {}
  60.         TclObject* create(int, const char*const* argv) {
  61.                 return (new ARPTable(argv[4], argv[5]));
  62.         }
  63. } class_arptable;
  64. int hdr_arp::offset_;
  65. static class ARPHeaderClass : public PacketHeaderClass {
  66. public:
  67.         ARPHeaderClass() : PacketHeaderClass("PacketHeader/ARP",
  68.                                              sizeof(hdr_arp)) { 
  69. bind_offset(&hdr_arp::offset_);
  70. }
  71. } class_arphdr;
  72. /* ======================================================================
  73.    Address Resolution (ARP) Table
  74.    ====================================================================== */
  75. ARPTable_List ARPTable::athead_ = { 0 };
  76. void
  77. ARPTable::Terminate()
  78. {
  79. ARPEntry *ll;
  80. for(ll = arphead_.lh_first; ll; ll = ll->arp_link_.le_next) {
  81. if(ll->hold_) {
  82. drop(ll->hold_, DROP_END_OF_SIMULATION);
  83. ll->hold_ = 0;
  84. }
  85. }
  86. }
  87. ARPTable::ARPTable(const char *tclnode, const char *tclmac) : LinkDelay() {
  88. LIST_INIT(&arphead_);
  89.         node_ = (MobileNode*) TclObject::lookup(tclnode);
  90. assert(node_);
  91. mac_ = (Mac*) TclObject::lookup(tclmac);
  92. assert(mac_);
  93. LIST_INSERT_HEAD(&athead_, this, link_);
  94. }
  95. int
  96. ARPTable::command(int argc, const char*const* argv)
  97. {
  98. if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {
  99. Terminate();
  100. //FALL-THROUGH to give parents a chance to reset
  101. }
  102. return LinkDelay::command(argc, argv);
  103. }
  104. int
  105. ARPTable::arpresolve(nsaddr_t dst, Packet *p, LL *ll)
  106. {
  107.         ARPEntry *llinfo ;
  108. assert(initialized());
  109. llinfo = arplookup(dst);
  110. #ifdef DEBUG
  111.         fprintf(stderr, "%d - %sn", node_->address(), __FUNCTION__);
  112. #endif
  113. if(llinfo && llinfo->up_) {
  114. mac_->hdr_dst((char*) HDR_MAC(p), llinfo->macaddr_);
  115. return 0;
  116. }
  117. if(llinfo == 0) {
  118. /*
  119.  *  Create a new ARP entry
  120.  */
  121. llinfo = new ARPEntry(&arphead_, dst);
  122. }
  123.         if(llinfo->count_ >= ARP_MAX_REQUEST_COUNT) {
  124.                 /*
  125.                  * Because there is not necessarily a scheduled event between
  126.                  * this callback and the point where the callback can return
  127.                  * to this point in the code, the order of operations is very
  128.                  * important here so that we don't get into an infinite loop.
  129.                  *                                      - josh
  130.                  */
  131.                 Packet *t = llinfo->hold_;
  132.                 llinfo->count_ = 0;
  133.                 llinfo->hold_ = 0;
  134. hdr_cmn* ch;
  135.                 if(t) {
  136.                         ch = HDR_CMN(t);
  137.                         if (ch->xmit_failure_) {
  138.                                 ch->xmit_reason_ = 0;
  139.                                 ch->xmit_failure_(t, ch->xmit_failure_data_);
  140.                         }
  141.                         else {
  142.                                 drop(t, DROP_IFQ_ARP_FULL);
  143.                         }
  144.                 }
  145.                 ch = HDR_CMN(p);
  146. if (ch->xmit_failure_) {
  147.                         ch->xmit_reason_ = 0;
  148.                         ch->xmit_failure_(p, ch->xmit_failure_data_);
  149.                 }
  150.                 else {
  151.                         drop(p, DROP_IFQ_ARP_FULL);
  152.                 }
  153.                 return EADDRNOTAVAIL;
  154.         }
  155. llinfo->count_++;
  156. if(llinfo->hold_)
  157. drop(llinfo->hold_, DROP_IFQ_ARP_FULL);
  158. llinfo->hold_ = p;
  159. /*
  160.  *  We don't have a MAC address for this node.  Send an ARP Request.
  161.  *
  162.  *  XXX: Do I need to worry about the case where I keep ARPing
  163.  *  for the SAME destination.
  164.  */
  165. int src = node_->address(); // this host's IP addr
  166. arprequest(src, dst, ll);
  167. return EADDRNOTAVAIL;
  168. }
  169. ARPEntry*
  170. ARPTable::arplookup(nsaddr_t dst)
  171. {
  172. ARPEntry *a;
  173. for(a = arphead_.lh_first; a; a = a->nextarp()) {
  174. if(a->ipaddr_ == dst)
  175. return a;
  176. }
  177. return 0;
  178. }
  179. void
  180. ARPTable::arprequest(nsaddr_t src, nsaddr_t dst, LL *ll)
  181. {
  182. Scheduler& s = Scheduler::instance();
  183. Packet *p = Packet::alloc();
  184. hdr_cmn *ch = HDR_CMN(p);
  185. char *mh = (char*) HDR_MAC(p);
  186. hdr_ll *lh = HDR_LL(p);
  187. hdr_arp *ah = HDR_ARP(p);
  188. ch->uid() = 0;
  189. ch->ptype() = PT_ARP;
  190. ch->size() = ARP_HDR_LEN;
  191. ch->iface() = -2;
  192. ch->error() = 0;
  193. mac_->hdr_dst(mh, MAC_BROADCAST);
  194. mac_->hdr_src(mh, ll->mac_->addr());
  195. mac_->hdr_type(mh, ETHERTYPE_ARP);
  196. lh->seqno() = 0;
  197. lh->lltype() = LL_DATA;
  198. ch->direction() = hdr_cmn::DOWN; // send this pkt down
  199. ah->arp_hrd = ARPHRD_ETHER;
  200. ah->arp_pro = ETHERTYPE_IP;
  201. ah->arp_hln = ETHER_ADDR_LEN;
  202. ah->arp_pln = sizeof(nsaddr_t);
  203. ah->arp_op  = ARPOP_REQUEST;
  204. ah->arp_sha = ll->mac_->addr();
  205. ah->arp_spa = src;
  206. ah->arp_tha = 0; // what were're looking for
  207. ah->arp_tpa = dst;
  208. s.schedule(ll->downtarget_, p, delay_);
  209. }
  210. void
  211. ARPTable::arpinput(Packet *p, LL *ll)
  212. {
  213. Scheduler& s = Scheduler::instance();
  214. hdr_arp *ah = HDR_ARP(p);
  215. ARPEntry *llinfo;
  216. assert(initialized());
  217. #ifdef DEBUG
  218. fprintf(stderr,
  219.                 "%d - %sntop: %x, sha: %x, tha: %x, spa: %x, tpa: %xn",
  220. node_->address(), __FUNCTION__, ah->arp_op,
  221.                 ah->arp_sha, ah->arp_tha, ah->arp_spa, ah->arp_tpa);
  222. #endif
  223. if((llinfo = arplookup(ah->arp_spa)) == 0) {
  224. /*
  225.  *  Create a new ARP entry
  226.  */
  227. llinfo = new ARPEntry(&arphead_, ah->arp_spa);
  228. }
  229.         assert(llinfo);
  230. llinfo->macaddr_ = ah->arp_sha;
  231. llinfo->up_ = 1;
  232. /*
  233.  *  Can we send whatever's being held?
  234.  */
  235. if(llinfo->hold_) {
  236. hdr_cmn *ch = HDR_CMN(llinfo->hold_);
  237. char *mh = (char*) HDR_MAC(llinfo->hold_);
  238.                 hdr_ip *ih = HDR_IP(llinfo->hold_);
  239.                 
  240. // XXXHACK for now: 
  241. // Future work: separate port-id from IP address ??
  242. int dst = Address::instance().get_nodeaddr(ih->daddr());
  243. if((ch->addr_type() == NS_AF_NONE &&
  244.                     dst == ah->arp_spa) ||
  245.                    (NS_AF_INET == ch->addr_type() &&
  246.                     ch->next_hop() == ah->arp_spa)) {
  247. #ifdef DEBUG
  248. fprintf(stderr, "tsending HELD packet.n");
  249. #endif
  250. mac_->hdr_dst(mh, ah->arp_sha);
  251. //ll->hdr_dst(p, ah->arp_sha);
  252. s.schedule(ll->downtarget_, llinfo->hold_, delay_);
  253. llinfo->hold_ = 0;
  254. }
  255.                 else {
  256.                         fprintf(stderr, "tfatal ARP error...n");
  257.                         exit(1);
  258.                 }
  259. }
  260. if(ah->arp_op == ARPOP_REQUEST &&
  261. ah->arp_tpa == node_->address()) {
  262. hdr_cmn *ch = HDR_CMN(p);
  263. char *mh = (char*)HDR_MAC(p);
  264. hdr_ll  *lh = HDR_LL(p);
  265. ch->size() = ARP_HDR_LEN;
  266. ch->error() = 0;
  267. ch->direction() = hdr_cmn::DOWN; // send this pkt down
  268. mac_->hdr_dst(mh, ah->arp_sha);
  269. mac_->hdr_src(mh, ll->mac_->addr());
  270. mac_->hdr_type(mh, ETHERTYPE_ARP);
  271. lh->seqno() = 0;
  272. lh->lltype() = LL_DATA;
  273. // ah->arp_hrd = 
  274. // ah->arp_pro =
  275. // ah->arp_hln =
  276. // ah->arp_pln =
  277. ah->arp_op  = ARPOP_REPLY;
  278. ah->arp_tha = ah->arp_sha;
  279. ah->arp_sha = ll->mac_->addr();
  280. nsaddr_t t = ah->arp_spa;
  281. ah->arp_spa = ah->arp_tpa;
  282. ah->arp_tpa = t;
  283. s.schedule(ll->downtarget_, p, delay_);
  284. return;
  285. }
  286. Packet::free(p);
  287. }