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