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