3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
43 #include "olsr_protocol.h"
45 #include "lq_packet.h"
46 #include "interfaces.h"
48 #include "neighbor_table.h"
50 #include "olsr_time.h"
51 #include "process_package.h" // XXX - remove
53 #include "build_msg.h"
55 #include "lq_plugin.h"
56 #include "olsr_logging.h"
60 bool lq_tc_pending = false;
62 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
64 static uint16_t local_ansn_number = 0;
66 uint16_t get_local_ansn_number(bool increase) {
69 return local_ansn_number;
74 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
76 struct link_entry *walker;
78 // initialize the static fields
80 lq_hello->comm.type = olsr_get_Hello_MessageId();
81 lq_hello->comm.vtime = me_to_reltime(outif->valtimes.hello);
82 lq_hello->comm.size = 0;
84 lq_hello->comm.orig = olsr_cnf->router_id;
86 lq_hello->comm.ttl = 1;
87 lq_hello->comm.hops = 0;
89 lq_hello->htime = outif->hello_etime;
90 lq_hello->will = olsr_cnf->willingness;
92 lq_hello->neigh = NULL;
94 // loop through the link set
96 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
98 // allocate a neighbour entry
99 struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor();
101 // a) this neighbor interface IS NOT visible via the output interface
102 if (olsr_ipcmp(&walker->local_iface_addr, &outif->ip_addr) != 0)
103 neigh->link_type = UNSPEC_LINK;
105 // b) this neighbor interface IS visible via the output interface
108 neigh->link_type = lookup_link_status(walker);
110 // set the entry's link quality
111 olsr_copy_hello_lq(neigh, walker);
113 // set the entry's neighbour type
115 if (walker->neighbor->is_mpr)
116 neigh->neigh_type = MPR_NEIGH;
118 else if (walker->neighbor->is_sym)
119 neigh->neigh_type = SYM_NEIGH;
122 neigh->neigh_type = NOT_NEIGH;
124 // set the entry's neighbour interface address
126 neigh->addr = walker->neighbor_iface_addr;
128 // queue the neighbour entry
129 neigh->next = lq_hello->neigh;
130 lq_hello->neigh = neigh;
133 OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
137 destroy_lq_hello(struct lq_hello_message *lq_hello)
139 struct lq_hello_neighbor *walker, *aux;
141 // loop through the queued neighbour entries and free them
143 for (walker = lq_hello->neigh; walker != NULL; walker = aux) {
145 olsr_free_lq_hello_neighbor(walker);
148 lq_hello->neigh = NULL;
152 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
154 struct link_entry *lnk;
155 struct nbr_entry *walker;
156 struct tc_mpr_addr *neigh;
157 static int ttl_list[] = { 2, 8, 2, 16, 2, 8, 2, MAX_TTL };
159 // remember that we have generated an LQ TC message; this is
160 // checked in net_output()
162 lq_tc_pending = true;
164 // initialize the static fields
166 lq_tc->comm.type = olsr_get_TC_MessageId();
167 lq_tc->comm.vtime = me_to_reltime(outif->valtimes.tc);
168 lq_tc->comm.size = 0;
170 lq_tc->comm.orig = olsr_cnf->router_id;
172 if (olsr_cnf->lq_fish > 0) {
173 if (outif->ttl_index >= (int)(ARRAYSIZE(ttl_list)))
174 outif->ttl_index = 0;
176 lq_tc->comm.ttl = (0 <= outif->ttl_index ? ttl_list[outif->ttl_index] : MAX_TTL);
179 OLSR_DEBUG(LOG_PACKET_CREATION, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
183 lq_tc->comm.ttl = MAX_TTL;
185 lq_tc->comm.hops = 0;
187 lq_tc->from = olsr_cnf->router_id;
189 lq_tc->ansn = get_local_ansn_number(false);
193 OLSR_FOR_ALL_NBR_ENTRIES(walker) {
198 * Only consider symmetric neighbours.
200 if (!walker->is_sym) {
207 * Only consider MPRs and MPR selectors
209 if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr && walker->mprs_count == 0) {
216 * Only consider MPR selectors
218 if (olsr_cnf->tc_redundancy == 0 && walker->mprs_count == 0) {
222 /* Set the entry's link quality */
223 lnk = get_best_link_to_neighbor(&walker->nbr_addr);
225 continue; // no link ?
228 if (lnk->linkcost >= LINK_COST_BROKEN) {
229 continue; // don't advertise links with very low LQ
232 /* Allocate a neighbour entry. */
233 neigh = olsr_malloc_tc_mpr_addr();
235 /* Set the entry's main address. */
236 neigh->address = walker->nbr_addr;
239 olsr_copylq_link_entry_2_tc_mpr_addr(neigh, lnk);
242 /* Queue the neighbour entry. */
244 // TODO: ugly hack until neighbor table is ported to avl tree
246 if (lq_tc->neigh == NULL || avl_comp_default(&lq_tc->neigh->address, &neigh->address) > 0) {
247 neigh->next = lq_tc->neigh;
248 lq_tc->neigh = neigh;
250 struct tc_mpr_addr *last = lq_tc->neigh, *n = last->next;
253 if (avl_comp_default(&n->address, &neigh->address) > 0) {
263 // neigh->next = lq_tc->neigh;
264 // lq_tc->neigh = neigh;
267 OLSR_FOR_ALL_NBR_ENTRIES_END(walker);
271 destroy_lq_tc(struct lq_tc_message *lq_tc)
273 struct tc_mpr_addr *walker, *aux;
275 // loop through the queued neighbour entries and free them
277 for (walker = lq_tc->neigh; walker != NULL; walker = aux) {
279 olsr_free_tc_mpr_addr(walker);
286 // return the size of the header shared by all OLSR messages
288 return (olsr_cnf->ip_version == AF_INET) ? sizeof(struct olsr_header_v4) : sizeof(struct olsr_header_v6);
292 serialize_common(struct olsr_common *comm)
294 if (olsr_cnf->ip_version == AF_INET) {
295 // serialize an IPv4 OLSR message header
296 struct olsr_header_v4 *olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
298 olsr_head_v4->type = comm->type;
299 olsr_head_v4->vtime = reltime_to_me(comm->vtime);
300 olsr_head_v4->size = htons(comm->size);
302 olsr_head_v4->orig = comm->orig.v4.s_addr;
304 olsr_head_v4->ttl = comm->ttl;
305 olsr_head_v4->hops = comm->hops;
306 olsr_head_v4->seqno = htons(get_msg_seqno());
308 // serialize an IPv6 OLSR message header
309 struct olsr_header_v6 *olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
311 olsr_head_v6->type = comm->type;
312 olsr_head_v6->vtime = reltime_to_me(comm->vtime);
313 olsr_head_v6->size = htons(comm->size);
315 memcpy(&olsr_head_v6->orig, &comm->orig.v6.s6_addr, sizeof(olsr_head_v6->orig));
317 olsr_head_v6->ttl = comm->ttl;
318 olsr_head_v6->hops = comm->hops;
319 olsr_head_v6->seqno = htons(get_msg_seqno());
324 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
326 static const int LINK_ORDER[] = { SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK };
327 int rem, size, req, expected_size = 0;
328 struct lq_hello_info_header *info_head;
329 struct lq_hello_neighbor *neigh;
334 // leave space for the OLSR header
335 int off = common_size();
337 // initialize the LQ_HELLO header
339 struct lq_hello_header *head = (struct lq_hello_header *)(msg_buffer + off);
342 head->htime = reltime_to_me(lq_hello->htime);
343 head->will = lq_hello->will;
345 // 'off' is the offset of the byte following the LQ_HELLO header
347 off += sizeof(struct lq_hello_header);
349 // our work buffer starts at 'off'...
351 buff = msg_buffer + off;
353 // ... that's why we start with a 'size' of 0 and subtract 'off' from
354 // the remaining bytes in the output buffer
357 rem = net_outbuffer_bytes_left(outif) - off;
360 * Initially, we want to put the complete lq_hello into the message.
361 * For this flush the output buffer (if there are some bytes in).
362 * This is a hack/fix, which prevents message fragementation resulting
363 * in instable links. The ugly lq/genmsg code should be reworked anyhow.
365 if (0 < net_output_pending(outif)) {
366 for (i = 0; i <= MAX_NEIGH; i++) {
368 for (j = 0; j < ARRAYSIZE(LINK_ORDER); j++) {
370 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
371 if (0 == i && 0 == j)
372 expected_size += olsr_cnf->ipsize + 4;
373 if (neigh->neigh_type == i && neigh->link_type == LINK_ORDER[j]) {
375 expected_size += sizeof(struct lq_hello_info_header);
384 if (rem < expected_size) {
386 rem = net_outbuffer_bytes_left(outif) - off;
391 // iterate through all neighbor types ('i') and all link types ('j')
393 for (i = 0; i <= MAX_NEIGH; i++) {
395 for (j = 0; j < ARRAYSIZE(LINK_ORDER); j++) {
398 // loop through neighbors
400 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
401 if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
404 // we need space for an IP address plus link quality
407 req = olsr_cnf->ipsize + 4;
409 // no, we also need space for an info header, as this is the
410 // first neighbor with the current neighor type and link type
413 req += sizeof(struct lq_hello_info_header);
415 // we do not have enough space left
417 // force signed comparison
419 if ((int)(size + req) > rem) {
420 // finalize the OLSR header
422 lq_hello->comm.size = size + off;
424 serialize_common(&lq_hello->comm);
426 // finalize the info header
428 info_head->size = ntohs(buff + size - (unsigned char *)info_head);
432 net_outbuffer_push(outif, msg_buffer, size + off);
436 // move to the beginning of the buffer
439 rem = net_outbuffer_bytes_left(outif) - off;
441 // we need a new info header
445 // create a new info header
448 info_head = (struct lq_hello_info_header *)(buff + size);
449 size += sizeof(struct lq_hello_info_header);
451 info_head->reserved = 0;
452 info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
454 // add the current neighbor's IP address
456 genipcopy(buff + size, &neigh->addr);
457 size += olsr_cnf->ipsize;
459 // add the corresponding link quality
460 size += olsr_serialize_hello_lq_pair(&buff[size], neigh);
465 // finalize the info header, if there are any neighbors with the
466 // current neighbor type and link type
469 info_head->size = ntohs(buff + size - (unsigned char *)info_head);
473 // finalize the OLSR header
475 lq_hello->comm.size = size + off;
477 serialize_common((struct olsr_common *)lq_hello);
479 // move the message to the output buffer
481 net_outbuffer_push(outif, msg_buffer, size + off);
485 calculate_border_flag(void *lower_border, void *higher_border)
487 uint8_t *lower = lower_border;
488 uint8_t *higher = higher_border;
490 uint8_t part, bitpos;
492 for (part = 0; part < olsr_cnf->ipsize; part++) {
493 if (lower[part] != higher[part]) {
498 if (part == olsr_cnf->ipsize) { // same IPs ?
501 // look for first bit of difference
503 for (bitpos = 0; bitpos < 8; bitpos++, bitmask <<= 1) {
504 if ((lower[part] & bitmask) == (higher[part] & bitmask)) {
509 bitpos += 8 * (olsr_cnf->ipsize - part - 1);
514 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
516 int off, rem, size, expected_size = 0;
517 struct lq_tc_header *head;
518 struct tc_mpr_addr *neigh;
521 union olsr_ip_addr *last_ip = NULL;
522 uint8_t left_border_flag = 0xff;
524 // leave space for the OLSR header
528 // initialize the LQ_TC header
530 head = (struct lq_tc_header *)(msg_buffer + off);
532 head->ansn = htons(lq_tc->ansn);
533 head->lower_border = 0;
534 head->upper_border = 0;
536 // 'off' is the offset of the byte following the LQ_TC header
538 off += sizeof(struct lq_tc_header);
540 // our work buffer starts at 'off'...
542 buff = msg_buffer + off;
544 // ... that's why we start with a 'size' of 0 and subtract 'off' from
545 // the remaining bytes in the output buffer
548 rem = net_outbuffer_bytes_left(outif) - off;
551 * Initially, we want to put the complete lq_tc into the message.
552 * For this flush the output buffer (if there are some bytes in).
553 * This is a hack/fix, which prevents message fragementation resulting
554 * in instable links. The ugly lq/genmsg code should be reworked anyhow.
556 if (0 < net_output_pending(outif)) {
557 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next) {
558 // TODO sizeof_tc_lq function required
559 expected_size += olsr_cnf->ipsize + 4;
563 if (rem < expected_size) {
565 rem = net_outbuffer_bytes_left(outif) - off;
567 // loop through neighbors
569 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next) {
570 // we need space for an IP address plus link quality
573 // force signed comparison
575 // TODO sizeof_tc_lq function required
576 if ((int)(size + olsr_cnf->ipsize + 4) > rem) {
577 head->lower_border = left_border_flag;
578 head->upper_border = calculate_border_flag(last_ip, &neigh->address);
579 left_border_flag = head->upper_border;
581 // finalize the OLSR header
583 lq_tc->comm.size = size + off;
585 serialize_common((struct olsr_common *)lq_tc);
589 net_outbuffer_push(outif, msg_buffer, size + off);
593 // move to the beginning of the buffer
596 rem = net_outbuffer_bytes_left(outif) - off;
598 // add the current neighbor's IP address
599 genipcopy(buff + size, &neigh->address);
602 last_ip = (union olsr_ip_addr *)(buff + size);
604 size += olsr_cnf->ipsize;
606 // add the corresponding link quality
607 size += olsr_serialize_tc_lq_pair(&buff[size], neigh);
610 // finalize the OLSR header
612 head->lower_border = left_border_flag;
613 head->upper_border = 0xff;
614 lq_tc->comm.size = size + off;
616 serialize_common((struct olsr_common *)lq_tc);
618 net_outbuffer_push(outif, msg_buffer, size + off);
622 olsr_output_lq_hello(void *para)
624 struct lq_hello_message lq_hello;
625 struct interface *outif = para;
630 // create LQ_HELLO in internal format
631 create_lq_hello(&lq_hello, outif);
633 // convert internal format into transmission format, send it
634 serialize_lq_hello(&lq_hello, outif);
636 // destroy internal format
637 destroy_lq_hello(&lq_hello);
639 if (net_output_pending(outif)) {
640 if (outif->immediate_send_tc) {
641 set_buffer_timer(outif);
649 * Callback for TC generation timer.
652 olsr_output_lq_tc(void *ctx)
654 struct lq_tc_message lq_tc;
655 struct interface *outif = ctx;
661 /* create LQ_TC in internal format */
662 create_lq_tc(&lq_tc, outif);
664 /* empty message ? */
669 /* convert internal format into transmission format, send it */
670 serialize_lq_tc(&lq_tc, outif);
672 /* destroy internal format */
673 destroy_lq_tc(&lq_tc);
675 if (net_output_pending(outif)) {
676 if (!outif->immediate_send_tc) {
677 set_buffer_timer(outif);
687 * indent-tabs-mode: nil