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); // 奇数代表无穷大,无效的意思
#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);//将此路由down掉
// Not sure whether this is the right thing to do
/*查看队列中是否有下一跳是此邻居的分组
若有的话,直接丢包;具体请看queue/priqueue.cc的filter函数*/
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
AODV::forward(aodv_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;
}
/*如果不是AODV数据包并且链路方向是上行并且是广播包或者此节点就是目的地址*/
if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
((u_int32_t)ih->daddr() == IP_BROADCAST)
|| ((u_int32_t)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_AODV); // 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 { // 非广播报文
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.);
}
}
}