Rework lq_fpm calculation to increase calculation accuracy
[olsrd.git] / src / lq_plugin_default_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 "olsr_spf.h"
45 #include "lq_packet.h"
46 #include "packet.h"
47 #include "olsr.h"
48 #include "lq_plugin_default_fpm.h"
49 #include "fpm.h"
50
51 /* etx lq plugin (fpm version) settings */
52 struct lq_handler lq_etx_fpm_handler = {
53     &default_lq_initialize_fpm,
54     
55     &default_lq_calc_cost_fpm,
56     &default_lq_calc_cost_fpm,
57     
58     &default_lq_is_relevant_costchange_fpm,
59     
60     &default_lq_packet_loss_worker_fpm,
61     &default_lq_memorize_foreign_hello_fpm,
62     &default_lq_copy_link2tc_fpm,
63     &default_lq_clear_fpm,
64     &default_lq_clear_fpm,
65     
66     &default_lq_serialize_hello_lq_pair_fpm,
67     &default_lq_serialize_tc_lq_pair_fpm,
68     &default_lq_deserialize_hello_lq_pair_fpm,
69     &default_lq_deserialize_tc_lq_pair_fpm,
70     
71     &default_lq_print_fpm,
72     &default_lq_print_fpm,
73     &default_lq_print_cost_fpm, 
74     
75     sizeof(struct default_lq_fpm),
76     sizeof(struct default_lq_fpm)
77 };
78
79 fpm aging_factor_new, aging_factor_old;
80 fpm aging_quickstart_new, aging_quickstart_old;
81
82 void default_lq_initialize_fpm(void) {
83   aging_factor_new = ftofpm(olsr_cnf->lq_aging);
84   aging_factor_old = fpmsub(itofpm(1), aging_factor_new);
85   
86   aging_quickstart_new = ftofpm(LQ_QUICKSTART_AGING);
87   aging_quickstart_old = fpmsub(itofpm(1), aging_quickstart_new);
88 }
89
90 olsr_linkcost default_lq_calc_cost_fpm(const void *ptr) {
91   const struct default_lq_fpm *lq = ptr;
92   olsr_linkcost cost;
93   
94   if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
95     return LINK_COST_BROKEN;
96   }
97   
98   cost = fpmidiv(itofpm(255 * 255), (int)lq->valueLq * (int)lq->valueNlq);
99
100   if (cost > LINK_COST_BROKEN)
101     return LINK_COST_BROKEN;
102   if (cost == 0)
103     return 1;
104   return cost;
105 }
106
107 int default_lq_serialize_hello_lq_pair_fpm(unsigned char *buff, void *ptr) {
108   struct default_lq_fpm *lq = ptr;
109   
110   buff[0] = (unsigned char)lq->valueLq;
111   buff[1] = (unsigned char)lq->valueNlq;
112   buff[2] = (unsigned char)(0);
113   buff[3] = (unsigned char)(0);
114   
115   return 4;
116 }
117
118 void default_lq_deserialize_hello_lq_pair_fpm(const olsr_u8_t **curr, void *ptr) {
119   struct default_lq_fpm *lq = ptr;
120   
121   pkt_get_u8(curr, &lq->valueLq);
122   pkt_get_u8(curr, &lq->valueNlq);
123   pkt_ignore_u16(curr);
124 }
125
126 olsr_bool default_lq_is_relevant_costchange_fpm(olsr_linkcost c1, olsr_linkcost c2) {
127   if (c1 > c2) {
128     return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FPM;
129   }
130   return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FPM;
131 }
132
133 int default_lq_serialize_tc_lq_pair_fpm(unsigned char *buff, void *ptr) {
134   struct default_lq_fpm *lq = ptr;
135   
136   buff[0] = (unsigned char)lq->valueLq;
137   buff[1] = (unsigned char)lq->valueNlq;
138   buff[2] = (unsigned char)(0);
139   buff[3] = (unsigned char)(0);
140   
141   return 4;
142 }
143
144 void default_lq_deserialize_tc_lq_pair_fpm(const olsr_u8_t **curr, void *ptr) {
145   struct default_lq_fpm *lq = ptr;
146   
147   pkt_get_u8(curr, &lq->valueLq);
148   pkt_get_u8(curr, &lq->valueNlq);
149   pkt_ignore_u16(curr);
150 }
151
152 olsr_linkcost default_lq_packet_loss_worker_fpm(struct link_entry *link, void *ptr, olsr_bool lost) {
153   struct default_lq_fpm *tlq = ptr;
154   fpm alpha_old = aging_factor_old;
155   fpm alpha_new = aging_factor_new;
156   
157   fpm link_loss_factor = fpmidiv(itofpm(link->loss_link_multiplier), 65536);
158   
159   if (tlq->quickstart < LQ_QUICKSTART_STEPS) {
160     alpha_new = aging_quickstart_new;
161     alpha_old = aging_quickstart_old;
162     tlq->quickstart++;
163   }
164   
165   // exponential moving average
166   tlq->valueLq = fpmmul(tlq->valueLq, alpha_old);
167   if (lost == 0) {
168     tlq->valueLq += fpmtoi(fpmmuli(fpmmul(alpha_new, link_loss_factor), 255));
169   }
170   return default_lq_calc_cost_fpm(ptr);
171 }
172
173 void default_lq_memorize_foreign_hello_fpm(void *ptrLocal, void *ptrForeign) {
174   struct default_lq_fpm *local = ptrLocal;
175   struct default_lq_fpm *foreign = ptrForeign;
176   
177   if (foreign) {
178     local->valueNlq = foreign->valueLq;
179   }
180   else {
181     local->valueNlq = 0;
182   }
183 }
184
185 void default_lq_copy_link2tc_fpm(void *target, void *source) {
186   memcpy(target, source, sizeof(struct default_lq_fpm));
187 }
188
189 void default_lq_clear_fpm(void *target) {
190   memset(target, 0, sizeof(struct default_lq_fpm));
191 }
192
193 const char *default_lq_print_fpm(void *ptr, struct lqtextbuffer *buffer) {
194   struct default_lq_fpm *lq = ptr;
195   
196   sprintf(buffer->buf, "%s/%s",
197     fpmtoa(fpmidiv(itofpm((int)lq->valueLq), 255)),
198     fpmtoa(fpmidiv(itofpm((int)lq->valueNlq), 255)));
199   return buffer->buf;
200 }
201
202 const char *default_lq_print_cost_fpm(olsr_linkcost cost, struct lqtextbuffer *buffer) {
203   sprintf(buffer->buf, "%s", fpmtoa(cost));
204   return buffer->buf;
205 }