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