mll-module.cc

00001 /*
00002  * Copyright (c) 2008, Karlstad University
00003  * Erik Andersson, Emil Ljungdahl, Lars-Olof Moilanen
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 are met:
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the <organization> nor the
00014  *       names of its contributors may be used to endorse or promote products
00015  *       derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS ``AS IS'' AND ANY
00018  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
00021  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  *
00028  * $Id: mll-module.cc 92 2008-03-25 19:35:54Z emil $
00029  */
00030 
00031 #include "mll-module.h"
00032 #include <mmac-clmsg.h>
00033 #include <ip-clmsg.h>
00034 
00035 extern ClMessage_t IP_CLMSG_SEND_ADDR;
00036 
00037 static class MLLModuleClass : public TclClass {
00038         public:
00039                 MLLModuleClass() : TclClass("Module/MLL") {}
00040                 TclObject* create(int, const char*const*) {
00041                         return (new MLLModule());
00042                 }
00043 } class_ll;
00044 
00045 MLLModule::MLLModule() : seqno_(0), ackno_(0)
00046 {
00047         arptable_ = new MARPTable();
00048 }
00049 
00050 MLLModule::~MLLModule()
00051 {
00052 }
00053 
00054 int MLLModule::crLayCommand(ClMessage* m)
00055 {
00056         if(m->type() == IP_CLMSG_SEND_ADDR)
00057         {
00058                 nsaddr_t tmp = ((IPClMsgSendAddr *)m)->getAddr();
00059                 netAddr.push_back(tmp);
00060                 delete m;
00061                 return 1;
00062         }
00063         return Module::crLayCommand(m);
00064 }
00065 
00066 
00067 int MLLModule::recvAsyncClMsg(ClMessage* m)
00068 {
00069         if(m->type() == IP_CLMSG_SEND_ADDR)
00070         {
00071                 nsaddr_t tmp = ((IPClMsgSendAddr *)m)->getAddr();
00072                 netAddr.push_back(tmp);
00073                 delete m;
00074                 return 1;
00075         }
00076         return Module::crLayCommand(m);
00077 }
00078 
00079 
00080 int MLLModule::command(int argc, const char*const* argv)
00081 {
00082   if (argc == 2)
00083     {
00084       if (strcasecmp(argv[1], "reset") == 0) {
00085         arptable_->clear();
00086         //FALL-THROUGH to give parents a chance to reset
00087       }
00088     }
00089   if (argc == 4)
00090     {
00091       if (strcasecmp(argv[1], "addentry") == 0)
00092         {
00093           nsaddr_t ipaddr = atoi(argv[2]);
00094           MARPEntry* e = new MARPEntry(ipaddr);
00095           e->macaddr_ = atoi(argv[3]);
00096           e->up_ = 1;
00097           arptable_->addEntry(e);
00098           return TCL_OK;
00099         }
00100     }
00101   return Module::command(argc, argv);
00102 }
00103 
00104 void MLLModule::recv(Packet* p)
00105 {
00106         recv(p, -1);
00107 }
00108 
00109 void MLLModule::recv(Packet *p, int idSrc)
00110 {
00111         hdr_cmn *ch = HDR_CMN(p);
00112         if(ch->direction() == hdr_cmn::UP)
00113         {
00114                 if(ch->ptype_ == PT_ARP)
00115                         processARP(p, idSrc);
00116                 else
00117                         sendUp(p);
00118         }
00119         else
00120         {
00121                 ch->direction() = hdr_cmn::DOWN;
00122                 sendDown(p);
00123         }
00124 }
00125 
00126 void MLLModule::sendDown(Packet* p)
00127 {
00128         hdr_cmn *ch = HDR_CMN(p);
00129         hdr_ip *ih = HDR_IP(p);
00130         nsaddr_t dst = ih->daddr();
00131         hdr_ll *llh = HDR_LL(p);
00132         hdr_mac *mh = HDR_MAC(p);
00133 
00134         llh->seqno_ = ++seqno_;
00135         llh->lltype() = LL_DATA;
00136 
00137         mh->macSA() = getDownAddr();
00138         mh->hdr_type() = ETHERTYPE_IP;
00139         int tx = 0;
00140 
00141         switch(ch->addr_type()) {
00142 
00143                 case NS_AF_ILINK:
00144                         /* Uhh!? nsaddr_t to int!? */
00145                         mh->macDA() = ch->next_hop();
00146                         break;
00147 
00148                 case NS_AF_INET:
00149                         dst = ch->next_hop();
00150                         /* FALL THROUGH */
00151 
00152                 case NS_AF_NONE:
00153                 
00154                         if (IP_BROADCAST == (u_int32_t) dst)
00155                         {
00156                                 mh->macDA() = MAC_BROADCAST;
00157                                 break;
00158                         }
00159 
00160                         /* Resolv ARP */
00161                         tx = arpResolve(dst, p);
00162                         break;
00163 
00164                 default:
00165                         mh->macDA() = MAC_BROADCAST;
00166                         break;
00167         }
00168 
00169         if (tx == 0)
00170         {
00171                 Module::sendDown(p);
00172         }
00173 }
00174 
00175 void MLLModule::sendUp(Packet* p)
00176 {
00177         Module::sendUp(p);
00178 }
00179 
00180 void MLLModule::processARP(Packet* p, int idSrc)
00181 {
00182         hdr_arp *ah = HDR_ARP(p);
00183         MARPEntry *llinfo;
00184 
00185         /* If we don't have requesting node already, add it */
00186         if((llinfo = arptable_->lookup(ah->arp_spa)) == 0) {
00187 
00188                 /* Create a new ARP entry */
00189                 llinfo = new MARPEntry(ah->arp_spa);
00190                 arptable_->addEntry(llinfo);
00191         }
00192         llinfo->macaddr_ = ah->arp_sha;
00193         llinfo->up_ = 1;
00194 
00195         /* If packet was stored, can we send whatever's being held? */
00196         if(llinfo->hold_)
00197         {
00198                 hdr_cmn *ch = HDR_CMN(llinfo->hold_);
00199                 hdr_mac *mh = HDR_MAC(llinfo->hold_);
00200                 hdr_ip *ih = HDR_IP(llinfo->hold_);
00201                 nsaddr_t dst = ih->daddr();
00202 
00203                 if((ch->addr_type() == NS_AF_NONE &&
00204                                   dst == ah->arp_spa) ||
00205                                   (NS_AF_INET == ch->addr_type() &&
00206                                   ch->next_hop() == ah->arp_spa))
00207                 {
00208                         if(debug_ > 5)
00209                                 printf("\tsending HELD packet.\n");
00210 
00211                         mh->macDA() = ah->arp_sha;
00212 
00213                         Module::sendDown(llinfo->hold_);
00214                         llinfo->hold_ = 0;
00215                 }
00216                 else
00217                 {
00218                         fprintf(stderr, "\tfatal ARP error...\n");
00219                          exit(1);
00220                 }
00221         }
00222 
00223         if(ah->arp_op == ARPOP_REQUEST && netAddrPresent(ah->arp_tpa))
00224         {
00225                 hdr_cmn *ch = HDR_CMN(p);
00226                 hdr_mac *mh = HDR_MAC(p);
00227                 hdr_ll  *lh = HDR_LL(p);
00228 
00229                 ch->size() = ARP_HDR_LEN;
00230                 ch->error() = 0;
00231                 ch->direction() = hdr_cmn::DOWN; // send this pkt down
00232 
00233                 int downAddr = getDownAddr(idSrc);
00234 
00235                 mh->macDA() = ah->arp_sha;
00236                 mh->macSA() = downAddr;
00237                 mh->hdr_type() = ETHERTYPE_ARP;
00238 
00239                 lh->seqno() = 0;
00240                 lh->lltype() = LL_DATA;
00241 
00242                 ah->arp_op  = ARPOP_REPLY;
00243                 ah->arp_tha = ah->arp_sha;
00244                 ah->arp_sha = downAddr;
00245 
00246                 nsaddr_t t = ah->arp_spa;
00247                 ah->arp_spa = ah->arp_tpa;
00248                 ah->arp_tpa = t;
00249 
00250                 Module::sendDown(p);
00251                 return;
00252         }
00253         Packet::free(p);
00254 }
00255 
00256 bool MLLModule::netAddrPresent(nsaddr_t addr)
00257 {
00258         fillNetAddrTable();
00259         vector<nsaddr_t>::iterator p = find(netAddr.begin(), netAddr.end(), addr);
00260         return (p != netAddr.end());
00261 }
00262 
00263 void MLLModule::fillNetAddrTable()
00264 {
00265         netAddr.clear();
00266         IPClMsgReqAddr *c = new IPClMsgReqAddr(getId());
00267         c->setDest(CLBROADCASTADDR);
00268         sendSyncClMsgUp(c);
00269         delete c;
00270 }
00271 
00272 int MLLModule::getDownAddr(int downId)
00273 {
00274         MacClMsgGetAddr *c;
00275         if(downId != -1)
00276         {
00277                 c = new MacClMsgGetAddr(UNICAST, downId);
00278                 sendSyncClMsgDown(c);
00279         }
00280         else
00281         {
00282                 c = new MacClMsgGetAddr(BROADCAST, CLBROADCASTADDR);
00283                 sendSyncClMsgDown(c);
00284         }
00285         int val = c->getAddr();
00286         delete c;
00287         return val;
00288 }
00289 
00290 int MLLModule::arpResolve(nsaddr_t dst, Packet* p)
00291 {
00292         hdr_mac *mh = HDR_MAC(p);
00293         MARPEntry *llinfo;
00294         llinfo = arptable_->lookup(dst);
00295 
00296         // Found entry, set dest and return
00297         if(llinfo && llinfo->up_)
00298         {
00299                 mh->macDA() = llinfo->macaddr_;
00300                 return 0;
00301         }
00302 
00303         if(llinfo == 0) {
00304                 /* Create a new ARP entry */
00305                 llinfo = new MARPEntry(dst);
00306                 arptable_->addEntry(llinfo);
00307         }
00308 
00309         if(llinfo->count_ >= ARP_MAX_REQUEST_COUNT) {
00310                 /*
00311                 * Because there is not necessarily a scheduled event between
00312                 * this callback and the point where the callback can return
00313                 * to this point in the code, the order of operations is very
00314                 * important here so that we don't get into an infinite loop.
00315                 *                                      - josh
00316                 */
00317                 Packet *t = llinfo->hold_;
00318 
00319                 llinfo->count_ = 0;
00320                 llinfo->hold_ = 0;
00321                 hdr_cmn* ch;
00322                 
00323                 if(t) {
00324                         ch = HDR_CMN(t);
00325 
00326                         if (ch->xmit_failure_) {
00327                                 ch->xmit_reason_ = 0;
00328                                 ch->xmit_failure_(t, ch->xmit_failure_data_);
00329                         }
00330                         else {
00331                                 drop(t, 1, DROP_IFQ_ARP_FULL);
00332                         }
00333                 }
00334 
00335                 ch = HDR_CMN(p);
00336 
00337                 if (ch->xmit_failure_) {
00338                         ch->xmit_reason_ = 0;
00339                         ch->xmit_failure_(p, ch->xmit_failure_data_);
00340                 }
00341                 else {
00342                         drop(p, 1, DROP_IFQ_ARP_FULL);
00343                 }
00344 
00345                 return EADDRNOTAVAIL;
00346         }
00347 
00348         llinfo->count_++;
00349         if(llinfo->hold_)
00350                 drop(llinfo->hold_, 1, DROP_IFQ_ARP_FULL);
00351         llinfo->hold_ = p;
00352 
00353         /*
00354         *  We don't have a MAC address for this node.  Send an ARP Request.
00355         *
00356         *  XXX: Do I need to worry about the case where I keep ARPing
00357         *        for the SAME destination.
00358         */
00359         fillNetAddrTable();
00360         if(netAddr.size() > 0)
00361                 arpRequest(netAddr[0], dst);
00362         else
00363                 arpRequest(0, dst);
00364         return EADDRNOTAVAIL;
00365 }
00366 
00367 void MLLModule::arpRequest(nsaddr_t src, nsaddr_t dst)
00368 {
00369         Packet *p = Packet::alloc();
00370 
00371         hdr_cmn *ch = HDR_CMN(p);
00372         hdr_mac *mh = HDR_MAC(p);
00373         hdr_ll  *lh = HDR_LL(p);
00374         hdr_arp *ah = HDR_ARP(p);
00375 
00376         ch->uid() = 0;
00377         ch->ptype() = PT_ARP;
00378         ch->size() = ARP_HDR_LEN;
00379         ch->iface() = -2;
00380         ch->error() = 0;
00381 
00382         mh->macDA() = MAC_BROADCAST;
00383         mh->macSA() = getDownAddr();
00384         mh->hdr_type() = ETHERTYPE_ARP;
00385 
00386         lh->seqno() = 0;
00387         lh->lltype() = LL_DATA;
00388 
00389         ch->direction() = hdr_cmn::DOWN; // send this pkt down
00390         ah->arp_hrd = ARPHRD_ETHER;
00391         ah->arp_pro = ETHERTYPE_IP;
00392         ah->arp_hln = ETHER_ADDR_LEN;
00393         ah->arp_pln = sizeof(nsaddr_t);
00394         ah->arp_op  = ARPOP_REQUEST;
00395         ah->arp_sha = mh->macSA();
00396         ah->arp_spa = src;
00397         ah->arp_tha = 0;                // what were're looking for
00398         ah->arp_tpa = dst;
00399 
00400         Module::sendDown(p);
00401 }

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