* killed lots of #ifdef ... #endif which make the source quite unreadable
[olsrd.git] / src / lq_plugin_default_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 "packet.h"
47 #include "olsr.h"
48 #include "lq_plugin_default_ff.h"
49 #include "parser.h"
50 #include "fpm.h"
51 #include "mid_set.h"
52 #include "scheduler.h"
53
54 /* etx lq plugin (freifunk fpm version) settings */
55 struct lq_handler lq_etx_ff_handler = {
56     &default_lq_initialize_ff,
57     &default_lq_calc_cost_ff,
58     &default_lq_calc_cost_ff,
59
60     &default_lq_is_relevant_costchange_ff,
61     &default_lq_packet_loss_worker_ff,
62
63     &default_lq_memorize_foreign_hello_ff,
64     &default_lq_copy_link2tc_ff,
65     &default_lq_clear_ff_hello,
66     &default_lq_clear_ff,
67
68     &default_lq_serialize_hello_lq_pair_ff,
69     &default_lq_serialize_tc_lq_pair_ff,
70     &default_lq_deserialize_hello_lq_pair_ff,
71     &default_lq_deserialize_tc_lq_pair_ff,
72
73     &default_lq_print_ff,
74     &default_lq_print_ff,
75     &default_lq_print_cost_ff,
76
77     sizeof(struct default_lq_ff_hello),
78     sizeof(struct default_lq_ff)
79 };
80
81 static void default_lq_parser_ff(struct olsr *olsr, struct interface *in_if, union olsr_ip_addr *from_addr) {
82   const union olsr_ip_addr *main_addr;
83   struct link_entry *lnk;
84   struct default_lq_ff_hello *lq;
85   olsr_u32_t seq_diff;
86
87   /* Find main address */
88   main_addr = mid_lookup_main_addr(from_addr);
89
90   /* Loopup link entry */
91   lnk = lookup_link_entry(from_addr, main_addr, in_if);
92   if (lnk == NULL) {
93     return;
94   }
95
96   lq = (struct default_lq_ff_hello *)lnk->linkquality;
97
98   if (lq->last_seq_nr > olsr->olsr_seqno) {
99     seq_diff = (olsr_u32_t)olsr->olsr_seqno + 65536 - lq->last_seq_nr;
100   } else {
101     seq_diff = olsr->olsr_seqno - lq->last_seq_nr;
102   }
103
104   /* Jump in sequence numbers ? */
105   if (seq_diff > 256) {
106     seq_diff = 1;
107   }
108
109   lq->received[lq->activePtr]++;
110   lq->lost[lq->activePtr] += (seq_diff - 1);
111
112   lq->last_seq_nr = olsr->olsr_seqno;
113 }
114
115 static void default_lq_ff_timer(void __attribute__((unused)) *context) {
116   struct link_entry *link;
117   OLSR_FOR_ALL_LINK_ENTRIES(link) {
118     struct default_lq_ff_hello *tlq = (struct default_lq_ff_hello *)link->linkquality;
119     fpm ratio;
120     olsr_u16_t i, received, lost;
121
122     received = 0;
123     lost = 0;
124
125     /* enlarge window if still in quickstart phase */
126     if (tlq->windowSize < LQ_FF_WINDOW) {
127       tlq->windowSize++;
128     }
129     for (i=0; i < tlq->windowSize; i++) {
130       received += tlq->received[i];
131       lost += tlq->lost[i];
132     }
133
134     /* calculate link quality */
135     if (received + lost == 0) {
136       tlq->lq.valueLq = 0;
137     }
138     else {
139       // start with link-loss-factor
140       ratio = fpmidiv(itofpm(link->loss_link_multiplier), 65536);
141
142       // calculate received/(received + loss) factor
143       ratio = fpmmuli(ratio, (int)received);
144       ratio = fpmidiv(ratio, (int)(received + lost));
145       ratio = fpmmuli(ratio, 255);
146
147       tlq->lq.valueLq = (olsr_u8_t)(fpmtoi(ratio));
148     }
149     link->linkcost = default_lq_calc_cost_ff(tlq);
150
151     // shift buffer
152     tlq->activePtr = (tlq->activePtr + 1) % LQ_FF_WINDOW;
153     tlq->lost[tlq->activePtr] = 0;
154     tlq->received[tlq->activePtr] = 0;
155   }OLSR_FOR_ALL_LINK_ENTRIES_END(link);
156 }
157
158 void default_lq_initialize_ff(void) {
159   olsr_packetparser_add_function(&default_lq_parser_ff);
160   olsr_start_timer(1000, 0, OLSR_TIMER_PERIODIC, &default_lq_ff_timer, NULL, 0);
161 }
162
163 olsr_linkcost default_lq_calc_cost_ff(const void *ptr) {
164   const struct default_lq_ff *lq = ptr;
165   olsr_linkcost cost;
166
167   if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
168     return LINK_COST_BROKEN;
169   }
170
171   cost = fpmidiv(itofpm(255 * 255), (int)lq->valueLq * (int)lq->valueNlq);
172
173   if (cost > LINK_COST_BROKEN)
174     return LINK_COST_BROKEN;
175   if (cost == 0)
176     return 1;
177   return cost;
178 }
179
180 int default_lq_serialize_hello_lq_pair_ff(unsigned char *buff, void *ptr) {
181   struct default_lq_ff *lq = ptr;
182
183   buff[0] = (unsigned char)lq->valueLq;
184   buff[1] = (unsigned char)lq->valueNlq;
185   buff[2] = (unsigned char)(0);
186   buff[3] = (unsigned char)(0);
187
188   return 4;
189 }
190
191 void default_lq_deserialize_hello_lq_pair_ff(const olsr_u8_t **curr, void *ptr) {
192   struct default_lq_ff *lq = ptr;
193
194   pkt_get_u8(curr, &lq->valueLq);
195   pkt_get_u8(curr, &lq->valueNlq);
196   pkt_ignore_u16(curr);
197 }
198
199 olsr_bool default_lq_is_relevant_costchange_ff(olsr_linkcost c1, olsr_linkcost c2) {
200   if (c1 > c2) {
201     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
202   }
203   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
204 }
205
206 int default_lq_serialize_tc_lq_pair_ff(unsigned char *buff, void *ptr) {
207   struct default_lq_ff *lq = ptr;
208
209   buff[0] = (unsigned char)lq->valueLq;
210   buff[1] = (unsigned char)lq->valueNlq;
211   buff[2] = (unsigned char)(0);
212   buff[3] = (unsigned char)(0);
213
214   return 4;
215 }
216
217 void default_lq_deserialize_tc_lq_pair_ff(const olsr_u8_t **curr, void *ptr) {
218   struct default_lq_ff *lq = ptr;
219
220   pkt_get_u8(curr, &lq->valueLq);
221   pkt_get_u8(curr, &lq->valueNlq);
222   pkt_ignore_u16(curr);
223 }
224
225 olsr_linkcost default_lq_packet_loss_worker_ff(struct link_entry __attribute__((unused)) *link, void __attribute__((unused)) *ptr, olsr_bool __attribute__((unused)) lost) {
226   return link->linkcost;
227 }
228
229 void default_lq_memorize_foreign_hello_ff(void *ptrLocal, void *ptrForeign) {
230   struct default_lq_ff *local = ptrLocal;
231   struct default_lq_ff *foreign = ptrForeign;
232
233   if (foreign) {
234     local->valueNlq = foreign->valueLq;
235   } else {
236     local->valueNlq = 0;
237   }
238 }
239
240 void default_lq_copy_link2tc_ff(void *target, void *source) {
241   memcpy(target, source, sizeof(struct default_lq_ff));
242 }
243
244 void default_lq_clear_ff(void *target) {
245   memset(target, 0, sizeof(struct default_lq_ff));
246 }
247
248 void default_lq_clear_ff_hello(void *target) {
249   struct default_lq_ff_hello *local = target;
250   int i;
251
252   default_lq_clear_ff(&local->lq);
253   local->windowSize = LQ_FF_QUICKSTART_INIT;
254   for (i=0; i<LQ_FF_WINDOW; i++) {
255     local->lost[i] = 3;
256   }
257 }
258
259 const char *default_lq_print_ff(void *ptr, char separator, struct lqtextbuffer *buffer) {
260   struct default_lq_ff *lq = ptr;
261
262   snprintf(buffer->buf, sizeof(buffer->buf), "%s%c%s",
263       fpmtoa(fpmidiv(itofpm((int)lq->valueLq), 255)),
264       separator,
265       fpmtoa(fpmidiv(itofpm((int)lq->valueNlq), 255)));
266   return buffer->buf;
267 }
268
269 const char *default_lq_print_cost_ff(olsr_linkcost cost, struct lqtextbuffer *buffer) {
270   snprintf(buffer->buf, sizeof(buffer->buf), "%s", fpmtoa(cost));
271   return buffer->buf;
272 }