00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include <errno.h>
00049
00050 #include "delay.h"
00051
00052 #include "mac.h"
00053 #include "arp.h"
00054 #include "topography.h"
00055 #include "cmu-trace.h"
00056 #include "mobilenode.h"
00057 #include "ll.h"
00058 #include "packet.h"
00059 #include <address.h>
00060
00061
00062
00063 static class ARPTableClass : public TclClass {
00064 public:
00065 ARPTableClass() : TclClass("ARPTable") {}
00066 TclObject* create(int, const char*const* argv) {
00067 return (new ARPTable(argv[4], argv[5]));
00068 }
00069 } class_arptable;
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 }
00079 } class_arphdr;
00080
00081
00082
00083
00084
00085 ARPTable_List ARPTable::athead_ = { 0 };
00086
00087 void
00088 ARPTable::Terminate()
00089 {
00090 ARPEntry *ll;
00091 for(ll = arphead_.lh_first; ll; ll = ll->arp_link_.le_next) {
00092 if(ll->hold_) {
00093 drop(ll->hold_, DROP_END_OF_SIMULATION);
00094 ll->hold_ = 0;
00095 }
00096 }
00097 }
00098
00099
00100 ARPTable::ARPTable(const char *tclnode, const char *tclmac) : LinkDelay() {
00101 LIST_INIT(&arphead_);
00102
00103 node_ = (MobileNode*) TclObject::lookup(tclnode);
00104 assert(node_);
00105
00106 mac_ = (Mac*) TclObject::lookup(tclmac);
00107 assert(mac_);
00108 LIST_INSERT_HEAD(&athead_, this, link_);
00109 }
00110
00111 int
00112 ARPTable::command(int argc, const char*const* argv)
00113 {
00114 if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {
00115 Terminate();
00116
00117 }
00118 return LinkDelay::command(argc, argv);
00119 }
00120
00121 int
00122 ARPTable::arpresolve(nsaddr_t dst, Packet *p, LL *ll)
00123 {
00124 ARPEntry *llinfo ;
00125
00126 assert(initialized());
00127 llinfo = arplookup(dst);
00128
00129 #ifdef DEBUG
00130 fprintf(stderr, "%d - %s\n", node_->address(), __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
00141
00142 llinfo = new ARPEntry(&arphead_, dst);
00143 }
00144
00145 if(llinfo->count_ >= ARP_MAX_REQUEST_COUNT) {
00146
00147
00148
00149
00150
00151
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
00191
00192
00193
00194
00195 int src = node_->address();
00196 arprequest(src, dst, ll);
00197 return EADDRNOTAVAIL;
00198 }
00199
00200
00201 ARPEntry*
00202 ARPTable::arplookup(nsaddr_t dst)
00203 {
00204 ARPEntry *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 ARPTable::arprequest(nsaddr_t src, nsaddr_t dst, LL *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;
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;
00247 ah->arp_tpa = dst;
00248
00249 s.schedule(ll->downtarget_, p, delay_);
00250 }
00251
00252 void
00253 ARPTable::arpinput(Packet *p, LL *ll)
00254 {
00255 Scheduler& s = Scheduler::instance();
00256 hdr_arp *ah = HDR_ARP(p);
00257 ARPEntry *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 node_->address(), __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
00272
00273 llinfo = new ARPEntry(&arphead_, ah->arp_spa);
00274 }
00275 assert(llinfo);
00276
00277 llinfo->macaddr_ = ah->arp_sha;
00278 llinfo->up_ = 1;
00279
00280
00281
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
00289
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 s.schedule(ll->downtarget_, llinfo->hold_, delay_);
00301 llinfo->hold_ = 0;
00302 }
00303 else {
00304 fprintf(stderr, "\tfatal ARP error...\n");
00305 exit(1);
00306 }
00307 }
00308
00309 if(ah->arp_op == ARPOP_REQUEST &&
00310 ah->arp_tpa == node_->address()) {
00311
00312 hdr_cmn *ch = HDR_CMN(p);
00313 char *mh = (char*)HDR_MAC(p);
00314 hdr_ll *lh = HDR_LL(p);
00315
00316 ch->size() = ARP_HDR_LEN;
00317 ch->error() = 0;
00318 ch->direction() = hdr_cmn::DOWN;
00319
00320 mac_->hdr_dst(mh, ah->arp_sha);
00321 mac_->hdr_src(mh, ll->mac_->addr());
00322 mac_->hdr_type(mh, ETHERTYPE_ARP);
00323
00324 lh->seqno() = 0;
00325 lh->lltype() = LL_DATA;
00326
00327
00328
00329
00330
00331
00332 ah->arp_op = ARPOP_REPLY;
00333 ah->arp_tha = ah->arp_sha;
00334 ah->arp_sha = ll->mac_->addr();
00335
00336 nsaddr_t t = ah->arp_spa;
00337 ah->arp_spa = ah->arp_tpa;
00338 ah->arp_tpa = t;
00339
00340 s.schedule(ll->downtarget_, p, delay_);
00341 return;
00342 }
00343 Packet::free(p);
00344 }
00345