2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2003, Andreas Tønnesen (andreto@olsr.org)
4 * 2004, Thomas Lopatic (thomas@lopatic.de)
5 * 2006, for some fixups, sven-ola(gmx.de)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * * Neither the name of olsr.org, olsrd nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * Visit http://www.olsr.org for more information.
37 * If you find this software useful feel free to make a donation
38 * to the project. For more information see the website or contact
39 * the copyright holders.
44 #include "olsr_protocol.h"
46 #include "lq_packet.h"
47 #include "interfaces.h"
49 #include "neighbor_table.h"
50 #include "mpr_selector_set.h"
53 #include "process_package.h" // XXX - remove
54 #include "two_hop_neighbor_table.h"
55 #include "hysteresis.h"
57 #include "build_msg.h"
61 olsr_bool lq_tc_pending = OLSR_FALSE;
63 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
66 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
68 struct link_entry *walker;
70 // initialize the static fields
72 lq_hello->comm.type = LQ_HELLO_MESSAGE;
73 lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
74 lq_hello->comm.size = 0;
76 lq_hello->comm.orig = olsr_cnf->main_addr;
78 lq_hello->comm.ttl = 1;
79 lq_hello->comm.hops = 0;
80 lq_hello->comm.seqno = get_msg_seqno();
82 lq_hello->htime = outif->hello_etime;
83 lq_hello->will = olsr_cnf->willingness;
85 lq_hello->neigh = NULL;
87 // loop through the link set
89 for (walker = get_link_set(); walker != NULL; walker = walker->next)
91 // allocate a neighbour entry
92 struct lq_hello_neighbor *neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
94 // a) this neighbor interface IS NOT visible via the output interface
95 if(!ipequal(&walker->local_iface_addr, &outif->ip_addr))
96 neigh->link_type = UNSPEC_LINK;
98 // b) this neighbor interface IS visible via the output interface
101 neigh->link_type = lookup_link_status(walker);
103 // set the entry's link quality
105 neigh->link_quality = walker->loss_link_quality;
106 neigh->neigh_link_quality = walker->neigh_link_quality;
108 // set the entry's neighbour type
110 if(walker->neighbor->is_mpr)
111 neigh->neigh_type = MPR_NEIGH;
113 else if (walker->neighbor->status == SYM)
114 neigh->neigh_type = SYM_NEIGH;
116 else if (walker->neighbor->status == NOT_SYM)
117 neigh->neigh_type = NOT_NEIGH;
119 // set the entry's neighbour interface address
121 neigh->addr = walker->neighbor_iface_addr;
123 // queue the neighbour entry
125 neigh->next = lq_hello->neigh;
126 lq_hello->neigh = neigh;
131 destroy_lq_hello(struct lq_hello_message *lq_hello)
133 struct lq_hello_neighbor *walker, *aux;
135 // loop through the queued neighbour entries and free them
137 for (walker = lq_hello->neigh; walker != NULL; walker = aux)
143 lq_hello->neigh = NULL;
147 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
150 static int ttl_list[] = { 2, 8, 2, 16, 2, 8, 2, MAX_TTL};
152 // remember that we have generated an LQ TC message; this is
153 // checked in net_output()
155 lq_tc_pending = OLSR_TRUE;
157 // initialize the static fields
159 lq_tc->comm.type = LQ_TC_MESSAGE;
160 lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
161 lq_tc->comm.size = 0;
163 lq_tc->comm.orig = olsr_cnf->main_addr;
165 if (olsr_cnf->lq_fish > 0)
167 // Sven-Ola: Too lazy to find the different iface inits. This will do it too.
168 if (outif->ttl_index >= (int)(sizeof(ttl_list) / sizeof(ttl_list[0])))
169 outif->ttl_index = 0;
171 lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
173 OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
177 lq_tc->comm.ttl = MAX_TTL;
179 lq_tc->comm.hops = 0;
180 lq_tc->comm.seqno = get_msg_seqno();
182 lq_tc->from = olsr_cnf->main_addr;
184 lq_tc->ansn = get_local_ansn();
188 // loop through all neighbours
190 for(i = 0; i < HASHSIZE; i++)
192 struct neighbor_entry *walker;
193 struct tc_mpr_addr *neigh;
194 for(walker = neighbortable[i].next; walker != &neighbortable[i];
195 walker = walker->next)
197 struct link_entry *lnk;
198 // only consider symmetric neighbours
200 if(walker->status != SYM)
203 // TC redundancy == 1: only consider MPRs and MPR selectors
205 if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
206 olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
209 // TC redundancy == 0: only consider MPR selectors
210 if (olsr_cnf->tc_redundancy == 0 &&
211 olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
214 // allocate a neighbour entry
215 neigh = olsr_malloc(sizeof (struct tc_mpr_addr), "Build LQ_TC");
217 // set the entry's main address
219 neigh->address = walker->neighbor_main_addr;
221 // set the entry's link quality
222 lnk = get_best_link_to_neighbor(&neigh->address);
225 neigh->link_quality = lnk->loss_link_quality;
226 neigh->neigh_link_quality = lnk->neigh_link_quality;
229 // queue the neighbour entry
231 neigh->next = lq_tc->neigh;
232 lq_tc->neigh = neigh;
238 destroy_lq_tc(struct lq_tc_message *lq_tc)
240 struct tc_mpr_addr *walker, *aux;
242 // loop through the queued neighbour entries and free them
244 for (walker = lq_tc->neigh; walker != NULL; walker = aux)
251 static int common_size(void)
253 // return the size of the header shared by all OLSR messages
255 return (olsr_cnf->ip_version == AF_INET) ?
256 sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
259 static void serialize_common(struct olsr_common *comm)
261 if (olsr_cnf->ip_version == AF_INET)
263 // serialize an IPv4 OLSR message header
264 struct olsr_header_v4 *olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
266 olsr_head_v4->type = comm->type;
267 olsr_head_v4->vtime = double_to_me(comm->vtime);
268 olsr_head_v4->size = htons(comm->size);
270 olsr_head_v4->orig = comm->orig.v4.s_addr;
272 olsr_head_v4->ttl = comm->ttl;
273 olsr_head_v4->hops = comm->hops;
274 olsr_head_v4->seqno = htons(comm->seqno);
278 // serialize an IPv6 OLSR message header
279 struct olsr_header_v6 *olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
281 olsr_head_v6->type = comm->type;
282 olsr_head_v6->vtime = double_to_me(comm->vtime);
283 olsr_head_v6->size = htons(comm->size);
285 memcpy(&olsr_head_v6->orig, &comm->orig.v6.s6_addr, sizeof(olsr_head_v6->orig));
287 olsr_head_v6->ttl = comm->ttl;
288 olsr_head_v6->hops = comm->hops;
289 olsr_head_v6->seqno = htons(comm->seqno);
294 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
296 static const int LINK_ORDER[] = {SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK};
297 int rem, size, req, expected_size = 0;
298 struct lq_hello_info_header *info_head;
299 struct lq_hello_neighbor *neigh;
304 // leave space for the OLSR header
305 int off = common_size();
307 // initialize the LQ_HELLO header
309 struct lq_hello_header *head = (struct lq_hello_header *)(msg_buffer + off);
312 head->htime = double_to_me(lq_hello->htime);
313 head->will = lq_hello->will;
315 // 'off' is the offset of the byte following the LQ_HELLO header
317 off += sizeof (struct lq_hello_header);
319 // our work buffer starts at 'off'...
321 buff = msg_buffer + off;
323 // ... that's why we start with a 'size' of 0 and subtract 'off' from
324 // the remaining bytes in the output buffer
327 rem = net_outbuffer_bytes_left(outif) - off;
330 * Initially, we want to put the complete lq_hello into the message.
331 * For this flush the output buffer (if there are some bytes in).
332 * This is a hack/fix, which prevents message fragementation resulting
333 * in instable links. The ugly lq/genmsg code should be reworked anyhow.
335 if (0 < net_output_pending(outif)) {
336 for (i = 0; i <= MAX_NEIGH; i++) {
338 for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++) {
339 is_first = OLSR_TRUE;
340 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
341 if (0 == i && 0 == j) expected_size += olsr_cnf->ipsize + 4;
342 if (neigh->neigh_type == i && neigh->link_type == LINK_ORDER[j]) {
344 expected_size += sizeof(struct lq_hello_info_header);
345 is_first = OLSR_FALSE;
353 if (rem < expected_size) {
355 rem = net_outbuffer_bytes_left(outif) - off;
360 // iterate through all neighbor types ('i') and all link types ('j')
362 for (i = 0; i <= MAX_NEIGH; i++)
365 for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++)
367 is_first = OLSR_TRUE;
369 // loop through neighbors
371 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
373 if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
376 // we need space for an IP address plus link quality
379 req = olsr_cnf->ipsize + 4;
381 // no, we also need space for an info header, as this is the
382 // first neighbor with the current neighor type and link type
385 req += sizeof (struct lq_hello_info_header);
387 // we do not have enough space left
389 // force signed comparison
391 if ((int)(size + req) > rem)
393 // finalize the OLSR header
395 lq_hello->comm.size = size + off;
397 serialize_common(&lq_hello->comm);
399 // finalize the info header
402 ntohs(buff + size - (unsigned char *)info_head);
406 net_outbuffer_push(outif, msg_buffer, size + off);
410 // move to the beginning of the buffer
413 rem = net_outbuffer_bytes_left(outif) - off;
415 // we need a new info header
417 is_first = OLSR_TRUE;
420 // create a new info header
424 info_head = (struct lq_hello_info_header *)(buff + size);
425 size += sizeof (struct lq_hello_info_header);
427 info_head->reserved = 0;
428 info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
431 // add the current neighbor's IP address
433 genipcopy(buff + size, &neigh->addr);
434 size += olsr_cnf->ipsize;
436 // add the corresponding link quality
438 buff[size++] = (unsigned char)(neigh->link_quality * 255);
439 buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
446 is_first = OLSR_FALSE;
449 // finalize the info header, if there are any neighbors with the
450 // current neighbor type and link type
453 info_head->size = ntohs(buff + size - (unsigned char *)info_head);
457 // finalize the OLSR header
459 lq_hello->comm.size = size + off;
461 serialize_common((struct olsr_common *)lq_hello);
463 // move the message to the output buffer
465 net_outbuffer_push(outif, msg_buffer, size + off);
469 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
471 int off, rem, size, expected_size = 0;
472 struct lq_tc_header *head;
473 struct tc_mpr_addr *neigh;
476 // leave space for the OLSR header
480 // initialize the LQ_TC header
482 head = (struct lq_tc_header *)(msg_buffer + off);
484 head->ansn = htons(lq_tc->ansn);
487 // 'off' is the offset of the byte following the LQ_TC header
489 off += sizeof (struct lq_tc_header);
491 // our work buffer starts at 'off'...
493 buff = msg_buffer + off;
495 // ... that's why we start with a 'size' of 0 and subtract 'off' from
496 // the remaining bytes in the output buffer
499 rem = net_outbuffer_bytes_left(outif) - off;
502 * Initially, we want to put the complete lq_tc into the message.
503 * For this flush the output buffer (if there are some bytes in).
504 * This is a hack/fix, which prevents message fragementation resulting
505 * in instable links. The ugly lq/genmsg code should be reworked anyhow.
507 if (0 < net_output_pending(outif)) {
508 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next) {
509 expected_size += olsr_cnf->ipsize + 4;
513 if (rem < expected_size) {
515 rem = net_outbuffer_bytes_left(outif) - off;
518 // loop through neighbors
520 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
522 // we need space for an IP address plus link quality
525 // force signed comparison
527 if ((int)(size + olsr_cnf->ipsize + 4) > rem)
529 // finalize the OLSR header
531 lq_tc->comm.size = size + off;
533 serialize_common((struct olsr_common *)lq_tc);
537 net_outbuffer_push(outif, msg_buffer, size + off);
541 // move to the beginning of the buffer
544 rem = net_outbuffer_bytes_left(outif) - off;
547 // add the current neighbor's IP address
548 genipcopy(buff + size, &neigh->address);
549 size += olsr_cnf->ipsize;
551 // add the corresponding link quality
552 buff[size++] = (unsigned char)(neigh->link_quality * 255);
553 buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
560 // finalize the OLSR header
562 lq_tc->comm.size = size + off;
564 serialize_common((struct olsr_common *)lq_tc);
566 net_outbuffer_push(outif, msg_buffer, size + off);
571 deserialize_lq_hello(struct hello_message *hello,
574 const unsigned char *limit;
578 const unsigned char *curr = ser;
579 pkt_get_u8(&curr, &type);
580 if (type != LQ_HELLO_MESSAGE) {
581 /* No need to do anything more */
584 pkt_get_double(&curr, &hello->vtime);
585 pkt_get_u16(&curr, &size);
586 pkt_get_ipaddress(&curr, &hello->source_addr);
588 pkt_get_u8(&curr, &hello->ttl);
589 pkt_get_u8(&curr, &hello->hop_count);
590 pkt_get_u16(&curr, &hello->packet_seq_number);
591 pkt_ignore_u16(&curr);
593 pkt_get_double(&curr, &hello->htime);
594 pkt_get_u8(&curr, &hello->willingness);
596 hello->neighbors = NULL;
597 limit = ((const unsigned char *)ser) + size;
598 while (curr < limit) {
599 const struct lq_hello_info_header *info_head = (const struct lq_hello_info_header *)curr;
600 const unsigned char *limit2 = curr + ntohs(info_head->size);
602 curr = (const unsigned char *)(info_head + 1);
603 while (curr < limit2) {
604 struct hello_neighbor *neigh = olsr_malloc(sizeof (struct hello_neighbor),
605 "LQ_HELLO deserialization");
606 pkt_get_ipaddress(&curr, &neigh->address);
608 pkt_get_lq(&curr, &neigh->link_quality);
609 pkt_get_lq(&curr, &neigh->neigh_link_quality);
610 pkt_ignore_u16(&curr);
612 neigh->link = EXTRACT_LINK(info_head->link_code);
613 neigh->status = EXTRACT_STATUS(info_head->link_code);
615 neigh->next = hello->neighbors;
616 hello->neighbors = neigh;
623 olsr_output_lq_hello(void *para)
625 struct lq_hello_message lq_hello;
626 struct interface *outif = para;
632 // create LQ_HELLO in internal format
633 create_lq_hello(&lq_hello, outif);
635 // convert internal format into transmission format, send it
636 serialize_lq_hello(&lq_hello, outif);
638 // destroy internal format
639 destroy_lq_hello(&lq_hello);
641 if(net_output_pending(outif)) {
647 olsr_output_lq_tc(void *para)
649 static int prev_empty = 1;
650 struct lq_tc_message lq_tc;
651 struct interface *outif = para;
656 // create LQ_TC in internal format
658 create_lq_tc(&lq_tc, outif);
660 // a) the message is not empty
662 if (lq_tc.neigh != NULL) {
665 // convert internal format into transmission format, send it
666 serialize_lq_tc(&lq_tc, outif);
668 // b) this is the first empty message
669 } else if (prev_empty == 0) {
672 set_empty_tc_timer(GET_TIMESTAMP(olsr_cnf->max_tc_vtime * 3 * 1000));
676 // convert internal format into transmission format, send it
678 serialize_lq_tc(&lq_tc, outif);
680 // c) this is not the first empty message, send if timer hasn't fired
681 } else if (!TIMED_OUT(get_empty_tc_timer())) {
682 serialize_lq_tc(&lq_tc, outif);
684 // destroy internal format
686 destroy_lq_tc(&lq_tc);
688 if(net_output_pending(outif) && TIMED_OUT(outif->fwdtimer)) {
689 set_buffer_timer(outif);
694 olsr_input_lq_hello(union olsr_message *ser,
695 struct interface *inif,
696 union olsr_ip_addr *from)
698 struct hello_message hello;
703 if (deserialize_lq_hello(&hello, ser) != 0) {
706 olsr_hello_tap(&hello, inif, from);