2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of olsr.org, olsrd nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Visit http://www.olsr.org for more information.
35 * If you find this software useful feel free to make a donation
36 * to the project. For more information see the website or contact
37 * the copyright holders.
39 * $Id: process_package.c,v 1.37 2006/01/07 08:16:20 kattemat Exp $
44 #include "process_package.h"
45 #include "lq_packet.h"
46 #include "hysteresis.h"
47 #include "two_hop_neighbor_table.h"
49 #include "mpr_selector_set.h"
53 #include "duplicate_set.h"
54 #include "rebuild_packet.h"
55 #include "scheduler.h"
59 *Initializing the parser functions we are using
62 olsr_init_package_process()
64 if (olsr_cnf->lq_level == 0)
66 olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
67 olsr_parser_add_function(&olsr_process_received_tc, TC_MESSAGE, 1);
72 olsr_parser_add_function(&olsr_input_lq_hello, LQ_HELLO_MESSAGE, 1);
73 olsr_parser_add_function(&olsr_input_lq_tc, LQ_TC_MESSAGE, 1);
76 olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
77 olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
81 olsr_hello_tap(struct hello_message *message, struct interface *in_if,
82 union olsr_ip_addr *from_addr)
84 struct link_entry *link;
85 struct neighbor_entry *neighbor;
86 struct hello_neighbor *walker;
93 link = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
95 if (olsr_cnf->lq_level > 0)
97 // just in case our neighbor has changed its HELLO interval
99 olsr_update_packet_loss_hello_int(link, message->htime);
101 // find the input interface in the list of neighbor interfaces
103 for (walker = message->neighbors; walker != NULL; walker = walker->next)
104 if (COMP_IP(&walker->address, &in_if->ip_addr))
107 // the current reference link quality
109 saved_lq = link->saved_neigh_link_quality;
114 // memorize our neighbour's idea of the link quality, so that we
115 // know the link quality in both directions
118 link->neigh_link_quality = walker->link_quality;
121 link->neigh_link_quality = 0.0;
123 // if the link quality has changed by more than 10 percent,
124 // print the new link quality table
126 rel_lq = link->neigh_link_quality / saved_lq;
128 if (rel_lq > 1.1 || rel_lq < 0.9)
130 link->saved_neigh_link_quality = link->neigh_link_quality;
132 if (olsr_cnf->lq_dlimit > 0)
134 changes_neighborhood = OLSR_TRUE;
135 changes_topology = OLSR_TRUE;
139 OLSR_PRINTF(3, "Skipping Dijkstra (2)\n")
143 // XXX - we should check whether we actually
144 // announce this neighbour
146 signal_link_changes(OLSR_TRUE);
150 neighbor = link->neighbor;
155 if(olsr_cnf->use_hysteresis)
157 /* Update HELLO timeout */
158 //printf("MESSAGE HTIME: %f\n", message->htime);
159 olsr_update_hysteresis_hello(link, message->htime);
162 /* Check if we are chosen as MPR */
163 if(olsr_lookup_mpr_status(message, in_if))
164 /* source_addr is always the main addr of a node! */
165 olsr_update_mprs_set(&message->source_addr, (float)message->vtime);
169 /* Check willingness */
170 if(neighbor->willingness != message->willingness)
172 OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n",
173 olsr_ip_to_string(&neighbor->neighbor_main_addr),
174 neighbor->willingness,
175 message->willingness)
177 *If willingness changed - recalculate
179 neighbor->willingness = message->willingness;
180 changes_neighborhood = OLSR_TRUE;
181 changes_topology = OLSR_TRUE;
185 /* Don't register neighbors of neighbors that announces WILL_NEVER */
186 if(neighbor->willingness != WILL_NEVER)
187 olsr_process_message_neighbors(neighbor, message);
189 /* Process changes immedeatly in case of MPR updates */
190 olsr_process_changes();
192 olsr_free_hello_packet(message);
198 *Processes a received HELLO message.
200 *@param m the incoming OLSR message
205 olsr_process_received_hello(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
207 struct hello_message message;
209 hello_chgestruct(&message, m);
211 if(!olsr_validate_address(&message.source_addr))
213 olsr_free_hello_packet(&message);
217 olsr_hello_tap(&message, in_if, from_addr);
221 olsr_tc_tap(struct tc_message *message, struct interface *in_if,
222 union olsr_ip_addr *from_addr, union olsr_message *m)
224 struct tc_mpr_addr *mpr;
225 struct tc_entry *tc_last;
227 if(!olsr_check_dup_table_proc(&message->originator,
228 message->packet_seq_number))
233 OLSR_PRINTF(3, "Processing TC from %s\n",
234 olsr_ip_to_string(&message->originator))
237 * If the sender interface (NB: not originator) of this message
238 * is not in the symmetric 1-hop neighborhood of this node, the
239 * message MUST be discarded.
242 if(check_neighbor_link(from_addr) != SYM_LINK)
244 OLSR_PRINTF(2, "Received TC from NON SYM neighbor %s\n",
245 olsr_ip_to_string(from_addr))
246 olsr_free_tc_packet(message);
250 if(olsr_cnf->debug_level > 2)
252 mpr = message->multipoint_relay_selector_address;
253 OLSR_PRINTF(3, "mpr_selector_list:[")
257 OLSR_PRINTF(3, "%s:", olsr_ip_to_string(&mpr->address))
261 OLSR_PRINTF(3, "]\n")
264 tc_last = olsr_lookup_tc_entry(&message->originator);
270 /* Delete destinations with lower ANSN */
271 if(olsr_tc_delete_mprs(tc_last, message))
272 changes_topology = OLSR_TRUE;
274 /* Update destinations */
275 if(olsr_tc_update_mprs(tc_last, message))
276 changes_topology = OLSR_TRUE;
278 /* Delete possible empty TC entry */
280 olsr_tc_delete_entry_if_empty(tc_last);
285 /*if message is empty then skip it */
286 if(message->multipoint_relay_selector_address != NULL)
289 tc_last = olsr_add_tc_entry(&message->originator);
291 /* Update destinations */
292 olsr_tc_update_mprs(tc_last, message);
294 changes_topology = OLSR_TRUE;
298 OLSR_PRINTF(3, "Dropping empty TC from %s\n",
299 olsr_ip_to_string(&message->originator))
303 /* Process changes */
304 //olsr_process_changes();
308 olsr_forward_message(m,
309 &message->originator,
310 message->packet_seq_number,
314 olsr_free_tc_packet(message);
320 *Process a received TopologyControl message
323 *@param m the incoming OLSR message
324 *@return 0 on success
327 olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
329 struct tc_message message;
331 tc_chgestruct(&message, m, from_addr);
333 if(!olsr_validate_address(&message.source_addr))
335 olsr_free_tc_packet(&message);
339 olsr_tc_tap(&message, in_if, from_addr, m);
348 *Process a received(and parsed) MID message
349 *For every address check if there is a topology node
350 *registered with it and update its addresses.
352 *@param m the OLSR message received.
353 *@return 1 on success
357 olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
359 struct mid_alias *tmp_adr;
360 struct mid_message message;
362 mid_chgestruct(&message, m);
364 if(!olsr_validate_address(&message.mid_origaddr))
366 olsr_free_mid_packet(&message);
370 if(!olsr_check_dup_table_proc(&message.mid_origaddr,
377 OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr))
379 tmp_adr = message.mid_addr;
382 * If the sender interface (NB: not originator) of this message
383 * is not in the symmetric 1-hop neighborhood of this node, the
384 * message MUST be discarded.
387 if(check_neighbor_link(from_addr) != SYM_LINK)
389 OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr))
390 olsr_free_mid_packet(&message);
394 /* Update the timeout of the MID */
395 olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
399 if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
401 OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr))
402 OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr))
403 insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
407 tmp_adr = tmp_adr->next;
411 olsr_forward_message(m,
412 &message.mid_origaddr,
416 olsr_free_mid_packet(&message);
426 *Process incoming HNA message.
427 *Forwards the message if that is to be done.
429 *@param m the incoming OLSR message
431 *@return 1 on success
435 olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
437 struct hna_net_addr *hna_tmp;
438 struct hna_message message;
441 OLSR_PRINTF(5, "Processing HNA\n")
444 hna_chgestruct(&message, m);
446 if(!olsr_validate_address(&message.originator))
448 olsr_free_hna_packet(&message);
452 if(!olsr_check_dup_table_proc(&message.originator,
453 message.packet_seq_number))
458 hna_tmp = message.hna_net;
461 * If the sender interface (NB: not originator) of this message
462 * is not in the symmetric 1-hop neighborhood of this node, the
463 * message MUST be discarded.
465 if(check_neighbor_link(from_addr) != SYM_LINK)
467 OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr))
468 olsr_free_hna_packet(&message);
474 olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime);
476 hna_tmp = hna_tmp->next;
480 olsr_forward_message(m,
482 message.packet_seq_number,
485 olsr_free_hna_packet(&message);
497 *Processes an list of neighbors from an incoming HELLO message.
498 *@param neighbor the neighbor who sendt the message.
499 *@param message the HELLO message
503 olsr_process_message_neighbors(struct neighbor_entry *neighbor,
504 struct hello_message *message)
506 struct hello_neighbor *message_neighbors;
508 for(message_neighbors = message->neighbors;
509 message_neighbors != NULL;
510 message_neighbors = message_neighbors->next)
512 union olsr_ip_addr *neigh_addr;
513 struct neighbor_2_entry *two_hop_neighbor;
516 *check all interfaces
517 *so that we don't add ourselves to the
521 if(if_ifwithaddr(&message_neighbors->address) != NULL)
524 /* Get the main address */
525 neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
527 if (neigh_addr != NULL)
528 COPY_IP(&message_neighbors->address, neigh_addr);
530 if(((message_neighbors->status == SYM_NEIGH) ||
531 (message_neighbors->status == MPR_NEIGH)))
533 struct neighbor_2_list_entry *two_hop_neighbor_yet =
534 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
536 OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address))
538 if (two_hop_neighbor_yet != NULL)
540 /* Updating the holding time for this neighbor */
541 two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
542 two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
547 olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
548 if (two_hop_neighbor == NULL)
552 "Adding 2 hop neighbor %s\n\n",
553 olsr_ip_to_string(&message_neighbors->address))
555 changes_neighborhood = OLSR_TRUE;
556 changes_topology = OLSR_TRUE;
559 olsr_malloc(sizeof(struct neighbor_2_entry),
562 two_hop_neighbor->neighbor_2_nblist.next =
563 &two_hop_neighbor->neighbor_2_nblist;
565 two_hop_neighbor->neighbor_2_nblist.prev =
566 &two_hop_neighbor->neighbor_2_nblist;
568 two_hop_neighbor->neighbor_2_pointer = 0;
570 COPY_IP(&two_hop_neighbor->neighbor_2_addr,
571 &message_neighbors->address);
573 olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
575 olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
576 (float)message->vtime);
581 linking to this two_hop_neighbor entry
583 changes_neighborhood = OLSR_TRUE;
584 changes_topology = OLSR_TRUE;
586 olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
587 (float)message->vtime);
591 if (olsr_cnf->lq_level > 0)
593 struct neighbor_list_entry *walker;
594 struct link_entry *link;
596 link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
601 // loop through the one-hop neighbors that see this
604 for (walker = two_hop_neighbor->neighbor_2_nblist.next;
605 walker != &two_hop_neighbor->neighbor_2_nblist;
606 walker = walker->next)
608 // have we found the one-hop neighbor that sent the
609 // HELLO message that we're current processing?
611 if (walker->neighbor == neighbor)
613 double saved_lq, rel_lq;
615 // saved previous total link quality
617 saved_lq = walker->saved_path_link_quality;
622 // path link quality = link quality between us
623 // and our one-hop neighbor x link quality between
624 // our one-hop neighbor and the two-hop neighbor
626 // let's compare this to ETX:
628 // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
629 // LQ1 * LQ2 > LQ3 * LQ4
631 // so comparing path link quality values with ">" is
632 // equivalent to comparing ETX values with "<"
634 // the link quality between the 1-hop neighbour and the
637 walker->second_hop_link_quality =
638 message_neighbors->link_quality *
639 message_neighbors->neigh_link_quality;
641 // the total quality for the route
642 // "us --- 1-hop --- 2-hop"
644 walker->path_link_quality =
645 walker->second_hop_link_quality *
646 link->loss_link_quality * link->neigh_link_quality;
648 // if the link quality has changed by more than 10
651 rel_lq = walker->path_link_quality / saved_lq;
653 if (rel_lq > 1.1 || rel_lq < 0.9)
655 walker->saved_path_link_quality =
656 walker->path_link_quality;
658 if (olsr_cnf->lq_dlimit > 0)
660 changes_neighborhood = OLSR_TRUE;
661 changes_topology = OLSR_TRUE;
665 OLSR_PRINTF(3, "Skipping Dijkstra (3)\n")
682 *Links a one-hop neighbor with a 2-hop neighbor.
684 *@param neighbor the 1-hop neighbor
685 *@param two_hop_neighbor the 2-hop neighbor
689 olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
691 struct neighbor_list_entry *list_of_1_neighbors;
692 struct neighbor_2_list_entry *list_of_2_neighbors;
694 list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
696 list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
698 list_of_1_neighbors->neighbor = neighbor;
700 list_of_1_neighbors->path_link_quality = 0.0;
701 list_of_1_neighbors->saved_path_link_quality = 0.0;
702 list_of_1_neighbors->second_hop_link_quality = 0.0;
705 two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
706 list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
707 two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
708 list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
711 list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
713 list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
716 neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
717 list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
718 neighbor->neighbor_2_list.next = list_of_2_neighbors;
719 list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
721 /*increment the pointer counter*/
722 two_hop_neighbor->neighbor_2_pointer++;
731 *Check if a hello message states this node as a MPR.
733 *@param message the message to check
734 *@param n_link the buffer to put the link status in
735 *@param n_status the buffer to put the status in
737 *@return 1 if we are selected as MPR 0 if not
740 olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
743 struct hello_neighbor *neighbors;
745 neighbors=message->neighbors;
747 while(neighbors!=NULL)
749 //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
750 //printf("against %s\n",olsr_ip_to_string(&main_addr));
753 if(olsr_cnf->ip_version == AF_INET)
756 if(COMP_IP(&neighbors->address, &in_if->ip_addr))
759 if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
768 if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
771 if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
778 neighbors = neighbors->next;