2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
39 * $Id: olsr.c,v 1.28 2004/11/21 13:45:50 kattemat Exp $
43 * All these functions are global
49 #include "two_hop_neighbor_table.h"
51 #include "duplicate_set.h"
52 #include "mpr_selector_set.h"
55 #if defined USE_LINK_QUALITY
59 #include "scheduler.h"
60 #include "generate_msg.h"
69 *Checks if a timer has timed out.
74 *Initiates a "timer", wich is a timeval structure,
75 *with the value given in time_value.
76 *@param time_value the value to initialize the timer with
77 *@param hold_timer the timer itself
81 olsr_init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
83 olsr_u16_t time_value_sec;
84 olsr_u16_t time_value_msec;
86 time_value_sec = time_value/1000;
87 time_value_msec = time_value-(time_value_sec*1000);
89 hold_timer->tv_sec = time_value_sec;
90 hold_timer->tv_usec = time_value_msec*1000;
98 *Generaties a timestamp a certain number of milliseconds
101 *@param time_value how many milliseconds from now
102 *@param hold_timer the timer itself
106 olsr_get_timestamp(olsr_u32_t delay, struct timeval *hold_timer)
108 hold_timer->tv_sec = now.tv_sec + delay / 1000;
109 hold_timer->tv_usec = now.tv_usec + (delay % 1000) * 1000;
111 if (hold_timer->tv_usec > 1000000)
113 hold_timer->tv_sec++;
114 hold_timer->tv_usec -= 1000000;
121 *Initialize the message sequence number as a random value
126 message_seqno = random() & 0xFFFF;
130 * Get and increment the message sequence number
137 return message_seqno++;
142 register_pcf(int (*f)(int, int, int))
146 olsr_printf(1, "Registering pcf function\n");
148 new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
150 new_pcf->function = f;
151 new_pcf->next = pcf_list;
158 *Process changes in neighborhood or/and topology.
159 *Re-calculates the neighborhooh/topology if there
160 *are any updates - then calls the right functions to
161 *update the routing table.
165 olsr_process_changes()
168 struct pcf *tmp_pc_list;
171 if(changes_neighborhood)
172 olsr_printf(3, "CHANGES IN NEIGHBORHOOD\n");
174 olsr_printf(3, "CHANGES IN TOPOLOGY\n");
176 olsr_printf(3, "CHANGES IN HNA\n");
179 if(!changes_neighborhood &&
184 if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1))
187 printf("<<<< %s (%s) >>>>\n", SOFTWARE_VERSION, __DATE__);
190 if (changes_neighborhood)
192 /* Calculate new mprs, HNA and routing table */
193 #if defined USE_LINK_QUALITY
194 if (olsr_cnf->lq_level < 1)
197 olsr_calculate_mpr();
198 #if defined USE_LINK_QUALITY
203 olsr_calculate_lq_mpr();
207 if (olsr_cnf->lq_level < 2)
210 olsr_calculate_routing_table();
211 #if defined USE_LINK_QUALITY
216 olsr_calculate_lq_routing_table();
220 olsr_calculate_hna_routes();
223 else if (changes_topology)
225 /* calculate the routing table and HNA */
226 #if defined USE_LINK_QUALITY
227 if (olsr_cnf->lq_level < 2)
230 olsr_calculate_routing_table();
231 #if defined USE_LINK_QUALITY
236 olsr_calculate_lq_routing_table();
239 olsr_calculate_hna_routes();
242 else if (changes_hna)
244 /* Update HNA routes */
245 olsr_calculate_hna_routes();
248 if (olsr_cnf->debug_level > 0)
251 if (olsr_cnf->debug_level > 1)
252 olsr_print_tc_table();
254 if (olsr_cnf->debug_level > 2)
256 olsr_print_mid_set();
258 if (olsr_cnf->debug_level > 3)
260 olsr_print_duplicate_table();
261 olsr_print_hna_set();
265 olsr_print_link_set();
266 olsr_print_neighbor_table();
269 for(tmp_pc_list = pcf_list;
271 tmp_pc_list = tmp_pc_list->next)
273 tmp_pc_list->function(changes_neighborhood,
278 changes_neighborhood = OLSR_FALSE;
279 changes_topology = OLSR_FALSE;
280 changes_hna = OLSR_FALSE;
291 *Initialize all the tables used(neighbor,
292 *topology, MID, HNA, MPR, dup).
293 *Also initalizes other variables
299 changes_topology = OLSR_FALSE;
300 changes_neighborhood = OLSR_FALSE;
301 changes_hna = OLSR_FALSE;
303 /* Initialize link set */
304 olsr_init_link_set();
306 /* Initialize duplicate table */
307 olsr_init_duplicate_table();
309 /* Initialize neighbor table */
310 olsr_init_neighbor_table();
312 /* Initialize routing table */
313 olsr_init_routing_table();
315 /* Initialize two hop table */
316 olsr_init_two_hop_table();
318 /* Initialize old route table */
319 olsr_init_old_table();
321 /* Initialize topology */
324 /* Initialize mpr selector table */
325 olsr_init_mprs_set();
327 /* Initialize MID set */
330 /* Initialize HNA set */
333 /* Initialize ProcessChanges list */
344 *Check if a message is to be forwarded and forward
347 *@param m the OLSR message recieved
348 *@param originator the originator of this message
349 *@param seqno the seqno of the message
351 *@returns positive if forwarded
354 olsr_forward_message(union olsr_message *m,
355 union olsr_ip_addr *originator,
357 struct interface *in_if,
358 union olsr_ip_addr *from_addr)
360 union olsr_ip_addr *src;
361 struct neighbor_entry *neighbor;
363 struct interface *ifn;
366 if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
369 olsr_printf(3, "Message already forwarded!\n");
374 /* Lookup sender address */
375 if(!(src = mid_lookup_main_addr(from_addr)))
379 if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
382 if(neighbor->status != SYM)
385 /* Update duplicate table interface */
386 olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
390 if(olsr_lookup_mprs_set(src) == NULL)
393 olsr_printf(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src));
399 /* Treat TTL hopcnt */
400 if(olsr_cnf->ip_version == AF_INET)
415 /* Update dup forwarded */
416 olsr_set_dup_forward(originator, seqno);
418 /* Update packet data */
421 msgsize = ntohs(m->v4.olsr_msgsize);
423 /* looping trough interfaces */
424 for (ifn = ifnet; ifn ; ifn = ifn->int_next)
426 if(net_output_pending(ifn))
429 * Check if message is to big to be piggybacked
431 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
436 set_buffer_timer(ifn);
438 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
440 olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
441 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
449 /* No forwarding pending */
450 set_buffer_timer(ifn);
452 if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
454 olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
455 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
466 set_buffer_timer(struct interface *ifn)
469 struct timeval jittertimer;
472 jitter = (float) random()/RAND_MAX;
473 jitter *= max_jitter;
475 olsr_init_timer((olsr_u32_t) (jitter*1000), &jittertimer);
477 timeradd(&now, &jittertimer, &fwdtimer[ifn->if_nr]);
484 olsr_init_willingness()
486 if(olsr_cnf->willingness_auto)
487 olsr_register_scheduler_event(&olsr_update_willingness, NULL, will_int, will_int, NULL);
491 olsr_update_willingness(void *foo)
495 tmp_will = olsr_cnf->willingness;
497 /* Re-calculate willingness */
498 olsr_cnf->willingness = olsr_calculate_willingness();
500 if(tmp_will != olsr_cnf->willingness)
502 olsr_printf(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
508 *Calculate this nodes willingness to act as a MPR
509 *based on either a fixed value or the power status
510 *of the node using APM
512 *@return a 8bit value from 0-7 representing the willingness
516 olsr_calculate_willingness()
518 struct olsr_apm_info ainfo;
520 /* If fixed willingness */
521 if(!olsr_cnf->willingness_auto)
522 return olsr_cnf->willingness;
524 #warning CHANGES IN THE apm INTERFACE(0.4.8)!
526 if(apm_read(&ainfo) < 1)
529 apm_printinfo(&ainfo);
532 if(ainfo.ac_line_status == OLSR_AC_POWERED)
535 /* If battery powered
537 * juice > 78% will: 3
538 * 78% > juice > 26% will: 2
539 * 26% > juice will: 1
541 return (ainfo.battery_percentage / 26);
547 *Termination function to be called whenever a error occures
548 *that requires the daemon to terminate
550 *@param msg the message to write to the syslog and possibly stdout
554 olsr_exit(const char *msg, int val)
556 olsr_printf(1, "OLSR EXIT: %s\n", msg);
557 olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
566 *Wrapper for malloc(3) that does error-checking
568 *@param size the number of bytes to allocalte
569 *@param caller a string identifying the caller for
570 *use in error messaging
572 *@return a void pointer to the memory allocated
575 olsr_malloc(size_t size, const char *id)
579 if((ptr = malloc(size)) == 0)
581 olsr_printf(1, "OUT OF MEMORY: %s\n", strerror(errno));
582 olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
583 olsr_exit((char *)id, EXIT_FAILURE);
590 *Wrapper for printf that prints to a specific
591 *debuglevel upper limit
596 olsr_printf(int loglevel, char *format, ...)
600 if(loglevel <= olsr_cnf->debug_level)
602 va_start(arglist, format);
604 vprintf(format, arglist);