Added some de-initializing funcs to plugins, lq_plugins, netfilter, parser
[olsrd.git] / src / lq_plugin_etx_ff.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "tc_set.h"
42 #include "link_set.h"
43 #include "lq_plugin.h"
44 #include "olsr_spf.h"
45 #include "lq_packet.h"
46 #include "olsr.h"
47 #include "lq_plugin_etx_ff.h"
48 #include "parser.h"
49 #include "mid_set.h"
50 #include "scheduler.h"
51
52 #define LQ_PLUGIN_RELEVANT_COSTCHANGE_FF 16
53
54 static void lq_etxff_initialize(void);
55 static void lq_etxff_deinitialize(void);
56
57 static olsr_linkcost lq_etxff_calc_link_entry_cost(struct link_entry *);
58 static olsr_linkcost lq_etxff_calc_lq_hello_neighbor_cost(
59     struct lq_hello_neighbor *);
60 static olsr_linkcost lq_etxff_calc_tc_mpr_addr_cost(struct tc_mpr_addr *);
61 static olsr_linkcost lq_etxff_calc_tc_edge_entry_cost(struct tc_edge_entry *);
62
63 static bool lq_etxff_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2);
64
65 static olsr_linkcost lq_etxff_packet_loss_handler(struct link_entry *, bool);
66
67 static void lq_etxff_memorize_foreign_hello(struct link_entry *,
68     struct lq_hello_neighbor *);
69 static void lq_etxff_copy_link_entry_lq_into_tc_mpr_addr(
70     struct tc_mpr_addr *target, struct link_entry *source);
71 static void lq_etxff_copy_link_entry_lq_into_tc_edge_entry(
72     struct tc_edge_entry *target, struct link_entry *source);
73 static void lq_etxff_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
74     struct link_entry *source);
75
76 static void lq_etxff_clear_link_entry(struct link_entry *);
77
78 static int lq_etxff_serialize_hello_lq(unsigned char *buff,
79     struct lq_hello_neighbor *lq);
80 static int lq_etxff_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *lq);
81 static void lq_etxff_deserialize_hello_lq(uint8_t const ** curr,
82     struct lq_hello_neighbor *lq);
83 static void lq_etxff_deserialize_tc_lq(uint8_t const ** curr,
84     struct tc_edge_entry *lq);
85
86 static char *lq_etxff_print_link_entry_lq(struct link_entry *entry, char separator,
87     struct lqtextbuffer *buffer);
88 static char *lq_etxff_print_tc_edge_entry_lq(struct tc_edge_entry *ptr,
89     char separator, struct lqtextbuffer * buffer);
90 static char *lq_etxff_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer);
91
92 static struct olsr_cookie_info *default_lq_ff_timer_cookie = NULL;
93
94 /* etx lq plugin (freifunk fpm version) settings */
95 struct lq_handler lq_etxff_handler = {
96   &lq_etxff_initialize,
97   &lq_etxff_deinitialize,
98
99   &lq_etxff_calc_link_entry_cost,
100   &lq_etxff_calc_lq_hello_neighbor_cost,
101   &lq_etxff_calc_tc_mpr_addr_cost,
102   &lq_etxff_calc_tc_edge_entry_cost,
103
104   &lq_etxff_is_relevant_costchange,
105
106   &lq_etxff_packet_loss_handler,
107
108   &lq_etxff_memorize_foreign_hello,
109   &lq_etxff_copy_link_entry_lq_into_tc_mpr_addr,
110   &lq_etxff_copy_link_entry_lq_into_tc_edge_entry,
111   &lq_etxff_copy_link_lq_into_neighbor,
112
113   &lq_etxff_clear_link_entry,
114   NULL,
115   NULL,
116   NULL,
117
118   &lq_etxff_serialize_hello_lq,
119   &lq_etxff_serialize_tc_lq,
120   &lq_etxff_deserialize_hello_lq,
121   &lq_etxff_deserialize_tc_lq,
122
123   &lq_etxff_print_link_entry_lq,
124   &lq_etxff_print_tc_edge_entry_lq,
125   &lq_etxff_print_cost,
126
127   sizeof(struct lq_etxff_tc_edge),
128   sizeof(struct lq_etxff_tc_mpr_addr),
129   sizeof(struct lq_etxff_lq_hello_neighbor),
130   sizeof(struct lq_etxff_link_entry),
131
132   LQ_HELLO_MESSAGE,
133   LQ_TC_MESSAGE
134 };
135
136 static void lq_etxff_packet_parser(struct olsr *olsr, struct interface *in_if,
137     union olsr_ip_addr *from_addr) {
138   const union olsr_ip_addr *main_addr;
139   struct lq_etxff_link_entry *lnk;
140   uint32_t seq_diff;
141
142   /* Find main address */
143   main_addr = olsr_lookup_main_addr_by_alias(from_addr);
144
145   /* Loopup link entry */
146   lnk = (struct lq_etxff_link_entry *) lookup_link_entry(from_addr, main_addr,
147       in_if);
148   if (lnk == NULL) {
149     return;
150   }
151
152   if (lnk->last_seq_nr > olsr->olsr_seqno) {
153     seq_diff = (uint32_t) olsr->olsr_seqno + 65536 - lnk->last_seq_nr;
154   } else {
155     seq_diff = olsr->olsr_seqno - lnk->last_seq_nr;
156   }
157
158   /* Jump in sequence numbers ? */
159   if (seq_diff > 256) {
160     seq_diff = 1;
161   }
162
163   lnk->received[lnk->activePtr]++;
164   lnk->lost[lnk->activePtr] += (seq_diff - 1);
165
166   lnk->last_seq_nr = olsr->olsr_seqno;
167 }
168
169 static void lq_etxff_timer(void __attribute__((unused)) *context) {
170   struct link_entry *link;
171   OLSR_FOR_ALL_LINK_ENTRIES(link)
172 {    struct lq_etxff_link_entry *lq_link;
173     uint32_t ratio;
174     uint16_t i, received, lost;
175
176 #if !defined(NODEBUG) && defined(DEBUG)
177     struct ipaddr_str buf;
178     struct lqtextbuffer lqbuffer;
179 #endif
180
181     lq_link = (struct lq_etxff_link_entry *)link;
182
183 #if !defined(NODEBUG) && defined(DEBUG)
184     OLSR_PRINTF(3, "LQ-FF new entry for %s: rec: %d lost: %d",
185         olsr_ip_to_string(&buf, &link->neighbor_iface_addr),
186         lq_link->received[lq_link->activePtr], lq_link->lost[lq_link->activePtr]);
187 #endif
188
189     lq_link = (struct lq_etxff_link_entry *)link;
190
191     received = 0;
192     lost = 0;
193
194     /* enlarge window if still in quickstart phase */
195     if (lq_link->windowSize < LQ_FF_WINDOW) {
196       lq_link->windowSize++;
197     }
198     for (i=0; i < lq_link->windowSize; i++) {
199       received += lq_link->received[i];
200       lost += lq_link->lost[i];
201     }
202
203 #if !defined(NODEBUG) && defined(DEBUG)
204     OLSR_PRINTF(3, " total-rec: %d total-lost: %d", received, lost);
205 #endif
206     /* calculate link quality */
207     if (received + lost == 0) {
208       lq_link->lq.valueLq = 0;
209     }
210     else {
211       // start with link-loss-factor
212       ratio = link->loss_link_multiplier;
213
214       // calculate received/(received + loss) factor
215       ratio = ratio * received;
216       ratio = ratio / (received + lost);
217       ratio = (ratio * 255) >> 16;
218
219       lq_link->lq.valueLq = (uint8_t)(ratio);
220     }
221     link->linkcost = lq_etxff_calc_link_entry_cost(link);
222
223 #if !defined(NODEBUG) && defined(DEBUG)
224     OLSR_PRINTF(3, " linkcost: %s\n", lq_etxff_print_cost(link->linkcost, &lqbuffer));
225 #endif
226
227     // shift buffer
228     lq_link->activePtr = (lq_link->activePtr + 1) % LQ_FF_WINDOW;
229     lq_link->lost[lq_link->activePtr] = 0;
230     lq_link->received[lq_link->activePtr] = 0;
231   }OLSR_FOR_ALL_LINK_ENTRIES_END(link);
232 }
233
234 static struct timer_entry *lq_etxff_timer_struct = NULL;
235
236 static void lq_etxff_initialize(void) {
237   /* Some cookies for stats keeping */
238   olsr_packetparser_add_function(&lq_etxff_packet_parser);
239   default_lq_ff_timer_cookie = olsr_alloc_cookie("Default Freifunk LQ",
240       OLSR_COOKIE_TYPE_TIMER);
241   lq_etxff_timer_struct = olsr_start_timer(1000, 0, OLSR_TIMER_PERIODIC,
242       &lq_etxff_timer, NULL, default_lq_ff_timer_cookie->ci_id);
243 }
244
245 static void lq_etxff_deinitialize(void) {
246   olsr_stop_timer(lq_etxff_timer_struct);
247   olsr_packetparser_remove_function(&lq_etxff_packet_parser);
248 }
249
250 static olsr_linkcost lq_etxff_calc_linkcost(struct lq_etxff_linkquality *lq) {
251   olsr_linkcost cost;
252
253   if (lq->valueLq < (unsigned int) (255 * MINIMAL_USEFUL_LQ) || lq->valueNlq
254       < (unsigned int) (255 * MINIMAL_USEFUL_LQ)) {
255     return LINK_COST_BROKEN;
256   }
257
258   cost = 65536 * 255/(int)lq->valueLq * 255/(int)lq->valueNlq;
259
260   if (cost > LINK_COST_BROKEN)
261     return LINK_COST_BROKEN;
262   if (cost == 0)
263     return 1;
264   return cost;
265 }
266
267 static olsr_linkcost lq_etxff_calc_link_entry_cost(struct link_entry *link) {
268   struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *) link;
269
270   return lq_etxff_calc_linkcost(&lq_link->lq);
271 }
272
273 static olsr_linkcost lq_etxff_calc_lq_hello_neighbor_cost(
274     struct lq_hello_neighbor *neigh) {
275   struct lq_etxff_lq_hello_neighbor *lq_neigh =
276       (struct lq_etxff_lq_hello_neighbor *) neigh;
277
278   return lq_etxff_calc_linkcost(&lq_neigh->lq);
279 }
280
281 static olsr_linkcost lq_etxff_calc_tc_mpr_addr_cost(struct tc_mpr_addr *mpr) {
282   struct lq_etxff_tc_mpr_addr *lq_mpr = (struct lq_etxff_tc_mpr_addr *) mpr;
283
284   return lq_etxff_calc_linkcost(&lq_mpr->lq);
285 }
286
287 static olsr_linkcost lq_etxff_calc_tc_edge_entry_cost(struct tc_edge_entry *edge) {
288   struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *) edge;
289
290   return lq_etxff_calc_linkcost(&lq_edge->lq);
291 }
292
293 static bool lq_etxff_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2) {
294   if (c1 > c2) {
295     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
296   }
297   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
298 }
299
300 static olsr_linkcost lq_etxff_packet_loss_handler(struct link_entry *link,
301     bool loss __attribute__((unused))) {
302   return link->linkcost;
303 }
304
305 static void lq_etxff_memorize_foreign_hello(struct link_entry *target,
306     struct lq_hello_neighbor *source) {
307   struct lq_etxff_link_entry *lq_target = (struct lq_etxff_link_entry *) target;
308   struct lq_etxff_lq_hello_neighbor *lq_source =
309       (struct lq_etxff_lq_hello_neighbor *) source;
310
311   if (source) {
312     lq_target->lq.valueNlq = lq_source->lq.valueLq;
313   } else {
314     lq_target->lq.valueNlq = 0;
315   }
316
317 }
318
319 static void lq_etxff_copy_link_entry_lq_into_tc_mpr_addr(
320     struct tc_mpr_addr *target, struct link_entry *source) {
321   struct lq_etxff_tc_mpr_addr *lq_target = (struct lq_etxff_tc_mpr_addr *) target;
322   struct lq_etxff_link_entry *lq_source = (struct lq_etxff_link_entry *) source;
323
324   lq_target->lq = lq_source->lq;
325 }
326
327 static void lq_etxff_copy_link_entry_lq_into_tc_edge_entry(
328     struct tc_edge_entry *target, struct link_entry *source) {
329   struct lq_etxff_tc_edge *lq_target = (struct lq_etxff_tc_edge *) target;
330   struct lq_etxff_link_entry *lq_source = (struct lq_etxff_link_entry *) source;
331
332   lq_target->lq = lq_source->lq;
333 }
334
335 static void lq_etxff_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
336     struct link_entry *source) {
337   struct lq_etxff_lq_hello_neighbor *lq_target =
338       (struct lq_etxff_lq_hello_neighbor *) target;
339   struct lq_etxff_link_entry *lq_source = (struct lq_etxff_link_entry *) source;
340
341   lq_target->lq = lq_source->lq;
342 }
343
344 static void lq_etxff_clear_link_entry(struct link_entry *link) {
345   struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *) link;
346   int i;
347
348   lq_link->windowSize = LQ_FF_QUICKSTART_INIT;
349   for (i = 0; i < LQ_FF_WINDOW; i++) {
350     lq_link->lost[i] = 3;
351   }
352 }
353
354 static int lq_etxff_serialize_hello_lq(unsigned char *buff,
355     struct lq_hello_neighbor *neigh) {
356   struct lq_etxff_lq_hello_neighbor *lq_neigh =
357       (struct lq_etxff_lq_hello_neighbor *) neigh;
358
359   buff[0] = (unsigned char) lq_neigh->lq.valueLq;
360   buff[1] = (unsigned char) lq_neigh->lq.valueNlq;
361   buff[2] = (unsigned char) (0);
362   buff[3] = (unsigned char) (0);
363
364   return 4;
365 }
366 static int lq_etxff_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *mpr) {
367   struct lq_etxff_tc_mpr_addr *lq_mpr = (struct lq_etxff_tc_mpr_addr *) mpr;
368
369   buff[0] = (unsigned char) lq_mpr->lq.valueLq;
370   buff[1] = (unsigned char) lq_mpr->lq.valueNlq;
371   buff[2] = (unsigned char) (0);
372   buff[3] = (unsigned char) (0);
373
374   return 4;
375 }
376
377 static void lq_etxff_deserialize_hello_lq(uint8_t const ** curr,
378     struct lq_hello_neighbor *neigh) {
379   struct lq_etxff_lq_hello_neighbor *lq_neigh =
380       (struct lq_etxff_lq_hello_neighbor *) neigh;
381
382   pkt_get_u8(curr, &lq_neigh->lq.valueLq);
383   pkt_get_u8(curr, &lq_neigh->lq.valueNlq);
384   pkt_ignore_u16(curr);
385
386 }
387 static void lq_etxff_deserialize_tc_lq(uint8_t const ** curr,
388     struct tc_edge_entry *edge) {
389   struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *) edge;
390
391   pkt_get_u8(curr, &lq_edge->lq.valueLq);
392   pkt_get_u8(curr, &lq_edge->lq.valueNlq);
393   pkt_ignore_u16(curr);
394 }
395
396 static char *lq_etxff_print_lq(struct lq_etxff_linkquality *lq, char separator,
397     struct lqtextbuffer *buffer) {
398   int i = 0;
399
400   if (lq->valueLq == 255) {
401         strcpy(buffer->buf, "1.000");
402         i += 5;
403   }
404   else {
405     i = sprintf(buffer->buf, "0.%03d", (lq->valueLq * 1000)/255);
406   }
407   buffer->buf[i++] = separator;
408
409   if (lq->valueNlq == 255) {
410     strcpy(&buffer->buf[i], "1.000");
411   }
412   else {
413     sprintf(&buffer->buf[i], "0.%03d", (lq->valueNlq * 1000) / 255);
414   }
415   return buffer->buf;
416 }
417
418 static char *lq_etxff_print_link_entry_lq(struct link_entry *link, char separator,
419     struct lqtextbuffer *buffer) {
420   struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *) link;
421
422   return lq_etxff_print_lq(&lq_link->lq, separator, buffer);
423 }
424
425 static char *lq_etxff_print_tc_edge_entry_lq(struct tc_edge_entry *edge,
426     char separator, struct lqtextbuffer * buffer) {
427   struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *) edge;
428
429   return lq_etxff_print_lq(&lq_edge->lq, separator, buffer);
430 }
431
432 static char *lq_etxff_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer) {
433   // must calculate
434   uint32_t roundDown = cost >> 16;
435   uint32_t fraction = ((cost & 0xffff) * 1000) >> 16;
436
437   sprintf(buffer->buf, "%u.%03u", roundDown, fraction);
438   return buffer->buf;
439 }
440
441 /*
442  * Local Variables:
443  * c-basic-offset: 2
444  * indent-tabs-mode: nil
445  * End:
446  */