Added some de-initializing funcs to plugins, lq_plugins, netfilter, parser
[olsrd.git] / src / lq_plugin_etx_fpm.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 "olsr_spf.h"
44 #include "lq_packet.h"
45 #include "olsr.h"
46 #include "lq_plugin_etx_fpm.h"
47
48 #define LQ_FPM_INTERNAL_MULTIPLIER 65535
49 #define LQ_FPM_LINKCOST_MULTIPLIER 65535
50
51 static void lq_etxfpm_initialize(void);
52 static void lq_etxfpm_deinitialize(void);
53
54 static olsr_linkcost lq_etxfpm_calc_link_entry_cost(struct link_entry *);
55 static olsr_linkcost lq_etxfpm_calc_lq_hello_neighbor_cost(
56     struct lq_hello_neighbor *);
57 static olsr_linkcost lq_etxfpm_calc_tc_mpr_addr_cost(struct tc_mpr_addr *);
58 static olsr_linkcost lq_etxfpm_calc_tc_edge_entry_cost(struct tc_edge_entry *);
59
60 static bool lq_etxfpm_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2);
61
62 static olsr_linkcost lq_etxfpm_packet_loss_handler(struct link_entry *, bool);
63
64 static void lq_etxfpm_memorize_foreign_hello(struct link_entry *,
65     struct lq_hello_neighbor *);
66 static void lq_etxfpm_copy_link_entry_lq_into_tc_mpr_addr(
67     struct tc_mpr_addr *target, struct link_entry *source);
68 static void lq_etxfpm_copy_link_entry_lq_into_tc_edge_entry(
69     struct tc_edge_entry *target, struct link_entry *source);
70 static void lq_etxfpm_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
71     struct link_entry *source);
72
73 static int lq_etxfpm_serialize_hello_lq(unsigned char *buff,
74     struct lq_hello_neighbor *lq);
75 static int lq_etxfpm_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *lq);
76 static void lq_etxfpm_deserialize_hello_lq(uint8_t const ** curr,
77     struct lq_hello_neighbor *lq);
78 static void lq_etxfpm_deserialize_tc_lq(uint8_t const ** curr,
79     struct tc_edge_entry *lq);
80
81 static char *lq_etxfpm_print_link_entry_lq(struct link_entry *entry, char separator,
82     struct lqtextbuffer *buffer);
83 static char *lq_etxfpm_print_tc_edge_entry_lq(struct tc_edge_entry *ptr,
84     char separator, struct lqtextbuffer * buffer);
85 static char *lq_etxfpm_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer);
86
87 /* etx lq plugin (freifunk fpm version) settings */
88 struct lq_handler lq_etxfpm_handler = {
89   &lq_etxfpm_initialize,
90   &lq_etxfpm_deinitialize,
91
92   &lq_etxfpm_calc_link_entry_cost,
93   &lq_etxfpm_calc_lq_hello_neighbor_cost,
94   &lq_etxfpm_calc_tc_mpr_addr_cost,
95   &lq_etxfpm_calc_tc_edge_entry_cost,
96
97   &lq_etxfpm_is_relevant_costchange,
98
99   &lq_etxfpm_packet_loss_handler,
100
101   &lq_etxfpm_memorize_foreign_hello,
102   &lq_etxfpm_copy_link_entry_lq_into_tc_mpr_addr,
103   &lq_etxfpm_copy_link_entry_lq_into_tc_edge_entry,
104   &lq_etxfpm_copy_link_lq_into_neighbor,
105
106   NULL,
107   NULL,
108   NULL,
109   NULL,
110
111   &lq_etxfpm_serialize_hello_lq,
112   &lq_etxfpm_serialize_tc_lq,
113   &lq_etxfpm_deserialize_hello_lq,
114   &lq_etxfpm_deserialize_tc_lq,
115
116   &lq_etxfpm_print_link_entry_lq,
117   &lq_etxfpm_print_tc_edge_entry_lq,
118   &lq_etxfpm_print_cost,
119
120   sizeof(struct lq_etxfpm_tc_edge),
121   sizeof(struct lq_etxfpm_tc_mpr_addr),
122   sizeof(struct lq_etxfpm_lq_hello_neighbor),
123   sizeof(struct lq_etxfpm_link_entry),
124
125   LQ_HELLO_MESSAGE,
126   LQ_TC_MESSAGE
127 };
128
129 static uint32_t aging_factor_new, aging_factor_old;
130 static uint32_t aging_quickstart_new, aging_quickstart_old;
131
132 static void lq_etxfpm_initialize(void) {
133   aging_factor_new = (uint32_t)(olsr_cnf->lq_aging * LQ_FPM_INTERNAL_MULTIPLIER);
134   aging_factor_old = LQ_FPM_INTERNAL_MULTIPLIER - aging_factor_new;
135
136   aging_quickstart_new = (uint32_t)(LQ_QUICKSTART_AGING * LQ_FPM_INTERNAL_MULTIPLIER);
137   aging_quickstart_old = LQ_FPM_INTERNAL_MULTIPLIER - aging_quickstart_new;
138 }
139
140 static void lq_etxfpm_deinitialize(void) {
141 }
142
143 static olsr_linkcost lq_etxfpm_calc_linkcost(struct lq_etxfpm_linkquality *lq) {
144   olsr_linkcost cost;
145
146   if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
147     return LINK_COST_BROKEN;
148   }
149
150   cost = LQ_FPM_LINKCOST_MULTIPLIER * 255/(int)lq->valueLq * 255/(int)lq->valueNlq;
151
152   if (cost > LINK_COST_BROKEN)
153     return LINK_COST_BROKEN;
154   if (cost == 0)
155     return 1;
156   return cost;
157 }
158
159 static olsr_linkcost lq_etxfpm_calc_link_entry_cost(struct link_entry *link) {
160   struct lq_etxfpm_link_entry *lq_link = (struct lq_etxfpm_link_entry *) link;
161
162   return lq_etxfpm_calc_linkcost(&lq_link->lq);
163 }
164
165 static olsr_linkcost lq_etxfpm_calc_lq_hello_neighbor_cost(
166     struct lq_hello_neighbor *neigh) {
167   struct lq_etxfpm_lq_hello_neighbor *lq_neigh =
168       (struct lq_etxfpm_lq_hello_neighbor *) neigh;
169
170   return lq_etxfpm_calc_linkcost(&lq_neigh->lq);
171 }
172
173 static olsr_linkcost lq_etxfpm_calc_tc_mpr_addr_cost(struct tc_mpr_addr *mpr) {
174   struct lq_etxfpm_tc_mpr_addr *lq_mpr = (struct lq_etxfpm_tc_mpr_addr *) mpr;
175
176   return lq_etxfpm_calc_linkcost(&lq_mpr->lq);
177 }
178
179 static olsr_linkcost lq_etxfpm_calc_tc_edge_entry_cost(struct tc_edge_entry *edge) {
180   struct lq_etxfpm_tc_edge *lq_edge = (struct lq_etxfpm_tc_edge *) edge;
181
182   return lq_etxfpm_calc_linkcost(&lq_edge->lq);
183 }
184
185 static bool lq_etxfpm_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2) {
186   if (c1 > c2) {
187     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
188   }
189   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
190 }
191
192 static olsr_linkcost lq_etxfpm_packet_loss_handler(struct link_entry *link,
193     bool loss) {
194   struct lq_etxfpm_link_entry *lq_link = (struct lq_etxfpm_link_entry *)link;
195
196   uint32_t alpha_old = aging_factor_old;
197   uint32_t alpha_new = aging_factor_new;
198
199   uint32_t value;
200   // fpm link_loss_factor = fpmidiv(itofpm(link->loss_link_multiplier), 65536);
201
202   if (lq_link->quickstart < LQ_QUICKSTART_STEPS) {
203     alpha_new = aging_quickstart_new;
204     alpha_old = aging_quickstart_old;
205     lq_link->quickstart++;
206   }
207
208   // exponential moving average
209   value = (uint32_t)(lq_link->lq.valueLq) * LQ_FPM_INTERNAL_MULTIPLIER / 255;
210
211   value = (value * alpha_old + LQ_FPM_INTERNAL_MULTIPLIER-1) / LQ_FPM_INTERNAL_MULTIPLIER;
212
213   if (!loss) {
214     uint32_t ratio;
215
216     ratio = (alpha_new * link->loss_link_multiplier + LINK_LOSS_MULTIPLIER-1) / LINK_LOSS_MULTIPLIER;
217     value += ratio;
218   }
219   lq_link->lq.valueLq = (value * 255 + LQ_FPM_INTERNAL_MULTIPLIER-1) / LQ_FPM_INTERNAL_MULTIPLIER;
220
221   return lq_etxfpm_calc_linkcost(&lq_link->lq);
222 }
223
224 static void lq_etxfpm_memorize_foreign_hello(struct link_entry *target,
225     struct lq_hello_neighbor *source) {
226   struct lq_etxfpm_link_entry *lq_target = (struct lq_etxfpm_link_entry *) target;
227   struct lq_etxfpm_lq_hello_neighbor *lq_source =
228       (struct lq_etxfpm_lq_hello_neighbor *) source;
229
230   if (source) {
231     lq_target->lq.valueNlq = lq_source->lq.valueLq;
232   } else {
233     lq_target->lq.valueNlq = 0;
234   }
235
236 }
237
238 static void lq_etxfpm_copy_link_entry_lq_into_tc_mpr_addr(
239     struct tc_mpr_addr *target, struct link_entry *source) {
240   struct lq_etxfpm_tc_mpr_addr *lq_target = (struct lq_etxfpm_tc_mpr_addr *) target;
241   struct lq_etxfpm_link_entry *lq_source = (struct lq_etxfpm_link_entry *) source;
242
243   lq_target->lq = lq_source->lq;
244 }
245
246 static void lq_etxfpm_copy_link_entry_lq_into_tc_edge_entry(
247     struct tc_edge_entry *target, struct link_entry *source) {
248   struct lq_etxfpm_tc_edge *lq_target = (struct lq_etxfpm_tc_edge *) target;
249   struct lq_etxfpm_link_entry *lq_source = (struct lq_etxfpm_link_entry *) source;
250
251   lq_target->lq = lq_source->lq;
252 }
253
254 static void lq_etxfpm_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
255     struct link_entry *source) {
256   struct lq_etxfpm_lq_hello_neighbor *lq_target =
257       (struct lq_etxfpm_lq_hello_neighbor *) target;
258   struct lq_etxfpm_link_entry *lq_source = (struct lq_etxfpm_link_entry *) source;
259
260   lq_target->lq = lq_source->lq;
261 }
262
263 static int lq_etxfpm_serialize_hello_lq(unsigned char *buff,
264     struct lq_hello_neighbor *neigh) {
265   struct lq_etxfpm_lq_hello_neighbor *lq_neigh =
266       (struct lq_etxfpm_lq_hello_neighbor *) neigh;
267
268   buff[0] = (unsigned char) lq_neigh->lq.valueLq;
269   buff[1] = (unsigned char) lq_neigh->lq.valueNlq;
270   buff[2] = (unsigned char) (0);
271   buff[3] = (unsigned char) (0);
272
273   return 4;
274 }
275 static int lq_etxfpm_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *mpr) {
276   struct lq_etxfpm_tc_mpr_addr *lq_mpr = (struct lq_etxfpm_tc_mpr_addr *) mpr;
277
278   buff[0] = (unsigned char) lq_mpr->lq.valueLq;
279   buff[1] = (unsigned char) lq_mpr->lq.valueNlq;
280   buff[2] = (unsigned char) (0);
281   buff[3] = (unsigned char) (0);
282
283   return 4;
284 }
285
286 static void lq_etxfpm_deserialize_hello_lq(uint8_t const ** curr,
287     struct lq_hello_neighbor *neigh) {
288   struct lq_etxfpm_lq_hello_neighbor *lq_neigh =
289       (struct lq_etxfpm_lq_hello_neighbor *) neigh;
290
291   pkt_get_u8(curr, &lq_neigh->lq.valueLq);
292   pkt_get_u8(curr, &lq_neigh->lq.valueNlq);
293   pkt_ignore_u16(curr);
294
295 }
296 static void lq_etxfpm_deserialize_tc_lq(uint8_t const ** curr,
297     struct tc_edge_entry *edge) {
298   struct lq_etxfpm_tc_edge *lq_edge = (struct lq_etxfpm_tc_edge *) edge;
299
300   pkt_get_u8(curr, &lq_edge->lq.valueLq);
301   pkt_get_u8(curr, &lq_edge->lq.valueNlq);
302   pkt_ignore_u16(curr);
303 }
304
305 static char *lq_etxfpm_print_lq(struct lq_etxfpm_linkquality *lq, char separator,
306     struct lqtextbuffer *buffer) {
307   int i = 0;
308
309   if (lq->valueLq == 255) {
310     strcpy(buffer->buf, "1.000");
311     i += 5;
312   } else {
313     i = sprintf(buffer->buf, "0.%03d", (lq->valueLq * 1000) / 255);
314   }
315   buffer->buf[i++] = separator;
316
317   if (lq->valueNlq == 255) {
318     strcpy(&buffer->buf[i], "1.000");
319   } else {
320     sprintf(&buffer->buf[i], "0.%03d", (lq->valueNlq * 1000) / 255);
321   }
322   return buffer->buf;
323 }
324
325 static char *lq_etxfpm_print_link_entry_lq(struct link_entry *link, char separator,
326     struct lqtextbuffer *buffer) {
327   struct lq_etxfpm_link_entry *lq_link = (struct lq_etxfpm_link_entry *) link;
328
329   return lq_etxfpm_print_lq(&lq_link->lq, separator, buffer);
330 }
331
332 static char *lq_etxfpm_print_tc_edge_entry_lq(struct tc_edge_entry *edge,
333     char separator, struct lqtextbuffer * buffer) {
334   struct lq_etxfpm_tc_edge *lq_edge = (struct lq_etxfpm_tc_edge *) edge;
335
336   return lq_etxfpm_print_lq(&lq_edge->lq, separator, buffer);
337 }
338
339 static char *lq_etxfpm_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer) {
340   // must calculate
341   uint32_t roundDown = cost >> 16;
342   uint32_t fraction = ((cost & 0xffff) * 1000) >> 16;
343
344   sprintf(buffer->buf, "%u.%03u", roundDown, fraction);
345   return buffer->buf;
346 }
347
348 /*
349  * Local Variables:
350  * c-basic-offset: 2
351  * indent-tabs-mode: nil
352  * End:
353  */