Some cleanup and logging during startup
[olsrd.git] / lib / lq_etx_float / src / lq_plugin_etx_float.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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_float.h"
47
48 #define LQ_PLUGIN_LC_MULTIPLIER 1024
49
50 static void lq_etxfloat_initialize(void);
51 static void lq_etxfloat_deinitialize(void);
52
53 static olsr_linkcost lq_etxfloat_calc_link_entry_cost(struct link_entry *);
54 static olsr_linkcost lq_etxfloat_calc_lq_hello_neighbor_cost(
55     struct lq_hello_neighbor *);
56 static olsr_linkcost lq_etxfloat_calc_tc_mpr_addr_cost(struct tc_mpr_addr *);
57 static olsr_linkcost lq_etxfloat_calc_tc_edge_entry_cost(struct tc_edge_entry *);
58
59 static bool lq_etxfloat_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2);
60
61 static olsr_linkcost lq_etxfloat_packet_loss_handler(struct link_entry *, bool);
62
63 static void lq_etxfloat_memorize_foreign_hello(struct link_entry *,
64     struct lq_hello_neighbor *);
65 static void lq_etxfloat_copy_link_entry_lq_into_tc_mpr_addr(
66     struct tc_mpr_addr *target, struct link_entry *source);
67 static void lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry(
68     struct tc_edge_entry *target, struct link_entry *source);
69 static void lq_etxfloat_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
70     struct link_entry *source);
71
72 static int lq_etxfloat_serialize_hello_lq(unsigned char *buff,
73     struct lq_hello_neighbor *lq);
74 static int lq_etxfloat_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *lq);
75 static void lq_etxfloat_deserialize_hello_lq(uint8_t const ** curr,
76     struct lq_hello_neighbor *lq);
77 static void lq_etxfloat_deserialize_tc_lq(uint8_t const ** curr,
78     struct tc_edge_entry *lq);
79
80 static char *lq_etxfloat_print_link_entry_lq(struct link_entry *entry, char separator,
81     struct lqtextbuffer *buffer);
82 static char *lq_etxfloat_print_tc_edge_entry_lq(struct tc_edge_entry *ptr,
83     char separator, struct lqtextbuffer * buffer);
84 static char *lq_etxfloat_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer);
85
86 /* etx lq plugin (freifunk fpm version) settings */
87 struct lq_handler lq_etxfloat_handler = {
88   "etx (float)",
89
90   &lq_etxfloat_initialize,
91   &lq_etxfloat_deinitialize,
92
93   &lq_etxfloat_calc_link_entry_cost,
94   &lq_etxfloat_calc_lq_hello_neighbor_cost,
95   &lq_etxfloat_calc_tc_mpr_addr_cost,
96   &lq_etxfloat_calc_tc_edge_entry_cost,
97
98   &lq_etxfloat_is_relevant_costchange,
99
100   &lq_etxfloat_packet_loss_handler,
101
102   &lq_etxfloat_memorize_foreign_hello,
103   &lq_etxfloat_copy_link_entry_lq_into_tc_mpr_addr,
104   &lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry,
105   &lq_etxfloat_copy_link_lq_into_neighbor,
106
107   NULL,
108   NULL,
109   NULL,
110   NULL,
111
112   &lq_etxfloat_serialize_hello_lq,
113   &lq_etxfloat_serialize_tc_lq,
114   &lq_etxfloat_deserialize_hello_lq,
115   &lq_etxfloat_deserialize_tc_lq,
116
117   &lq_etxfloat_print_link_entry_lq,
118   &lq_etxfloat_print_tc_edge_entry_lq,
119   &lq_etxfloat_print_cost,
120
121   sizeof(struct lq_etxfloat_tc_edge),
122   sizeof(struct lq_etxfloat_tc_mpr_addr),
123   sizeof(struct lq_etxfloat_lq_hello_neighbor),
124   sizeof(struct lq_etxfloat_link_entry),
125
126   LQ_HELLO_MESSAGE,
127   LQ_TC_MESSAGE
128 };
129
130 static void lq_etxfloat_initialize(void) {
131 }
132
133 static void lq_etxfloat_deinitialize(void) {
134 }
135
136 static olsr_linkcost lq_etxfloat_calc_linkcost(struct lq_etxfloat_linkquality *lq) {
137   olsr_linkcost cost;
138
139   if (lq->valueLq < MINIMAL_USEFUL_LQ || lq->valueNlq < MINIMAL_USEFUL_LQ) {
140     return LINK_COST_BROKEN;
141   }
142
143   cost = (olsr_linkcost)(1.0/(lq->valueLq * lq->valueNlq) * LQ_PLUGIN_LC_MULTIPLIER);
144
145   if (cost > LINK_COST_BROKEN)
146     return LINK_COST_BROKEN;
147   if (cost == 0) {
148     return 1;
149   }
150   return cost;
151 }
152
153 static olsr_linkcost lq_etxfloat_calc_link_entry_cost(struct link_entry *link) {
154   struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *) link;
155
156   return lq_etxfloat_calc_linkcost(&lq_link->lq);
157 }
158
159 static olsr_linkcost lq_etxfloat_calc_lq_hello_neighbor_cost(
160     struct lq_hello_neighbor *neigh) {
161   struct lq_etxfloat_lq_hello_neighbor *lq_neigh =
162       (struct lq_etxfloat_lq_hello_neighbor *) neigh;
163
164   return lq_etxfloat_calc_linkcost(&lq_neigh->lq);
165 }
166
167 static olsr_linkcost lq_etxfloat_calc_tc_mpr_addr_cost(struct tc_mpr_addr *mpr) {
168   struct lq_etxfloat_tc_mpr_addr *lq_mpr = (struct lq_etxfloat_tc_mpr_addr *) mpr;
169
170   return lq_etxfloat_calc_linkcost(&lq_mpr->lq);
171 }
172
173 static olsr_linkcost lq_etxfloat_calc_tc_edge_entry_cost(struct tc_edge_entry *edge) {
174   struct lq_etxfloat_tc_edge *lq_edge = (struct lq_etxfloat_tc_edge *) edge;
175
176   return lq_etxfloat_calc_linkcost(&lq_edge->lq);
177 }
178
179 static bool lq_etxfloat_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2) {
180   if (c1 > c2) {
181     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
182   }
183   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
184 }
185
186 static olsr_linkcost lq_etxfloat_packet_loss_handler(struct link_entry *link,
187     bool loss) {
188   struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
189
190   float alpha = lq_aging;
191
192   if (lq_link->quickstart < LQ_QUICKSTART_STEPS) {
193     alpha = LQ_QUICKSTART_AGING; /* fast enough to get the LQ value within 6 Hellos up to 0.9 */
194     lq_link->quickstart++;
195   }
196   // exponential moving average
197   lq_link->lq.valueLq *= (1 - alpha);
198   if (!loss) {
199     lq_link->lq.valueLq += (alpha * link->loss_link_multiplier / 65536);
200   }
201   return lq_etxfloat_calc_linkcost(&lq_link->lq);
202 }
203
204 static void lq_etxfloat_memorize_foreign_hello(struct link_entry *target,
205     struct lq_hello_neighbor *source) {
206   struct lq_etxfloat_link_entry *lq_target = (struct lq_etxfloat_link_entry *) target;
207   struct lq_etxfloat_lq_hello_neighbor *lq_source =
208       (struct lq_etxfloat_lq_hello_neighbor *) source;
209
210   if (source) {
211     lq_target->lq.valueNlq = lq_source->lq.valueLq;
212   } else {
213     lq_target->lq.valueNlq = 0;
214   }
215
216 }
217
218 static void lq_etxfloat_copy_link_entry_lq_into_tc_mpr_addr(
219     struct tc_mpr_addr *target, struct link_entry *source) {
220   struct lq_etxfloat_tc_mpr_addr *lq_target = (struct lq_etxfloat_tc_mpr_addr *) target;
221   struct lq_etxfloat_link_entry *lq_source = (struct lq_etxfloat_link_entry *) source;
222
223   lq_target->lq = lq_source->lq;
224 }
225
226 static void lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry(
227     struct tc_edge_entry *target, struct link_entry *source) {
228   struct lq_etxfloat_tc_edge *lq_target = (struct lq_etxfloat_tc_edge *) target;
229   struct lq_etxfloat_link_entry *lq_source = (struct lq_etxfloat_link_entry *) source;
230
231   lq_target->lq = lq_source->lq;
232 }
233
234 static void lq_etxfloat_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target,
235     struct link_entry *source) {
236   struct lq_etxfloat_lq_hello_neighbor *lq_target =
237       (struct lq_etxfloat_lq_hello_neighbor *) target;
238   struct lq_etxfloat_link_entry *lq_source = (struct lq_etxfloat_link_entry *) source;
239
240   lq_target->lq = lq_source->lq;
241 }
242
243 static int lq_etxfloat_serialize_hello_lq(unsigned char *buff,
244     struct lq_hello_neighbor *neigh) {
245   struct lq_etxfloat_lq_hello_neighbor *lq_neigh =
246       (struct lq_etxfloat_lq_hello_neighbor *) neigh;
247
248   buff[0] = (unsigned char) (lq_neigh->lq.valueLq * 255);
249   buff[1] = (unsigned char) (lq_neigh->lq.valueNlq * 255);
250   buff[2] = (unsigned char) (0);
251   buff[3] = (unsigned char) (0);
252
253   return 4;
254 }
255 static int lq_etxfloat_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *mpr) {
256   struct lq_etxfloat_tc_mpr_addr *lq_mpr = (struct lq_etxfloat_tc_mpr_addr *) mpr;
257
258   buff[0] = (unsigned char) (lq_mpr->lq.valueLq * 255);
259   buff[1] = (unsigned char) (lq_mpr->lq.valueNlq * 255);
260   buff[2] = (unsigned char) (0);
261   buff[3] = (unsigned char) (0);
262
263   return 4;
264 }
265
266 static void lq_etxfloat_deserialize_hello_lq(uint8_t const ** curr,
267     struct lq_hello_neighbor *neigh) {
268   struct lq_etxfloat_lq_hello_neighbor *lq_neigh =
269       (struct lq_etxfloat_lq_hello_neighbor *) neigh;
270
271   uint8_t lq_value, nlq_value;
272
273   pkt_get_u8(curr, &lq_value);
274   pkt_get_u8(curr, &nlq_value);
275   pkt_ignore_u16(curr);
276
277   lq_neigh->lq.valueLq = (float)lq_value / 255.0;
278   lq_neigh->lq.valueNlq = (float)nlq_value / 255.0;
279 }
280
281 static void lq_etxfloat_deserialize_tc_lq(uint8_t const ** curr,
282     struct tc_edge_entry *edge) {
283   struct lq_etxfloat_tc_edge *lq_edge = (struct lq_etxfloat_tc_edge *) edge;
284
285   uint8_t lq_value, nlq_value;
286
287   pkt_get_u8(curr, &lq_value);
288   pkt_get_u8(curr, &nlq_value);
289   pkt_ignore_u16(curr);
290
291   lq_edge->lq.valueLq = (float)lq_value / 255.0;
292   lq_edge->lq.valueNlq = (float)nlq_value / 255.0;
293 }
294
295 static char *lq_etxfloat_print_lq(struct lq_etxfloat_linkquality *lq, char separator,
296     struct lqtextbuffer *buffer) {
297   snprintf(buffer->buf, sizeof(struct lqtextbuffer), "%2.3f%c%2.3f",
298       lq->valueLq,
299       separator,
300       lq->valueNlq);
301   return buffer->buf;
302 }
303
304 static char *lq_etxfloat_print_link_entry_lq(struct link_entry *link, char separator,
305     struct lqtextbuffer *buffer) {
306   struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *) link;
307
308   return lq_etxfloat_print_lq(&lq_link->lq, separator, buffer);
309 }
310
311 static char *lq_etxfloat_print_tc_edge_entry_lq(struct tc_edge_entry *edge,
312     char separator, struct lqtextbuffer * buffer) {
313   struct lq_etxfloat_tc_edge *lq_edge = (struct lq_etxfloat_tc_edge *) edge;
314
315   return lq_etxfloat_print_lq(&lq_edge->lq, separator, buffer);
316 }
317
318 static char *lq_etxfloat_print_cost(olsr_linkcost cost, struct lqtextbuffer * buffer) {
319   // must calculate
320   snprintf(buffer->buf, sizeof(struct lqtextbuffer), "%2.3f", ((float)cost)/LQ_PLUGIN_LC_MULTIPLIER );
321   return buffer->buf;
322 }
323
324 /*
325  * Local Variables:
326  * c-basic-offset: 2
327  * indent-tabs-mode: nil
328  * End:
329  */