2 * OLSR ad-hoc routing table management protocol
3 * Copyright (C) 2004 Andreas Tønnesen (andreto@ifi.uio.no)
5 * This file is part of the olsr.org OLSR daemon.
7 * olsr.org is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * olsr.org is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with olsr.org; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * $Id: olsr.c,v 1.22 2004/11/15 15:50:08 tlopatic Exp $
27 * All these functions are global
33 #include "two_hop_neighbor_table.h"
35 #include "duplicate_set.h"
36 #include "mpr_selector_set.h"
39 #if defined USE_LINK_QUALITY
43 #include "scheduler.h"
44 #include "generate_msg.h"
52 *Checks if a timer has timed out.
57 *Initiates a "timer", wich is a timeval structure,
58 *with the value given in time_value.
59 *@param time_value the value to initialize the timer with
60 *@param hold_timer the timer itself
64 olsr_init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
66 olsr_u16_t time_value_sec;
67 olsr_u16_t time_value_msec;
69 time_value_sec = time_value/1000;
70 time_value_msec = time_value-(time_value_sec*1000);
72 hold_timer->tv_sec = time_value_sec;
73 hold_timer->tv_usec = time_value_msec*1000;
81 *Generaties a timestamp a certain number of milliseconds
84 *@param time_value how many milliseconds from now
85 *@param hold_timer the timer itself
89 olsr_get_timestamp(olsr_u32_t delay, struct timeval *hold_timer)
91 hold_timer->tv_sec = now.tv_sec + delay / 1000;
92 hold_timer->tv_usec = now.tv_usec + (delay % 1000) * 1000;
94 if (hold_timer->tv_usec > 1000000)
97 hold_timer->tv_usec -= 1000000;
104 *Initialize the message sequence number as a random value
109 message_seqno = random() & 0xFFFF;
113 * Get and increment the message sequence number
120 return message_seqno++;
125 register_pcf(int (*f)(int, int, int))
129 olsr_printf(1, "Registering pcf function\n");
131 new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
133 new_pcf->function = f;
134 new_pcf->next = pcf_list;
141 *Process changes in neighborhood or/and topology.
142 *Re-calculates the neighborhooh/topology if there
143 *are any updates - then calls the right functions to
144 *update the routing table.
148 olsr_process_changes()
151 struct pcf *tmp_pc_list;
154 if(changes_neighborhood)
155 olsr_printf(3, "CHANGES IN NEIGHBORHOOD\n");
157 olsr_printf(3, "CHANGES IN TOPOLOGY\n");
159 olsr_printf(3, "CHANGES IN HNA\n");
162 if(!changes_neighborhood &&
167 if(changes_neighborhood)
169 /* Calculate new mprs, HNA and routing table */
170 #if defined USE_LINK_QUALITY
171 if (olsr_cnf->lq_level < 1)
174 olsr_calculate_mpr();
175 #if defined USE_LINK_QUALITY
180 olsr_calculate_lq_mpr();
184 if (olsr_cnf->lq_level < 2)
187 olsr_calculate_routing_table();
188 #if defined USE_LINK_QUALITY
193 olsr_calculate_lq_routing_table();
197 olsr_calculate_hna_routes();
199 /* Print updated info */
200 if(olsr_cnf->debug_level > 0)
202 #ifdef USE_LINK_QUALITY
203 olsr_print_link_set();
205 olsr_print_neighbor_table();
207 if(olsr_cnf->debug_level > 1)
208 olsr_print_tc_table();
210 if(olsr_cnf->debug_level > 2)
212 // the MPR selector set is now displayed as part of the
214 // olsr_print_mprs_set();
215 olsr_print_mid_set();
216 olsr_print_duplicate_table();
219 olsr_print_hna_set();
227 /* calculate the routing table and HNA */
228 #if defined USE_LINK_QUALITY
229 if (olsr_cnf->lq_level < 2)
232 olsr_calculate_routing_table();
233 #if defined USE_LINK_QUALITY
238 olsr_calculate_lq_routing_table();
241 olsr_calculate_hna_routes();
243 /* Print updated info */
244 if(olsr_cnf->debug_level > 1)
245 olsr_print_tc_table();
248 olsr_print_hna_set();
255 /* Update HNA routes */
256 olsr_calculate_hna_routes();
258 olsr_print_hna_set();
265 for(tmp_pc_list = pcf_list;
267 tmp_pc_list = tmp_pc_list->next)
269 tmp_pc_list->function(changes_neighborhood,
274 changes_neighborhood = OLSR_FALSE;
275 changes_topology = OLSR_FALSE;
276 changes_hna = OLSR_FALSE;
287 *Initialize all the tables used(neighbor,
288 *topology, MID, HNA, MPR, dup).
289 *Also initalizes other variables
295 changes_topology = OLSR_FALSE;
296 changes_neighborhood = OLSR_FALSE;
297 changes_hna = OLSR_FALSE;
299 /* Initialize link set */
300 olsr_init_link_set();
302 /* Initialize duplicate table */
303 olsr_init_duplicate_table();
305 /* Initialize neighbor table */
306 olsr_init_neighbor_table();
308 /* Initialize routing table */
309 olsr_init_routing_table();
311 /* Initialize two hop table */
312 olsr_init_two_hop_table();
314 /* Initialize old route table */
315 olsr_init_old_table();
317 /* Initialize topology */
320 /* Initialize mpr selector table */
321 olsr_init_mprs_set();
323 /* Initialize MID set */
326 /* Initialize HNA set */
329 /* Initialize ProcessChanges list */
340 *Check if a message is to be forwarded and forward
343 *@param m the OLSR message recieved
344 *@param originator the originator of this message
345 *@param seqno the seqno of the message
347 *@returns positive if forwarded
350 olsr_forward_message(union olsr_message *m,
351 union olsr_ip_addr *originator,
353 struct interface *in_if,
354 union olsr_ip_addr *from_addr)
356 union olsr_ip_addr *src;
357 struct neighbor_entry *neighbor;
359 struct interface *ifn;
362 if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
365 olsr_printf(3, "Message already forwarded!\n");
370 /* Lookup sender address */
371 if(!(src = mid_lookup_main_addr(from_addr)))
375 if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
378 if(neighbor->status != SYM)
381 /* Update duplicate table interface */
382 olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
386 if(olsr_lookup_mprs_set(src) == NULL)
389 olsr_printf(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src));
395 /* Treat TTL hopcnt */
396 if(olsr_cnf->ip_version == AF_INET)
411 /* Update dup forwarded */
412 olsr_set_dup_forward(originator, seqno);
414 /* Update packet data */
417 msgsize = ntohs(m->v4.olsr_msgsize);
419 /* looping trough interfaces */
420 for (ifn = ifnet; ifn ; ifn = ifn->int_next)
422 if(net_output_pending(ifn))
425 * Check if message is to big to be piggybacked
427 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
432 set_buffer_timer(ifn);
434 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
436 olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
437 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
445 /* No forwarding pending */
446 set_buffer_timer(ifn);
448 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
450 olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
451 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
462 set_buffer_timer(struct interface *ifn)
465 struct timeval jittertimer;
468 jitter = (float) random()/RAND_MAX;
469 jitter *= max_jitter;
471 olsr_init_timer((olsr_u32_t) (jitter*1000), &jittertimer);
473 timeradd(&now, &jittertimer, &fwdtimer[ifn->if_nr]);
480 olsr_init_willingness()
482 if(olsr_cnf->willingness_auto)
483 olsr_register_scheduler_event(&olsr_update_willingness, NULL, will_int, will_int, NULL);
487 olsr_update_willingness(void *foo)
491 tmp_will = olsr_cnf->willingness;
493 /* Re-calculate willingness */
494 olsr_cnf->willingness = olsr_calculate_willingness();
496 if(tmp_will != olsr_cnf->willingness)
498 olsr_printf(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
504 *Calculate this nodes willingness to act as a MPR
505 *based on either a fixed value or the power status
506 *of the node using APM
508 *@return a 8bit value from 0-7 representing the willingness
512 olsr_calculate_willingness()
514 struct olsr_apm_info ainfo;
516 /* If fixed willingness */
517 if(!olsr_cnf->willingness_auto)
518 return olsr_cnf->willingness;
520 #warning CHANGES IN THE apm INTERFACE(0.4.8)!
522 if(apm_read(&ainfo) < 1)
525 apm_printinfo(&ainfo);
528 if(ainfo.ac_line_status == OLSR_AC_POWERED)
531 /* If battery powered
533 * juice > 78% will: 3
534 * 78% > juice > 26% will: 2
535 * 26% > juice will: 1
537 return (ainfo.battery_percentage / 26);
543 *Termination function to be called whenever a error occures
544 *that requires the daemon to terminate
546 *@param msg the message to write to the syslog and possibly stdout
550 olsr_exit(const char *msg, int val)
552 olsr_printf(1, "OLSR EXIT: %s\n", msg);
553 olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
562 *Wrapper for malloc(3) that does error-checking
564 *@param size the number of bytes to allocalte
565 *@param caller a string identifying the caller for
566 *use in error messaging
568 *@return a void pointer to the memory allocated
571 olsr_malloc(size_t size, const char *id)
575 if((ptr = malloc(size)) == 0)
577 olsr_printf(1, "OUT OF MEMORY: %s\n", strerror(errno));
578 olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
579 olsr_exit((char *)id, EXIT_FAILURE);
586 *Wrapper for printf that prints to a specific
587 *debuglevel upper limit
592 olsr_printf(int loglevel, char *format, ...)
596 if(loglevel <= olsr_cnf->debug_level)
598 va_start(arglist, format);
600 vprintf(format, arglist);