/*ns2 中aodv.cc的源代码,并加了一定的注解,便于理解和查阅。*/
25. //#include <ip.h>
26. #include <aodv/aodv.h>
27. #include <aodv/aodv_packet.h>
28. #include <random.h>
29. #include <cmu-trace.h>
30. //#include <energy-model.h>
31. #define max(a,b) ( (a) > (b) ? (a) : (b) )
32. #define CURRENT_TIME Scheduler::instance().clock()
33. //#define DEBUG
34. //#define ERROR
35. #ifdef DEBUG
36. static int extra_route_reply = 0;
37. static int limit_route_request = 0;
38. static int route_request = 0;
39. #endif
40.
41. /*
42. TCL Hooks
43. */
44.
45. int hdr_aodv::offset_;
46. static class AODVHeaderClass : public PacketHeaderClass {
47. public:
48. AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV",
49. sizeof(hdr_all_aodv)) {
50. bind_offset(&hdr_aodv::offset_);
51. }
52. } class_rtProtoAODV_hdr;
53. static class AODVclass : public TclClass {
54. public:
55. AODVclass() : TclClass("Agent/AODV") {}
56. TclObject* create(int argc, const char*const* argv) {
57. assert(argc == 5);
58. //return (new AODV((nsaddr_t) atoi(argv[4])));
59. return (new AODV((nsaddr_t) Address::instance().str2addr(argv[4])));
60. }
61. } class_rtProtoAODV;
62.
63. int
64. AODV::command(int argc, const char*const* argv) {
65. if(argc == 2) {
66. Tcl& tcl = Tcl::instance();
67.
68. if(strncasecmp(argv[1], "id", 2) == 0) {
69. tcl.resultf("%d", index);
70. return TCL_OK;
71. }
72.
73. if(strncasecmp(argv[1], "start", 2) == 0) {
74. btimer.handle((Event*) 0);
75. #ifndef AODV_LINK_LAYER_DETECTION
76. htimer.handle((Event*) 0);
77. ntimer.handle((Event*) 0);
78. #endif // LINK LAYER DETECTION
79. rtimer.handle((Event*) 0);
80. return TCL_OK;
81. }
82. }
83. else if(argc == 3) {
84. if(strcmp(argv[1], "index") == 0) {
85. index = atoi(argv[2]);
86. return TCL_OK;
87. }
88. else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {
89. logtarget = (Trace*) TclObject::lookup(argv[2]);
90. if(logtarget == 0)
91. return TCL_ERROR;
92. return TCL_OK;
93. }
94. else if(strcmp(argv[1], "drop-target") == 0) {
95. int stat = rqueue.command(argc,argv);
96. if (stat != TCL_OK) return stat;
97. return Agent::command(argc, argv);
98. }
99. else if(strcmp(argv[1], "if-queue") == 0) {
100. ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
101.
102. if(ifqueue == 0)
103. return TCL_ERROR;
104. return TCL_OK;
105. }
106. else if (strcmp(argv[1], "port-dmux") == 0) {
107. dmux_ = (PortClassifier *)TclObject::lookup(argv[2]);
108. if (dmux_ == 0) {
109. fprintf (stderr, "%s: %s lookup of %s failed/n", __FILE__,
110. argv[1], argv[2]);
111. return TCL_ERROR;
112. }
113. return TCL_OK;
114. }
115. }
116. return Agent::command(argc, argv);
117. }
118. /*
119. Constructor
120. */
121. AODV::AODV(nsaddr_t id) : Agent(PT_AODV),
122. btimer(this), htimer(this), ntimer(this),
123. rtimer(this), lrtimer(this), rqueue() {
124.
125.
126. index = id;
127. seqno = 2;
128. bid = 1;
129. LIST_INIT(&nbhead);
130. LIST_INIT(&bihead);
131. logtarget = 0;
132. ifqueue = 0;
133. }
134. /*
135. Timers
136. */
137. void
138. BroadcastTimer::handle(Event*) {
139. agent->id_purge();
140. Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
141. }
142. void
143. HelloTimer::handle(Event*) {
144. agent->sendHello();
145. double interval = MinHelloInterval +
146. ((MaxHelloInterval - MinHelloInterval) * Random::uniform());
147. assert(interval >= 0);
148. Scheduler::instance().schedule(this, &intr, interval);
149. }
150. void
151. NeighborTimer::handle(Event*) {
152. agent->nb_purge();
153. Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
154. }
155. void
156. RouteCacheTimer::handle(Event*) {
157. agent->rt_purge();
158. #define FREQUENCY 0.5 // sec
159. Scheduler::instance().schedule(this, &intr, FREQUENCY);
160. }
161. void
162. LocalRepairTimer::handle(Event* p) { // SRD: 5/4/99
163. aodv_rt_entry *rt;
164. struct hdr_ip *ih = HDR_IP( (Packet *)p);
165. /* you get here after the timeout in a local repair attempt */
166. /* fprintf(stderr, "%s/n", __FUNCTION__); */
167.
168. rt = agent->rtable.rt_lookup(ih->daddr());
169.
170. if (rt && rt->rt_flags != RTF_UP) {
171. // route is yet to be repaired
172. // I will be conservative and bring down the route
173. // and send route errors upstream.
174. /* The following assert fails, not sure why */
175. /* assert (rt->rt_flags == RTF_IN_REPAIR); */
176.
177. //rt->rt_seqno++;
178. agent->rt_down(rt);
179. // send RERR
180. #ifdef DEBUG
181. fprintf(stderr,"Node %d: Dst - %d, failed local repair/n",index, rt->rt_dst);
182. #endif
183. }
184. Packet::free((Packet *)p);
185. }
186.
187. /*
188. Broadcast ID Management Functions
189. */
190.
191. void
192. AODV::id_insert(nsaddr_t id, u_int32_t bid) {
193. BroadcastID *b = new BroadcastID(id, bid);
194. assert(b);
195. b->expire = CURRENT_TIME + BCAST_ID_SAVE;
196. LIST_INSERT_HEAD(&bihead, b, link);
197. }
198. /* SRD */
199. bool
200. AODV::id_lookup(nsaddr_t id, u_int32_t bid) {
201. BroadcastID *b = bihead.lh_first;
202.
203. // Search the list for a match of source and bid
204. for( ; b; b = b->link.le_next) {
205. if ((b->src == id) && (b->id == bid))
206. return true;
207. }
208. return false;
209. }
210. void
211. AODV::id_purge() {
212. BroadcastID *b = bihead.lh_first;
213. BroadcastID *bn;
214. double now = CURRENT_TIME;
215. for(; b; b = bn) {
216. bn = b->link.le_next;
217. if(b->expire <= now) {
218. LIST_REMOVE(b,link);
219. delete b;
220. }
221. }
222. }
223. /*
224. Helper Functions
225. */
226. double
227. AODV::PerHopTime(aodv_rt_entry *rt) {
228. int num_non_zero = 0, i;
229. double total_latency = 0.0;
230. if (!rt)
231. return ((double) NODE_TRAVERSAL_TIME );
232.
233. for (i=0; i < MAX_HISTORY; i++) {
234. if (rt->rt_disc_latency[i] > 0.0) {
235. num_non_zero++;
236. total_latency += rt->rt_disc_latency[i];
237. }
238. }
239. if (num_non_zero > 0)
240. return(total_latency / (double) num_non_zero);
241. else
242. return((double) NODE_TRAVERSAL_TIME);
243. }
244. /*
245. Link Failure Management Functions
246. */
247. static void
248. aodv_rt_failed_callback(Packet *p, void *arg) {
249. ((AODV*) arg)->rt_ll_failed(p);
250. }
251. /*
252. * This routine is invoked when the link-layer reports a route failed.
253. */
254. void
255. AODV::rt_ll_failed(Packet *p) {
256. struct hdr_cmn *ch = HDR_CMN(p);
257. struct hdr_ip *ih = HDR_IP(p);
258. aodv_rt_entry *rt;
259. nsaddr_t broken_nbr = ch->next_hop_;
260. #ifndef AODV_LINK_LAYER_DETECTION
261. drop(p, DROP_RTR_MAC_CALLBACK);
262. #else
263. /*
264. * Non-data packets and Broadcast Packets can be dropped.
265. */
266. if(! DATA_PACKET(ch->ptype()) ||
267. (u_int32_t) ih->daddr() == IP_BROADCAST) {
268. drop(p, DROP_RTR_MAC_CALLBACK);
269. return;
270. }
271. log_link_broke(p);
272. if((rt = rtable.rt_lookup(ih->daddr())) == 0) {
273. drop(p, DROP_RTR_MAC_CALLBACK);
274. return;
275. }
276. log_link_del(ch->next_hop_);
277. #ifdef AODV_LOCAL_REPAIR
278. /* if the broken link is closer to the dest than source,
279. attempt a local repair. Otherwise, bring down the route. */
280.
281. if (ch->num_forwards() > rt->rt_hops) {
282. local_rt_repair(rt, p); // local repair
283. // retrieve all the packets in the ifq using this link,
284. // queue the packets for which local repair is done,
285. return;
286. }
287. else
288. #endif // LOCAL REPAIR
289. {
290. drop(p, DROP_RTR_MAC_CALLBACK);
291. // Do the same thing for other packets in the interface queue using the
292. // broken link -Mahesh
293. while((p = ifqueue->filter(broken_nbr))) {
294. drop(p, DROP_RTR_MAC_CALLBACK);
295. }
296. nb_delete(broken_nbr);
297. }
298. #endif // LINK LAYER DETECTION
299. }
300. void
301. AODV::handle_link_failure(nsaddr_t id) {
302. aodv_rt_entry *rt, *rtn;
303. Packet *rerr = Packet::alloc();
304. struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
305. re->DestCount = 0;
306. for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
307. rtn = rt->rt_link.le_next;
308. if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) {
309. assert (rt->rt_flags == RTF_UP);
310. assert((rt->rt_seqno%2) == 0);
311. rt->rt_seqno++;
312. re->unreachable_dst[re->DestCount] = rt->rt_dst;
313. re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
314. #ifdef DEBUG
315. fprintf(stderr, "%s(%f): %d/t(%d/t%u/t%d)/n", __FUNCTION__, CURRENT_TIME,
316. index, re->unreachable_dst[re->DestCount],
317. re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop);
318. #endif // DEBUG
319. re->DestCount += 1;
320. rt_down(rt);
321. }
322. // remove the lost neighbor from all the precursor lists
323. rt->pc_delete(id);
324. }
325. if (re->DestCount > 0) {
326. #ifdef DEBUG
327. fprintf(stderr, "%s(%f): %d/tsending RERR.../n", __FUNCTION__, CURRENT_TIME, index);
328. #endif // DEBUG
329. sendError(rerr, false);
330. }
331. else {
332. Packet::free(rerr);
333. }
334. }
335. void
336. AODV::local_rt_repair(aodv_rt_entry *rt, Packet *p) {
337. #ifdef DEBUG
338. fprintf(stderr,"%s: Dst - %d/n", __FUNCTION__, rt->rt_dst);
339. #endif
340. // Buffer the packet
341. rqueue.enque(p);
342. // mark the route as under repair
343. rt->rt_flags = RTF_IN_REPAIR;
344. sendRequest(rt->rt_dst);
345. // set up a timer interrupt
346. Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout);
347. }
348. void
349. AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric,
350. nsaddr_t nexthop, double expire_time) {
351. rt->rt_seqno = seqnum;
352. rt->rt_hops = metric;
353. rt->rt_flags = RTF_UP;
354. rt->rt_nexthop = nexthop;
355. rt->rt_expire = expire_time;
356. }
357. void
358. AODV::rt_down(aodv_rt_entry *rt) {
359. /*
360. * Make sure that you don't "down" a route more than once.
361. */
362. if(rt->rt_flags == RTF_DOWN) {
363. return;
364. }
365. // assert (rt->rt_seqno%2); // is the seqno odd?
366. rt->rt_last_hop_count = rt->rt_hops;
367. rt->rt_hops = INFINITY2;
368. rt->rt_flags = RTF_DOWN;
369. rt->rt_nexthop = 0;
370. rt->rt_expire = 0;
371. } /* rt_down function */
372. /*
373. Route Handling Functions
374. */
375. void
376. AODV::rt_resolve(Packet *p) {//解析收到的分组
377. struct hdr_cmn *ch = HDR_CMN(p);
378. struct hdr_ip *ih = HDR_IP(p);
379. aodv_rt_entry *rt;
380. /*
381. * Set the transmit failure callback. That
382. * won't change.
383. */
384. ch->xmit_failure_ = aodv_rt_failed_callback;
385. ch->xmit_failure_data_ = (void*) this;
386. rt = rtable.rt_lookup(ih->daddr());//查找是否又到目的节点的路由
387. if(rt == 0) {//如果没有到目的节点的路由,那么就添加该目的节点的路由,此时添加的路由是无效
388. //的
389. rt = rtable.rt_add(ih->daddr());
390. }
391. /*
392. * If the route is up, forward the packet
393. */
394. //如果路由有效,则根据路由表中的信息转发分组。
395. if(rt->rt_flags == RTF_UP) {
396. assert(rt->rt_hops != INFINITY2);
397. forward(rt, p, NO_DELAY);
398. }
399. /*
400. * if I am the source of the packet, then do a Route Request.
401. */
402. //如果本节点是该分组的源节点,那么说明没有到目的节点的路由,发送RREQ找路。
403. else if(ih->saddr() == index) {
404. rqueue.enque(p);
405. sendRequest(rt->rt_dst);
406. }
407. /*
408. * A local repair is in progress. Buffer the packet.
409. */
410. //链路中断,进行所谓的路由维护。
411. else if (rt->rt_flags == RTF_IN_REPAIR) {
412. rqueue.enque(p);
413. }
414. /*
415. * I am trying to forward a packet for someone else to which
416. * I don't have a route.
417. */
418. //本节点转发数据分组,但是不知道到目的节点的路由,发送RRER说明链路中断。
419. else {
420. Packet *rerr = Packet::alloc();
421. struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
422. /*
423. * For now, drop the packet and send error upstream.
424. * Now the route errors are broadcast to upstream
425. * neighbors - Mahesh 09/11/99
426. */
427.
428. assert (rt->rt_flags == RTF_DOWN);
429. re->DestCount = 0;
430. re->unreachable_dst[re->DestCount] = rt->rt_dst;
431. re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
432. re->DestCount += 1;
433. #ifdef DEBUG
434. fprintf(stderr, "%s: sending RERR.../n", __FUNCTION__);
435. #endif
436. sendError(rerr, false);
437. drop(p, DROP_RTR_NO_ROUTE);
438. }
439. }
440. void
441. AODV::rt_purge() {
442. aodv_rt_entry *rt, *rtn;
443. double now = CURRENT_TIME;
444. double delay = 0.0;
445. Packet *p;
446. for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
447. rtn = rt->rt_link.le_next;
448. if ((rt->rt_flags == RTF_UP) && (rt->rt_expire < now)) {
449. // if a valid route has expired, purge all packets from
450. // send buffer and invalidate the route.
451. assert(rt->rt_hops != INFINITY2);
452. while((p = rqueue.deque(rt->rt_dst))) {
453. #ifdef DEBUG
454. fprintf(stderr, "%s: calling drop()/n",
455. __FUNCTION__);
456. #endif // DEBUG
457. drop(p, DROP_RTR_NO_ROUTE);
458. }
459. rt->rt_seqno++;
460. assert (rt->rt_seqno%2);
461. rt_down(rt);
462. }
463. else if (rt->rt_flags == RTF_UP) {
464. // If the route is not expired,
465. // and there are packets in the sendbuffer waiting,
466. // forward them. This should not be needed, but this extra
467. // check does no harm.
468. assert(rt->rt_hops != INFINITY2);
469. while((p = rqueue.deque(rt->rt_dst))) {
470. forward (rt, p, delay);
471. delay += ARP_DELAY;
472. }
473. }
474. else if (rqueue.find(rt->rt_dst))
475. // If the route is down and
476. // if there is a packet for this destination waiting in
477. // the sendbuffer, then send out route request. sendRequest
478. // will check whether it is time to really send out request
479. // or not.
480. // This may not be crucial to do it here, as each generated
481. // packet will do a sendRequest anyway.
482. sendRequest(rt->rt_dst);
483. }
484. }
485. /*
486. Packet Reception Routines
487. */
488. void
489. AODV::recv(Packet *p, Handler*) {
490. //
491. struct hdr_cmn *ch = HDR_CMN(p);
492. struct hdr_ip *ih = HDR_IP(p);
493. assert(initialized());
494. //assert(p->incoming == 0);
495. // XXXXX NOTE: use of incoming flag has been depracated; In order to track direction of pkt flow, direction_ in hdr_cmn is used instead. see packet.h for details.
496. if(ch->ptype() == PT_AODV) {//判断是不是aodv的包,如果是的话那么就调用recvAODV(p)
497. ih->ttl_ -= 1;
498. recvAODV(p);
499. return;
500. }
501.
502. /*
503. * Must be a packet I'm originating...
504. */
505. //本节点产生的aodv包,添加ip头;
506. if((ih->saddr() == index) && (ch->num_forwards() == 0)) {
507. /*
508. * Add the IP Header
509. */
510. ch->size() += IP_HDR_LEN;
511. // Added by Parag Dadhania && John Novatnack to handle broadcasting
512. if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
513. ih->ttl_ = NETWORK_DIAMETER;
514. }
515. /*
516. * I received a packet that I sent. Probably
517. * a routing loop.
518. */
519. //收到本节点发出的包,说明有路由环,丢掉它;
520. else if(ih->saddr() == index) {
521. drop(p, DROP_RTR_ROUTE_LOOP);
522. return;
523. }
524. /*
525. * Packet I'm forwarding...
526. */
527. //本节点是中间节点,
528. else {
529. /*
530. * Check the TTL. If it is zero, then discard.
531. */
532. //TTL是分组最多可以转发的次数。
533. if(--ih->ttl_ == 0) {
534. drop(p, DROP_RTR_TTL);
535. return;
536. }
537. }
538.
539. // Added by Parag Dadhania && John Novatnack to handle broadcasting
540. if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
541. //收到的不是广播分组,解析分组
542. rt_resolve(p);
543.
544. //收到的是广播分组就转发
545. else
546. forward((aodv_rt_entry*) 0, p, NO_DELAY);
547. }
548.
549. void
550. AODV::recvAODV(Packet *p) {//根据包的类型调用不同的函数。
551. struct hdr_aodv *ah = HDR_AODV(p);
552. assert(HDR_IP (p)->sport() == RT_PORT);
553. assert(HDR_IP (p)->dport() == RT_PORT);
554. /*
555. * Incoming Packets.
556. */
557. switch(ah->ah_type) {
558. case AODVTYPE_RREQ:
559. recvRequest(p);
560. break;
561. case AODVTYPE_RREP:
562. recvReply(p);
563. break;
564. case AODVTYPE_RERR:
565. recvError(p);
566. break;
567. case AODVTYPE_HELLO:
568. recvHello(p);
569. break;
570.
571. default:
572. fprintf(stderr, "Invalid AODV type (%x)/n", ah->ah_type);
573. exit(1);
574. }
575. }
576.
577. void
578. AODV::recvRequest(Packet *p) {//收到RREQ
579. struct hdr_ip *ih = HDR_IP(p);
580. struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
581. aodv_rt_entry *rt;
582. /*
583. * Drop if:
584. * - I'm the source
585. * - I recently heard this request.
586. */
587. if(rq->rq_src == index) { //看看这个request是不是自己发出来的。
588. #ifdef DEBUG
589. fprintf(stderr, "%s: got my own REQUEST/n", __FUNCTION__);
590. #endif // DEBUG
591. Packet::free(p); //如果是的话就将这个包丢弃。
592. return;
593. }
594. if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {//看看是不是曾经收到过的rreq.
595. //两个判据一个是request source(源节点IP地址) 一个是 广播序列号
596. #ifdef DEBUG
597. fprintf(stderr, "%s: discarding request/n", __FUNCTION__);
598. #endif // DEBUG
599.
600. Packet::free(p); //如果是的话就丢弃
601. return;
602. }
603. /*
604. * Cache the broadcast ID
605. */
606. //用于判断是否已经收到过该RREQ
607. id_insert(rq->rq_src, rq->rq_bcast_id); //刷新自己节点的RREQ的broadcast id(就是RREQ)
608.
609. /* 在这种情况下我们有两种选择,一种是将RREQ继续传播下去,一种是产生RREP
610. * 在这之前我们要确定,反向路由已经在路由表中存在。如果存在反向路由,在考虑
611. 是否应该想源节点发送RREP
612. */
613. aodv_rt_entry *rt0; // rt0 is the reverse route
614.
615. rt0 = rtable.rt_lookup(rq->rq_src); //寻找反向路由
616. if(rt0 == 0) { /* if not in the route table 如果不在路由表中的话*/
617. // create an entry for the reverse route.
618. rt0 = rtable.rt_add(rq->rq_src); //将反向路由写入路由表
619. }
620.
621. rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));
622. //定义ROUTE的生命期
623. if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||
624. ((rq->rq_src_seqno == rt0->rt_seqno) &&
625. (rq->rq_hop_count < rt0->rt_hops)) ) {
626. //这里就是路由判据,当遇到新的RREQ的时候
627. //比较在路由表中已经存在的到目的节点的路由,比较目的节点的序列号(用来保证使用最新路由
628. //防止路由环)在目的节点序列号相同的情况下,采用跳数较小的。在这种情况下
629. //就更新路由表。
630. // If we have a fresher seq no. or lesser #hops for the
631. // same seq no., update the rt entry. Else don't bother.
632. rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),
633. max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)) );
634. //上面两行命令就是如何更新路由表,更新路由表中的哪些项。
635. if (rt0->rt_req_timeout > 0.0) {
636. // Reset the soft state and
637. // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
638. // This is because route is used in the forward direction,
639. // but only sources get benefited by this change
640. rt0->rt_req_cnt = 0;
641. rt0->rt_req_timeout = 0.0;
642. rt0->rt_req_last_ttl = rq->rq_hop_count;
643. rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
644. }
645. /* Find out whether any buffered packet can benefit from the
646. * reverse route.
647. * May need some change in the following code - Mahesh 09/11/99
648. */
649. //缓存中是否有到源节点的路由,有则删除,无则添加
650. //缓存中是否有到源节点的数据分组,有则,建立好路由开始发送数据。
651. //查找是否有到目的节点的有效路由,有则向源节点发送RREP,没有则继续发送RREQ。
652. //注意转发前要更新RREQ的部分内容;
653. assert (rt0->rt_flags == RTF_UP);
654. Packet *buffered_pkt;
655. while ((buffered_pkt = rqueue.deque(rt0->rt_dst))) {
656. if (rt0 && (rt0->rt_flags == RTF_UP)) {
657. assert(rt0->rt_hops != INFINITY2);
658. forward(rt0, buffered_pkt, NO_DELAY);
659. }
660. }
661. }
662. // End for putting reverse route in rt table
663.
664. /*反向路径已经清楚了(搞定了)
665. * We have taken care of the reverse route stuff.
666. * Now see whether we can send a route reply.
667. //现在就看看是否应该在此节点处发送RREP
668. */
669. rt = rtable.rt_lookup(rq->rq_dst);//在路由表中查找目的节点是RREQ_DEST的路由参看aodv_rtable
670. //.cc文件中的rt_lookup函数。
671. // First check if I am the destination ..
672. if(rq->rq_dst == index) {
673. #ifdef DEBUG
674. fprintf(stderr, "%d - %s: destination sending reply/n",
675. index, __FUNCTION__);
676. #endif // DEBUG
677.
678. // Just to be safe, I use the max. Somebody may have为了安全起见,使用目的节点序列号最大
679. //的路由+1
680. // incremented the dst seqno.
681. seqno = max(seqno, rq->rq_dst_seqno)+1;
682. if (seqno%2) seqno++;//如果目的节点序列号是奇数就将其变成偶数,保证目的节点序列号是偶数
683. sendReply(rq->rq_src, // IP Destination目的节点IP
684. 1, // Hop Count
685. index, // Dest IP Address
686. seqno, // Dest Sequence Num目的节点序列号
687. MY_ROUTE_TIMEOUT, // Lifetime
688. rq->rq_timestamp); // timestamp没搞清楚什么东西
689.
690. Packet::free(p); //释放RREQ ,产生RREP(这是后话)
691. #ifdef DEBUG
692. fprintf(stderr, "%d - %s: destination sending reply/n",
693. index, __FUNCTION__);
694. #endif // DEBUG
695.
696. // Just to be safe, I use the max. Somebody may have
697. // incremented the dst seqno.
698. seqno = max(seqno, rq->rq_dst_seqno)+1;
699. if (seqno%2) seqno++;
700. sendReply(rq->rq_src, // IP Destination
701. 1, // Hop Count
702. index, // Dest IP Address
703. seqno, // Dest Sequence Num
704. MY_ROUTE_TIMEOUT, // Lifetime
705. rq->rq_timestamp); // timestamp
706.
707. Packet::free(p);
708. }
709. // I am not the destination, but I may have a fresh enough route.
710. //如果不是destination,但是有够新的路由
711. else if (rt && (rt->rt_hops != INFINITY2) &&
712. (rt->rt_seqno >= rq->rq_dst_seqno) ) {//保证够新(目的节点序列号)
713. //assert (rt->rt_flags == RTF_UP);
714. assert(rq->rq_dst == rt->rt_dst);
715. //assert ((rt->rt_seqno%2) == 0); // is the seqno even?
716. sendReply(rq->rq_src,
717. rt->rt_hops + 1, //如果是目的节点的话就设成一,这里不是目的节点就在
718. //这个RREQ中的跳数加1;
719. rq->rq_dst, //如果是目的节点这一项就是目的节点的IP地址(这个节点本身的地址),
720. //这里是RREQ中的目的节点IP地址
721. rt->rt_seqno,
722. (u_int32_t) (rt->rt_expire - CURRENT_TIME),
723. // rt->rt_expire - CURRENT_TIME,
724. rq->rq_timestamp);
725. // Insert nexthops to RREQ source and RREQ destination in the
726. // precursor lists of destination and source respectively
727. //将下一跳节点分别加入前向路由,反向路由中;
728. rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
729. rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination
730. #ifdef RREQ_GRAT_RREP
731. sendReply(rq->rq_dst,
732. rq->rq_hop_count,
733. rq->rq_src,
734. rq->rq_src_seqno,
735. (u_int32_t) (rt->rt_expire - CURRENT_TIME),
736. // rt->rt_expire - CURRENT_TIME,就是剩下的生命周期
737. rq->rq_timestamp);
738. #endif
739.
740. // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq->rq_hop_counT
741. //产生RREP发向源节点(RREP的目的节点)RREP中使用RREQ中的rq->rq_src_seqno,rq->rq_hop_count
742. // DONE: Included gratuitous replies to be sent as per IETF aodv draft specification.
743. //As of now, G flag has not been dynamically used and is always set or reset in aodv-packet.h --- Anant Utgikar, 09/16/02.
744. //G flag用来设定或者重设aodv packet.
745. Packet::free(p);
746. }
747. /*
748. * Can't reply. So forward the Route Request
749. */
750. //
751. else {
752. ih->saddr() = index;
753. ih->daddr() = IP_BROADCAST;
754. rq->rq_hop_count += 1;
755. // Maximum sequence number seen en route
756. if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno);
757. forward((aodv_rt_entry*) 0, p, DELAY);
758. }
759. }
760.
761. void
762. AODV::recvReply(Packet *p) {
763. //查看是否有到目的节点的路由,没有则建立,否则就更新。
764. //如果收到信息的节点是RREP的目的节点也就是发送信息的源节点,则建立到目的节点的路由。
765. //否则根据路由表中到源节点的路由(这个路由在建立RREQ的过程中已经建立,也就是
766. //reverse路由)转发RREP;
767. //struct hdr_cmn *ch = HDR_CMN(p);
768. struct hdr_ip *ih = HDR_IP(p);
769. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
770. aodv_rt_entry *rt;
771. char suppress_reply = 0;
772. double delay = 0.0;
773.
774. #ifdef DEBUG
775. fprintf(stderr, "%d - %s: received a REPLY/n", index, __FUNCTION__);
776. #endif // DEBUG
777.
778. /*
779. * Got a reply. So reset the "soft state" maintained for
780. * route requests in the request table. We don't really have
781. * have a separate request table. It is just a part of the
782. * routing table itself. 收到一个reply就更新发送请求表,但是没有单独的发送请求表,
783. //发送请求表示路由表的一部分。
784. */
785. // Note that rp_dst(RREP_dest) is the dest of the data packets, not the
786. // the dest of the reply(不是REPLY的终点), which is the src of the data packets.
787. //而是数据包的的源点。
788. rt = rtable.rt_lookup(rp->rp_dst);
789.
790. /* 收到reply后就查看这个reply是否已经收到过。
791. * If I don't have a rt entry to this host... adding
792. */
793. if(rt == 0) {
794. //如果没有收到就就将其添加进路由表中。
795. rt = rtable.rt_add(rp->rp_dst);
796. }
797. /*
798. * Add a forward route table entry... here I am following
799. * Perkins-Royer AODV paper almost literally - SRD 5/99
800. */
801. if ( (rt->rt_seqno < rp->rp_dst_seqno) || // newer route
802. ((rt->rt_seqno == rp->rp_dst_seqno) &&
803. (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route
804. //还是路由判据,如果收到reply就比较以前收到的reply目的节点序列号,如果目的节点序列号相同就比较
805. //比较跳数,取跳数较小的,然后将不合格的RREP删除。
806. //aodv的RREQ没走一步就会建立一个反向路径就会产生一个RREP,然后将跳数以及中间节点,
807. //目的节点序列号
808. //加入路由表中,
809. // Update the rt entry
810. rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count,
811. rp->rp_src, CURRENT_TIME + rp->rp_lifetime);
812. //参看这个文件中的rt_update函数。
813. // reset the soft state
814. rt->rt_req_cnt = 0;
815. rt->rt_req_timeout = 0.0;
816. rt->rt_req_last_ttl = rp->rp_hop_count;
817.
818. if (ih->daddr() == index) {
819. // If I am the original source,如果收到rrep的是源节点
820. // Update the route discovery latency statistics,更新路由发现潜存策略
821. // rp->rp_timestamp is the time of request origination??????不清楚
822.
823. rt->rt_disc_latency[(unsigned char)rt->hist_indx] = (CURRENT_TIME - rp->rp_timestamp)
824. / (double) rp->rp_hop_count;
825. // increment indx for next time
826. rt->hist_indx = (rt->hist_indx + 1) % MAX_HISTORY;
827. }
828. /*
829. * Send all packets queued in the sendbuffer destined for
830. * this destination. 路由建立之后将放在缓存区中的要发向目的节点所有数据包都发出去。
831. * XXX - observe the "second" use of p.
832. */
833. Packet *buf_pkt;
834. while((buf_pkt = rqueue.deque(rt->rt_dst))) {
835. if(rt->rt_hops != INFINITY2) {
836. assert (rt->rt_flags == RTF_UP);
837. // Delay them a little to help ARP. Otherwise ARP
838. //我们都知道ns软件中有ARP模块(连接链路层)用来将ip地址转化为mac地址.这个过程需要时间,所以
839. //要为它设定预留延迟,否则就会出现丢包现象
840. // may drop packets. -SRD 5/23/99
841. forward(rt, buf_pkt, delay);
842. delay += ARP_DELAY;//为ARP模块预留命令
843. }
844. }
845. }
846. else {
847. //如果收到RREP的不是源节点
848. suppress_reply = 1;
849. }
850. /*
851. * If reply is for me, discard it.
852. *如果目的节点受到了rrep直接DISCARD
853. */
854. if(ih->daddr() == index || suppress_reply) {
855. Packet::free(p);
856. }
857. /*
858. * Otherwise, forward the Route Reply.
859. *不是的话就继续向前发rrep
860. */
861. else {
862. // Find the rt entry
863. aodv_rt_entry *rt0 = rtable.rt_lookup(ih->daddr());
864. // If the rt is up, forward
865. if(rt0 && (rt0->rt_hops != INFINITY2)) {
866. assert (rt0->rt_flags == RTF_UP);
867. rp->rp_hop_count += 1;
868. rp->rp_src = index;
869. forward(rt0, p, NO_DELAY);
870. //
871. // Insert the nexthop towards the RREQ source to
872. // the precursor list of the RREQ destination
873. rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
874.
875. }
876. else {
877. // I don't know how to forward .. drop the reply.
878. #ifdef DEBUG
879. fprintf(stderr, "%s: dropping Route Reply/n", __FUNCTION__);
880. #endif // DEBUG
881. drop(p, DROP_RTR_NO_ROUTE);
882. }
883. }
884. }
885.
886. void
887. AODV::recvError(Packet *p) {//收到RERR,查看那些路径受到了中断链路的影响,
888. //更新RERR,并向受影响的节点发送RERR
889. struct hdr_ip *ih = HDR_IP(p);
890. struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
891. aodv_rt_entry *rt;
892. u_int8_t i;
893. Packet *rerr = Packet::alloc();
894. struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr);
895. nre->DestCount = 0;
896. for (i=0; i<re->DestCount; i++) {
897. // For each unreachable destination
898. rt = rtable.rt_lookup(re->unreachable_dst[i]);
899. if ( rt && (rt->rt_hops != INFINITY2) &&
900. (rt->rt_nexthop == ih->saddr()) &&
901. (rt->rt_seqno <= re->unreachable_dst_seqno[i]) ) {
902. assert(rt->rt_flags == RTF_UP);
903. assert((rt->rt_seqno%2) == 0); // is the seqno even?
904. #ifdef DEBUG
905. fprintf(stderr, "%s(%f): %d/t(%d/t%u/t%d)/t(%d/t%u/t%d)/n", __FUNCTION__,CURRENT_TIME,
906. index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop,
907. re->unreachable_dst[i],re->unreachable_dst_seqno[i],
908. ih->saddr());
909. #endif // DEBUG
910. rt->rt_seqno = re->unreachable_dst_seqno[i];
911. rt_down(rt);
912. // Not sure whether this is the right thing to do
913. Packet *pkt;
914. while((pkt = ifqueue->filter(ih->saddr()))) {
915. drop(pkt, DROP_RTR_MAC_CALLBACK);
916. }
917. // if precursor list non-empty add to RERR and delete the precursor list
918. if (!rt->pc_empty()) {
919. nre->unreachable_dst[nre->DestCount] = rt->rt_dst;
920. nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno;
921. nre->DestCount += 1;
922. rt->pc_delete();
923. }
924. }
925. }
926. if (nre->DestCount > 0) {
927. #ifdef DEBUG
928. fprintf(stderr, "%s(%f): %d/t sending RERR.../n", __FUNCTION__, CURRENT_TIME, index);
929. #endif // DEBUG
930. sendError(rerr);
931. }
932. else {
933. Packet::free(rerr);
934. }
935. Packet::free(p);
936. }
937.
938. /*
939. Packet Transmission Routines
940. */
941. void
942. AODV::forward(aodv_rt_entry *rt, Packet *p, double delay) {
943. struct hdr_cmn *ch = HDR_CMN(p);
944. struct hdr_ip *ih = HDR_IP(p);
945. if(ih->ttl_ == 0) {
946. #ifdef DEBUG
947. fprintf(stderr, "%s: calling drop()/n", __PRETTY_FUNCTION__);
948. #endif // DEBUG
949.
950. drop(p, DROP_RTR_TTL);
951. return;
952. }
953. if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
954. ((u_int32_t)ih->daddr() == IP_BROADCAST)
955. || (ih->daddr() == here_.addr_)) {
956. dmux_->recv(p,0);
957. return;
958. }
959. if (rt) {
960. assert(rt->rt_flags == RTF_UP);
961. rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
962. ch->next_hop_ = rt->rt_nexthop;
963. ch->addr_type() = NS_AF_INET;
964. ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
965. }
966. else { // if it is a broadcast packet
967. // assert(ch->ptype() == PT_AODV); // maybe a diff pkt type like gaf
968. assert(ih->daddr() == (nsaddr_t) IP_BROADCAST);
969. ch->addr_type() = NS_AF_NONE;
970. ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
971. }
972. if (ih->daddr() == (nsaddr_t) IP_BROADCAST) {
973. // If it is a broadcast packet
974. assert(rt == 0);
975. /*
976. * Jitter the sending of broadcast packets by 10ms
977. */
978. Scheduler::instance().schedule(target_, p,
979. 0.01 * Random::uniform());
980. }
981. else { // Not a broadcast packet
982. if(delay > 0.0) {
983. Scheduler::instance().schedule(target_, p, delay);
984. }
985. else {
986. // Not a broadcast packet, no delay, send immediately
987. Scheduler::instance().schedule(target_, p, 0.);
988. }
989. }
990. }
991.
992. void
993. AODV::sendRequest(nsaddr_t dst) {//发送RREQ
994. // Allocate a RREQ packet
995. Packet *p = Packet::alloc();
996. struct hdr_cmn *ch = HDR_CMN(p);
997. struct hdr_ip *ih = HDR_IP(p);
998. struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
999. aodv_rt_entry *rt = rtable.rt_lookup(dst);//添加到目的节点的路由,此时路由是不可用的,无效。
1000. assert(rt);
1001. /*
1002. * Rate limit sending of Route Requests. We are very conservative
1003. * about sending out route requests.
1004. */
1005. if (rt->rt_flags == RTF_UP) {//不清楚
1006. assert(rt->rt_hops != INFINITY2);
1007. Packet::free((Packet *)p);
1008. return;
1009. }
1010. if (rt->rt_req_timeout > CURRENT_TIME) {//不到RREQ的发送时间,注意文件开头的RREQ定时器
1011. //若没有收到RREP,那么要定时发送RREQ;
1012. Packet::free((Packet *)p);
1013. return;
1014. }
1015. // rt_req_cnt is the no. of times we did network-wide broadcast
1016. // RREQ_RETRIES is the maximum number we will allow before
1017. // going to a long timeout.生命期就是我们允许RREQ重播的次数
1018. //如果AODV中多次发送RREQ,仍然找不到到目的节点的路由,那么丢包。(这个if中代码干的事)
1019. if (rt->rt_req_cnt > RREQ_RETRIES) {
1020. rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
1021. rt->rt_req_cnt = 0;
1022. Packet *buf_pkt;
1023. while ((buf_pkt = rqueue.deque(rt->rt_dst))) {
1024. drop(buf_pkt, DROP_RTR_NO_ROUTE);
1025. }
1026. Packet::free((Packet *)p);
1027. return;
1028. }
1029. //下面的内容是填充路由表以及RREQ数据分组的内容,需要结合路由表文件来看。
1030. #ifdef DEBUG
1031. fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d/n",
1032. ++route_request, index, rt->rt_dst);
1033. #endif // DEBUG
1034. // Determine the TTL to be used this time. 动态的确定这次RREQ的生命期,
1035. // Dynamic TTL evaluation - SRD 用SRD来球RREQ。
1036. rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count);
1037. if (0 == rt->rt_req_last_ttl) {
1038. // first time query broadcast第一次广播
1039. ih->ttl_ = TTL_START;
1040. }
1041. else {
1042. // Expanding ring search.
1043. if (rt->rt_req_last_ttl < TTL_THRESHOLD)
1044. ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT;//逐步增加生命周期,知道最大值(TTL_
1045. //_THRESHOLD)
1046. else {//如果已经超期了,那么RREQ的广播次数加一
1047. // network-wide broadcast
1048. ih->ttl_ = NETWORK_DIAMETER;
1049. rt->rt_req_cnt += 1;
1050. }
1051. }
1052. // remember the TTL used for the next time
1053. rt->rt_req_last_ttl = ih->ttl_;
1054. // PerHopTime is the roundtrip time per hop for route requests.每一跳的时间,就是ROUTE
1055. //REQUEST在两节点间传播一次时间
1056. // The factor 2.0 is just to be safe .. SRD 5/22/99将这个时间设成2.0是比较安全的,
1057. //当然我们也可以改
1058. // Also note that we are making timeouts to be larger if we have
1059. // done network wide broadcast before.
1060. rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); //?
1061. if (rt->rt_req_cnt > 0)//如果不是第一次传播
1062. rt->rt_req_timeout *= rt->rt_req_cnt;
1063. rt->rt_req_timeout += CURRENT_TIME;
1064. // Don't let the timeout to be too large, however .. SRD 6/8/99如果不想让生命期太长
1065. if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
1066. rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
1067. rt->rt_expire = 0;
1068. #ifdef DEBUG
1069. fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms/n",
1070. ++route_request,
1071. index, rt->rt_dst,
1072. rt->rt_req_timeout - CURRENT_TIME);
1073. #endif // DEBUG
1074.
1075. // Fill out the RREQ packet 填写RREQ数据包的各个元素。
1076. // ch->uid() = 0;
1077. ch->ptype() = PT_AODV;
1078. ch->size() = IP_HDR_LEN + rq->size();
1079. ch->iface() = -2;
1080. ch->error() = 0;
1081. ch->addr_type() = NS_AF_NONE;
1082. ch->prev_hop_ = index; // AODV hack
1083. ih->saddr() = index;
1084. ih->daddr() = IP_BROADCAST;
1085. ih->sport() = RT_PORT;
1086. ih->dport() = RT_PORT;
1087. // Fill up some more fields.
1088. rq->rq_type = AODVTYPE_RREQ;
1089. rq->rq_hop_count = 1;
1090. rq->rq_bcast_id = bid++;
1091. rq->rq_dst = dst;
1092. rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);
1093. rq->rq_src = index;
1094. seqno += 2;
1095. assert ((seqno%2) == 0);
1096. rq->rq_src_seqno = seqno;
1097. rq->rq_timestamp = CURRENT_TIME;
1098. Scheduler::instance().schedule(target_, p, 0.);
1099. }
1100. //这个函数主要是填充RREP的内容(我注解的可能有问题)
1101. void
1102. AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst,
1103. u_int32_t rpseq, u_int32_t lifetime, double timestamp) {
1104. //目的节点IP地址,从源节点到目的节点的跳数,rrep目的节点(源节点IP地址),
1105. //目的节点序列号,生命周期,最后一个不清楚
1106. Packet *p = Packet::alloc();
1107. struct hdr_cmn *ch = HDR_CMN(p);
1108. struct hdr_ip *ih = HDR_IP(p);
1109. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
1110. aodv_rt_entry *rt = rtable.rt_lookup(ipdst);
1111. /*这个就是lookup函数
1112. aodv_rtable::rt_lookup(nsaddr_t id)
1113. {
1114. aodv_rt_entry *rt = rthead.lh_first;
1115. for(; rt; rt = rt->rt_link.le_next) {
1116. if(rt->rt_dst == id)
1117. break;
1118. }
1119. return rt;
1120. }
1121. */
1122. #ifdef DEBUG
1123. fprintf(stderr, "sending Reply from %d at %.2f/n", index, Scheduler::instance().clock());
1124. #endif // DEBUG
1125. assert(rt);
1126. rp->rp_type = AODVTYPE_RREP; //确定数据包的类型为RREP
1127. //rp->rp_flags = 0x00;
1128. rp->rp_hop_count = hop_count; // hop_count = rt_hops + 1,通告上一个节点到达目的节点的跳书
1129. rp->rp_dst = rpdst; //路由询问rq的目标IP地址
1130. rp->rp_dst_seqno = rpseq;
1131. rp->rp_src = index; //rq的源是本节点的IP地址
1132. rp->rp_lifetime = lifetime;
1133. rp->rp_timestamp = timestamp;
1134.
1135. // ch->uid() = 0;
1136. ch->ptype() = PT_AODV;
1137. ch->size() = IP_HDR_LEN + rp->size();
1138. ch->iface() = -2;
1139. ch->error() = 0;
1140. ch->addr_type() = NS_AF_INET;
1141. ch->next_hop_ = rt->rt_nexthop;
1142. ch->prev_hop_ = index; // AODV hack
1143. ch->direction() = hdr_cmn::DOWN;
1144. ih->saddr() = index; //定义了发送节点的ip地址
1145. ih->daddr() = ipdst; //目的节点
1146. ih->sport() = RT_PORT;
1147. ih->dport() = RT_PORT;
1148. ih->ttl_ = NETWORK_DIAMETER;
1149. Scheduler::instance().schedule(target_, p, 0.);
1150. }
1151. void
1152. AODV::sendError(Packet *p, bool jitter) {//链路中断,需要发送RRER。
1153. //通知所有受影响的节点,函数体关于填充RRER的内容,不用细看。
1154. struct hdr_cmn *ch = HDR_CMN(p);
1155. struct hdr_ip *ih = HDR_IP(p);
1156. struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
1157.
1158. #ifdef ERROR
1159. fprintf(stderr, "sending Error from %d at %.2f/n", index, Scheduler::instance().clock());
1160. #endif // DEBUG
1161. re->re_type = AODVTYPE_RERR;
1162. //re->reserved[0] = 0x00; re->reserved[1] = 0x00;
1163. // DestCount and list of unreachable destinations are already filled
1164. // ch->uid() = 0;
1165. ch->ptype() = PT_AODV;
1166. ch->size() = IP_HDR_LEN + re->size();
1167. ch->iface() = -2;
1168. ch->error() = 0;
1169. ch->addr_type() = NS_AF_NONE;
1170. ch->next_hop_ = 0;
1171. ch->prev_hop_ = index; // AODV hack
1172. ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
1173. ih->saddr() = index;
1174. ih->daddr() = IP_BROADCAST;
1175. ih->sport() = RT_PORT;
1176. ih->dport() = RT_PORT;
1177. ih->ttl_ = 1;
1178. // Do we need any jitter? Yes
1179. if (jitter)
1180. Scheduler::instance().schedule(target_, p, 0.01*Random::uniform());
1181. else
1182. Scheduler::instance().schedule(target_, p, 0.0);
1183. }
1184.
1185. /*
1186. Neighbor Management Functions
1187. */
1188. void
1189. AODV::sendHello() {//周期发送HELLOW分组,以检测邻居节点的联通性。
1190. Packet *p = Packet::alloc();
1191. struct hdr_cmn *ch = HDR_CMN(p);
1192. struct hdr_ip *ih = HDR_IP(p);
1193. struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p);
1194. #ifdef DEBUG
1195. fprintf(stderr, "sending Hello from %d at %.2f/n", index, Scheduler::instance().clock());
1196. #endif // DEBUG
1197. rh->rp_type = AODVTYPE_HELLO;
1198. //rh->rp_flags = 0x00;
1199. rh->rp_hop_count = 1;
1200. rh->rp_dst = index;
1201. rh->rp_dst_seqno = seqno;
1202. rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
1203. // ch->uid() = 0;
1204. ch->ptype() = PT_AODV;
1205. ch->size() = IP_HDR_LEN + rh->size();
1206. ch->iface() = -2;
1207. ch->error() = 0;
1208. ch->addr_type() = NS_AF_NONE;
1209. ch->prev_hop_ = index; // AODV hack
1210. ih->saddr() = index;
1211. ih->daddr() = IP_BROADCAST;
1212. ih->sport() = RT_PORT;
1213. ih->dport() = RT_PORT;
1214. ih->ttl_ = 1;
1215. Scheduler::instance().schedule(target_, p, 0.0);
1216. }
1217.
1218. void
1219. AODV::recvHello(Packet *p) {
1220. //struct hdr_ip *ih = HDR_IP(p);
1221. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
1222. AODV_Neighbor *nb;
1223. nb = nb_lookup(rp->rp_dst);
1224. if(nb == 0) {
1225. nb_insert(rp->rp_dst);
1226. }
1227. else {
1228. nb->nb_expire = CURRENT_TIME +
1229. (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
1230. }
1231. Packet::free(p);
1232. }
1233. void
1234. AODV::nb_insert(nsaddr_t id) {
1235. AODV_Neighbor *nb = new AODV_Neighbor(id);
1236. assert(nb);
1237. nb->nb_expire = CURRENT_TIME +
1238. (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
1239. LIST_INSERT_HEAD(&nbhead, nb, nb_link);
1240. seqno += 2; // set of neighbors changed
1241. assert ((seqno%2) == 0);
1242. }
1243.
1244. AODV_Neighbor*
1245. AODV::nb_lookup(nsaddr_t id) {
1246. AODV_Neighbor *nb = nbhead.lh_first;
1247. for(; nb; nb = nb->nb_link.le_next) {
1248. if(nb->nb_addr == id) break;
1249. }
1250. return nb;
1251. }
1252.
1253. /*
1254. * Called when we receive *explicit* notification that a Neighbor
1255. * is no longer reachable.
1256. */
1257. void
1258. AODV::nb_delete(nsaddr_t id) {
1259. AODV_Neighbor *nb = nbhead.lh_first;
1260. log_link_del(id);
1261. seqno += 2; // Set of neighbors changed
1262. assert ((seqno%2) == 0);
1263. for(; nb; nb = nb->nb_link.le_next) {
1264. if(nb->nb_addr == id) {
1265. LIST_REMOVE(nb,nb_link);
1266. delete nb;
1267. break;
1268. }
1269. }
1270. handle_link_failure(id);
1271. }
1272.
1273. /*
1274. * Purges all timed-out Neighbor Entries - runs every
1275. * HELLO_INTERVAL * 1.5 seconds.
1276. */
1277. void
1278. AODV::nb_purge() {
1279. AODV_Neighbor *nb = nbhead.lh_first;
1280. AODV_Neighbor *nbn;
1281. double now = CURRENT_TIME;
1282. for(; nb; nb = nbn) {
1283. nbn = nb->nb_link.le_next;
1284. if(nb->nb_expire <= now) {
1285. nb_delete(nb->nb_addr);
1286. }
1287. }
1288. }
文章浏览阅读3.4w次,点赞39次,收藏191次。一、 前言:项目舍弃了原本的SSH框架,改用Spring Boot框架,并且要引入Spring Security为系统提供安全访问控制解决方案,接下来记录一下这两天在Spring Boot中引入Spring Security 的过程。主要参考了以下项目、博客和手册:(目前最新的Spring Security版本为5.0.4,我使用的是5.0.3,前三个链接中用的应该都是Spring Securit..._springboot org.springframework.security.web.access.intercept.filtersecurityi
文章浏览阅读486次。是 PyTorch 中用于处理变长序列数据的函数。它的主要作用是将一个批次的序列数据打包成适合输入到 RNN(循环神经网络)模型中的形式,以避免对填充部分进行多余的计算。在自然语言处理任务中,例如文本分类、机器翻译等,输入的文本序列长度往往不同,为了方便进行批量处理,需要对较短的序列进行填充(padding)使其与最长序列的长度相同。但是,在某些情况下,填充的部分对模型来说是没有意义的,而且会导致额外的计算开销。因此,函数将填充的部分从计算中移除,以提高模型的效率。下面是一个示例,介绍了如何使用。_pack_padded_sequence
文章浏览阅读1.1k次。为什么要使用绑定变量:在JAVA中的SQL 语句的编写方面,没有使用ORACLE 绑定变量,很大程度上降低了数据库的性能,表现在两个方面:1、SQL语句硬分析(Hard Parse)太多,严重消耗CPU资源,延长了SQL语句总的执行时间。SQL语句的执行过程分几个步骤:语法检查、分析、执行、返回结果。其中分析又分为硬分析(Hard Parse)和软分析(Soft P..._java oracle绑定变量
文章浏览阅读127次。flutter mixin_flutter mixin 混入 mixin
文章浏览阅读888次。贴个图众所周知,Windows Terminal没有美化后那个傻大蓝,沉默黑简直不忍直视。没有像官方演示的那么美观(所以得自己捯饬捯饬好看的样子)美化开始第一步安装相关的模块和PowerLine主题Install-Module posh-git -Scope CurrentUserInstall-Module oh-my-posh -Scope CurrentUser如果你使用管理员权限打开PowerShell并且想把oh-my-posh安装到所有用户,则输入Install-Module _aka terminal美化
文章浏览阅读435次。一、前言自从研究Qt编写自定义控件以来,一发不可收拾,越多越多人有类似的需求找我定制控件,陆陆续续写了上百个控件,目前已超过150个,于是逐渐衍生了另外一个需求,提供一个控件属性设计器,类似QtDesigner一样,可以方便的拖曳控件,改变属性,立即应用,并导出到文件方便下次直接加载,这个设计器有点像组态中的一个雏形,提供了基本的加载控件,导入导出数据,数据源绑定等。本系列文章将从加..._qt实现属性编辑
文章浏览阅读512次。gradle 是一个打包工具, 是一个开源构建自动化工具,足够灵活,可以构建几乎任何类型的软件,高性能、可扩展、能洞察等。其中洞察,可以用于分析构建过程中数据,提供分析参考,方便排查问题和不断优化构建性能,以下一次编译分析报告。_maven转gradle插件
文章浏览阅读979次,点赞21次,收藏9次。基于java的在线问卷调查系统的设计与实现的主要使用者分为:管理员权限操作的功能包括对注册用户信息的管理,对问卷,题目,问卷调查,新闻资讯等信息的管理。用户权限操作的功能包括参与问卷调查,查看新闻,查看问卷调查记录。
文章浏览阅读974次。勒让德惯性椭圆求解1.matlab利用二阶矩求解椭圆长轴、短轴、离心率、长轴与x轴夹角xbar=stats(k).Centroid(1);%区域的重心坐标ybar = stats(k).Centroid(2); x = list(:,1) - xbar; y = -(list(:,2) - ybar); % This is negative for the % orientation calculation (measured in the % counter-clockwise dire_二阶矩确认椭圆
文章浏览阅读155次。在本教程中,我们涵盖了Python编程的主要主题,包括Python基础知识、Python数学、Python网络编程、Python算法和数据结构、Python机器学习、Python Web开发和Python游戏开发。
文章浏览阅读67次。在Ubuntu 12.04 64 位 搭载Android4.4源码编译环境 一、准备工作:(1) VMare Workstation 10(2)Ubuntu12.04 64bit(3) JDK1.6(4)Android 4.4 源码(PS:...
文章浏览阅读1.2k次,点赞19次,收藏24次。本文主要介绍了图像数据的几种增广方式,其中包括随机翻转、随机裁剪和随机颜色变换等,使用时一般在训练集上综合使用以达到鲁棒效果。_图像增广