Added some de-initializing funcs to plugins, lq_plugins, netfilter, parser
[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 "olsr.h"
48 #include "olsr_cookie.h"
49 #include "two_hop_neighbor_table.h"
50 #include "common/avl.h"
51 #include "common/string.h"
52
53 #include "lq_plugin_etx_float.h"
54 #include "lq_plugin_etx_fpm.h"
55 #include "lq_plugin_etx_ff.h"
56 #include "lq_plugin_rfc.h"
57
58 static  struct avl_tree lq_handler_tree;
59 struct lq_handler *active_lq_handler = NULL;
60
61 static struct olsr_cookie_info *tc_mpr_addr_mem_cookie = NULL;
62 static struct olsr_cookie_info *tc_edge_mem_cookie = NULL;
63 static struct olsr_cookie_info *lq_hello_neighbor_mem_cookie = NULL;
64 static struct olsr_cookie_info *link_entry_mem_cookie = NULL;
65
66 static int
67 avl_strcasecmp(const void *str1, const void *str2)
68 {
69   return strcasecmp(str1, str2);
70 }
71
72
73 void
74 init_lq_handler_tree(void)
75 {
76   avl_init(&lq_handler_tree, &avl_strcasecmp);
77   register_lq_handler(&lq_etxfloat_handler, LQ_ALGORITHM_ETX_FLOAT_NAME);
78   register_lq_handler(&lq_etxfpm_handler, LQ_ALGORITHM_ETX_FPM_NAME);
79   register_lq_handler(&lq_etxff_handler, LQ_ALGORITHM_ETX_FF_NAME);
80   register_lq_handler(&lq_rfc_handler, LQ_ALGORITHM_RFC_NAME);
81 }
82
83 /*
84  * set_lq_handler
85  *
86  * this function is used by routing metric plugins to activate their link
87  * quality handler
88  *
89  * The name parameter is marked as "unused" to squelch a compiler warning if debug
90  * output is not active
91  *
92  * @param pointer to lq_handler structure
93  * @param name of the link quality handler for debug output
94  */
95 void
96 register_lq_handler(struct lq_handler *handler, const char *name)
97 {
98   struct lq_handler_node *node;
99   size_t name_size = sizeof(*node) + strlen(name) + 1;
100
101   node = olsr_malloc(name_size, "olsr lq handler");
102
103   strscpy(node->name, name, name_size);
104   node->node.key = node->name;
105   node->handler = handler;
106
107   avl_insert(&lq_handler_tree, &node->node, false);
108 }
109
110 void
111 activate_lq_handler(void)
112 {
113   const char *default_lq_algo = LQ_ALGORITHM_ETX_FPM_NAME;
114   struct lq_handler_node *node = NULL;
115
116   if (olsr_cnf->lq_algorithm) {
117     node = (struct lq_handler_node *) avl_find(&lq_handler_tree, olsr_cnf->lq_algorithm);
118     if (node == NULL) {
119       OLSR_PRINTF(1, "Error, unknown lq_handler '%s'\n", olsr_cnf->lq_algorithm);
120       olsr_exit("Cannot start without lq algorithm", 1);
121     }
122     OLSR_PRINTF(1, "Using '%s' algorithm for lq calculation.\n", olsr_cnf->lq_algorithm);
123   }
124   else {
125     node = (struct lq_handler_node *) avl_find(&lq_handler_tree, default_lq_algo);
126     OLSR_PRINTF(1, "Using default '%s' algorithm for lq calculation.\n", default_lq_algo);
127     if (node == NULL) {
128       OLSR_PRINTF(1, "Error, cannot find default algorithmus '%s'\n", default_lq_algo);
129       olsr_exit("Cannot start without lq algorithm", 1);
130     }
131   }
132
133   tc_edge_mem_cookie = olsr_alloc_cookie("tc_edge", OLSR_COOKIE_TYPE_MEMORY);
134   olsr_cookie_set_memory_size(tc_edge_mem_cookie, node->handler->size_tc_edge);
135
136   tc_mpr_addr_mem_cookie = olsr_alloc_cookie("tc_mpr_addr", OLSR_COOKIE_TYPE_MEMORY);
137   olsr_cookie_set_memory_size(tc_mpr_addr_mem_cookie, node->handler->size_tc_mpr_addr);
138
139   lq_hello_neighbor_mem_cookie = olsr_alloc_cookie("lq_hello_neighbor", OLSR_COOKIE_TYPE_MEMORY);
140   olsr_cookie_set_memory_size(lq_hello_neighbor_mem_cookie, node->handler->size_lq_hello_neighbor);
141
142   link_entry_mem_cookie = olsr_alloc_cookie("link_entry", OLSR_COOKIE_TYPE_MEMORY);
143   olsr_cookie_set_memory_size(link_entry_mem_cookie, node->handler->size_link_entry);
144
145   active_lq_handler = node->handler;
146   active_lq_handler->initialize();
147 }
148
149 void
150 deactivate_lq_handler(void)
151 {
152   struct lq_handler_node *handler;
153   active_lq_handler->deinitialize();
154   OLSR_FOR_ALL_LQ_HANDLERS(handler) {
155     avl_delete(&lq_handler_tree, &handler->node);
156     free(handler);
157   } OLSR_FOR_ALL_LQ_HANDLERS_END(handler);
158 }
159
160 /*
161  * olsr_calc_tc_cost
162  *
163  * this function calculates the linkcost of a tc_edge_entry
164  *
165  * @param pointer to the tc_edge_entry
166  * @return linkcost
167  */
168 olsr_linkcost
169 olsr_calc_tc_cost(struct tc_edge_entry *tc_edge)
170 {
171   return active_lq_handler->calc_tc_edge_entry_cost(tc_edge);
172 }
173
174 /*
175  * olsr_is_relevant_costchange
176  *
177  * decides if the difference between two costs is relevant
178  * (for changing the route for example)
179  *
180  * @param first linkcost value
181  * @param second linkcost value
182  * @return boolean
183  */
184 bool
185 olsr_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2)
186 {
187   return active_lq_handler->is_relevant_costchange(c1, c2);
188 }
189
190 /*
191  * olsr_serialize_hello_lq_pair
192  *
193  * this function converts the lq information of a lq_hello_neighbor into binary package
194  * format
195  *
196  * @param pointer to binary buffer to write into
197  * @param pointer to lq_hello_neighbor
198  * @return number of bytes that have been written
199  */
200 int
201 olsr_serialize_hello_lq_pair(unsigned char *buff,
202                              struct lq_hello_neighbor *neigh)
203 {
204   return active_lq_handler->serialize_hello_lq(buff, neigh);
205 }
206
207 /*
208  * olsr_deserialize_hello_lq_pair
209  *
210  * this function reads the lq information of a binary package into a hello_neighbor
211  * It also initialize the cost variable of the hello_neighbor
212  *
213  * @param pointer to the current buffer pointer
214  * @param pointer to hello_neighbor
215  */
216 void
217 olsr_deserialize_hello_lq_pair(const uint8_t ** curr,
218                                struct lq_hello_neighbor *neigh)
219 {
220   active_lq_handler->deserialize_hello_lq(curr, neigh);
221   neigh->cost = active_lq_handler->calc_lq_hello_neighbor_cost(neigh);
222 }
223
224 /*
225  * olsr_serialize_tc_lq_pair
226  *
227  * this function converts the lq information of a olsr_serialize_tc_lq_pair
228  * into binary package format
229  *
230  * @param pointer to binary buffer to write into
231  * @param pointer to olsr_serialize_tc_lq_pair
232  * @return number of bytes that have been written
233  */
234 int
235 olsr_serialize_tc_lq_pair(unsigned char *buff, struct tc_mpr_addr *neigh)
236 {
237   return active_lq_handler->serialize_tc_lq(buff, neigh);
238 }
239
240 /*
241  * olsr_deserialize_tc_lq_pair
242  *
243  * this function reads the lq information of a binary package into a tc_edge_entry
244  *
245  * @param pointer to the current buffer pointer
246  * @param pointer to tc_edge_entry
247  */
248 void
249 olsr_deserialize_tc_lq_pair(const uint8_t ** curr, struct tc_edge_entry *edge)
250 {
251   active_lq_handler->deserialize_tc_lq(curr, edge);
252 }
253
254 /*
255  * olsr_update_packet_loss_worker
256  *
257  * this function is called every times a hello package for a certain link_entry
258  * is lost (timeout) or received. This way the lq-plugin can update the links link
259  * quality value.
260  *
261  * @param pointer to link_entry
262  * @param true if hello package was lost
263  */
264 void
265 olsr_update_packet_loss_worker(struct link_entry *entry, bool lost)
266 {
267   olsr_linkcost lq;
268   lq = active_lq_handler->packet_loss_handler(entry, lost);
269
270   if (olsr_is_relevant_costchange(lq, entry->linkcost)) {
271     entry->linkcost = lq;
272
273     if (olsr_cnf->lq_dlimit > 0) {
274       changes_neighborhood = true;
275       changes_topology = true;
276     }
277
278     else
279       OLSR_PRINTF(3, "Skipping Dijkstra (1)\n");
280
281     /* XXX - we should check whether we actually announce this neighbour */
282     signal_link_changes(true);
283   }
284 }
285
286 /*
287  * olsr_memorize_foreign_hello_lq
288  *
289  * this function is called to copy the link quality information from a received
290  * hello package into a link_entry.
291  *
292  * @param pointer to link_entry
293  * @param pointer to hello_neighbor, if NULL the neighbor link quality information
294  * of the link entry has to be reset to "zero"
295  */
296 void
297 olsr_memorize_foreign_hello_lq(struct link_entry *local,
298                                struct lq_hello_neighbor *foreign)
299 {
300   if (foreign) {
301     active_lq_handler->memorize_foreign_hello(local, foreign);
302   } else {
303     active_lq_handler->memorize_foreign_hello(local, NULL);
304   }
305 }
306
307 /*
308  * get_link_entry_text
309  *
310  * this function returns the text representation of a link_entry cost value.
311  * It's not thread save and should not be called twice with the same println
312  * value in the same context (a single printf command for example).
313  *
314  * @param pointer to link_entry
315  * @param char separator between LQ and NLQ
316  * @param buffer for output
317  * @return pointer to a buffer with the text representation
318  */
319 const char *
320 get_link_entry_text(struct link_entry *entry, char separator, struct lqtextbuffer *buffer)
321 {
322   return active_lq_handler->print_link_entry_lq(entry, separator, buffer);
323 }
324
325 /*
326  * get_tc_edge_entry_text
327  *
328  * this function returns the text representation of a tc_edge_entry cost value.
329  * It's not thread save and should not be called twice with the same println
330  * value in the same context (a single printf command for example).
331  *
332  * @param pointer to tc_edge_entry
333  * @param char separator between LQ and NLQ
334  * @param pointer to buffer
335  * @return pointer to the buffer with the text representation
336  */
337 const char *
338 get_tc_edge_entry_text(struct tc_edge_entry *entry, char separator, struct lqtextbuffer *buffer)
339 {
340   return active_lq_handler->print_tc_edge_entry_lq(entry, separator, buffer);
341 }
342
343 /*
344  * get_linkcost_text
345  *
346  * This function transforms an olsr_linkcost value into it's text representation and copies
347  * the result into a buffer.
348  *
349  * @param linkcost value
350  * @param true to transform the cost of a route, false for a link
351  * @param pointer to buffer
352  * @return pointer to buffer filled with text
353  */
354 const char *
355 get_linkcost_text(olsr_linkcost cost, bool route,
356                   struct lqtextbuffer *buffer)
357 {
358   static const char *infinite = "INFINITE";
359
360   if (route) {
361     if (cost == ROUTE_COST_BROKEN) {
362       return infinite;
363     }
364   } else {
365     if (cost >= LINK_COST_BROKEN) {
366       return infinite;
367     }
368   }
369   return active_lq_handler->print_cost(cost, buffer);
370 }
371
372 /*
373  * olsr_copy_hello_lq
374  *
375  * this function copies the link quality information from a link_entry to a
376  * lq_hello_neighbor.
377  *
378  * @param pointer to target lq_hello_neighbor
379  * @param pointer to source link_entry
380  */
381 void
382 olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source)
383 {
384   active_lq_handler->copy_link_lq_into_neighbor(target, source);
385 }
386
387 /*
388  * olsr_copylq_link_entry_2_tc_mpr_addr
389  *
390  * this function copies the link quality information from a link_entry to a
391  * tc_mpr_addr.
392  *
393  * @param pointer to tc_mpr_addr
394  * @param pointer to link_entry
395  */
396 void
397 olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target,
398                                      struct link_entry *source)
399 {
400   active_lq_handler->copy_link_entry_lq_into_tc_mpr_addr(target, source);
401 }
402
403 /*
404  * olsr_copylq_link_entry_2_tc_edge_entry
405  *
406  * this function copies the link quality information from a link_entry to a
407  * tc_edge_entry.
408  *
409  * @param pointer to tc_edge_entry
410  * @param pointer to link_entry
411  */
412 void
413 olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target,
414                                        struct link_entry *source)
415 {
416   active_lq_handler->copy_link_entry_lq_into_tc_edge_entry(target, source);
417 }
418
419 /*
420  * olsr_malloc_tc_mpr_addr
421  *
422  * this function allocates memory for an tc_mpr_addr inclusive
423  * linkquality data.
424  *
425  * @return pointer to tc_mpr_addr
426  */
427 struct tc_edge_entry *olsr_malloc_tc_edge_entry(void)
428 {
429   struct tc_edge_entry *t;
430
431   t = olsr_cookie_malloc(tc_edge_mem_cookie);
432   if (active_lq_handler->clear_tc_edge_entry)
433     active_lq_handler->clear_tc_edge_entry(t);
434   return t;
435 }
436
437 /*
438  * olsr_malloc_tc_mpr_addr
439  *
440  * this function allocates memory for an tc_mpr_addr inclusive
441  * linkquality data.
442  *
443  * @return pointer to tc_mpr_addr
444  */
445 struct tc_mpr_addr *
446 olsr_malloc_tc_mpr_addr(void)
447 {
448   struct tc_mpr_addr *t;
449
450   t = olsr_cookie_malloc(tc_mpr_addr_mem_cookie);
451   if (active_lq_handler->clear_tc_mpr_addr)
452     active_lq_handler->clear_tc_mpr_addr(t);
453   return t;
454 }
455
456 /*
457  * olsr_malloc_lq_hello_neighbor
458  *
459  * this function allocates memory for an lq_hello_neighbor inclusive
460  * linkquality data.
461  *
462  * @return pointer to lq_hello_neighbor
463  */
464 struct lq_hello_neighbor *
465 olsr_malloc_lq_hello_neighbor(void)
466 {
467   struct lq_hello_neighbor *h;
468
469   h = olsr_cookie_malloc(lq_hello_neighbor_mem_cookie);
470   if (active_lq_handler->clear_lq_hello_neighbor)
471     active_lq_handler->clear_lq_hello_neighbor(h);
472   return h;
473 }
474
475 /*
476  * olsr_malloc_link_entry
477  *
478  * this function allocates memory for an link_entry inclusive
479  * linkquality data.
480  *
481  * @return pointer to link_entry
482  */
483 struct link_entry *
484 olsr_malloc_link_entry(void)
485 {
486   struct link_entry *h;
487
488   h = olsr_cookie_malloc(link_entry_mem_cookie);
489   if (active_lq_handler->clear_link_entry)
490     active_lq_handler->clear_link_entry(h);
491   return h;
492 }
493
494 /**
495  * olsr_free_link_entry
496  *
497  * this functions free a link_entry inclusive linkquality data
498  *
499  * @param pointer to link_entry
500  */
501 void olsr_free_link_entry(struct link_entry *link) {
502   olsr_cookie_free(link_entry_mem_cookie, link);
503 }
504
505 /**
506  * olsr_free_lq_hello_neighbor
507  *
508  * this functions free a lq_hello_neighbor inclusive linkquality data
509  *
510  * @param pointer to lq_hello_neighbor
511  */
512 void olsr_free_lq_hello_neighbor(struct lq_hello_neighbor *neigh) {
513   olsr_cookie_free(lq_hello_neighbor_mem_cookie, neigh);
514 }
515
516 /**
517  * olsr_free_tc_edge_entry
518  *
519  * this functions free a tc_edge_entry inclusive linkquality data
520  *
521  * @param pointer to tc_edge_entry
522  */
523 void olsr_free_tc_edge_entry(struct tc_edge_entry *edge) {
524   olsr_cookie_free(tc_edge_mem_cookie, edge);
525 }
526
527 /**
528  * olsr_free_tc_mpr_addr
529  *
530  * this functions free a tc_mpr_addr inclusive linkquality data
531  *
532  * @param pointer to tc_mpr_addr
533  */
534 void olsr_free_tc_mpr_addr(struct tc_mpr_addr *mpr) {
535   olsr_cookie_free(tc_mpr_addr_mem_cookie, mpr);
536 }
537
538 /**
539  * olsr_get_Hello_MessageId
540  *
541  * @return olsr id of hello message
542  */
543 uint8_t olsr_get_Hello_MessageId(void) {
544   return active_lq_handler->messageid_hello;
545 }
546
547 /**
548  * olsr_get_TC_MessageId
549  *
550  * @return olsr id of tc message
551  */
552 uint8_t olsr_get_TC_MessageId(void) {
553   return active_lq_handler->messageid_tc;
554 }
555
556 /*
557  * Local Variables:
558  * c-basic-offset: 2
559  * indent-tabs-mode: nil
560  * End:
561  */