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