Give TTL1 messages another chance through MODE==ether links.
[olsrd.git] / src / lq_plugin.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
16  *   distribution.
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.
20  *
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.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
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.
39  *
40  */
41
42 #include "tc_set.h"
43 #include "link_set.h"
44 #include "olsr_spf.h"
45 #include "lq_packet.h"
46 #include "packet.h"
47 #include "olsr.h"
48 #include "two_hop_neighbor_table.h"
49 #include "common/avl.h"
50
51 #include "lq_plugin_default_float.h"
52 #include "lq_plugin_default_fpm.h"
53 #include "lq_plugin_default_ff.h"
54 #include "lq_plugin_default_ffeth.h"
55
56 #include <assert.h>
57
58 struct avl_tree lq_handler_tree;
59 struct lq_handler *active_lq_handler = NULL;
60
61 int
62 avl_strcasecmp(const void *str1, const void *str2)
63 {
64   return strcasecmp(str1, str2);
65 }
66
67 void
68 init_lq_handler_tree(void)
69 {
70   avl_init(&lq_handler_tree, &avl_strcasecmp);
71   register_lq_handler(&lq_etx_float_handler, LQ_ALGORITHM_ETX_FLOAT_NAME);
72   register_lq_handler(&lq_etx_fpm_handler, LQ_ALGORITHM_ETX_FPM_NAME);
73   register_lq_handler(&lq_etx_ff_handler, LQ_ALGORITHM_ETX_FF_NAME);
74   register_lq_handler(&lq_etx_ffeth_handler, LQ_ALGORITHM_ETX_FFETH_NAME);
75
76   if (olsr_cnf->lq_algorithm == NULL) {
77     activate_lq_handler(LQ_ALGORITHM_ETX_FF_NAME);
78   }
79   else {
80     activate_lq_handler(olsr_cnf->lq_algorithm);
81   }
82 }
83
84 /*
85  * set_lq_handler
86  *
87  * this function is used by routing metric plugins to activate their link
88  * quality handler
89  *
90  * The name parameter is marked as "unused" to squelch a compiler warning if debug
91  * output is not active
92  *
93  * @param pointer to lq_handler structure
94  * @param name of the link quality handler for debug output
95  */
96 void
97 register_lq_handler(struct lq_handler *handler, const char *name)
98 {
99   struct lq_handler_node *node;
100   size_t name_size = sizeof(*node) + strlen(name) + 1;
101
102   node = olsr_malloc(name_size, "olsr lq handler");
103
104   strscpy(node->name, name, name_size);
105   node->node.key = node->name;
106   node->handler = handler;
107
108   avl_insert(&lq_handler_tree, &node->node, false);
109 }
110
111 void
112 activate_lq_handler(const char *name)
113 {
114   struct lq_handler_node *node;
115
116   node = (struct lq_handler_node *)avl_find(&lq_handler_tree, name);
117   if (node == NULL) {
118     OLSR_PRINTF(1, "Error, unknown lq_handler '%s'\n", name);
119     olsr_exit("", 1);
120   }
121
122   OLSR_PRINTF(1, "Using '%s' algorithm for lq calculation.\n", name);
123   active_lq_handler = node->handler;
124   active_lq_handler->initialize();
125 }
126
127 /*
128  * olsr_calc_tc_cost
129  *
130  * this function calculates the linkcost of a tc_edge_entry
131  *
132  * @param pointer to the tc_edge_entry
133  * @return linkcost
134  */
135 olsr_linkcost
136 olsr_calc_tc_cost(const struct tc_edge_entry * tc_edge)
137 {
138   assert((const char *)tc_edge + sizeof(*tc_edge) >= (const char *)tc_edge->linkquality);
139   return active_lq_handler->calc_tc_cost(tc_edge->linkquality);
140 }
141
142 /*
143  * olsr_serialize_hello_lq_pair
144  *
145  * this function converts the lq information of a lq_hello_neighbor into binary package
146  * format
147  *
148  * @param pointer to binary buffer to write into
149  * @param pointer to lq_hello_neighbor
150  * @return number of bytes that have been written
151  */
152 int
153 olsr_serialize_hello_lq_pair(unsigned char *buff, struct lq_hello_neighbor *neigh)
154 {
155   assert((const char *)neigh + sizeof(*neigh) >= (const char *)neigh->linkquality);
156   return active_lq_handler->serialize_hello_lq(buff, neigh->linkquality);
157 }
158
159 /*
160  * olsr_deserialize_hello_lq_pair
161  *
162  * this function reads the lq information of a binary package into a hello_neighbor
163  * It also initialize the cost variable of the hello_neighbor
164  *
165  * @param pointer to the current buffer pointer
166  * @param pointer to hello_neighbor
167  */
168 void
169 olsr_deserialize_hello_lq_pair(const uint8_t ** curr, struct hello_neighbor *neigh)
170 {
171   assert((const char *)neigh + sizeof(*neigh) >= (const char *)neigh->linkquality);
172   active_lq_handler->deserialize_hello_lq(curr, neigh->linkquality);
173   neigh->cost = active_lq_handler->calc_hello_cost(neigh->linkquality);
174 }
175
176 /*
177  * olsr_serialize_tc_lq_pair
178  *
179  * this function converts the lq information of a olsr_serialize_tc_lq_pair
180  * into binary package format
181  *
182  * @param pointer to binary buffer to write into
183  * @param pointer to olsr_serialize_tc_lq_pair
184  * @return number of bytes that have been written
185  */
186 int
187 olsr_serialize_tc_lq_pair(unsigned char *buff, struct tc_mpr_addr *neigh)
188 {
189   assert((const char *)neigh + sizeof(*neigh) >= (const char *)neigh->linkquality);
190   return active_lq_handler->serialize_tc_lq(buff, neigh->linkquality);
191 }
192
193 /*
194  * olsr_deserialize_tc_lq_pair
195  *
196  * this function reads the lq information of a binary package into a tc_edge_entry
197  *
198  * @param pointer to the current buffer pointer
199  * @param pointer to tc_edge_entry
200  */
201 void
202 olsr_deserialize_tc_lq_pair(const uint8_t ** curr, struct tc_edge_entry *edge)
203 {
204   assert((const char *)edge + sizeof(*edge) >= (const char *)edge->linkquality);
205   active_lq_handler->deserialize_tc_lq(curr, edge->linkquality);
206 }
207
208 /*
209  * olsr_update_packet_loss_worker
210  *
211  * this function is called every times a hello package for a certain link_entry
212  * is lost (timeout) or received. This way the lq-plugin can update the links link
213  * quality value.
214  *
215  * @param pointer to link_entry
216  * @param true if hello package was lost
217  */
218 void
219 olsr_update_packet_loss_worker(struct link_entry *entry, bool lost)
220 {
221   assert((const char *)entry + sizeof(*entry) >= (const char *)entry->linkquality);
222   active_lq_handler->packet_loss_handler(entry, entry->linkquality, lost);
223 }
224
225 /*
226  * olsr_memorize_foreign_hello_lq
227  *
228  * this function is called to copy the link quality information from a received
229  * hello package into a link_entry.
230  *
231  * @param pointer to link_entry
232  * @param pointer to hello_neighbor, if NULL the neighbor link quality information
233  * of the link entry has to be reset to "zero"
234  */
235 void
236 olsr_memorize_foreign_hello_lq(struct link_entry *local, struct hello_neighbor *foreign)
237 {
238   assert((const char *)local + sizeof(*local) >= (const char *)local->linkquality);
239   if (foreign) {
240     assert((const char *)foreign + sizeof(*foreign) >= (const char *)foreign->linkquality);
241     active_lq_handler->memorize_foreign_hello(local->linkquality, foreign->linkquality);
242   } else {
243     active_lq_handler->memorize_foreign_hello(local->linkquality, NULL);
244   }
245 }
246
247 /*
248  * get_link_entry_text
249  *
250  * this function returns the text representation of a link_entry cost value.
251  * It's not thread save and should not be called twice with the same println
252  * value in the same context (a single printf command for example).
253  *
254  * @param pointer to link_entry
255  * @param char separator between LQ and NLQ
256  * @param buffer for output
257  * @return pointer to a buffer with the text representation
258  */
259 const char *
260 get_link_entry_text(struct link_entry *entry, char separator, struct lqtextbuffer *buffer)
261 {
262   assert((const char *)entry + sizeof(*entry) >= (const char *)entry->linkquality);
263   return active_lq_handler->print_hello_lq(entry->linkquality, separator, buffer);
264 }
265
266 /*
267  * get_tc_edge_entry_text
268  *
269  * this function returns the text representation of a tc_edge_entry cost value.
270  * It's not thread save and should not be called twice with the same println
271  * value in the same context (a single printf command for example).
272  *
273  * @param pointer to tc_edge_entry
274  * @param char separator between LQ and NLQ
275  * @param pointer to buffer
276  * @return pointer to the buffer with the text representation
277  */
278 const char *
279 get_tc_edge_entry_text(struct tc_edge_entry *entry, char separator, struct lqtextbuffer *buffer)
280 {
281   assert((const char *)entry + sizeof(*entry) >= (const char *)entry->linkquality);
282   return active_lq_handler->print_tc_lq(entry->linkquality, separator, buffer);
283 }
284
285 /*
286  * get_linkcost_text
287  *
288  * This function transforms an olsr_linkcost value into it's text representation and copies
289  * the result into a buffer.
290  *
291  * @param linkcost value
292  * @param true to transform the cost of a route, false for a link
293  * @param pointer to buffer
294  * @return pointer to buffer filled with text
295  */
296 const char *
297 get_linkcost_text(olsr_linkcost cost, bool route, struct lqtextbuffer *buffer)
298 {
299   static const char *infinite = "INFINITE";
300
301   if (route) {
302     if (cost == ROUTE_COST_BROKEN) {
303       return infinite;
304     }
305   } else {
306     if (cost >= LINK_COST_BROKEN) {
307       return infinite;
308     }
309   }
310   return active_lq_handler->print_cost(cost, buffer);
311 }
312
313 /*
314  * olsr_copy_hello_lq
315  *
316  * this function copies the link quality information from a link_entry to a
317  * lq_hello_neighbor.
318  *
319  * @param pointer to target lq_hello_neighbor
320  * @param pointer to source link_entry
321  */
322 void
323 olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source)
324 {
325   assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);
326   assert((const char *)source + sizeof(*source) >= (const char *)source->linkquality);
327   active_lq_handler->copy_link_lq_into_neigh(target->linkquality, source->linkquality);
328 }
329
330 /*
331  * olsr_copylq_link_entry_2_tc_mpr_addr
332  *
333  * this function copies the link quality information from a link_entry to a
334  * tc_mpr_addr.
335  *
336  * @param pointer to tc_mpr_addr
337  * @param pointer to link_entry
338  */
339 void
340 olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target, struct link_entry *source)
341 {
342   assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);
343   assert((const char *)source + sizeof(*source) >= (const char *)source->linkquality);
344   active_lq_handler->copy_link_lq_into_tc(target->linkquality, source->linkquality);
345 }
346
347 /*
348  * olsr_copylq_link_entry_2_tc_edge_entry
349  *
350  * this function copies the link quality information from a link_entry to a
351  * tc_edge_entry.
352  *
353  * @param pointer to tc_edge_entry
354  * @param pointer to link_entry
355  */
356 void
357 olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source)
358 {
359   assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);
360   assert((const char *)source + sizeof(*source) >= (const char *)source->linkquality);
361   active_lq_handler->copy_link_lq_into_tc(target->linkquality, source->linkquality);
362 }
363
364 /* clear the lq of a link set entry */
365 void olsr_clear_hello_lq(struct link_entry *link) {
366   active_lq_handler->clear_hello(link->linkquality);
367 }
368
369 /*
370  * olsr_clear_tc_lq
371  *
372  * this function resets the linkquality value of a tc_mpr_addr
373  *
374  * @param pointer to tc_mpr_addr
375  */
376 void
377 olsr_clear_tc_lq(struct tc_mpr_addr *target)
378 {
379   assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);
380   active_lq_handler->clear_tc(target->linkquality);
381 }
382
383 /*
384  * olsr_malloc_hello_neighbor
385  *
386  * this function allocates memory for an hello_neighbor inclusive
387  * linkquality data.
388  *
389  * @param id string for memory debugging
390  *
391  * @return pointer to hello_neighbor
392  */
393 struct hello_neighbor *
394 olsr_malloc_hello_neighbor(const char *id)
395 {
396   struct hello_neighbor *h;
397
398   h = olsr_malloc(sizeof(struct hello_neighbor) + active_lq_handler->hello_lq_size, id);
399
400   assert((const char *)h + sizeof(*h) >= (const char *)h->linkquality);
401   active_lq_handler->clear_hello(h->linkquality);
402   return h;
403 }
404
405 /*
406  * olsr_malloc_tc_mpr_addr
407  *
408  * this function allocates memory for an tc_mpr_addr inclusive
409  * linkquality data.
410  *
411  * @param id string for memory debugging
412  *
413  * @return pointer to tc_mpr_addr
414  */
415 struct tc_mpr_addr *
416 olsr_malloc_tc_mpr_addr(const char *id)
417 {
418   struct tc_mpr_addr *t;
419
420   t = olsr_malloc(sizeof(struct tc_mpr_addr) + active_lq_handler->tc_lq_size, id);
421
422   assert((const char *)t + sizeof(*t) >= (const char *)t->linkquality);
423   active_lq_handler->clear_tc(t->linkquality);
424   return t;
425 }
426
427 /*
428  * olsr_malloc_lq_hello_neighbor
429  *
430  * this function allocates memory for an lq_hello_neighbor inclusive
431  * linkquality data.
432  *
433  * @param id string for memory debugging
434  *
435  * @return pointer to lq_hello_neighbor
436  */
437 struct lq_hello_neighbor *
438 olsr_malloc_lq_hello_neighbor(const char *id)
439 {
440   struct lq_hello_neighbor *h;
441
442   h = olsr_malloc(sizeof(struct lq_hello_neighbor) + active_lq_handler->hello_lq_size, id);
443
444   assert((const char *)h + sizeof(*h) >= (const char *)h->linkquality);
445   active_lq_handler->clear_hello(h->linkquality);
446   return h;
447 }
448
449 /*
450  * olsr_malloc_link_entry
451  *
452  * this function allocates memory for an link_entry inclusive
453  * linkquality data.
454  *
455  * @param id string for memory debugging
456  *
457  * @return pointer to link_entry
458  */
459 struct link_entry *
460 olsr_malloc_link_entry(const char *id)
461 {
462   struct link_entry *h;
463
464   h = olsr_malloc(sizeof(struct link_entry) + active_lq_handler->hello_lq_size, id);
465
466   assert((const char *)h + sizeof(*h) >= (const char *)h->linkquality);
467   active_lq_handler->clear_hello(h->linkquality);
468   return h;
469 }
470
471 /**
472  * This function should be called whenever the current linkcost
473  * value changed in a relevant way.
474  *
475  * @param link pointer to current link
476  * @param newcost new cost of this link
477  */
478 void olsr_relevant_linkcost_change(void) {
479   if (olsr_cnf->lq_dlimit > 0) {
480     changes_neighborhood = true;
481     changes_topology = true;
482   }
483   else {
484     OLSR_PRINTF(3, "Skipping Dijkstra (1)\n");
485   }
486
487   /* XXX - we should check whether we actually announce this neighbour */
488   signal_link_changes(true);
489 }
490
491 /*
492  * Local Variables:
493  * c-basic-offset: 2
494  * indent-tabs-mode: nil
495  * End:
496  */