2 * OLSR ad-hoc routing table management protocol
3 * Copyright (C) 2003 Andreas Tønnesen (andreto@ifi.uio.no)
4 * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
6 * This file is part of the olsr.org OLSR daemon.
8 * olsr.org is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * olsr.org is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with olsr.org; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * $Id: lq_packet.c,v 1.3 2004/11/05 20:58:10 tlopatic Exp $
27 #if defined USE_LINK_QUALITY
28 #include "olsr_protocol.h"
30 #include "interfaces.h"
32 #include "neighbor_table.h"
33 #include "mpr_selector_set.h"
36 #include "process_package.h" // XXX - remove
37 #include "two_hop_neighbor_table.h"
38 #include "hysteresis.h"
40 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
43 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
45 struct lq_hello_neighbor *neigh;
46 struct link_entry *walker;
48 // initialize the static fields
50 lq_hello->comm.type = LQ_HELLO_MESSAGE;
51 lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
52 lq_hello->comm.size = 0;
54 COPY_IP(&lq_hello->comm.orig, &main_addr);
56 lq_hello->comm.ttl = 1;
57 lq_hello->comm.hops = 0;
58 lq_hello->comm.seqno = get_msg_seqno();
60 lq_hello->htime = me_to_double(outif->hello_etime);
61 lq_hello->will = olsr_cnf->willingness;
63 lq_hello->neigh = NULL;
65 // loop through the link set
67 for (walker = link_set; walker != NULL; walker = walker->next)
69 // allocate a neighbour entry
71 neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
73 // a) this neighbor interface IS NOT visible via the output interface
75 if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
76 neigh->link_type = UNSPEC_LINK;
78 // b) this neighbor interface IS visible via the output interface
81 neigh->link_type = lookup_link_status(walker);
83 // set the entry's link quality
85 neigh->link_quality = walker->loss_link_quality;
86 neigh->neigh_link_quality = walker->neigh_link_quality;
88 // set the entry's neighbour type
90 if(walker->neighbor->is_mpr)
91 neigh->neigh_type = MPR_NEIGH;
93 else if (walker->neighbor->status == SYM)
94 neigh->neigh_type = SYM_NEIGH;
96 else if (walker->neighbor->status == NOT_SYM)
97 neigh->neigh_type = NOT_NEIGH;
99 // set the entry's neighbour interface address
101 COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
103 // queue the neighbour entry
105 neigh->next = lq_hello->neigh;
106 lq_hello->neigh = neigh;
111 destroy_lq_hello(struct lq_hello_message *lq_hello)
113 struct lq_hello_neighbor *walker, *aux;
115 // loop through the queued neighbour entries and free them
117 for (walker = lq_hello->neigh; walker != NULL; walker = aux)
123 lq_hello->neigh = NULL;
127 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
129 struct lq_tc_neighbor *neigh;
131 struct neighbor_entry *walker;
133 // initialize the static fields
135 lq_tc->comm.type = LQ_TC_MESSAGE;
136 lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
137 lq_tc->comm.size = 0;
139 COPY_IP(&lq_tc->comm.orig, &main_addr);
141 lq_tc->comm.ttl = MAX_TTL;
142 lq_tc->comm.hops = 0;
143 lq_tc->comm.seqno = get_msg_seqno();
145 COPY_IP(&lq_tc->from, &main_addr);
151 // loop through all neighbours
153 for(i = 0; i < HASHSIZE; i++)
155 for(walker = neighbortable[i].next; walker != &neighbortable[i];
156 walker = walker->next)
158 // only consider symmetric neighbours
160 if(walker->status != SYM)
163 // TC redundancy == 1: only consider MPRs and MPR selectors
165 if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
166 olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
169 // TC redundancy == 0: only consider MPR selectors
171 else if (olsr_cnf->tc_redundancy == 0 &&
172 olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
175 // allocate a neighbour entry
177 neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
179 // set the entry's main address
181 COPY_IP(&neigh->main, &walker->neighbor_main_addr);
183 // set the entry's link quality
185 neigh->link_quality =
186 olsr_neighbor_best_link_quality(&neigh->main);
188 // queue the neighbour entry
190 neigh->next = lq_tc->neigh;
191 lq_tc->neigh = neigh;
197 destroy_lq_tc(struct lq_tc_message *lq_tc)
199 struct lq_tc_neighbor *walker, *aux;
201 // loop through the queued neighbour entries and free them
203 for (walker = lq_tc->neigh; walker != NULL; walker = aux)
210 static int common_size(void)
212 // return the size of the header shared by all OLSR messages
214 return (olsr_cnf->ip_version == AF_INET) ?
215 sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
218 static void serialize_common(struct olsr_common *comm)
220 struct olsr_header_v4 *olsr_head_v4;
221 struct olsr_header_v6 *olsr_head_v6;
223 // serialize an IPv4 OLSR message header
225 if (olsr_cnf->ip_version == AF_INET)
227 olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
229 olsr_head_v4->type = comm->type;
230 olsr_head_v4->vtime = double_to_me(comm->vtime);
231 olsr_head_v4->size = htons(comm->size);
233 COPY_IP(&olsr_head_v4->orig, &comm->orig);
235 olsr_head_v4->ttl = comm->ttl;
236 olsr_head_v4->hops = comm->hops;
237 olsr_head_v4->seqno = htons(comm->seqno);
240 // serialize an IPv6 OLSR message header
242 olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
244 olsr_head_v6->type = comm->type;
245 olsr_head_v6->vtime = double_to_me(comm->vtime);
246 olsr_head_v6->size = htons(comm->size);
248 COPY_IP(&olsr_head_v6->orig, &comm->orig);
250 olsr_head_v6->ttl = comm->ttl;
251 olsr_head_v6->hops = comm->hops;
252 olsr_head_v6->seqno = htons(comm->seqno);
256 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
258 int off, rem, size, req;
259 struct lq_hello_header *head;
260 struct lq_hello_info_header *info_head;
261 struct lq_hello_neighbor *neigh;
266 if (lq_hello == NULL || outif == NULL)
269 // leave space for the OLSR header
273 // initialize the LQ_HELLO header
275 head = (struct lq_hello_header *)(msg_buffer + off);
278 head->htime = double_to_me(lq_hello->htime);
279 head->will = lq_hello->will;
281 // 'off' is the offset of the byte following the LQ_HELLO header
283 off += sizeof (struct lq_hello_header);
285 // our work buffer starts at 'off'...
287 buff = msg_buffer + off;
289 // ... that's why we start with a 'size' of 0 and subtract 'off' from
290 // the remaining bytes in the output buffer
293 rem = net_outbuffer_bytes_left(outif) - off;
295 // initially, we want to put at least an info header, an IP address,
296 // and the corresponding link quality into the message
298 if (rem < sizeof (struct lq_hello_info_header) + ipsize + 4)
302 rem = net_outbuffer_bytes_left(outif) - off;
307 // iterate through all neighbor types ('i') and all link types ('j')
309 for (i = 0; i <= MAX_NEIGH; i++)
311 for(j = 0; j <= MAX_LINK; j++)
318 // loop through neighbors
320 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
322 if (neigh->neigh_type != i || neigh->link_type != j)
325 // we need space for an IP address plus link quality
330 // no, we also need space for an info header, as this is the
331 // first neighbor with the current neighor type and link type
334 req += sizeof (struct lq_hello_info_header);
336 // we do not have enough space left
338 if (size + req > rem)
340 // finalize the OLSR header
342 lq_hello->comm.size = size + off;
344 serialize_common((struct olsr_common *)lq_hello);
346 // finalize the info header
349 ntohs(buff + size - (unsigned char *)info_head);
353 net_outbuffer_push(outif, msg_buffer, size + off);
357 // move to the beginning of the buffer
360 rem = net_outbuffer_bytes_left(outif) - off;
362 // we need a new info header
367 // create a new info header
371 info_head = (struct lq_hello_info_header *)(buff + size);
372 size += sizeof (struct lq_hello_info_header);
374 info_head->reserved = 0;
375 info_head->link_code = CREATE_LINK_CODE(i, j);
378 // add the current neighbor's IP address
380 COPY_IP(buff + size, &neigh->addr);
383 // add the corresponding link quality
385 buff[size++] = (unsigned char)(neigh->link_quality * 256);
386 buff[size++] = (unsigned char)(neigh->neigh_link_quality * 256);
396 // finalize the info header, if there are any neighbors with the
397 // current neighbor type and link type
400 info_head->size = ntohs(buff + size - (unsigned char *)info_head);
404 // finalize the OLSR header
406 lq_hello->comm.size = size + off;
408 serialize_common((struct olsr_common *)lq_hello);
410 // move the message to the output buffer
412 net_outbuffer_push(outif, msg_buffer, size + off);
416 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
419 struct lq_tc_header *head;
420 struct lq_tc_neighbor *neigh;
423 if (lq_tc == NULL || outif == NULL)
426 // leave space for the OLSR header
430 // initialize the LQ_TC header
432 head = (struct lq_tc_header *)(msg_buffer + off);
434 head->ansn = htons(lq_tc->ansn);
437 // 'off' is the offset of the byte following the LQ_TC header
439 off += sizeof (struct lq_tc_header);
441 // our work buffer starts at 'off'...
443 buff = msg_buffer + off;
445 // ... that's why we start with a 'size' of 0 and subtract 'off' from
446 // the remaining bytes in the output buffer
449 rem = net_outbuffer_bytes_left(outif) - off;
451 // initially, we want to put at least an IP address and the corresponding
452 // link quality into the message
454 if (rem < ipsize + 4)
458 rem = net_outbuffer_bytes_left(outif) - off;
461 // loop through neighbors
463 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
465 // we need space for an IP address plus link quality
468 if (size + ipsize + 4 > rem)
470 // finalize the OLSR header
472 lq_tc->comm.size = size + off;
474 serialize_common((struct olsr_common *)lq_tc);
478 net_outbuffer_push(outif, msg_buffer, size + off);
482 // move to the beginning of the buffer
485 rem = net_outbuffer_bytes_left(outif) - off;
488 // add the current neighbor's IP address
490 COPY_IP(buff + size, &neigh->main);
493 // add the corresponding link quality
495 buff[size++] = (unsigned char)(neigh->link_quality * 256);
504 // finalize the OLSR header
506 lq_tc->comm.size = size + off;
508 serialize_common((struct olsr_common *)lq_tc);
510 net_outbuffer_push(outif, msg_buffer, size + off);
513 static void *deserialize_common(struct olsr_common *comm, void *ser)
515 struct olsr_header_v4 *olsr_head_v4;
516 struct olsr_header_v6 *olsr_head_v6;
518 // deserialize an IPv4 OLSR message header
520 if (olsr_cnf->ip_version == AF_INET)
522 olsr_head_v4 = (struct olsr_header_v4 *)ser;
524 comm->type = olsr_head_v4->type;
525 comm->vtime = me_to_double(olsr_head_v4->vtime);
526 comm->size = ntohs(olsr_head_v4->size);
528 COPY_IP(&comm->orig, &olsr_head_v4->orig);
530 comm->ttl = olsr_head_v4->ttl;
531 comm->hops = olsr_head_v4->hops;
532 comm->seqno = ntohs(olsr_head_v4->seqno);
534 return (void *)(olsr_head_v4 + 1);
537 // deserialize an IPv6 OLSR message header
539 olsr_head_v6 = (struct olsr_header_v6 *)ser;
541 comm->type = olsr_head_v6->type;
542 comm->vtime = me_to_double(olsr_head_v6->vtime);
543 comm->size = ntohs(olsr_head_v6->size);
545 COPY_IP(&comm->orig, &olsr_head_v6->orig);
547 comm->ttl = olsr_head_v6->ttl;
548 comm->hops = olsr_head_v6->hops;
549 comm->seqno = ntohs(olsr_head_v6->seqno);
551 return (void *)(olsr_head_v6 + 1);
555 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
557 struct lq_hello_header *head;
558 struct lq_hello_info_header *info_head;
559 unsigned char *curr, *limit, *limit2;
560 struct lq_hello_neighbor *neigh;
562 lq_hello->neigh = NULL;
567 head = (struct lq_hello_header *)
568 deserialize_common((struct olsr_common *)lq_hello, ser);
570 if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
573 limit = ((unsigned char *)ser) + lq_hello->comm.size;
575 lq_hello->htime = me_to_double(head->htime);
576 lq_hello->will = head->will;
578 curr = (unsigned char *)(head + 1);
582 info_head = (struct lq_hello_info_header *)curr;
584 limit2 = curr + ntohs(info_head->size);
586 curr = (unsigned char *)(info_head + 1);
588 while (curr < limit2)
590 neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
591 "LQ_HELLO deserialization");
593 COPY_IP(&neigh->addr, curr);
596 neigh->link_quality = (double)*curr++ / 256.0;
597 neigh->neigh_link_quality = (double)*curr++ / 256.0;
601 neigh->link_type = EXTRACT_LINK(info_head->link_code);
602 neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
604 neigh->next = lq_hello->neigh;
605 lq_hello->neigh = neigh;
611 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
612 union olsr_ip_addr *from)
614 struct lq_tc_header *head;
615 union olsr_ip_addr *addr;
616 unsigned char *curr, *limit;
617 struct lq_tc_neighbor *neigh;
624 head = (struct lq_tc_header *)
625 deserialize_common((struct olsr_common *)lq_tc, ser);
627 if (lq_tc->comm.type != LQ_TC_MESSAGE)
630 limit = ((unsigned char *)ser) + lq_tc->comm.size;
632 addr = mid_lookup_main_addr(from);
635 COPY_IP(&lq_tc->from, from);
638 COPY_IP(&lq_tc->from, addr);
640 lq_tc->ansn = ntohs(head->ansn);
642 curr = (unsigned char *)(head + 1);
646 neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
647 "LQ_TC deserialization");
649 COPY_IP(&neigh->main, curr);
652 neigh->link_quality = (double)*curr / 256.0;
655 neigh->next = lq_tc->neigh;
656 lq_tc->neigh = neigh;
661 olsr_output_lq_hello(void *para)
663 struct lq_hello_message lq_hello;
664 struct interface *outif = (struct interface *)para;
666 // create LQ_HELLO in internal format
668 create_lq_hello(&lq_hello, outif);
670 // convert internal format into transmission format, send it
672 serialize_lq_hello(&lq_hello, outif);
674 // destroy internal format
676 destroy_lq_hello(&lq_hello);
678 if(net_output_pending(outif))
683 olsr_output_lq_tc(void *para)
685 static int prev_empty = 1;
686 struct lq_tc_message lq_tc;
687 struct interface *outif = (struct interface *)para;
688 struct timeval timer;
690 // create LQ_TC in internal format
692 create_lq_tc(&lq_tc, outif);
694 // a) the message is not empty
696 if (lq_tc.neigh != NULL)
700 // convert internal format into transmission format, send it
702 serialize_lq_tc(&lq_tc, outif);
705 // b) this is the first empty message
707 else if (prev_empty == 0)
711 olsr_init_timer((olsr_u32_t)(max_tc_vtime * 3) * 1000, &timer);
712 timeradd(&now, &timer, &send_empty_tc);
716 // convert internal format into transmission format, send it
718 serialize_lq_tc(&lq_tc, outif);
721 // c) this is not the first empty message, send if timer hasn't fired
723 else if (!TIMED_OUT(&send_empty_tc))
724 serialize_lq_tc(&lq_tc, outif);
726 // destroy internal format
728 destroy_lq_tc(&lq_tc);
730 if(net_output_pending(outif) && TIMED_OUT(&fwdtimer[outif->if_nr]))
731 set_buffer_timer(outif);
735 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
736 union olsr_ip_addr *from)
738 struct hello_message hello;
739 struct lq_hello_neighbor *neigh;
740 struct hello_neighbor *new_neigh;
742 // XXX - translation is ugly; everybody should use lq_hello_message :-)
744 // move the static fields from LQ_HELLO to HELLO
746 hello.vtime = lq_hello->comm.vtime;
747 hello.htime = lq_hello->htime;
749 COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
751 hello.packet_seq_number = lq_hello->comm.seqno;
752 hello.hop_count = lq_hello->comm.hops;
753 hello.ttl = lq_hello->comm.ttl;
754 hello.willingness = lq_hello->will;
756 // move all LQ_HELLO neighbours to HELLO
758 for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
760 // allocate HELLO neighbour
762 new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
763 "LQ_HELLO translation");
767 new_neigh->status = neigh->neigh_type;
768 new_neigh->link = neigh->link_type;
769 new_neigh->link_quality = neigh->link_quality;
771 COPY_IP(&new_neigh->address, &neigh->addr);
773 // queue HELLO neighbour
775 new_neigh->next = hello.neighbors;
776 hello.neighbors = new_neigh;
779 olsr_hello_tap(&hello, inif, from);
783 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
784 union olsr_ip_addr *from, union olsr_message *ser)
786 struct tc_message tc;
787 struct lq_tc_neighbor *neigh;
788 struct tc_mpr_addr *new_neigh;
790 // XXX - translation is ugly; everybody should use lq_tc_message :-)
792 // move the static fields from LQ_TC to TC
794 tc.vtime = lq_tc->comm.vtime;
796 COPY_IP(&tc.source_addr, &lq_tc->from);
797 COPY_IP(&tc.originator, &lq_tc->comm.orig);
799 tc.packet_seq_number = lq_tc->comm.seqno;
800 tc.hop_count = lq_tc->comm.hops;
801 tc.ttl = lq_tc->comm.ttl;
802 tc.ansn = lq_tc->ansn;
804 // move all LQ_TC neighbours to TC
806 for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
808 // allocate TC neighbour
810 new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
811 "LQ_TC translation");
815 new_neigh->link_quality = neigh->link_quality;
817 COPY_IP(&new_neigh->address, &neigh->main);
819 // queue TC neighbour
821 new_neigh->next = tc.multipoint_relay_selector_address;
822 tc.multipoint_relay_selector_address = new_neigh;
825 olsr_tc_tap(&tc, inif, from, ser);
829 olsr_input_lq_hello(union olsr_message *ser,
830 struct interface *inif,
831 union olsr_ip_addr *from)
833 struct lq_hello_message lq_hello;
835 // convert received packet from transmission format into internal format
837 deserialize_lq_hello(&lq_hello, ser);
839 // process internal format
841 process_lq_hello(&lq_hello, inif, from);
843 // destroy internal format
845 destroy_lq_hello(&lq_hello);
849 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
850 union olsr_ip_addr *from)
852 struct lq_tc_message lq_tc;
854 // convert received packet from transmission format into internal format
856 deserialize_lq_tc(&lq_tc, ser, from);
858 // process internal format
860 process_lq_tc(&lq_tc, inif, from, ser);
862 // destroy internal format
864 destroy_lq_tc(&lq_tc);