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.
42 #include "process_package.h"
45 #include "neighbor_table.h"
49 #include "olsr_logging.h"
51 static void olsr_input_hello(struct olsr_message *msg, const uint8_t *payload, const uint8_t *end,
52 struct interface *, union olsr_ip_addr *, enum duplicate_status);
54 static void process_message_neighbors(struct nbr_entry *, const struct lq_hello_message *);
56 static bool lookup_mpr_status(const struct lq_hello_message *, const struct interface *);
58 static void hello_tap(struct lq_hello_message *, struct interface *, const union olsr_ip_addr *);
62 * Processes an list of neighbors from an incoming HELLO message.
63 * @param neighbor the neighbor who sent the message.
64 * @param message the HELLO message
68 process_message_neighbors(struct nbr_entry *neighbor, const struct lq_hello_message *message)
70 struct lq_hello_neighbor *message_neighbors;
71 olsr_linkcost first_hop_pathcost;
72 struct link_entry *lnk;
73 union olsr_ip_addr *neigh_addr;
74 struct nbr_con *connector;
77 * Walk our 2-hop neighbors.
79 for (message_neighbors = message->neigh; message_neighbors; message_neighbors = message_neighbors->next) {
82 * Check all interfaces such that we don't add ourselves to the 2 hop list.
85 if (if_ifwithaddr(&message_neighbors->addr) != NULL) {
89 /* Get the main address */
90 neigh_addr = olsr_lookup_main_addr_by_alias(&message_neighbors->addr);
91 if (neigh_addr != NULL) {
92 message_neighbors->addr = *neigh_addr;
96 * We are only interested in symmetrical or MPR neighbors.
98 if (message_neighbors->neigh_type != SYM_NEIGH && message_neighbors->neigh_type != MPR_NEIGH) {
102 olsr_link_nbr_nbr2(neighbor, &message_neighbors->addr, message->comm->vtime);
106 lnk = get_best_link_to_neighbor(&neighbor->nbr_addr);
111 /* calculate first hop path quality */
112 first_hop_pathcost = lnk->linkcost;
114 * Second pass : calculate the best 2-hop
115 * path costs to all the 2-hop neighbors indicated in the
116 * HELLO message. Since the same 2-hop neighbor may be listed
117 * more than once in the same HELLO message (each at a possibly
118 * different quality) we want to select only the best one, not just
119 * the last one listed in the HELLO message.
121 for (message_neighbors = message->neigh; message_neighbors != NULL; message_neighbors = message_neighbors->next) {
122 if (if_ifwithaddr(&message_neighbors->addr) != NULL) {
125 if (message_neighbors->neigh_type == SYM_NEIGH || message_neighbors->neigh_type == MPR_NEIGH) {
126 olsr_linkcost new_second_hop_linkcost;
127 olsr_linkcost new_path_linkcost;
128 connector = olsr_lookup_nbr_con_entry(neighbor, &message_neighbors->addr);
134 new_second_hop_linkcost = message_neighbors->cost;
136 // the total cost for the route
137 // "us --- 1-hop --- 2-hop"
138 new_path_linkcost = first_hop_pathcost + new_second_hop_linkcost;
140 // Only copy the link quality if it is better than what we have
141 // for this 2-hop neighbor
142 if (new_path_linkcost < connector->path_linkcost) {
143 connector->second_hop_linkcost = new_second_hop_linkcost;
144 connector->path_linkcost = new_path_linkcost;
146 if (olsr_is_relevant_costchange(new_path_linkcost, connector->saved_path_linkcost)) {
147 connector->saved_path_linkcost = new_path_linkcost;
149 if (olsr_cnf->lq_dlimit > 0) {
150 changes_neighborhood = true;
151 changes_topology = true;
161 * Check if a hello message states this node as a MPR.
163 * @param message the message to check
164 * @param n_link the buffer to put the link status in
166 * @return 1 if we are selected as MPR 0 if not
169 lookup_mpr_status(const struct lq_hello_message *message, const struct interface *in_if)
171 struct lq_hello_neighbor *neighbors;
173 for (neighbors = message->neigh; neighbors; neighbors = neighbors->next) {
174 if ( neighbors->link_type != UNSPEC_LINK
175 && (olsr_cnf->ip_version == AF_INET
176 ? ip4cmp(&neighbors->addr.v4, &in_if->ip_addr.v4) == 0
177 : ip6cmp(&neighbors->addr.v6, &in_if->int6_addr.sin6_addr) == 0)) {
178 return neighbors->link_type == SYM_LINK && neighbors->neigh_type == MPR_NEIGH ? true : false;
186 * Initializing the parser functions we are using
187 * For downwards compatibility reasons we also understand the non-LQ messages.
190 olsr_init_package_process(void)
192 olsr_parser_add_function(&olsr_input_hello, olsr_get_Hello_MessageId());
193 olsr_parser_add_function(&olsr_input_tc, olsr_get_TC_MessageId());
194 olsr_parser_add_function(&olsr_input_mid, MID_MESSAGE);
195 olsr_parser_add_function(&olsr_input_hna, HNA_MESSAGE);
199 olsr_deinit_package_process(void)
201 olsr_parser_remove_function(&olsr_input_hello);
202 olsr_parser_remove_function(&olsr_input_tc);
203 olsr_parser_remove_function(&olsr_input_mid);
204 olsr_parser_remove_function(&olsr_input_hna);
208 deserialize_hello(struct lq_hello_message *hello, struct olsr_message *msg, const uint8_t *payload, const uint8_t *end)
210 const uint8_t *curr = payload;
213 /* parse HELLO specific header */
214 pkt_ignore_u16(&curr);
215 pkt_get_reltime(&curr, &hello->htime);
216 pkt_get_u8(&curr, &hello->will);
220 const uint8_t *ptr, *limit2;
225 pkt_get_u8(&curr, &link_code);
226 pkt_ignore_u8(&curr);
227 pkt_get_u16(&curr, &size);
230 while (curr + olsr_cnf->ipsize + olsr_sizeof_HelloLQ() <= limit2) {
231 struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor();
232 pkt_get_ipaddress(&curr, &neigh->addr);
234 olsr_deserialize_hello_lq_pair(&curr, neigh);
235 if (is_lost_interface_ip(&neigh->addr)) {
236 /* this is a lost interface IP of this node... ignore it */
237 olsr_free_lq_hello_neighbor(neigh);
241 neigh->link_type = EXTRACT_LINK(link_code);
242 neigh->neigh_type = EXTRACT_STATUS(link_code);
244 neigh->next = hello->neigh;
245 hello->neigh = neigh;
252 static void olsr_update_mprs_set(struct lq_hello_message *message, struct link_entry *link) {
253 bool new_mprs_status;
255 new_mprs_status = lookup_mpr_status(message, link->inter);
257 if (new_mprs_status && !link->is_mprs) {
258 link->neighbor->mprs_count++;
260 if (!new_mprs_status && link->is_mprs) {
261 link->neighbor->mprs_count--;
264 link->is_mprs = new_mprs_status;
268 hello_tap(struct lq_hello_message *message, struct interface *in_if, const union olsr_ip_addr *from_addr)
273 struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
274 struct lq_hello_neighbor *walker;
275 /* just in case our neighbor has changed its HELLO interval */
276 olsr_update_packet_loss_hello_int(lnk, message->htime);
278 /* find the input interface in the list of neighbor interfaces */
279 for (walker = message->neigh; walker != NULL; walker = walker->next) {
280 if (walker->link_type != UNSPEC_LINK && olsr_ipcmp(&walker->addr, &in_if->ip_addr) == 0) {
285 olsr_update_mprs_set(message, lnk);
288 * memorize our neighbour's idea of the link quality, so that we
289 * know the link quality in both directions
291 * walker is NULL if there the current interface was not included in
292 * the message (or was included as an UNSPEC_LINK)
294 olsr_memorize_foreign_hello_lq(lnk, walker);
296 /* update packet loss for link quality calculation */
297 olsr_update_packet_loss(lnk);
299 /* Check willingness */
300 if (lnk->neighbor->willingness != message->will) {
301 #if !defined REMOVE_LOG_DEBUG
302 struct ipaddr_str buf;
304 OLSR_DEBUG(LOG_LINKS, "Willingness for %s changed from %d to %d - UPDATING\n",
305 olsr_ip_to_string(&buf, &lnk->neighbor->nbr_addr), lnk->neighbor->willingness, message->will);
307 *If willingness changed - recalculate
309 lnk->neighbor->willingness = message->will;
310 changes_neighborhood = true;
311 changes_topology = true;
314 /* Don't register neighbors of neighbors that announces WILL_NEVER */
315 if (lnk->neighbor->willingness != WILL_NEVER) {
316 process_message_neighbors(lnk->neighbor, message);
319 /* Process changes immedeatly in case of MPR updates */
320 olsr_process_changes();
322 destroy_lq_hello(message);
326 olsr_input_hello(struct olsr_message *msg, const uint8_t *payload, const uint8_t *end,
327 struct interface *inif, union olsr_ip_addr *from,
328 enum duplicate_status status __attribute__ ((unused)))
330 struct lq_hello_message hello;
331 if (!deserialize_hello(&hello, msg, payload, end)) {
332 hello_tap(&hello, inif, from);
339 * indent-tabs-mode: nil