mrcl_arp.cc

00001 /*-*-   Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
00002  *
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Computer Systems
00017  *      Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/arp.cc,v 1.12 2005/04/26 18:56:35 haldar Exp $
00035  */
00036 
00037 
00038 /* 
00039  * Ported from CMU/Monarch's code, nov'98 -Padma.
00040  *
00041  * basic arp cache and MAC addr resolution
00042  *
00043  * Note: code in this file violates the convention that addresses of
00044  * type Af_INET stored in nsaddr_t variables are stored in 24/8 format.
00045  * Many variables in nsaddr_t's in this file store ip addrs as simple ints.
00046  */
00047 
00048 #include <errno.h>
00049 
00050 #include "delay.h"
00051 //#include "debug.h"
00052 #include "mac.h"
00053 #include "mrcl_arp.h"
00054 #include "topography.h"
00055 #include "cmu-trace.h"
00056 #include "mobilenode.h"
00057 #include "mrcl_ll.h"
00058 #include "packet.h"
00059 #include <address.h>
00060 
00061 // #define DEBUG
00062 
00063 static class MrclMrclARPTableClass : public TclClass {
00064 public:
00065         MrclMrclARPTableClass() : TclClass("ARPTable/Mrcl") {}
00066         TclObject* create(int, const char*const* argv) {
00067                 return (new MrclARPTable(argv[4], argv[5]));
00068         }
00069 } class_mrclarptable;
00070 
00071 // int hdr_arp::offset_;
00072 
00073 // static class ARPHeaderClass : public PacketHeaderClass {
00074 // public:
00075 //         ARPHeaderClass() : PacketHeaderClass("PacketHeader/ARP",
00076 //                                              sizeof(hdr_arp)) { 
00077 //              bind_offset(&hdr_arp::offset_);
00078 //              bind();
00079 //      }
00080 // } class_arphdr;
00081 
00082 /* ======================================================================
00083    Address Resolution (ARP) Table
00084    ====================================================================== */
00085 
00086 MrclARPTable_List MrclARPTable::athead_ = { 0 };
00087 
00088 void
00089 MrclARPTable::Terminate()
00090 {
00091         MrclARPEntry *ll;
00092         for(ll = arphead_.lh_first; ll; ll = ll->arp_link_.le_next) {
00093                 if(ll->hold_) {
00094                         drop(ll->hold_, DROP_END_OF_SIMULATION);
00095                         ll->hold_ = 0;
00096                 }
00097         }
00098 }
00099 
00100 
00101 MrclARPTable::MrclARPTable(const char * IPaddr, const char *tclmac) : LinkDelay() {
00102         LIST_INIT(&arphead_);
00103 
00104         //node_ = (MobileNode*) TclObject::lookup(tclnode);
00105         //assert(node_);
00106         IPaddress_ = atoi(IPaddr);
00107         mac_ = (Mac*) TclObject::lookup(tclmac);
00108         assert(mac_);
00109         LIST_INSERT_HEAD(&athead_, this, link_);
00110 }
00111 
00112 int
00113 MrclARPTable::command(int argc, const char*const* argv)
00114 {
00115         if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {
00116                 Terminate();
00117                 //FALL-THROUGH to give parents a chance to reset
00118         }
00119         return LinkDelay::command(argc, argv);
00120 }
00121 
00122 int
00123 MrclARPTable::arpresolve(nsaddr_t dst, Packet *p, MrclLL *ll)
00124 {
00125         MrclARPEntry *llinfo ;
00126         assert(initialized());
00127         llinfo = arplookup(dst);
00128 
00129 #ifdef DEBUG
00130         fprintf(stderr, "%d - %s\n", IPaddress_, __FUNCTION__);
00131 #endif
00132         
00133         if(llinfo && llinfo->up_) {
00134                 mac_->hdr_dst((char*) HDR_MAC(p), llinfo->macaddr_);
00135                 return 0;
00136         }
00137 
00138         if(llinfo == 0) {
00139                 /*
00140                  *  Create a new ARP entry
00141                  */
00142                 llinfo = new MrclARPEntry(&arphead_, dst);
00143         }
00144 
00145         if(llinfo->count_ >= ARP_MAX_REQUEST_COUNT) {
00146                 /*
00147                  * Because there is not necessarily a scheduled event between
00148                  * this callback and the point where the callback can return
00149                  * to this point in the code, the order of operations is very
00150                  * important here so that we don't get into an infinite loop.
00151                  *                                      - josh
00152                  */
00153                 Packet *t = llinfo->hold_;
00154 
00155                 llinfo->count_ = 0;
00156                 llinfo->hold_ = 0;
00157                 hdr_cmn* ch;
00158                 
00159                 if(t) {
00160                         ch = HDR_CMN(t);
00161 
00162                         if (ch->xmit_failure_) {
00163                                 ch->xmit_reason_ = 0;
00164                                 ch->xmit_failure_(t, ch->xmit_failure_data_);
00165                         }
00166                         else {
00167                                 drop(t, DROP_IFQ_ARP_FULL);
00168                         }
00169                 }
00170 
00171                 ch = HDR_CMN(p);
00172 
00173                 if (ch->xmit_failure_) {
00174                         ch->xmit_reason_ = 0;
00175                         ch->xmit_failure_(p, ch->xmit_failure_data_);
00176                 }
00177                 else {
00178                         drop(p, DROP_IFQ_ARP_FULL);
00179                 }
00180 
00181                 return EADDRNOTAVAIL;
00182         }
00183 
00184         llinfo->count_++;
00185         if(llinfo->hold_)
00186                 drop(llinfo->hold_, DROP_IFQ_ARP_FULL);
00187         llinfo->hold_ = p;
00188 
00189         /*
00190          *  We don't have a MAC address for this node.  Send an ARP Request.
00191          *
00192          *  XXX: Do I need to worry about the case where I keep ARPing
00193          *       for the SAME destination.
00194          */
00195         int src = IPaddress_; // this host's IP addr
00196         arprequest(src, dst, ll);
00197         return EADDRNOTAVAIL;
00198 }
00199 
00200 
00201 MrclARPEntry*
00202 MrclARPTable::arplookup(nsaddr_t dst)
00203 {
00204         MrclARPEntry *a;
00205 
00206         for(a = arphead_.lh_first; a; a = a->nextarp()) {
00207                 if(a->ipaddr_ == dst)
00208                         return a;
00209         }
00210         return 0;
00211 }
00212 
00213 
00214 void
00215 MrclARPTable::arprequest(nsaddr_t src, nsaddr_t dst, MrclLL *ll)
00216 {
00217         Scheduler& s = Scheduler::instance();
00218         Packet *p = Packet::alloc();
00219 
00220         hdr_cmn *ch = HDR_CMN(p);
00221         char    *mh = (char*) HDR_MAC(p);
00222         hdr_ll  *lh = HDR_LL(p);
00223         hdr_arp *ah = HDR_ARP(p);
00224 
00225         ch->uid() = 0;
00226         ch->ptype() = PT_ARP;
00227         ch->size() = ARP_HDR_LEN;
00228         ch->iface() = -2;
00229         ch->error() = 0;
00230 
00231         mac_->hdr_dst(mh, MAC_BROADCAST);
00232         mac_->hdr_src(mh, ll->mac_->addr());
00233         mac_->hdr_type(mh, ETHERTYPE_ARP);
00234 
00235         lh->seqno() = 0;
00236         lh->lltype() = LL_DATA;
00237 
00238         ch->direction() = hdr_cmn::DOWN; // send this pkt down
00239         ah->arp_hrd = ARPHRD_ETHER;
00240         ah->arp_pro = ETHERTYPE_IP;
00241         ah->arp_hln = ETHER_ADDR_LEN;
00242         ah->arp_pln = sizeof(nsaddr_t);
00243         ah->arp_op  = ARPOP_REQUEST;
00244         ah->arp_sha = ll->mac_->addr();
00245         ah->arp_spa = src;
00246         ah->arp_tha = 0;                // what were're looking for
00247         ah->arp_tpa = dst;
00248 
00249         s.schedule(ll->downtarget_, p, delay_);
00250 }
00251 
00252 void
00253 MrclARPTable::arpinput(Packet *p, MrclLL *ll)
00254 {
00255         Scheduler& s = Scheduler::instance();
00256         hdr_arp *ah = HDR_ARP(p);
00257         MrclARPEntry *llinfo;
00258 
00259         assert(initialized());
00260 
00261 #ifdef DEBUG
00262         fprintf(stderr,
00263                 "%d - %s\n\top: %x, sha: %x, tha: %x, spa: %x, tpa: %x\n",
00264                 IPaddress_, __FUNCTION__, ah->arp_op,
00265                 ah->arp_sha, ah->arp_tha, ah->arp_spa, ah->arp_tpa);
00266 #endif
00267 
00268         if((llinfo = arplookup(ah->arp_spa)) == 0) {
00269 
00270                 /*
00271                  *  Create a new ARP entry
00272                  */
00273                 llinfo = new MrclARPEntry(&arphead_, ah->arp_spa);
00274         }
00275         assert(llinfo);
00276 
00277         llinfo->macaddr_ = ah->arp_sha;
00278         llinfo->up_ = 1;
00279 
00280         /*
00281          *  Can we send whatever's being held?
00282          */
00283         if(llinfo->hold_) {
00284                 hdr_cmn *ch = HDR_CMN(llinfo->hold_);
00285                 char *mh = (char*) HDR_MAC(llinfo->hold_);
00286                 hdr_ip *ih = HDR_IP(llinfo->hold_);
00287                 
00288                 // XXXHACK for now: 
00289                 // Future work: separate port-id from IP address ??
00290                 int dst = Address::instance().get_nodeaddr(ih->daddr());
00291                 
00292                 if((ch->addr_type() == NS_AF_NONE &&
00293                     dst == ah->arp_spa) ||
00294                    (NS_AF_INET == ch->addr_type() &&
00295                     ch->next_hop() == ah->arp_spa)) {
00296 #ifdef DEBUG
00297                         fprintf(stderr, "\tsending HELD packet.\n");
00298 #endif
00299                         mac_->hdr_dst(mh, ah->arp_sha);
00300                         //ll->hdr_dst(p, ah->arp_sha);
00301                         
00302                         s.schedule(ll->downtarget_, llinfo->hold_, delay_);
00303                         llinfo->hold_ = 0;
00304                 }
00305                 else {
00306                         fprintf(stderr, "\tfatal ARP error...\n");
00307                         exit(1);
00308                 }
00309         }
00310 
00311         if(ah->arp_op == ARPOP_REQUEST &&
00312                 ah->arp_tpa == IPaddress_) {
00313                 
00314                 hdr_cmn *ch = HDR_CMN(p);
00315                 char    *mh = (char*)HDR_MAC(p);
00316                 hdr_ll  *lh = HDR_LL(p);
00317 
00318                 ch->size() = ARP_HDR_LEN;
00319                 ch->error() = 0;
00320                 ch->direction() = hdr_cmn::DOWN; // send this pkt down
00321 
00322                 mac_->hdr_dst(mh, ah->arp_sha);
00323                 mac_->hdr_src(mh, ll->mac_->addr());
00324                 mac_->hdr_type(mh, ETHERTYPE_ARP);
00325 
00326                 lh->seqno() = 0;
00327                 lh->lltype() = LL_DATA;
00328 
00329                 // ah->arp_hrd = 
00330                 // ah->arp_pro =
00331                 // ah->arp_hln =
00332                 // ah->arp_pln =
00333 
00334                 ah->arp_op  = ARPOP_REPLY;
00335                 ah->arp_tha = ah->arp_sha;
00336                 ah->arp_sha = ll->mac_->addr();
00337 
00338                 nsaddr_t t = ah->arp_spa;
00339                 ah->arp_spa = ah->arp_tpa;
00340                 ah->arp_tpa = t;
00341 
00342                 s.schedule(ll->downtarget_, p, delay_);
00343                 return;
00344         }
00345         Packet::free(p);
00346 }
00347 

Generated on Wed Nov 26 15:47:28 2008 for NS-MIRACLE library by  doxygen 1.5.2