Fix GCC warning
[olsrd.git] / src / neighbor_table.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 "ipcalc.h"
43 #include "defs.h"
44 #include "two_hop_neighbor_table.h"
45 #include "mid_set.h"
46 #include "mpr.h"
47 #include "neighbor_table.h"
48 #include "olsr.h"
49 #include "scheduler.h"
50 #include "link_set.h"
51 #include "mpr_selector_set.h"
52 #include "net_olsr.h"
53
54 struct neighbor_entry neighbortable[HASHSIZE];
55
56 void
57 olsr_init_neighbor_table(void)
58 {
59   int i;
60
61   for (i = 0; i < HASHSIZE; i++) {
62     neighbortable[i].next = &neighbortable[i];
63     neighbortable[i].prev = &neighbortable[i];
64   }
65 }
66
67 /**
68  * Unlink, delete and free a nbr2_list entry.
69  */
70 static void
71 olsr_del_nbr2_list(struct neighbor_2_list_entry *nbr2_list)
72 {
73   struct neighbor_entry *nbr;
74   struct neighbor_2_entry *nbr2;
75
76   nbr = nbr2_list->nbr2_nbr;
77   nbr2 = nbr2_list->neighbor_2;
78
79   if (nbr2->neighbor_2_pointer < 1) {
80     DEQUEUE_ELEM(nbr2);
81     free(nbr2);
82   }
83
84   /*
85    * Kill running timers.
86    */
87   olsr_stop_timer(nbr2_list->nbr2_list_timer);
88   nbr2_list->nbr2_list_timer = NULL;
89
90   /* Dequeue */
91   DEQUEUE_ELEM(nbr2_list);
92
93   free(nbr2_list);
94
95   /* Set flags to recalculate the MPR set and the routing table */
96   changes_neighborhood = true;
97   changes_topology = true;
98 }
99
100 /**
101  * Delete a two hop neighbor from a neighbors two hop neighbor list.
102  *
103  * @param neighbor the neighbor to delete the two hop neighbor from.
104  * @param address the IP address of the two hop neighbor to delete.
105  *
106  * @return positive if entry deleted
107  */
108 int
109 olsr_delete_neighbor_2_pointer(struct neighbor_entry *neighbor, struct neighbor_2_entry *neigh2)
110 {
111   struct neighbor_2_list_entry *nbr2_list;
112
113   nbr2_list = neighbor->neighbor_2_list.next;
114
115   while (nbr2_list != &neighbor->neighbor_2_list) {
116     if (nbr2_list->neighbor_2 == neigh2) {
117       olsr_del_nbr2_list(nbr2_list);
118       return 1;
119     }
120     nbr2_list = nbr2_list->next;
121   }
122   return 0;
123 }
124
125 /**
126  *Check if a two hop neighbor is reachable via a given
127  *neighbor.
128  *
129  *@param neighbor neighbor-entry to check via
130  *@param neighbor_main_address the addres of the two hop neighbor
131  *to find.
132  *
133  *@return a pointer to the neighbor_2_list_entry struct
134  *representing the two hop neighbor if found. NULL if not found.
135  */
136 struct neighbor_2_list_entry *
137 olsr_lookup_my_neighbors(const struct neighbor_entry *neighbor, const union olsr_ip_addr *neighbor_main_address)
138 {
139   struct neighbor_2_list_entry *entry;
140
141   for (entry = neighbor->neighbor_2_list.next; entry != &neighbor->neighbor_2_list; entry = entry->next) {
142
143     if (ipequal(&entry->neighbor_2->neighbor_2_addr, neighbor_main_address))
144       return entry;
145
146   }
147   return NULL;
148 }
149
150 /**
151  * Update a neighbours main_addr inlcuding hash
152 */
153
154 void
155 olsr_update_neighbor_main_addr(struct neighbor_entry *entry, const union olsr_ip_addr *new_main_addr)
156 {
157   /*remove from old pos*/
158   DEQUEUE_ELEM(entry);
159
160   /*update main addr*/
161   entry->neighbor_main_addr = *new_main_addr;
162
163   /*insert it again*/
164   QUEUE_ELEM(neighbortable[olsr_ip_hashing(new_main_addr)], entry);
165
166 }
167
168 /**
169  *Delete a neighbr table entry.
170  *
171  *Remember: Deleting a neighbor entry results
172  *the deletion of its 2 hop neighbors list!!!
173  *@param neighbor the neighbor entry to delete
174  *
175  *@return nada
176  */
177
178 int
179 olsr_delete_neighbor_table(const union olsr_ip_addr *neighbor_addr)
180 {
181   struct neighbor_2_list_entry *two_hop_list, *two_hop_to_delete;
182   uint32_t hash;
183   struct neighbor_entry *entry;
184
185   //printf("inserting neighbor\n");
186
187   hash = olsr_ip_hashing(neighbor_addr);
188
189   entry = neighbortable[hash].next;
190
191   /*
192    * Find neighbor entry
193    */
194   while (entry != &neighbortable[hash]) {
195     if (ipequal(&entry->neighbor_main_addr, neighbor_addr))
196       break;
197
198     entry = entry->next;
199   }
200
201   if (entry == &neighbortable[hash])
202     return 0;
203
204   two_hop_list = entry->neighbor_2_list.next;
205
206   while (two_hop_list != &entry->neighbor_2_list) {
207     two_hop_to_delete = two_hop_list;
208     two_hop_list = two_hop_list->next;
209
210     two_hop_to_delete->neighbor_2->neighbor_2_pointer--;
211     olsr_delete_neighbor_pointer(two_hop_to_delete->neighbor_2, entry);
212
213     olsr_del_nbr2_list(two_hop_to_delete);
214   }
215
216   /* Dequeue */
217   DEQUEUE_ELEM(entry);
218
219   free(entry);
220
221   changes_neighborhood = true;
222   return 1;
223
224 }
225
226 /**
227  *Insert a neighbor entry in the neighbor table
228  *
229  *@param main_addr the main address of the new node
230  *
231  *@return 0 if neighbor already exists 1 if inserted
232  */
233 struct neighbor_entry *
234 olsr_insert_neighbor_table(const union olsr_ip_addr *main_addr)
235 {
236   uint32_t hash;
237   struct neighbor_entry *new_neigh;
238
239   hash = olsr_ip_hashing(main_addr);
240
241   /* Check if entry exists */
242
243   for (new_neigh = neighbortable[hash].next; new_neigh != &neighbortable[hash]; new_neigh = new_neigh->next) {
244     if (ipequal(&new_neigh->neighbor_main_addr, main_addr))
245       return new_neigh;
246   }
247
248   //printf("inserting neighbor\n");
249
250   new_neigh = olsr_malloc(sizeof(struct neighbor_entry), "New neighbor entry");
251
252   /* Set address, willingness and status */
253   new_neigh->neighbor_main_addr = *main_addr;
254   new_neigh->willingness = WILL_NEVER;
255   new_neigh->status = NOT_SYM;
256
257   new_neigh->neighbor_2_list.next = &new_neigh->neighbor_2_list;
258   new_neigh->neighbor_2_list.prev = &new_neigh->neighbor_2_list;
259
260   new_neigh->linkcount = 0;
261   new_neigh->is_mpr = false;
262   new_neigh->was_mpr = false;
263
264   /* Queue */
265   QUEUE_ELEM(neighbortable[hash], new_neigh);
266
267   return new_neigh;
268 }
269
270 /**
271  *Lookup a neighbor entry in the neighbortable based on an address.
272  *
273  *@param dst the IP address of the neighbor to look up
274  *
275  *@return a pointer to the neighbor struct registered on the given
276  *address. NULL if not found.
277  */
278 struct neighbor_entry *
279 olsr_lookup_neighbor_table(const union olsr_ip_addr *dst)
280 {
281   /*
282    *Find main address of node
283    */
284   union olsr_ip_addr *tmp_ip = mid_lookup_main_addr(dst);
285   if (tmp_ip != NULL)
286     dst = tmp_ip;
287   return olsr_lookup_neighbor_table_alias(dst);
288 }
289
290 /**
291  *Lookup a neighbor entry in the neighbortable based on an address.
292  *
293  *@param dst the IP address of the neighbor to look up
294  *
295  *@return a pointer to the neighbor struct registered on the given
296  *address. NULL if not found.
297  */
298 struct neighbor_entry *
299 olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *dst)
300 {
301   struct neighbor_entry *entry;
302   uint32_t hash = olsr_ip_hashing(dst);
303
304   //printf("\nLookup %s\n", olsr_ip_to_string(&buf, dst));
305   for (entry = neighbortable[hash].next; entry != &neighbortable[hash]; entry = entry->next) {
306     //printf("Checking %s\n", olsr_ip_to_string(&buf, &entry->neighbor_main_addr));
307     if (ipequal(&entry->neighbor_main_addr, dst))
308       return entry;
309
310   }
311   //printf("NOPE\n\n");
312
313   return NULL;
314
315 }
316
317 int
318 update_neighbor_status(struct neighbor_entry *entry, int lnk)
319 {
320   /*
321    * Update neighbor entry
322    */
323
324   if (lnk == SYM_LINK) {
325     /* N_status is set to SYM */
326     if (entry->status == NOT_SYM) {
327       struct neighbor_2_entry *two_hop_neighbor;
328
329       /* Delete posible 2 hop entry on this neighbor */
330       if ((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&entry->neighbor_main_addr)) != NULL) {
331         olsr_delete_two_hop_neighbor_table(two_hop_neighbor);
332       }
333
334       changes_neighborhood = true;
335       changes_topology = true;
336       if (olsr_cnf->tc_redundancy > 1)
337         signal_link_changes(true);
338     }
339     entry->status = SYM;
340   } else {
341     if (entry->status == SYM) {
342       changes_neighborhood = true;
343       changes_topology = true;
344       if (olsr_cnf->tc_redundancy > 1)
345         signal_link_changes(true);
346     }
347     /* else N_status is set to NOT_SYM */
348     entry->status = NOT_SYM;
349     /* remove neighbor from routing list */
350   }
351
352   return entry->status;
353 }
354
355 /**
356  * Callback for the nbr2_list timer.
357  */
358 void
359 olsr_expire_nbr2_list(void *context)
360 {
361   struct neighbor_2_list_entry *nbr2_list;
362   struct neighbor_entry *nbr;
363   struct neighbor_2_entry *nbr2;
364
365   nbr2_list = (struct neighbor_2_list_entry *)context;
366   nbr2_list->nbr2_list_timer = NULL;
367
368   nbr = nbr2_list->nbr2_nbr;
369   nbr2 = nbr2_list->neighbor_2;
370
371   nbr2->neighbor_2_pointer--;
372   olsr_delete_neighbor_pointer(nbr2, nbr);
373
374   olsr_del_nbr2_list(nbr2_list);
375 }
376
377 /**
378  *Prints the registered neighbors and two hop neighbors
379  *to STDOUT.
380  *
381  *@return nada
382  */
383 void
384 olsr_print_neighbor_table(void)
385 {
386 #ifdef NODEBUG
387   /* The whole function doesn't do anything else. */
388 #ifndef NODEBUG
389   const int iplen = olsr_cnf->ip_version == AF_INET ? 15 : 39;
390 #endif
391   int idx;
392   OLSR_PRINTF(1,
393               "\n--- %02d:%02d:%02d.%02d ------------------------------------------------ NEIGHBORS\n\n"
394               "%*s  LQ     NLQ    SYM   MPR   MPRS  will\n", nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec, (int)now.tv_usec / 10000,
395               iplen, "IP address");
396
397   for (idx = 0; idx < HASHSIZE; idx++) {
398     struct neighbor_entry *neigh;
399     for (neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) {
400       struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
401       if (lnk) {
402         struct ipaddr_str buf;
403         OLSR_PRINTF(1, "%-*s  %5.3f  %5.3f  %s  %s  %s  %d\n", iplen, olsr_ip_to_string(&buf, &neigh->neighbor_main_addr),
404                     lnk->loss_link_quality, lnk->neigh_link_quality, neigh->status == SYM ? "YES " : "NO  ",
405                     neigh->is_mpr ? "YES " : "NO  ", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO  " : "YES ",
406                     neigh->willingness);
407       }
408     }
409   }
410 #endif
411 }
412
413 /*
414  * Local Variables:
415  * c-basic-offset: 2
416  * indent-tabs-mode: nil
417  * End:
418  */