/*
* The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* to the project. For more information see the website or contact
* the copyright holders.
*
- * $Id: process_package.c,v 1.30 2005/02/14 15:54:30 tlopatic Exp $
*/
-
-#include "defs.h"
#include "process_package.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "lq_packet.h"
#include "hysteresis.h"
#include "two_hop_neighbor_table.h"
#include "tc_set.h"
#include "parser.h"
#include "duplicate_set.h"
#include "rebuild_packet.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+#include <stddef.h>
-/**
- *Initializing the parser functions we are using
- */
-void
-olsr_init_package_process()
-{
- if (olsr_cnf->lq_level == 0)
- {
- olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
- olsr_parser_add_function(&olsr_process_received_tc, TC_MESSAGE, 1);
- }
-
- else
- {
- olsr_parser_add_function(&olsr_input_lq_hello, LQ_HELLO_MESSAGE, 1);
- olsr_parser_add_function(&olsr_input_lq_tc, LQ_TC_MESSAGE, 1);
- }
-
- olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
- olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
-}
-
-void
-olsr_hello_tap(struct hello_message *message, struct interface *in_if,
- union olsr_ip_addr *from_addr)
-{
- struct link_entry *link;
- struct neighbor_entry *neighbor;
- struct hello_neighbor *walker;
- double saved_lq;
- double rel_lq;
-
- /*
- * Update link status
- */
- link = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
-
- if (olsr_cnf->lq_level > 0)
- {
- // just in case our neighbor has changed its HELLO interval
-
- olsr_update_packet_loss_hello_int(link, message->htime);
-
- // find the input interface in the list of neighbor interfaces
-
- for (walker = message->neighbors; walker != NULL; walker = walker->next)
- if (COMP_IP(&walker->address, &in_if->ip_addr))
- break;
-
- // the current reference link quality
-
- saved_lq = link->saved_neigh_link_quality;
-
- if (saved_lq == 0.0)
- saved_lq = -1.0;
-
- // memorize our neighbour's idea of the link quality, so that we
- // know the link quality in both directions
-
- if (walker != NULL)
- link->neigh_link_quality = walker->link_quality;
-
- else
- link->neigh_link_quality = 0.0;
-
- // if the link quality has changed by more than 10 percent,
- // print the new link quality table
-
- rel_lq = link->neigh_link_quality / saved_lq;
-
- if (rel_lq > 1.1 || rel_lq < 0.9)
- {
- link->saved_neigh_link_quality = link->neigh_link_quality;
-
- changes_neighborhood = OLSR_TRUE;
- changes_topology = OLSR_TRUE;
-
- // create a new ANSN
-
- // XXX - we should check whether we actually
- // announce this neighbour
-
- changes = OLSR_TRUE;
- }
- }
-
- neighbor = link->neighbor;
-
- /*
- * Hysteresis
- */
- if(olsr_cnf->use_hysteresis)
- {
- /* Update HELLO timeout */
- //printf("MESSAGE HTIME: %f\n", message->htime);
- olsr_update_hysteresis_hello(link, message->htime);
- }
-
- /* Check if we are chosen as MPR */
- if(olsr_lookup_mpr_status(message, in_if))
- /* source_addr is always the main addr of a node! */
- olsr_update_mprs_set(&message->source_addr, (float)message->vtime);
-
-
-
- /* Check willingness */
- if(neighbor->willingness != message->willingness)
- {
- olsr_printf(1, "Willingness for %s changed from %d to %d - UPDATING\n",
- olsr_ip_to_string(&neighbor->neighbor_main_addr),
- neighbor->willingness,
- message->willingness);
- /*
- *If willingness changed - recalculate
- */
- neighbor->willingness = message->willingness;
- changes_neighborhood = OLSR_TRUE;
- changes_topology = OLSR_TRUE;
- }
-
-
- /* Don't register neighbors of neighbors that announces WILL_NEVER */
- if(neighbor->willingness != WILL_NEVER)
- olsr_process_message_neighbors(neighbor, message);
-
- /* Process changes immedeatly in case of MPR updates */
- olsr_process_changes();
-
- olsr_free_hello_packet(message);
-
- return;
-}
-
-/**
- *Processes a received HELLO message.
- *
- *@param m the incoming OLSR message
- *@return 0 on sucess
- */
-
-void
-olsr_process_received_hello(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{
- struct hello_message message;
-
- hello_chgestruct(&message, m);
-
- olsr_hello_tap(&message, in_if, from_addr);
-}
-
-void
-olsr_tc_tap(struct tc_message *message, struct interface *in_if,
- union olsr_ip_addr *from_addr, union olsr_message *m)
-{
- struct tc_mpr_addr *mpr;
- struct tc_entry *tc_last;
-
- if(!olsr_check_dup_table_proc(&message->originator,
- message->packet_seq_number))
- {
- goto forward;
- }
-
- olsr_printf(3, "Processing TC from %s\n",
- olsr_ip_to_string(&message->originator));
-
- /*
- * If the sender interface (NB: not originator) of this message
- * is not in the symmetric 1-hop neighborhood of this node, the
- * message MUST be discarded.
- */
-
- if(check_neighbor_link(from_addr) != SYM_LINK)
- {
- olsr_printf(2, "Received TC from NON SYM neighbor %s\n",
- olsr_ip_to_string(from_addr));
- olsr_free_tc_packet(message);
- return;
- }
-
- if(olsr_cnf->debug_level > 2)
- {
- mpr = message->multipoint_relay_selector_address;
- olsr_printf(3, "mpr_selector_list:[");
-
- while(mpr!=NULL)
- {
- olsr_printf(3, "%s:", olsr_ip_to_string(&mpr->address));
- mpr=mpr->next;
- }
-
- olsr_printf(3, "]\n");
- }
-
- tc_last = olsr_lookup_tc_entry(&message->originator);
-
- if(tc_last != NULL)
- {
- /* Update entry */
-
- /* Delete destinations with lower ANSN */
- if(olsr_tc_delete_mprs(tc_last, message))
- changes_topology = OLSR_TRUE;
-
- /* Update destinations */
- if(olsr_tc_update_mprs(tc_last, message))
- changes_topology = OLSR_TRUE;
-
- /* Delete possible empty TC entry */
- if(changes_topology)
- olsr_tc_delete_entry_if_empty(tc_last);
- }
-
- else
- {
- /*if message is empty then skip it */
- if(message->multipoint_relay_selector_address != NULL)
- {
- /* New entry */
- tc_last = olsr_add_tc_entry(&message->originator);
-
- /* Update destinations */
- olsr_tc_update_mprs(tc_last, message);
-
- changes_topology = OLSR_TRUE;
- }
- else
- {
- olsr_printf(3, "Dropping empty TC from %s\n",
- olsr_ip_to_string(&message->originator));
- }
- }
-
- /* Process changes */
- //olsr_process_changes();
-
- forward:
-
- olsr_forward_message(m,
- &message->originator,
- message->packet_seq_number,
- in_if,
- from_addr);
-
- olsr_free_tc_packet(message);
-
- return;
-}
-
-/**
- *Process a received TopologyControl message
- *
- *
- *@param m the incoming OLSR message
- *@return 0 on success
- */
-void
-olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{
- struct tc_message message;
-
- tc_chgestruct(&message, m, from_addr);
-
- olsr_tc_tap(&message, in_if, from_addr, m);
-}
-
-
-
-
-
-
-/**
- *Process a received(and parsed) MID message
- *For every address check if there is a topology node
- *registered with it and update its addresses.
- *
- *@param m the OLSR message received.
- *@return 1 on success
- */
-
-void
-olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{
- struct mid_alias *tmp_adr;
- struct mid_message message;
-
- mid_chgestruct(&message, m);
-
- if(!olsr_check_dup_table_proc(&message.mid_origaddr,
- message.mid_seqno))
- {
- goto forward;
- }
-
-#ifdef DEBUG
- olsr_printf(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr));
-#endif
- tmp_adr = message.mid_addr;
-
- /*
- * If the sender interface (NB: not originator) of this message
- * is not in the symmetric 1-hop neighborhood of this node, the
- * message MUST be discarded.
- */
-
- if(check_neighbor_link(from_addr) != SYM_LINK)
- {
- olsr_printf(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
- olsr_free_mid_packet(&message);
- return;
- }
-
- /* Update the timeout of the MID */
- olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
-
- while(tmp_adr)
- {
- if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
- {
- olsr_printf(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr));
- olsr_printf(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr));
- insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
- }
-
-
- tmp_adr = tmp_adr->next;
- }
-
- forward:
- olsr_forward_message(m,
- &message.mid_origaddr,
- message.mid_seqno,
- in_if,
- from_addr);
- olsr_free_mid_packet(&message);
-
- return;
-}
-
-
-
-
-
-/**
- *Process incoming HNA message.
- *Forwards the message if that is to be done.
- *
- *@param m the incoming OLSR message
- *the OLSR message.
- *@return 1 on success
- */
-
-void
-olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{
- struct hna_net_addr *hna_tmp;
- struct hna_message message;
-
-#ifdef DEBUG
- olsr_printf(5, "Processing HNA\n");
-#endif
-
- hna_chgestruct(&message, m);
-
- if(!olsr_check_dup_table_proc(&message.originator,
- message.packet_seq_number))
- {
- goto forward;
- }
-
- hna_tmp = message.hna_net;
-
- /*
- * If the sender interface (NB: not originator) of this message
- * is not in the symmetric 1-hop neighborhood of this node, the
- * message MUST be discarded.
- */
- if(check_neighbor_link(from_addr) != SYM_LINK)
- {
- olsr_printf(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
- olsr_free_hna_packet(&message);
- return;
- }
-
- while(hna_tmp)
- {
- olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime);
-
- hna_tmp = hna_tmp->next;
- }
-
- forward:
- olsr_forward_message(m,
- &message.originator,
- message.packet_seq_number,
- in_if,
- from_addr);
- olsr_free_hna_packet(&message);
-
- return;
-}
-
-
-
+static void process_message_neighbors(struct neighbor_entry *,
+ const struct hello_message *);
+static void linking_this_2_entries(struct neighbor_entry *,
+ struct neighbor_2_entry *, olsr_reltime);
+static olsr_bool lookup_mpr_status(const struct hello_message *,
+ const struct interface *);
/**
*Processes an list of neighbors from an incoming HELLO message.
- *@param neighbor the neighbor who sendt the message.
+ *@param neighbor the neighbor who sent the message.
*@param message the HELLO message
*@return nada
*/
-void
-olsr_process_message_neighbors(struct neighbor_entry *neighbor,
- struct hello_message *message)
+static void
+process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
{
struct hello_neighbor *message_neighbors;
message_neighbors != NULL;
message_neighbors = message_neighbors->next)
{
+#ifdef DEBUG
+ struct ipaddr_str buf;
+#endif
union olsr_ip_addr *neigh_addr;
struct neighbor_2_entry *two_hop_neighbor;
/* Get the main address */
neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
- if (neigh_addr != NULL)
- COPY_IP(&message_neighbors->address, neigh_addr);
-
+ if (neigh_addr != NULL) {
+ message_neighbors->address = *neigh_addr;
+ }
+
if(((message_neighbors->status == SYM_NEIGH) ||
(message_neighbors->status == MPR_NEIGH)))
{
struct neighbor_2_list_entry *two_hop_neighbor_yet =
olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
#ifdef DEBUG
- olsr_printf(7, "\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address));
+ OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&buf, &message_neighbors->address));
#endif
if (two_hop_neighbor_yet != NULL)
{
/* Updating the holding time for this neighbor */
- two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
+ olsr_set_timer(&two_hop_neighbor_yet->nbr2_list_timer,
+ message->vtime, OLSR_NBR2_LIST_JITTER,
+ OLSR_TIMER_ONESHOT, &olsr_expire_nbr2_list,
+ two_hop_neighbor_yet, 0);
two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
+
+ /*
+ * For link quality OLSR, reset the path link quality here.
+ * The path link quality will be calculated in the second pass, below.
+ * Keep the saved_path_link_quality for reference.
+ */
+
+ if (olsr_cnf->lq_level > 0)
+ {
+ /*
+ * loop through the one-hop neighbors that see this
+ * 'two_hop_neighbor'
+ */
+
+ struct neighbor_list_entry *walker;
+
+ for (walker = two_hop_neighbor->neighbor_2_nblist.next;
+ walker != &two_hop_neighbor->neighbor_2_nblist;
+ walker = walker->next)
+ {
+ /*
+ * have we found the one-hop neighbor that sent the
+ * HELLO message that we're current processing?
+ */
+
+ if (walker->neighbor == neighbor)
+ {
+ walker->path_linkcost = LINK_COST_BROKEN;
+ }
+ }
+ }
}
else
{
if (two_hop_neighbor == NULL)
{
#ifdef DEBUG
- olsr_printf(5,
+ OLSR_PRINTF(5,
"Adding 2 hop neighbor %s\n\n",
- olsr_ip_to_string(&message_neighbors->address));
+ olsr_ip_to_string(&buf, &message_neighbors->address));
#endif
changes_neighborhood = OLSR_TRUE;
changes_topology = OLSR_TRUE;
two_hop_neighbor =
- olsr_malloc(sizeof(struct neighbor_2_entry),
- "Process HELLO");
+ olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");
two_hop_neighbor->neighbor_2_nblist.next =
&two_hop_neighbor->neighbor_2_nblist;
two_hop_neighbor->neighbor_2_pointer = 0;
- COPY_IP(&two_hop_neighbor->neighbor_2_addr,
- &message_neighbors->address);
+ two_hop_neighbor->neighbor_2_addr = message_neighbors->address;
olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
- olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
- (float)message->vtime);
+ linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
}
else
{
changes_neighborhood = OLSR_TRUE;
changes_topology = OLSR_TRUE;
- olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
- (float)message->vtime);
+ linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
}
}
+ }
+ }
+
+ /* Separate, second pass for link quality OLSR */
+ /* Separate, second and third pass for link quality OLSR */
- if (olsr_cnf->lq_level > 0)
+ if (olsr_cnf->lq_level > 0)
+ {
+ olsr_linkcost first_hop_pathcost;
+ struct link_entry *lnk =
+ get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
+
+ if(!lnk)
+ return;
+
+ /* calculate first hop path quality */
+ first_hop_pathcost = lnk->linkcost;
+ /*
+ * Second pass for link quality OLSR: calculate the best 2-hop
+ * path costs to all the 2-hop neighbors indicated in the
+ * HELLO message. Since the same 2-hop neighbor may be listed
+ * more than once in the same HELLO message (each at a possibly
+ * different quality) we want to select only the best one, not just
+ * the last one listed in the HELLO message.
+ */
+
+ for(message_neighbors = message->neighbors;
+ message_neighbors != NULL;
+ message_neighbors = message_neighbors->next)
+ {
+ if(if_ifwithaddr(&message_neighbors->address) != NULL)
+ continue;
+
+ if(((message_neighbors->status == SYM_NEIGH) ||
+ (message_neighbors->status == MPR_NEIGH)))
{
- struct neighbor_list_entry *walker;
- struct link_entry *link;
+ struct neighbor_list_entry *walker;
+ struct neighbor_2_entry *two_hop_neighbor;
+ struct neighbor_2_list_entry *two_hop_neighbor_yet =
+ olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
- link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
+ if(!two_hop_neighbor_yet)
+ continue;
+
+ two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
- // loop through the one-hop neighbors that see this
- // two hop neighbour
+ /*
+ * loop through the one-hop neighbors that see this
+ * 'two_hop_neighbor'
+ */
for (walker = two_hop_neighbor->neighbor_2_nblist.next;
walker != &two_hop_neighbor->neighbor_2_nblist;
walker = walker->next)
{
- // have we found the one-hop neighbor that sent the
- // HELLO message that we're current processing?
+ /*
+ * have we found the one-hop neighbor that sent the
+ * HELLO message that we're current processing?
+ */
if (walker->neighbor == neighbor)
{
- double saved_lq, rel_lq;
-
- // saved previous total link quality
-
- saved_lq = walker->saved_path_link_quality;
+ olsr_linkcost new_second_hop_linkcost, new_path_linkcost;
- if (saved_lq == 0.0)
- saved_lq = -1.0;
+ // the link cost between the 1-hop neighbour and the
+ // 2-hop neighbour
- // path link quality = link quality between us
- // and our one-hop neighbor x link quality between
- // our one-hop neighbor and the two-hop neighbor
+ new_second_hop_linkcost = message_neighbors->cost;
- // let's compare this to ETX:
+ // the total cost for the route
+ // "us --- 1-hop --- 2-hop"
- // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
- // LQ1 * LQ2 > LQ3 * LQ4
+ new_path_linkcost =
+ first_hop_pathcost + new_second_hop_linkcost;
- // so comparing path link quality values with ">" is
- // equivalent to comparing ETX values with "<"
-
- walker->path_link_quality =
- link->loss_link_quality * link->neigh_link_quality *
- message_neighbors->link_quality *
- message_neighbors->neigh_link_quality;
-
- // if the link quality has changed by more than 10
- // percent, signal
-
- rel_lq = walker->path_link_quality / saved_lq;
-
- if (rel_lq > 1.1 || rel_lq < 0.9)
+ // Only copy the link quality if it is better than what we have
+ // for this 2-hop neighbor
+ if (new_path_linkcost < walker->path_linkcost)
{
- walker->saved_path_link_quality =
- walker->path_link_quality;
-
- changes_neighborhood = OLSR_TRUE;
- changes_topology = OLSR_TRUE;
+ walker->second_hop_linkcost = new_second_hop_linkcost;
+ walker->path_linkcost = new_path_linkcost;
+
+ if (olsr_is_relevant_costchange(new_path_linkcost, walker->saved_path_linkcost))
+ {
+ walker->saved_path_linkcost = new_path_linkcost;
+
+ if (olsr_cnf->lq_dlimit > 0)
+ {
+ changes_neighborhood = OLSR_TRUE;
+ changes_topology = OLSR_TRUE;
+ }
+
+ else
+ OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
+ }
}
}
}
}
}
-
-
-
-
-
-
-
/**
*Links a one-hop neighbor with a 2-hop neighbor.
*
*@param two_hop_neighbor the 2-hop neighbor
*@return nada
*/
-void
-olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
+static void
+linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry *two_hop_neighbor, olsr_reltime vtime)
{
- struct neighbor_list_entry *list_of_1_neighbors;
- struct neighbor_2_list_entry *list_of_2_neighbors;
-
- list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
-
- list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
+ struct neighbor_list_entry *list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
+ struct neighbor_2_list_entry *list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
list_of_1_neighbors->neighbor = neighbor;
- list_of_1_neighbors->path_link_quality = 0.0;
- list_of_1_neighbors->saved_path_link_quality = 0.0;
+ list_of_1_neighbors->path_linkcost = LINK_COST_BROKEN;
+ list_of_1_neighbors->saved_path_linkcost = LINK_COST_BROKEN;
+ list_of_1_neighbors->second_hop_linkcost = LINK_COST_BROKEN;
/* Queue */
two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
+
two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
-
-
list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
+ list_of_2_neighbors->nbr2_nbr = neighbor; /* XXX refcount */
- list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
+ olsr_change_timer(list_of_2_neighbors->nbr2_list_timer, vtime,
+ OLSR_NBR2_LIST_JITTER, OLSR_TIMER_ONESHOT);
/* Queue */
neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
two_hop_neighbor->neighbor_2_pointer++;
}
+/**
+ * Check if a hello message states this node as a MPR.
+ *
+ * @param message the message to check
+ * @param n_link the buffer to put the link status in
+ *
+ *@return 1 if we are selected as MPR 0 if not
+ */
+static olsr_bool
+lookup_mpr_status(const struct hello_message *message,
+ const struct interface *in_if)
+{
+ struct hello_neighbor *neighbors;
+
+ for (neighbors = message->neighbors; neighbors; neighbors = neighbors->next) {
+ if (olsr_cnf->ip_version == AF_INET
+ ? ip4equal(&neighbors->address.v4, &in_if->ip_addr.v4)
+ : ip6equal(&neighbors->address.v6, &in_if->int6_addr.sin6_addr)) {
+
+ if (neighbors->link == SYM_LINK && neighbors->status == MPR_NEIGH) {
+ return OLSR_TRUE;
+ }
+ break;
+ }
+ }
+ /* Not found */
+ return OLSR_FALSE;
+}
+static int deserialize_hello(struct hello_message *hello, const void *ser) {
+ const unsigned char *limit;
+ olsr_u8_t type;
+ olsr_u16_t size;
+
+ const unsigned char *curr = ser;
+ pkt_get_u8(&curr, &type);
+ if (type != HELLO_MESSAGE && type != LQ_HELLO_MESSAGE) {
+ /* No need to do anything more */
+ return 1;
+ }
+ pkt_get_reltime(&curr, &hello->vtime);
+ pkt_get_u16(&curr, &size);
+ pkt_get_ipaddress(&curr, &hello->source_addr);
+
+ pkt_get_u8(&curr, &hello->ttl);
+ pkt_get_u8(&curr, &hello->hop_count);
+ pkt_get_u16(&curr, &hello->packet_seq_number);
+ pkt_ignore_u16(&curr);
+
+ pkt_get_reltime(&curr, &hello->htime);
+ pkt_get_u8(&curr, &hello->willingness);
+
+ hello->neighbors = NULL;
+ limit = ((const unsigned char *)ser) + size;
+ while (curr < limit) {
+ const struct lq_hello_info_header *info_head = (const struct lq_hello_info_header *)curr;
+ const unsigned char *limit2 = curr + ntohs(info_head->size);
+
+ curr = (const unsigned char *)(info_head + 1);
+ while (curr < limit2) {
+ struct hello_neighbor *neigh = olsr_malloc_hello_neighbor("HELLO deserialization");
+ pkt_get_ipaddress(&curr, &neigh->address);
+
+ if (type == LQ_HELLO_MESSAGE) {
+ olsr_deserialize_hello_lq_pair(&curr, neigh);
+ }
+ neigh->link = EXTRACT_LINK(info_head->link_code);
+ neigh->status = EXTRACT_STATUS(info_head->link_code);
+
+ neigh->next = hello->neighbors;
+ hello->neighbors = neigh;
+ }
+ }
+ return 0;
+}
+void olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from) {
+ struct hello_message hello;
+
+ if (ser == NULL) {
+ return;
+ }
+ if (deserialize_hello(&hello, ser) != 0) {
+ return;
+ }
+ olsr_hello_tap(&hello, inif, from);
+}
+/**
+ *Initializing the parser functions we are using
+ */
+void
+olsr_init_package_process(void)
+{
+ if (olsr_cnf->lq_level == 0)
+ {
+ olsr_parser_add_function(&olsr_input_hello, HELLO_MESSAGE, 1);
+ olsr_parser_add_function(&olsr_input_tc, TC_MESSAGE, 1);
+ }
+ else
+ {
+ olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
+ olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
+ }
+ olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
+ olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
+}
+
+void
+olsr_hello_tap(struct hello_message *message,
+ struct interface *in_if,
+ const union olsr_ip_addr *from_addr)
+{
+ struct neighbor_entry *neighbor;
+
+ /*
+ * Update link status
+ */
+ struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
+
+ if (olsr_cnf->lq_level > 0)
+ {
+ struct hello_neighbor *walker;
+ /* just in case our neighbor has changed its HELLO interval */
+ olsr_update_packet_loss_hello_int(lnk, message->htime);
+
+ /* find the input interface in the list of neighbor interfaces */
+ for (walker = message->neighbors; walker != NULL; walker = walker->next)
+ if (ipequal(&walker->address, &in_if->ip_addr))
+ break;
+
+ // memorize our neighbour's idea of the link quality, so that we
+ // know the link quality in both directions
+ olsr_memorize_foreign_hello_lq(lnk, walker);
+
+ /* update packet loss for link quality calculation */
+ olsr_update_packet_loss(lnk);
+ }
+
+ neighbor = lnk->neighbor;
+
+ /*
+ * Hysteresis
+ */
+ if(olsr_cnf->use_hysteresis)
+ {
+ /* Update HELLO timeout */
+ /* printf("MESSAGE HTIME: %f\n", message->htime);*/
+ olsr_update_hysteresis_hello(lnk, message->htime);
+ }
+
+ /* Check if we are chosen as MPR */
+ if(lookup_mpr_status(message, in_if))
+ /* source_addr is always the main addr of a node! */
+ olsr_update_mprs_set(&message->source_addr, message->vtime);
+
+
+
+ /* Check willingness */
+ if(neighbor->willingness != message->willingness)
+ {
+ struct ipaddr_str buf;
+ OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n",
+ olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
+ neighbor->willingness,
+ message->willingness);
+ /*
+ *If willingness changed - recalculate
+ */
+ neighbor->willingness = message->willingness;
+ changes_neighborhood = OLSR_TRUE;
+ changes_topology = OLSR_TRUE;
+ }
+
+
+ /* Don't register neighbors of neighbors that announces WILL_NEVER */
+ if(neighbor->willingness != WILL_NEVER)
+ process_message_neighbors(neighbor, message);
+
+ /* Process changes immedeatly in case of MPR updates */
+ olsr_process_changes();
+
+ olsr_free_hello_packet(message);
+
+ return;
+}
/**
- *Check if a hello message states this node as a MPR.
- *
- *@param message the message to check
- *@param n_link the buffer to put the link status in
- *@param n_status the buffer to put the status in
+ *Process a received(and parsed) MID message
+ *For every address check if there is a topology node
+ *registered with it and update its addresses.
*
- *@return 1 if we are selected as MPR 0 if not
+ *@param m the OLSR message received.
+ *@return 1 on success
*/
-int
-olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
+
+void
+olsr_process_received_mid(union olsr_message *m,
+ struct interface *in_if __attribute__((unused)),
+ union olsr_ip_addr *from_addr)
{
-
- struct hello_neighbor *neighbors;
+#ifdef DEBUG
+ struct ipaddr_str buf;
+#endif
+ struct mid_alias *tmp_adr;
+ struct mid_message message;
+
+ mid_chgestruct(&message, m);
+
+ if (!olsr_validate_address(&message.mid_origaddr)) {
+ olsr_free_mid_packet(&message);
+ return;
+ }
+
+#ifdef DEBUG
+ OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
+#endif
+ tmp_adr = message.mid_addr;
+
+ /*
+ * If the sender interface (NB: not originator) of this message
+ * is not in the symmetric 1-hop neighborhood of this node, the
+ * message MUST be discarded.
+ */
+
+ if(check_neighbor_link(from_addr) != SYM_LINK) {
+ struct ipaddr_str buf;
+ OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
+ olsr_free_mid_packet(&message);
+ return;
+ }
+
+ /* Update the timeout of the MID */
+ olsr_update_mid_table(&message.mid_origaddr, message.vtime);
- neighbors=message->neighbors;
+ while (tmp_adr) {
+ if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
+ struct ipaddr_str buf;
+ OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&buf, &message.mid_origaddr));
+ OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &tmp_adr->alias_addr));
+ insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, message.vtime);
+ }
+ tmp_adr = tmp_adr->next;
+ }
- while(neighbors!=NULL)
- {
- //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
- //printf("against %s\n",olsr_ip_to_string(&main_addr));
-
-
- if(olsr_cnf->ip_version == AF_INET)
- {
- /* IPv4 */
- if(COMP_IP(&neighbors->address, &in_if->ip_addr))
- {
- //printf("ok");
- if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
- return 1;
-
- return 0;
- }
+ olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
+
+ olsr_forward_message(m, from_addr);
+ olsr_free_mid_packet(&message);
+}
+
+
+/**
+ *Process incoming HNA message.
+ *Forwards the message if that is to be done.
+ *
+ *@param m the incoming OLSR message
+ *the OLSR message.
+ *@return 1 on success
+ */
+
+void
+olsr_process_received_hna(union olsr_message *m,
+ struct interface *in_if __attribute__((unused)),
+ union olsr_ip_addr *from_addr)
+{
+
+ olsr_u8_t olsr_msgtype;
+ olsr_reltime vtime;
+ olsr_u16_t olsr_msgsize;
+ union olsr_ip_addr originator;
+ olsr_u8_t hop_count;
+ olsr_u16_t packet_seq_number;
+
+ int hnasize;
+ const olsr_u8_t *curr, *curr_end;
+
+#ifdef DEBUG
+ OLSR_PRINTF(5, "Processing HNA\n");
+#endif
+
+ /* Check if everyting is ok */
+ if (!m) {
+ return;
+ }
+ curr = (const olsr_u8_t *)m;
+
+ /* olsr_msgtype */
+ pkt_get_u8(&curr, &olsr_msgtype);
+ if (olsr_msgtype != HNA_MESSAGE) {
+ OLSR_PRINTF(0, "not a HNA message!\n");
+ return;
+ }
+ /* Get vtime */
+ pkt_get_reltime(&curr, &vtime);
+
+ /* olsr_msgsize */
+ pkt_get_u16(&curr, &olsr_msgsize);
+ hnasize = olsr_msgsize - (olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message));
+ if (hnasize < 0) {
+ OLSR_PRINTF(0, "message size %d too small (at least %lu)!\n", olsr_msgsize, (unsigned long)(olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message)));
+ return;
+ }
+ if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
+ OLSR_PRINTF(0, "Illegal message size %d!\n", olsr_msgsize);
+ return;
+ }
+ curr_end = (const olsr_u8_t *)m + olsr_msgsize;
+
+ /* validate originator */
+ pkt_get_ipaddress(&curr, &originator);
+ /*printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));*/
+
+ /* ttl */
+ pkt_ignore_u8(&curr);
+
+ /* hopcnt */
+ pkt_get_u8(&curr, &hop_count);
+
+ /* seqno */
+ pkt_get_u16(&curr, &packet_seq_number);
+
+ /*
+ * If the sender interface (NB: not originator) of this message
+ * is not in the symmetric 1-hop neighborhood of this node, the
+ * message MUST be discarded.
+ */
+ if (check_neighbor_link(from_addr) != SYM_LINK) {
+ struct ipaddr_str buf;
+ OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
+ return;
+ }
+#if 1
+ while (curr < curr_end) {
+ union olsr_ip_addr net;
+ olsr_u8_t prefixlen;
+ struct ip_prefix_list *entry;
+
+ pkt_get_ipaddress(&curr, &net);
+ pkt_get_prefixlen(&curr, &prefixlen);
+ entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
+ if (entry == NULL) {
+ /* only update if it's not from us */
+ olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
}
- else
- {
- /* IPv6 */
- if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
- {
- //printf("ok");
- if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
- return 1;
-
- return 0;
- }
+ }
+#else
+ while (hna_tmp) {
+ /* Don't add an HNA entry that we are advertising ourselves. */
+ if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
+ olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
}
-
- neighbors = neighbors->next;
}
-
- /* Not found */
- return 0;
+#endif
+ olsr_forward_message(m, from_addr);
}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */