serialized LQ data is not always 4 bytes long, so we need a function to precalculate...
[olsrd.git] / lib / lq_rfc / src / lq_plugin_rfc.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 "plugin_util.h"
48 #include "olsr_logging.h"
49 #include "lq_plugin_rfc.h"
50
51 #define PLUGIN_DESCR      "RFC 3626 based hopcount metric. Does not work well, use ETX !"
52 #define PLUGIN_AUTHOR     "Henning Rogge"
53
54 #define DEF_USE_HYST            false
55 #define HYST_THRESHOLD_HIGH     0.8
56 #define HYST_THRESHOLD_LOW      0.3
57 #define HYST_SCALING            0.5
58
59 #define LQ_PLUGIN_LC_MULTIPLIER 1024
60
61 static int set_plugin_float(const char *, void *, set_plugin_parameter_addon);
62
63 static olsr_linkcost lq_rfc_calc_link_entry_cost(struct link_entry *);
64 static olsr_linkcost lq_rfc_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor *);
65 static olsr_linkcost lq_rfc_calc_tc_mpr_addr_cost(struct tc_mpr_addr *);
66 static olsr_linkcost lq_rfc_calc_tc_edge_entry_cost(struct tc_edge_entry *);
67
68 static bool lq_rfc_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2);
69
70 static olsr_linkcost lq_rfc_packet_loss_handler(struct link_entry *, bool);
71
72 static void lq_rfc_memorize_foreign_hello(struct link_entry *, struct lq_hello_neighbor *);
73 static void lq_rfc_copy_link_entry_lq_into_tc_mpr_addr(struct tc_mpr_addr *target, struct link_entry *source);
74 static void lq_rfc_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source);
75 static void lq_rfc_copy_link_lq_into_neighbor(struct lq_hello_neighbor *target, struct link_entry *source);
76
77 static int lq_rfc_serialize_hello_lq(unsigned char *buff, struct lq_hello_neighbor *lq);
78 static int lq_rfc_serialize_tc_lq(unsigned char *buff, struct tc_mpr_addr *lq);
79 static void lq_rfc_deserialize_hello_lq(uint8_t const **curr, struct lq_hello_neighbor *lq);
80 static void lq_rfc_deserialize_tc_lq(uint8_t const **curr, struct tc_edge_entry *lq);
81
82 static char *lq_rfc_print_link_entry_lq(struct link_entry *entry, char separator, struct lqtextbuffer *buffer);
83 static char *lq_rfc_print_tc_edge_entry_lq(struct tc_edge_entry *ptr, char separator, struct lqtextbuffer *buffer);
84 static char *lq_rfc_print_cost(olsr_linkcost cost, struct lqtextbuffer *buffer);
85
86 /* RFC "lq" handler (hopcount metric with hysteresis) */
87 struct lq_handler lq_rfc_handler = {
88   "rfc",
89
90   NULL,
91   NULL,
92
93   &lq_rfc_calc_link_entry_cost,
94   &lq_rfc_calc_lq_hello_neighbor_cost,
95   &lq_rfc_calc_tc_mpr_addr_cost,
96   &lq_rfc_calc_tc_edge_entry_cost,
97
98   &lq_rfc_is_relevant_costchange,
99
100   &lq_rfc_packet_loss_handler,
101
102   &lq_rfc_memorize_foreign_hello,
103   &lq_rfc_copy_link_entry_lq_into_tc_mpr_addr,
104   &lq_rfc_copy_link_entry_lq_into_tc_edge_entry,
105   &lq_rfc_copy_link_lq_into_neighbor,
106
107   NULL,
108   NULL,
109   NULL,
110   NULL,
111
112   &lq_rfc_serialize_hello_lq,
113   &lq_rfc_serialize_tc_lq,
114   &lq_rfc_deserialize_hello_lq,
115   &lq_rfc_deserialize_tc_lq,
116
117   &lq_rfc_print_link_entry_lq,
118   &lq_rfc_print_tc_edge_entry_lq,
119   &lq_rfc_print_cost,
120
121   sizeof(struct tc_edge_entry),
122   sizeof(struct tc_mpr_addr),
123   sizeof(struct lq_hello_neighbor),
124   sizeof(struct lq_rfc_link_entry),
125
126   HELLO_MESSAGE,
127   TC_MESSAGE,
128
129   0,0
130 };
131
132 static bool use_hysteresis = DEF_USE_HYST;
133 static float scaling = HYST_SCALING;
134 static float thr_high = HYST_THRESHOLD_HIGH;
135 static float thr_low = HYST_THRESHOLD_LOW;
136
137 static const struct olsrd_plugin_parameters plugin_parameters[] = {
138   {.name = "UseHysteresis",.set_plugin_parameter = &set_plugin_boolean,.data = &use_hysteresis},
139   {.name = "HystScaling",.set_plugin_parameter = &set_plugin_float,.data = &scaling},
140   {.name = "HystThrHigh",.set_plugin_parameter = &set_plugin_float,.data = &thr_high},
141   {.name = "HystThrLow",.set_plugin_parameter = &set_plugin_float,.data = &thr_low},
142 };
143
144 DEFINE_PLUGIN6(PLUGIN_DESCR, PLUGIN_AUTHOR, NULL, NULL, NULL, NULL, false, plugin_parameters)
145
146 static int
147 set_plugin_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused)))
148 {
149   if (data != NULL) {
150     sscanf(value, "%f", (float *)data);
151     OLSR_INFO(LOG_LQ_PLUGINS, "%s float %f\n", "Got", *(float *)data);
152   } else {
153     OLSR_INFO(LOG_LQ_PLUGINS, "%s float %s\n", "Ignored", value);
154   }
155   return 0;
156 }
157
158 static olsr_linkcost
159 lq_rfc_calc_link_entry_cost(struct link_entry __attribute__ ((unused)) * link)
160 {
161   return 1;
162 }
163
164 static olsr_linkcost
165 lq_rfc_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor __attribute__ ((unused)) * neigh)
166 {
167   return 1;
168 }
169
170 static olsr_linkcost
171 lq_rfc_calc_tc_mpr_addr_cost(struct tc_mpr_addr __attribute__ ((unused)) * mpr)
172 {
173   return 1;
174 }
175
176 static olsr_linkcost
177 lq_rfc_calc_tc_edge_entry_cost(struct tc_edge_entry __attribute__ ((unused)) * edge)
178 {
179   return 1;
180 }
181
182 static bool
183 lq_rfc_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2)
184 {
185   return c1 != c2;
186 }
187
188 static olsr_linkcost
189 lq_rfc_packet_loss_handler(struct link_entry *link, bool loss)
190 {
191   struct lq_rfc_link_entry *link_entry = (struct lq_rfc_link_entry *)link;
192
193   if (!use_hysteresis)
194     return 1;
195
196   link_entry->hysteresis *= (1 - scaling);
197   if (!loss) {
198     link_entry->hysteresis += scaling;
199   }
200
201   if (link_entry->active && link_entry->hysteresis < thr_low) {
202     link_entry->active = false;
203   } else if (!link_entry->active && link_entry->hysteresis > thr_high) {
204     link_entry->active = true;
205   }
206
207   return link_entry->active ? 1 : LINK_COST_BROKEN;
208 }
209
210 static void
211 lq_rfc_memorize_foreign_hello(struct link_entry __attribute__ ((unused)) * target,
212                               struct lq_hello_neighbor __attribute__ ((unused)) * source)
213 {
214 }
215
216 static void
217 lq_rfc_copy_link_entry_lq_into_tc_mpr_addr(struct tc_mpr_addr __attribute__ ((unused)) * target, struct link_entry
218                                            __attribute__ ((unused)) * source)
219 {
220 }
221
222 static void
223 lq_rfc_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry __attribute__ ((unused)) * target, struct link_entry
224                                              __attribute__ ((unused)) * source)
225 {
226 }
227
228 static void
229 lq_rfc_copy_link_lq_into_neighbor(struct lq_hello_neighbor __attribute__ ((unused)) * target,
230                                   struct link_entry __attribute__ ((unused)) * source)
231 {
232 }
233
234 static int
235 lq_rfc_serialize_hello_lq(unsigned char __attribute__ ((unused)) * buff, struct lq_hello_neighbor __attribute__ ((unused)) * neigh)
236 {
237   return 0;
238 }
239 static int
240 lq_rfc_serialize_tc_lq(unsigned char __attribute__ ((unused)) * buff, struct tc_mpr_addr __attribute__ ((unused)) * mpr)
241 {
242   return 0;
243 }
244
245 static void
246 lq_rfc_deserialize_hello_lq(uint8_t const __attribute__ ((unused)) ** curr,
247                             struct lq_hello_neighbor __attribute__ ((unused)) * neigh)
248 {
249 }
250
251 static void
252 lq_rfc_deserialize_tc_lq(uint8_t const __attribute__ ((unused)) ** curr, struct tc_edge_entry __attribute__ ((unused)) * edge)
253 {
254 }
255
256 static char *
257 lq_rfc_print_link_entry_lq(struct link_entry __attribute__ ((unused)) * link, char __attribute__ ((unused)) separator,
258                            struct lqtextbuffer *buffer)
259 {
260   strcpy(buffer->buf, "");
261   return buffer->buf;
262 }
263
264 static char *
265 lq_rfc_print_tc_edge_entry_lq(struct tc_edge_entry __attribute__ ((unused)) * edge,
266                               char __attribute__ ((unused)) separator, struct lqtextbuffer *buffer)
267 {
268   strcpy(buffer->buf, "");
269   return buffer->buf;
270 }
271
272 static char *
273 lq_rfc_print_cost(olsr_linkcost cost, struct lqtextbuffer *buffer)
274 {
275   sprintf(buffer->buf, "%d", cost);
276   return buffer->buf;
277 }
278
279 /*
280  * Local Variables:
281  * c-basic-offset: 2
282  * indent-tabs-mode: nil
283  * End:
284  */