Cleanup of memory cookie system. Changed name from "cookie" to "memcookie".
[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_memcookie.h"
49 #include "common/avl.h"
50 #include "common/string.h"
51 #include "olsr_logging.h"
52 #include "neighbor_table.h"
53
54 #include "assert.h"
55
56 struct lq_handler *active_lq_handler = NULL;
57
58 static struct olsr_memcookie_info *tc_edge_mem_cookie = NULL;
59 static struct olsr_memcookie_info *lq_hello_neighbor_mem_cookie = NULL;
60 static struct olsr_memcookie_info *link_entry_mem_cookie = NULL;
61
62 void
63 init_lq_handler(void)
64 {
65   if (NULL == active_lq_handler) {
66     OLSR_ERROR(LOG_LQ_PLUGINS, "You removed the static linked LQ plugin and don't provide another one.\n");
67     olsr_exit(1);
68   }
69
70   OLSR_INFO(LOG_LQ_PLUGINS, "Initializing LQ handler %s...\n", active_lq_handler->name);
71
72   tc_edge_mem_cookie = olsr_memcookie_add("tc_edge", active_lq_handler->size_tc_edge);
73
74   lq_hello_neighbor_mem_cookie =
75       olsr_memcookie_add("lq_hello_neighbor", active_lq_handler->size_lq_hello_neighbor);
76
77   link_entry_mem_cookie =
78       olsr_memcookie_add("link_entry", active_lq_handler->size_link_entry);
79
80   if (active_lq_handler->initialize) {
81     active_lq_handler->initialize();
82   }
83 }
84
85 void
86 deinit_lq_handler(void)
87 {
88   if (NULL != active_lq_handler) {
89     if (active_lq_handler->deinitialize) {
90       active_lq_handler->deinitialize();
91     }
92     active_lq_handler = NULL;
93   }
94 }
95
96 /*
97  * olsr_calc_tc_cost
98  *
99  * this function calculates the linkcost of a tc_edge_entry
100  *
101  * @param pointer to the tc_edge_entry
102  * @return linkcost
103  */
104 olsr_linkcost
105 olsr_calc_tc_cost(struct tc_edge_entry *tc_edge)
106 {
107   return active_lq_handler->calc_tc_edge_entry_cost(tc_edge);
108 }
109
110 /*
111  * olsr_serialize_hello_lq_pair
112  *
113  * this function converts the lq information of a lq_hello_neighbor into binary package
114  * format
115  *
116  * @param pointer to binary buffer to write into
117  * @param pointer to link_entry
118  */
119 void
120 olsr_serialize_hello_lq_pair(uint8_t **buff, struct link_entry *link)
121 {
122   active_lq_handler->serialize_hello_lq(buff, link);
123 }
124
125 /*
126  * olsr_deserialize_hello_lq_pair
127  *
128  * this function reads the lq information of a binary package into a hello_neighbor
129  * It also initialize the cost variable of the hello_neighbor
130  *
131  * @param pointer to the current buffer pointer
132  * @param pointer to hello_neighbor
133  */
134 void
135 olsr_deserialize_hello_lq_pair(const uint8_t ** curr, struct lq_hello_neighbor *neigh)
136 {
137   active_lq_handler->deserialize_hello_lq(curr, neigh);
138   neigh->cost = active_lq_handler->calc_lq_hello_neighbor_cost(neigh);
139 }
140
141 /*
142  * olsr_serialize_tc_lq
143  *
144  * this function converts the lq information of a olsr_serialize_tc_lq_pair
145  * into binary package format
146  *
147  * @param pointer to binary buffer to write into
148  * @param pointer to link_entry
149  */
150 void
151 olsr_serialize_tc_lq(unsigned char **curr, struct link_entry *lnk)
152 {
153   active_lq_handler->serialize_tc_lq(curr, lnk);
154 }
155
156 /*
157  * olsr_deserialize_tc_lq_pair
158  *
159  * this function reads the lq information of a binary package into a tc_edge_entry
160  *
161  * @param pointer to the current buffer pointer
162  * @param pointer to tc_edge_entry
163  */
164 void
165 olsr_deserialize_tc_lq_pair(const uint8_t ** curr, struct tc_edge_entry *edge)
166 {
167   active_lq_handler->deserialize_tc_lq(curr, edge);
168 }
169
170 /*
171  * olsr_lq_hello_handler
172  *
173  * this function is called every times a hello package for a certain link_entry
174  * is lost (timeout) or received. This way the lq-plugin can update the links link
175  * quality value.
176  *
177  * @param pointer to link_entry
178  * @param true if hello package was lost
179  */
180 void
181 olsr_lq_hello_handler(struct link_entry *entry, bool lost)
182 {
183   active_lq_handler->hello_handler(entry, lost);
184 }
185
186 static void
187 internal_clear_tc_edge_lq(struct tc_edge_entry *edge) {
188
189   if (active_lq_handler->clear_tc_edge_entry)  {
190     active_lq_handler->clear_tc_edge_entry(edge);
191   }
192   else {
193     uint8_t *ptr = (uint8_t *) edge;
194
195     memset (ptr + sizeof(*edge), 0, active_lq_handler->size_tc_edge - sizeof(*edge));
196   }
197 }
198
199 void
200 olsr_neighbor_cost_may_changed(struct nbr_entry *nbr) {
201   struct link_entry *link;
202   struct tc_edge_entry *edge;
203   olsr_linkcost cost = LINK_COST_BROKEN;
204
205   link = get_best_link_to_neighbor(nbr);
206   edge = nbr->tc_edge;
207
208   if (link) {
209     cost = link->linkcost;
210     active_lq_handler->copy_link_entry_lq_into_tc_edge_entry(edge, link);
211   }
212   else {
213     internal_clear_tc_edge_lq(edge);
214   }
215
216   if (edge->cost != cost) {
217     edge->cost = cost;
218
219     if (olsr_cnf->lq_dlimit > 0) {
220       changes_neighborhood = true;
221       changes_topology = true;
222       signal_link_changes(true);
223     }
224   }
225 }
226
227 /*
228  * olsr_memorize_foreign_hello_lq
229  *
230  * this function is called to copy the link quality information from a received
231  * hello package into a link_entry.
232  *
233  * @param pointer to link_entry
234  * @param pointer to hello_neighbor, if NULL the neighbor link quality information
235  * of the link entry has to be reset to "zero"
236  */
237 void
238 olsr_memorize_foreign_hello_lq(struct link_entry *local, struct lq_hello_neighbor *foreign)
239 {
240   active_lq_handler->memorize_foreign_hello(local, foreign);
241 }
242
243 /*
244  * get_linkcost_text
245  *
246  * This function transforms an olsr_linkcost value into it's text representation and copies
247  * the result into a buffer.
248  *
249  * @param linkcost value
250  * @param true to transform the cost of a route, false for a link
251  * @param pointer to buffer
252  * @param size of buffer
253  * @return pointer to buffer filled with text
254  */
255 const char *
256 olsr_get_linkcost_text(olsr_linkcost cost, bool route, char *buffer, size_t bufsize)
257 {
258   static const char *infinite = "INF";
259
260   if (route) {
261     if (cost == ROUTE_COST_BROKEN) {
262       strscpy(buffer, infinite, bufsize);
263       return buffer;
264     }
265   } else {
266     if (cost >= LINK_COST_BROKEN) {
267       strscpy(buffer, infinite, bufsize);
268       return buffer;
269     }
270   }
271   return active_lq_handler->print_cost(cost, buffer, bufsize);
272 }
273
274 /*
275  * olsr_get_linkdata_text
276  *
277  * this function returns the text representation of one linkquality parameter.
278  *
279  * @param pointer to link_entry
280  * @param index of linkquality parameter
281  * @param buffer for output
282  * @param size of buffer
283  * @return pointer to a buffer with the text representation
284  */
285 const char *
286 olsr_get_linkdata_text(struct link_entry *entry, int idx, char *buffer, size_t bufsize)
287 {
288   if (idx == 0) {
289     return olsr_get_linkcost_text(entry->linkcost, false, buffer, bufsize);
290   }
291   return active_lq_handler->print_link_entry_lq(entry, idx, buffer, bufsize);
292 }
293
294 /*
295  * olsr_get_linklabel
296  *
297  * this function returns the label of a linkquality parameter
298  *
299  * @param index of lq parameter (0 is always "linkcost")
300  * @return pointer to static string with label
301  */
302 const char *
303 olsr_get_linklabel (int idx) {
304   assert (idx >= 0 && idx < active_lq_handler->linkdata_hello_count);
305   return active_lq_handler->linkdata_hello[idx].name;
306 }
307
308 /*
309  * olsr_get_linklabel_maxlength
310  *
311  * this function returns the maximum length (in characters)
312  * of a linkquality parameter value
313  *
314  * @param index of lq parameter (0 is always "linkcost")
315  * @return number of bytes necessary to store a lq value string
316  */
317 size_t
318 olsr_get_linklabel_maxlength (int idx) {
319   assert (idx >= 0 && idx < active_lq_handler->linkdata_hello_count);
320   return active_lq_handler->linkdata_hello[idx].name_maxlen;
321 }
322
323 /*
324  * olsr_get_linklabel_count
325  *
326  * @return number of linkquality parameters including linkcost
327  */
328 size_t olsr_get_linklabel_count (void) {
329   return active_lq_handler->linkdata_hello_count;
330 }
331
332 /*
333  * olsr_get_linkdata_quality
334  *
335  * This function allows you to judge the quality of a certain linkquality parameter
336  * (in the categories BEST, GOOD, AVERAGE, BAD and WORST)
337  *
338  * @param link entry
339  * @param index of linkquality parameter
340  * @return enum with linkquality estinate
341  */
342 enum lq_linkdata_quality olsr_get_linkdata_quality (struct link_entry *link, int idx) {
343   struct lq_linkdata_type *linkdata;
344   int value;
345
346   assert (idx >= 0 && idx < active_lq_handler->linkdata_hello_count);
347   linkdata = &active_lq_handler->linkdata_hello[idx];
348   value = active_lq_handler->get_link_entry_data(link, idx);
349
350   if (value == linkdata->best) {
351     return LQ_QUALITY_BEST;
352   }
353   if (value == linkdata->worst) {
354     return LQ_QUALITY_WORST;
355   }
356
357   if (linkdata->best < linkdata->worst) {
358     if (value > linkdata->good) {
359       return LQ_QUALITY_GOOD;
360     }
361     if (value > linkdata->average) {
362       return LQ_QUALITY_AVERAGE;
363     }
364   }
365   else {
366     if (value < linkdata->good) {
367       return LQ_QUALITY_GOOD;
368     }
369     if (value < linkdata->average) {
370       return LQ_QUALITY_AVERAGE;
371     }
372   }
373   return LQ_QUALITY_BAD;
374 }
375
376 /*
377  * olsr_malloc_tc_edge_entry
378  *
379  * this function allocates memory for an tc_mpr_addr inclusive
380  * linkquality data.
381  *
382  * @return pointer to tc_mpr_addr
383  */
384 struct tc_edge_entry *
385 olsr_malloc_tc_edge_entry(void)
386 {
387   struct tc_edge_entry *t;
388
389   t = olsr_memcookie_malloc(tc_edge_mem_cookie);
390   if (active_lq_handler->clear_tc_edge_entry)
391     active_lq_handler->clear_tc_edge_entry(t);
392   return t;
393 }
394
395 /*
396  * olsr_malloc_lq_hello_neighbor
397  *
398  * this function allocates memory for an lq_hello_neighbor inclusive
399  * linkquality data.
400  *
401  * @return pointer to lq_hello_neighbor
402  */
403 struct lq_hello_neighbor *
404 olsr_malloc_lq_hello_neighbor(void)
405 {
406   struct lq_hello_neighbor *h;
407
408   h = olsr_memcookie_malloc(lq_hello_neighbor_mem_cookie);
409   if (active_lq_handler->clear_lq_hello_neighbor)
410     active_lq_handler->clear_lq_hello_neighbor(h);
411   return h;
412 }
413
414 /*
415  * olsr_malloc_link_entry
416  *
417  * this function allocates memory for an link_entry inclusive
418  * linkquality data.
419  *
420  * @return pointer to link_entry
421  */
422 struct link_entry *
423 olsr_malloc_link_entry(void)
424 {
425   struct link_entry *h;
426
427   h = olsr_memcookie_malloc(link_entry_mem_cookie);
428   if (active_lq_handler->clear_link_entry)
429     active_lq_handler->clear_link_entry(h);
430   return h;
431 }
432
433 /**
434  * olsr_free_link_entry
435  *
436  * this functions free a link_entry inclusive linkquality data
437  *
438  * @param pointer to link_entry
439  */
440 void
441 olsr_free_link_entry(struct link_entry *link)
442 {
443   olsr_memcookie_free(link_entry_mem_cookie, link);
444 }
445
446 /**
447  * olsr_free_lq_hello_neighbor
448  *
449  * this functions free a lq_hello_neighbor inclusive linkquality data
450  *
451  * @param pointer to lq_hello_neighbor
452  */
453 void
454 olsr_free_lq_hello_neighbor(struct lq_hello_neighbor *neigh)
455 {
456   olsr_memcookie_free(lq_hello_neighbor_mem_cookie, neigh);
457 }
458
459 /**
460  * olsr_free_tc_edge_entry
461  *
462  * this functions free a tc_edge_entry inclusive linkquality data
463  *
464  * @param pointer to tc_edge_entry
465  */
466 void
467 olsr_free_tc_edge_entry(struct tc_edge_entry *edge)
468 {
469   olsr_memcookie_free(tc_edge_mem_cookie, edge);
470 }
471
472 /**
473  * olsr_get_Hello_MessageId
474  *
475  * @return olsr id of hello message
476  */
477 uint8_t
478 olsr_get_Hello_MessageId(void)
479 {
480   return active_lq_handler->messageid_hello;
481 }
482
483 /**
484  * olsr_get_TC_MessageId
485  *
486  * @return olsr id of tc message
487  */
488 uint8_t
489 olsr_get_TC_MessageId(void)
490 {
491   return active_lq_handler->messageid_tc;
492 }
493
494 /**
495  * olsr_sizeof_HelloLQ
496  *
497  * @return number of bytes necessary to store HelloLQ data
498  */
499 size_t
500 olsr_sizeof_HelloLQ(void) {
501   return active_lq_handler->serialized_lqhello_size;
502 }
503
504 /**
505  * olsr_sizeof_TCLQ
506  *
507  * @return number of bytes necessary to store TCLQ data
508  */
509 size_t
510 olsr_sizeof_TCLQ(void) {
511   return active_lq_handler->serialized_lqtc_size;
512 }
513
514 /*
515  * Local Variables:
516  * c-basic-offset: 2
517  * indent-tabs-mode: nil
518  * End:
519  */