37e3e80453e45909fcbb21ec6a0da5875bfa664d
[olsrd.git] / src / hysteresis.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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 <time.h>
43
44 #include "olsr_protocol.h"
45 #include "hysteresis.h"
46 #include "defs.h"
47 #include "olsr.h"
48 #include "net_olsr.h"
49 #include "ipcalc.h"
50 #include "scheduler.h"
51
52 #define hscaling olsr_cnf->hysteresis_param.scaling
53 #define hhigh    olsr_cnf->hysteresis_param.thr_high
54 #define hlow     olsr_cnf->hysteresis_param.thr_low
55
56 float
57 olsr_hyst_calc_stability(float old_quality)
58 {
59   return (((1 - hscaling) * old_quality) + hscaling);
60 }
61
62 float
63 olsr_hyst_calc_instability(float old_quality)
64 {
65   return ((1 - hscaling) * old_quality);
66 }
67
68 int
69 olsr_process_hysteresis(struct link_entry *entry)
70 {
71   //printf("PROCESSING QUALITY: %f\n", entry->L_link_quality);
72   if (entry->L_link_quality > hhigh) {
73     if (entry->L_link_pending == 1) {
74       struct ipaddr_str buf;
75       OLSR_PRINTF(1, "HYST[%s] link set to NOT pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
76       changes_neighborhood = true;
77     }
78
79     /* Pending = false */
80     entry->L_link_pending = 0;
81
82     if (!TIMED_OUT(entry->L_LOST_LINK_time))
83       changes_neighborhood = true;
84
85     /* time = now -1 */
86     entry->L_LOST_LINK_time = now_times - 1;
87
88     return 1;
89   }
90
91   if (entry->L_link_quality < hlow) {
92     if (entry->L_link_pending == 0) {
93       struct ipaddr_str buf;
94       OLSR_PRINTF(1, "HYST[%s] link set to pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
95       changes_neighborhood = true;
96     }
97
98     /* Pending = true */
99     entry->L_link_pending = 1;
100
101     if (TIMED_OUT(entry->L_LOST_LINK_time))
102       changes_neighborhood = true;
103
104     /* Timer = min (L_time, current time + NEIGHB_HOLD_TIME) */
105     entry->L_LOST_LINK_time = MIN(GET_TIMESTAMP(NEIGHB_HOLD_TIME * MSEC_PER_SEC), entry->link_timer->timer_clock);
106
107     /* (the link is then considered as lost according to section
108        8.5 and this may produce a neighbor loss).
109        WTF?
110      */
111     return -1;
112   }
113
114   /*
115    *If we get here then:
116    *(HYST_THRESHOLD_LOW <= entry->L_link_quality <= HYST_THRESHOLD_HIGH)
117    */
118
119   /* L_link_pending and L_LOST_LINK_time remain unchanged. */
120   return 0;
121
122 }
123
124 /**
125  *Update the hello timeout of a hysteresis link
126  *entry
127  *
128  *@param entry the link entry to update
129  *@param htime the hello interval to use
130  *
131  *@return nada
132  */
133 void
134 olsr_update_hysteresis_hello(struct link_entry *entry, olsr_reltime htime)
135 {
136   struct ipaddr_str buf;
137   OLSR_PRINTF(3, "HYST[%s]: HELLO update vtime %u ms\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr), htime + htime / 2);
138
139   olsr_set_timer(&entry->link_hello_timer, htime + htime / 2, OLSR_LINK_HELLO_JITTER, OLSR_TIMER_PERIODIC,
140                  &olsr_expire_link_hello_timer, entry, 0);
141
142   return;
143 }
144
145 void
146 update_hysteresis_incoming(union olsr_ip_addr *remote, struct interface *local, uint16_t seqno)
147 {
148   struct link_entry *lnk = lookup_link_entry(remote, NULL, local);
149
150   /* Calculate new quality */
151   if (lnk != NULL) {
152 #ifdef DEBUG
153     struct ipaddr_str buf;
154 #endif
155     lnk->L_link_quality = olsr_hyst_calc_stability(lnk->L_link_quality);
156 #ifdef DEBUG
157     OLSR_PRINTF(3, "HYST[%s]: %f\n", olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
158 #endif
159
160     /*
161      * see how many packets we have missed and update the link quality
162      * for each missed packet; HELLOs have already been accounted for by
163      * the timeout function and the number of missed HELLOs has already
164      * been added to olsr_seqno there
165      */
166
167     if (lnk->olsr_seqno_valid && (unsigned short)(seqno - lnk->olsr_seqno) < 100)
168       while (lnk->olsr_seqno != seqno) {
169         lnk->L_link_quality = olsr_hyst_calc_instability(lnk->L_link_quality);
170 #ifdef DEBUG
171         OLSR_PRINTF(5, "HYST[%s] PACKET LOSS! %f\n", olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
172 #endif
173         if (lnk->L_link_quality < olsr_cnf->hysteresis_param.thr_low)
174           break;
175
176         lnk->olsr_seqno++;
177       }
178
179     lnk->olsr_seqno = seqno + 1;
180     lnk->olsr_seqno_valid = true;
181
182     //printf("Updating seqno to: %d\n", lnk->olsr_seqno);
183   }
184   return;
185 }
186
187 /*
188  * Local Variables:
189  * c-basic-offset: 2
190  * indent-tabs-mode: nil
191  * End:
192  */