📄 noah.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */extern "C" {#include <stdarg.h>#include <float.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <assert.h>};#include <random.h>#include <address.h>#include <mobilenode.h>#include <cmu-trace.h>#include "noah.h"#define NOAH_BROADCAST_JITTER 0.01 // jitter for all broadcast packets//#define NOAH_DEBUG// Returns a random number between 0 and maxstatic inline double jitter (double max, int be_random_){ return (be_random_ ? Random::uniform(max) : 0);}static class NOAHClass:public TclClass{public: NOAHClass ():TclClass ("Agent/NOAH") {} TclObject *create (int, const char *const *) { return (new NOAH_Agent ()); }} class_noah;NOAH_Agent::NOAH_Agent (): Agent (PT_MESSAGE), myaddr_ (0), subnet_ (0), node_ (0), port_dmux_(0), table_(0), be_random_ (1), use_mac_ (0), table_size(0){ bind ("use_mac_", &use_mac_); bind ("be_random_", &be_random_);}voidNOAH_Agent::trace (char *fmt,...){ va_list ap; if (!tracetarget) return; va_start (ap, fmt); vsprintf (tracetarget->pt_->buffer (), fmt, ap); tracetarget->pt_->dump (); va_end (ap);}voidNOAH_Agent::lost_link (Packet *p){ hdr_cmn *ch = HDR_CMN (p); if(use_mac_ == 0) { drop(p, DROP_RTR_MAC_CALLBACK); return; } if (!use_mac_ || ch->addr_type_ != NS_AF_INET) return; // Queue these packets up... recv(p, 0);}static void mac_callback (Packet * p, void *arg){ ((NOAH_Agent *) arg)->lost_link (p);}intNOAH_Agent::getEntry(int dst){ if (table_) { for (int i = 0; i < table_size; ++i) { if (dst == table_[i].dst) return table_[i].hop; } } return -3;}voidNOAH_Agent::forwardPacket (Packet * p){ hdr_cmn *ch = HDR_CMN(p); hdr_ip *iph = HDR_IP(p); int dst; int next_hop; // if the destination is outside mobilenode's domain // forward it to base_stn node // Note: pkt is not buffered if route to base_stn is unknown if (table_) { dst = Address::instance().get_nodeaddr(iph->daddr()); next_hop = getEntry(dst); if (diff_subnet(iph->daddr())) { if (next_hop == -3) { dst = node_->base_stn(); next_hop = getEntry(dst); if (next_hop == -3) { //drop pkt with warning fprintf(stderr, "warning: Route to base_stn not known: dropping pkt\n"); Packet::free(p); return; } } } if (next_hop == -3) { //drop pkt with warning fprintf(stderr, "warning: no route known: dropping pkt %f dst %i node %i\n", Scheduler::instance().clock(), dst, node_->address()); for (int i = 0; i < table_size; ++i) fprintf(stderr, "%i %i, ", table_[i].dst, table_[i].hop); fprintf(stderr, "\n"); Packet::free(p); return; } ch->next_hop_ = next_hop; } else { if (node_->base_stn() != -1) { // code below is for Mobile IP (base station is present) if (node_->base_stn() == node_->address()) { // node is its own BS --> HA or FA ch->next_hop_ = Address::instance().get_nodeaddr(iph->daddr()); } else { // MH sends to BS // JCW set next hop in mip-reg.cc when sending request etc. // don't set when destination already set by MIPMH if (ch->next_hop_ <= -2) // see packet.h ch->next_hop_ = Address::instance().get_nodeaddr(node_->base_stn()); } } else { // wireless-only network -> try to use ARP to get MAC address ch->next_hop_ = Address::instance().get_nodeaddr(iph->daddr()); } } ch->direction() = hdr_cmn::DOWN; ch->addr_type_ = NS_AF_INET; ch->xmit_failure_ = mac_callback; ch->xmit_failure_data_ = this; assert (!HDR_CMN (p)->xmit_failure_ || HDR_CMN (p)->xmit_failure_ == mac_callback);#ifdef NOAH_DEBUG printf("%f NOAH forward (node %s) to %s (via %s), packet %i\n", Scheduler::instance().clock(), Address::instance().print_nodeaddr(node_->address()), Address::instance().print_nodeaddr(iph->daddr()), Address::instance().print_nodeaddr(ch->next_hop_), ch->uid()); // JCW#endif target_->recv(p, (Handler *)0); return;}void NOAH_Agent::sendOutBCastPkt(Packet *p){ Scheduler & s = Scheduler::instance ();#ifdef NOAH_DEBUG hdr_ip *iph = HDR_IP(p); hdr_cmn *ch = HDR_CMN(p); printf("%f NOAH broadcast (node %s) to %s, packet %i\n", Scheduler::instance().clock(), Address::instance().print_nodeaddr(node_->address()), Address::instance().print_nodeaddr(iph->daddr()), ch->uid()); // JCW#endif s.schedule (target_, p, jitter(NOAH_BROADCAST_JITTER, be_random_));}voidNOAH_Agent::recv (Packet * p, Handler *){ hdr_ip *iph = HDR_IP(p); hdr_cmn *ch = HDR_CMN(p); int src = Address::instance().get_nodeaddr(iph->saddr()); int dst = ch->next_hop(); /* * Must be a packet I'm originating... */ if(src == myaddr_ && ch->num_forwards() == 0) { /* * Add the IP Header */ ch->size() += IP_HDR_LEN; iph->ttl_ = IP_DEF_TTL; } /* * I received a packet that I sent. Probably * a routing loop. */ else if(src == myaddr_) {#ifdef NOAH_DEBUG printf("%f NOAH dropped packet (routing loop)\n", Scheduler::instance().clock());#endif drop(p, DROP_RTR_ROUTE_LOOP); return; } /* * Packet I'm forwarding... */ else { /* * Check the TTL. If it is zero, then discard. */ if(--iph->ttl_ == 0) {#ifdef NOAH_DEBUG printf("%f NOAH dropped packet (TTL)\n", Scheduler::instance().clock());#endif drop(p, DROP_RTR_TTL); return; } } if ((u_int32_t) dst == IP_BROADCAST && (iph->dport() != ROUTER_PORT)) { if (src == myaddr_) { // handle brdcast pkt sendOutBCastPkt(p); } else { // hand it over to the port-demux (in case there is one, i.e. Mobile IP) if (port_dmux_) {#ifdef NOAH_DEBUG printf("%f NOAH broadcast demuxed (node %s) from %s, packet %i\n", Scheduler::instance().clock(), Address::instance().print_nodeaddr(node_->address()), Address::instance().print_nodeaddr(iph->daddr()), ch->uid()); // JCW#endif port_dmux_->recv(p, (Handler*)0); } else {#ifdef NOAH_DEBUG printf("%f NOAH broadcast dropped (node %s) from %s, packet %i\n", Scheduler::instance().clock(), Address::instance().print_nodeaddr(node_->address()), Address::instance().print_nodeaddr(iph->daddr()), ch->uid()); // JCW#endif drop(p, DROP_RTR_NO_ROUTE); } } } else { forwardPacket(p); }}int NOAH_Agent::command (int argc, const char *const *argv){ if (argc == 3) { if (strcasecmp (argv[1], "addr") == 0) { myaddr_ = Address::instance().str2addr(argv[2]); subnet_ = Address::instance().get_subnetaddr(myaddr_); return TCL_OK; } TclObject *obj; if ((obj = TclObject::lookup (argv[2])) == 0) { fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1], argv[2]); return TCL_ERROR; } if (strcasecmp (argv[1], "tracetarget") == 0) { tracetarget = (Trace *) obj; return TCL_OK; } else if (strcasecmp (argv[1], "node") == 0) { node_ = (MobileNode*) obj; return TCL_OK; } else if (strcasecmp (argv[1], "port-dmux") == 0) { port_dmux_ = (NsObject *) obj; return TCL_OK; } } else if (argc >= 5) { if (strcasecmp (argv[1], "routing") == 0) { table_size = atoi(argv[2]); if (2 * table_size != argc - 3) { fprintf (stderr, "%s: routing table size mismatch %s\n", __FILE__, argv[2]); return TCL_ERROR; } if (table_) delete []table_; table_ = new struct NOAH_Table[table_size]; for (int i = 0; i < table_size; ++i) { table_[i].dst = atoi(argv[i * 2 + 3]); table_[i].hop = atoi(argv[i * 2 + 4]); } return TCL_OK; } } return (Agent::command (argc, argv));}int NOAH_Agent::diff_subnet(int dst) { // XXX inefficient but we don't have startUp like DSDV subnet_ = Address::instance().get_subnetaddr(myaddr_); char* dstnet = Address::instance().get_subnetaddr(dst); if (subnet_ != NULL) { if (dstnet != NULL) { if (strcmp(dstnet, subnet_) != 0) { delete [] dstnet; return 1; } delete [] dstnet; } } //assert(dstnet == NULL); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -