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