📄 caodv.cc
字号:
// I don't know how to forward .. drop the reply.
#ifdef DEBUG
fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__);
#endif // DEBUG
drop(p, DROP_RTR_NO_ROUTE);
}
}
}
void
CAODV::recvError(Packet *p) {
struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_error *re = HDR_CAODV_ERROR(p);
caodv_rt_entry *rt;
u_int8_t i;
Packet *rerr = Packet::alloc();
struct hdr_caodv_error *nre = HDR_CAODV_ERROR(rerr);
nre->DestCount = 0;
for (i=0; i<re->DestCount; i++) {
// For each unreachable destination
rt = rtable.rt_lookup(re->unreachable_dst[i]);
if ( rt && (rt->rt_hops != INFINITY2) &&
(rt->rt_nexthop == ih->saddr()) &&
(rt->rt_seqno <= re->unreachable_dst_seqno[i]) ) {
assert(rt->rt_flags == RTF_UP);
assert((rt->rt_seqno%2) == 0); // is the seqno even?
#ifdef DEBUG
fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTION__,CURRENT_TIME,
index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop,
re->unreachable_dst[i],re->unreachable_dst_seqno[i],
ih->saddr());
#endif // DEBUG
rt->rt_seqno = re->unreachable_dst_seqno[i];
rt_down(rt);
// Not sure whether this is the right thing to do
Packet *pkt;
while((pkt = ifqueue->filter(ih->saddr()))) {
drop(pkt, DROP_RTR_MAC_CALLBACK);
}
// if precursor list non-empty add to RERR and delete the precursor list
if (!rt->pc_empty()) {
nre->unreachable_dst[nre->DestCount] = rt->rt_dst;
nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno;
nre->DestCount += 1;
rt->pc_delete();
}
}
}
if (nre->DestCount > 0) {
#ifdef DEBUG
fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT_TIME, index);
#endif // DEBUG
sendError(rerr);
}
else {
Packet::free(rerr);
}
Packet::free(p);
}
/*
Packet Transmission Routines
*/
void
CAODV::forward(caodv_rt_entry *rt, Packet *p, double delay) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
if(ih->ttl_ == 0) {
#ifdef DEBUG
fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__);
#endif // DEBUG
drop(p, DROP_RTR_TTL);
return;
}
if (ch->ptype() != PT_CAODV && ch->direction() == hdr_cmn::UP &&
((u_int32_t)ih->daddr() == IP_BROADCAST)
|| (ih->daddr() == here_.addr_)) {
dmux_->recv(p,0);
return;
}
if (rt) {
assert(rt->rt_flags == RTF_UP);
rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
ch->next_hop_ = rt->rt_nexthop;
ch->addr_type() = NS_AF_INET;
ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
}
else { // if it is a broadcast packet
// assert(ch->ptype() == PT_CAODV); // maybe a diff pkt type like gaf
assert(ih->daddr() == (nsaddr_t) IP_BROADCAST);
ch->addr_type() = NS_AF_NONE;
ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
}
if (ih->daddr() == (nsaddr_t) IP_BROADCAST) {
// If it is a broadcast packet
assert(rt == 0);
/*
* Jitter the sending of broadcast packets by 10ms
*/
Scheduler::instance().schedule(target_, p,
0.01 * Random::uniform());
}
else { // Not a broadcast packet
if(delay > 0.0) {
Scheduler::instance().schedule(target_, p, delay);
}
else {
// Not a broadcast packet, no delay, send immediately
Scheduler::instance().schedule(target_, p, 0.);
}
}
}
void
CAODV::sendRequest(nsaddr_t dst) {
// Allocate a RREQ packet
Packet *p = Packet::alloc();
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_request *rq = HDR_CAODV_REQUEST(p);
caodv_rt_entry *rt = rtable.rt_lookup(dst);
assert(rt);
/*
* Rate limit sending of Route Requests. We are very conservative
* about sending out route requests.
*/
if (rt->rt_flags == RTF_UP) {
assert(rt->rt_hops != INFINITY2);
Packet::free((Packet *)p);
return;
}
if (rt->rt_req_timeout > CURRENT_TIME) {
Packet::free((Packet *)p);
return;
}
// rt_req_cnt is the no. of times we did network-wide broadcast
// RREQ_RETRIES is the maximum number we will allow before
// going to a long timeout.
if (rt->rt_req_cnt > RREQ_RETRIES) {
rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
rt->rt_req_cnt = 0;
Packet *buf_pkt;
while ((buf_pkt = rqueue.deque(rt->rt_dst))) {
drop(buf_pkt, DROP_RTR_NO_ROUTE);
}
Packet::free((Packet *)p);
return;
}
#ifdef DEBUG
fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n",
++route_request, index, rt->rt_dst);
#endif // DEBUG
// Determine the TTL to be used this time.
// Dynamic TTL evaluation - SRD
rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count);
if (0 == rt->rt_req_last_ttl) {
// first time query broadcast
ih->ttl_ = TTL_START;
}
else {
// Expanding ring search.
if (rt->rt_req_last_ttl < TTL_THRESHOLD)
ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT;
else {
// network-wide broadcast
ih->ttl_ = NETWORK_DIAMETER;
rt->rt_req_cnt += 1;
}
}
// remember the TTL used for the next time
rt->rt_req_last_ttl = ih->ttl_;
// PerHopTime is the roundtrip time per hop for route requests.
// The factor 2.0 is just to be safe .. SRD 5/22/99
// Also note that we are making timeouts to be larger if we have
// done network wide broadcast before.
rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt);
if (rt->rt_req_cnt > 0)
rt->rt_req_timeout *= rt->rt_req_cnt;
rt->rt_req_timeout += CURRENT_TIME;
// Don't let the timeout to be too large, however .. SRD 6/8/99
if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
rt->rt_expire = 0;
#ifdef DEBUG
fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n",
++route_request,
index, rt->rt_dst,
rt->rt_req_timeout - CURRENT_TIME);
#endif // DEBUG
// Fill out the RREQ packet
// ch->uid() = 0;
ch->ptype() = PT_CAODV;
ch->size() = IP_HDR_LEN + rq->size();
ch->iface() = -2;
ch->error() = 0;
ch->addr_type() = NS_AF_NONE;
ch->prev_hop_ = index; // CAODV hack
ih->saddr() = index;
ih->daddr() = IP_BROADCAST;
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
// Fill up some more fields.
rq->rq_type = CAODVTYPE_RREQ;
rq->rq_hop_count = 1;
rq->rq_bcast_id = bid++;
rq->rq_dst = dst;
rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);
rq->rq_src = index;
seqno += 2;
assert ((seqno%2) == 0);
rq->rq_src_seqno = seqno;
rq->rq_timestamp = CURRENT_TIME;
Scheduler::instance().schedule(target_, p, 0.);
}
void
CAODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst,
u_int32_t rpseq, u_int32_t lifetime, double timestamp) {
Packet *p = Packet::alloc();
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_reply *rp = HDR_CAODV_REPLY(p);
caodv_rt_entry *rt = rtable.rt_lookup(ipdst);
#ifdef DEBUG
fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::instance().clock());
#endif // DEBUG
assert(rt);
rp->rp_type = CAODVTYPE_RREP;
//rp->rp_flags = 0x00;
rp->rp_hop_count = hop_count;
rp->rp_dst = rpdst;
rp->rp_dst_seqno = rpseq;
rp->rp_src = index;
rp->rp_lifetime = lifetime;
rp->rp_timestamp = timestamp;
// ch->uid() = 0;
ch->ptype() = PT_CAODV;
ch->size() = IP_HDR_LEN + rp->size();
ch->iface() = -2;
ch->error() = 0;
ch->addr_type() = NS_AF_INET;
ch->next_hop_ = rt->rt_nexthop;
ch->prev_hop_ = index; // CAODV hack
ch->direction() = hdr_cmn::DOWN;
ih->saddr() = index;
ih->daddr() = ipdst;
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
ih->ttl_ = NETWORK_DIAMETER;
Scheduler::instance().schedule(target_, p, 0.);
}
void
CAODV::sendError(Packet *p, bool jitter) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_error *re = HDR_CAODV_ERROR(p);
#ifdef ERROR
fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::instance().clock());
#endif // DEBUG
re->re_type = CAODVTYPE_RERR;
//re->reserved[0] = 0x00; re->reserved[1] = 0x00;
// DestCount and list of unreachable destinations are already filled
// ch->uid() = 0;
ch->ptype() = PT_CAODV;
ch->size() = IP_HDR_LEN + re->size();
ch->iface() = -2;
ch->error() = 0;
ch->addr_type() = NS_AF_NONE;
ch->next_hop_ = 0;
ch->prev_hop_ = index; // CAODV hack
ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
ih->saddr() = index;
ih->daddr() = IP_BROADCAST;
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
ih->ttl_ = 1;
// Do we need any jitter? Yes
if (jitter)
Scheduler::instance().schedule(target_, p, 0.01*Random::uniform());
else
Scheduler::instance().schedule(target_, p, 0.0);
}
/*
Neighbor Management Functions
*/
void
CAODV::sendHello() {
Packet *p = Packet::alloc();
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_reply *rh = HDR_CAODV_REPLY(p);
#ifdef DEBUG
fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::instance().clock());
#endif // DEBUG
rh->rp_type = CAODVTYPE_HELLO;
//rh->rp_flags = 0x00;
rh->rp_hop_count = 1;
rh->rp_dst = index;
rh->rp_dst_seqno = seqno;
rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
// ch->uid() = 0;
ch->ptype() = PT_CAODV;
ch->size() = IP_HDR_LEN + rh->size();
ch->iface() = -2;
ch->error() = 0;
ch->addr_type() = NS_AF_NONE;
ch->prev_hop_ = index; // CAODV hack
ih->saddr() = index;
ih->daddr() = IP_BROADCAST;
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
ih->ttl_ = 1;
Scheduler::instance().schedule(target_, p, 0.0);
}
void
CAODV::recvHello(Packet *p) {
//struct hdr_ip *ih = HDR_IP(p);
struct hdr_caodv_reply *rp = HDR_CAODV_REPLY(p);
CAODV_Neighbor *nb;
nb = nb_lookup(rp->rp_dst);
if(nb == 0) {
nb_insert(rp->rp_dst);
}
else {
nb->nb_expire = CURRENT_TIME +
(1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
}
Packet::free(p);
}
void
CAODV::nb_insert(nsaddr_t id) {
CAODV_Neighbor *nb = new CAODV_Neighbor(id);
assert(nb);
nb->nb_expire = CURRENT_TIME +
(1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
LIST_INSERT_HEAD(&nbhead, nb, nb_link);
seqno += 2; // set of neighbors changed
assert ((seqno%2) == 0);
}
CAODV_Neighbor*
CAODV::nb_lookup(nsaddr_t id) {
CAODV_Neighbor *nb = nbhead.lh_first;
for(; nb; nb = nb->nb_link.le_next) {
if(nb->nb_addr == id) break;
}
return nb;
}
/*
* Called when we receive *explicit* notification that a Neighbor
* is no longer reachable.
*/
void
CAODV::nb_delete(nsaddr_t id) {
CAODV_Neighbor *nb = nbhead.lh_first;
log_link_del(id);
seqno += 2; // Set of neighbors changed
assert ((seqno%2) == 0);
for(; nb; nb = nb->nb_link.le_next) {
if(nb->nb_addr == id) {
LIST_REMOVE(nb,nb_link);
delete nb;
break;
}
}
handle_link_failure(id);
}
/*
* Purges all timed-out Neighbor Entries - runs every
* HELLO_INTERVAL * 1.5 seconds.
*/
void
CAODV::nb_purge() {
CAODV_Neighbor *nb = nbhead.lh_first;
CAODV_Neighbor *nbn;
double now = CURRENT_TIME;
for(; nb; nb = nbn) {
nbn = nb->nb_link.le_next;
if(nb->nb_expire <= now) {
nb_delete(nb->nb_addr);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -