Added FPM plugin for routing
[olsrd.git] / lib / lq_etx_fpm / src / lq_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 "lq_plugin.h"
44 #include "lq_route.h"
45 #include "lq_packet.h"
46 #include "packet.h"
47 #include "olsr.h"
48 #include "lq_etx_fpm.h"
49 #include "fpm.h"
50
51 /* etx lq plugin (fpm version) settings */
52 struct lq_handler lq_etx_fpm_handler = {
53     &lq_etx_fpm_calc_cost,
54     &lq_etx_fpm_calc_cost,
55     
56     &lq_etx_fpm_olsr_is_relevant_costchange,
57     
58     &lq_etx_fpm_packet_loss_worker,
59     &lq_etx_fpm_olsr_memorize_foreign_hello_lq,
60     &lq_etx_fpm_olsr_copy_link_lq_into_tc,
61     &lq_etx_fpm_olsr_clear_lq,
62     &lq_etx_fpm_olsr_clear_lq,
63     
64     &lq_etx_fpm_olsr_serialize_hello_lq_pair,
65     &lq_etx_fpm_olsr_serialize_tc_lq_pair,
66     &lq_etx_fpm_olsr_deserialize_hello_lq_pair,
67     &lq_etx_fpm_olsr_deserialize_tc_lq_pair,
68     
69     &lq_etx_fpm_olsr_print_lq,
70     &lq_etx_fpm_olsr_print_lq,
71     &lq_etx_fpm_olsr_print_cost, 
72     
73     sizeof(struct lq_etx_fpm),
74     sizeof(struct lq_etx_fpm)
75 };
76
77 fpm MINIMAL_LQ;
78 fpm aging_factor1, aging_factor2;
79
80 void set_lq_etx_fpm_alpha(fpm alpha) {
81   OLSR_PRINTF(3, "lq_etx_fpm: Set alpha to %s\n", fpmtoa(alpha));
82   aging_factor1 = alpha;
83   aging_factor2 = fpmsub(itofpm(1), alpha);
84 }
85
86 int init_lq_etx_fpm(void) {
87   if (aging_factor1 == 0 && aging_factor2 == 0) {
88     OLSR_PRINTF(1, "Alpha factor for lq_etx_fgm not set !\n");
89     return 0; // error
90   }
91   
92   MINIMAL_LQ = ftofpm(0.1);
93   
94   // activate plugin
95   set_lq_handler(&lq_etx_fpm_handler, LQ_ETX_FPM_HANDLER_NAME);
96   return 1;
97 }
98
99 olsr_linkcost lq_etx_fpm_calc_cost(const void *ptr) {
100   const struct lq_etx_fpm *lq = ptr;
101   olsr_linkcost cost;
102   
103   if (lq->lq < MINIMAL_LQ || lq->nlq < MINIMAL_LQ) {
104     return LINK_COST_BROKEN;
105   }
106   
107   cost = fpmdiv(itofpm(1), fpmmul(lq->lq, lq->nlq));
108
109   if (cost > LINK_COST_BROKEN)
110     return LINK_COST_BROKEN;
111   if (cost == 0)
112     return 1;
113   return cost;
114 }
115
116 int lq_etx_fpm_olsr_serialize_hello_lq_pair(unsigned char *buff, void *ptr) {
117   struct lq_etx_fpm *lq = ptr;
118   
119   buff[0] = (unsigned char)fpmtoi(fpmmuli(lq->lq, 255));
120   buff[1] = (unsigned char)fpmtoi(fpmmuli(lq->nlq, 255));
121   buff[2] = (unsigned char)(0);
122   buff[3] = (unsigned char)(0);
123   
124   return 4;
125 }
126
127 void lq_etx_fpm_olsr_deserialize_hello_lq_pair(const olsr_u8_t **curr, void *ptr) {
128   struct lq_etx_fpm *lq = ptr;
129   olsr_u8_t valueLq, valueNlq;
130   
131   pkt_get_u8(curr, &valueLq);
132   pkt_get_u8(curr, &valueNlq);
133   pkt_ignore_u16(curr);
134   
135   lq->lq = fpmidiv(itofpm((int)valueLq), 255);
136   lq->nlq = fpmidiv(itofpm((int)valueNlq), 255);
137 }
138
139 olsr_bool lq_etx_fpm_olsr_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2) {
140   if (c1 > c2) {
141     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
142   }
143   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
144 }
145
146 int lq_etx_fpm_olsr_serialize_tc_lq_pair(unsigned char *buff, void *ptr) {
147   struct lq_etx_fpm *lq = ptr;
148   
149   buff[0] = (unsigned char)fpmtoi(fpmmuli(lq->lq, 255));
150   buff[1] = (unsigned char)fpmtoi(fpmmuli(lq->nlq, 255));
151   buff[2] = (unsigned char)(0);
152   buff[3] = (unsigned char)(0);
153   
154   return 4;
155 }
156
157 void lq_etx_fpm_olsr_deserialize_tc_lq_pair(const olsr_u8_t **curr, void *ptr) {
158   struct lq_etx_fpm *lq = ptr;
159   olsr_u8_t valueLq, valueNlq;
160   
161   pkt_get_u8(curr, &valueLq);
162   pkt_get_u8(curr, &valueNlq);
163   pkt_ignore_u16(curr);
164   
165   lq->lq = fpmidiv(itofpm(valueLq), 255);
166   lq->nlq = fpmidiv(itofpm(valueNlq), 255);
167 }
168
169 olsr_linkcost lq_etx_fpm_packet_loss_worker(void *ptr, olsr_bool lost) {
170   struct lq_etx_fpm *tlq = ptr;
171   
172   // exponential moving average
173   tlq->lq = fpmmul(tlq->lq, aging_factor2);
174   if (lost == 0) {
175     tlq->lq = fpmadd(tlq->lq, aging_factor1);
176   }
177   return lq_etx_fpm_calc_cost(ptr);
178 }
179
180 void lq_etx_fpm_olsr_memorize_foreign_hello_lq(void *ptrLocal, void *ptrForeign) {
181   struct lq_etx_fpm *local = ptrLocal;
182   struct lq_etx_fpm *foreign = ptrForeign;
183   
184   if (foreign) {
185     local->nlq = foreign->lq;
186   }
187   else {
188     local->nlq = itofpm(0);
189   }
190 }
191
192 void lq_etx_fpm_olsr_copy_link_lq_into_tc(void *target, void *source) {
193   memcpy(target, source, sizeof(struct lq_etx_fpm));
194 }
195
196 void lq_etx_fpm_olsr_clear_lq(void *target) {
197   memset(target, 0, sizeof(struct lq_etx_fpm));
198 }
199
200 const char *lq_etx_fpm_olsr_print_lq(void *ptr, struct lqtextbuffer *buffer) {
201   struct lq_etx_fpm *lq = ptr;
202   
203   sprintf(buffer->buf, "%s/%s", fpmtoa(lq->lq), fpmtoa(lq->nlq));
204   return buffer->buf;
205 }
206
207 const char *lq_etx_fpm_olsr_print_cost(olsr_linkcost cost, struct lqtextbuffer *buffer) {
208   sprintf(buffer->buf, "%s", fpmtoa(cost));
209   return buffer->buf;
210 }