Updated debug output generation, tebles are now printed only upon changes. Also added...
[olsrd.git] / src / olsr.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
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.
11  *
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.
16  *
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
20  * 
21  * 
22  * $Id: olsr.c,v 1.20 2004/11/09 21:09:58 kattemat Exp $
23  *
24  */
25
26 /**
27  * All these functions are global
28  */
29
30 #include "defs.h"
31 #include "olsr.h"
32 #include "link_set.h"
33 #include "two_hop_neighbor_table.h"
34 #include "tc_set.h"
35 #include "duplicate_set.h"
36 #include "mpr_selector_set.h"
37 #include "mid_set.h"
38 #include "mpr.h"
39 #if defined USE_LINK_QUALITY
40 #include "lq_mpr.h"
41 #include "lq_route.h"
42 #endif
43 #include "scheduler.h"
44 #include "generate_msg.h"
45 #include "apm.h"
46
47 #include <stdarg.h>
48 #include <signal.h>
49
50
51 /**
52  *Checks if a timer has timed out.
53  */
54
55
56 /**
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
61  *@return nada
62  */
63 inline void
64 olsr_init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
65
66   olsr_u16_t  time_value_sec;
67   olsr_u16_t  time_value_msec;
68
69   time_value_sec = time_value/1000;
70   time_value_msec = time_value-(time_value_sec*1000);
71
72   hold_timer->tv_sec = time_value_sec;
73   hold_timer->tv_usec = time_value_msec*1000;   
74 }
75
76
77
78
79
80 /**
81  *Generaties a timestamp a certain number of milliseconds
82  *into the future.
83  *
84  *@param time_value how many milliseconds from now
85  *@param hold_timer the timer itself
86  *@return nada
87  */
88 inline void
89 olsr_get_timestamp(olsr_u32_t delay, struct timeval *hold_timer)
90
91   hold_timer->tv_sec = now.tv_sec + delay / 1000;
92   hold_timer->tv_usec = now.tv_usec + (delay % 1000) * 1000;
93   
94   if (hold_timer->tv_usec > 1000000)
95     {
96       hold_timer->tv_sec++;
97       hold_timer->tv_usec -= 1000000;
98     }
99 }
100
101
102
103 /**
104  *Initialize the message sequence number as a random value
105  */
106 void
107 init_msg_seqno()
108 {
109   message_seqno = random() & 0xFFFF;
110 }
111
112 /**
113  * Get and increment the message sequence number
114  *
115  *@return the seqno
116  */
117 inline olsr_u16_t
118 get_msg_seqno()
119 {
120   return message_seqno++;
121 }
122
123
124 void
125 register_pcf(int (*f)(int, int, int))
126 {
127   struct pcf *new_pcf;
128
129   olsr_printf(1, "Registering pcf function\n");
130
131   new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
132
133   new_pcf->function = f;
134   new_pcf->next = pcf_list;
135   pcf_list = new_pcf;
136
137 }
138
139
140 /**
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.
145  *@return 0
146  */
147 inline void
148 olsr_process_changes()
149 {
150
151   struct pcf *tmp_pc_list;
152
153 #ifdef DEBUG
154   if(changes_neighborhood)
155     olsr_printf(3, "CHANGES IN NEIGHBORHOOD\n");
156   if(changes_topology)
157     olsr_printf(3, "CHANGES IN TOPOLOGY\n");
158   if(changes_hna)
159     olsr_printf(3, "CHANGES IN HNA\n");  
160 #endif
161
162   if(!changes_neighborhood &&
163      !changes_topology &&
164      !changes_hna)
165     return;
166
167   if(changes_neighborhood)
168     {
169       /* Calculate new mprs, HNA and routing table */
170 #if defined USE_LINK_QUALITY
171       if (olsr_cnf->lq_level < 1)
172         {
173 #endif
174           olsr_calculate_mpr();
175 #if defined USE_LINK_QUALITY
176         }
177
178       else
179         {
180           olsr_calculate_lq_mpr();
181         }
182
183
184       if (olsr_cnf->lq_level < 2)
185         {
186 #endif
187           olsr_calculate_routing_table();
188 #if defined USE_LINK_QUALITY
189         }
190
191       else
192         {
193           olsr_calculate_lq_routing_table();
194         }
195 #endif
196
197       olsr_calculate_hna_routes();
198       
199       /* Print updated info */
200       if(olsr_cnf->debug_level > 0) 
201         {
202 #ifdef USE_LINK_QUALITY
203           olsr_print_link_set();
204 #endif
205           olsr_print_neighbor_table();
206
207           if(olsr_cnf->debug_level > 1)
208             olsr_print_tc_table();
209
210           if(olsr_cnf->debug_level > 2) 
211             {
212               olsr_print_mprs_set();
213               olsr_print_mid_set();
214               olsr_print_duplicate_table();
215             }
216           if(changes_hna)
217             olsr_print_hna_set();
218
219         }
220       goto process_pcf;  
221     }
222   
223   if(changes_topology)
224     {
225       /* calculate the routing table and HNA */
226 #if defined USE_LINK_QUALITY
227       if (olsr_cnf->lq_level < 2)
228         {
229 #endif
230           olsr_calculate_routing_table();
231 #if defined USE_LINK_QUALITY
232         }
233
234       else
235         {
236           olsr_calculate_lq_routing_table();
237         }
238 #endif
239       olsr_calculate_hna_routes();
240
241       /* Print updated info */
242       if(olsr_cnf->debug_level > 1)
243         olsr_print_tc_table();
244
245       if(changes_hna)
246         olsr_print_hna_set();
247
248       goto process_pcf;  
249     }
250
251   if(changes_hna)
252     {
253       /* Update HNA routes */
254       olsr_calculate_hna_routes();
255
256       olsr_print_hna_set();
257
258       goto process_pcf;
259     }
260   
261  process_pcf:
262
263   for(tmp_pc_list = pcf_list; 
264       tmp_pc_list != NULL;
265       tmp_pc_list = tmp_pc_list->next)
266     {
267       tmp_pc_list->function(changes_neighborhood,
268                             changes_topology,
269                             changes_hna);
270     }
271
272   changes_neighborhood = OLSR_FALSE;
273   changes_topology = OLSR_FALSE;
274   changes_hna = OLSR_FALSE;
275
276
277   return;
278 }
279
280
281
282
283
284 /**
285  *Initialize all the tables used(neighbor,
286  *topology, MID,  HNA, MPR, dup).
287  *Also initalizes other variables
288  */
289 void
290 olsr_init_tables()
291 {
292   
293   changes_topology = OLSR_FALSE;
294   changes_neighborhood = OLSR_FALSE;
295   changes_hna = OLSR_FALSE;
296
297   /* Initialize link set */
298   olsr_init_link_set();
299
300   /* Initialize duplicate table */
301   olsr_init_duplicate_table();
302
303   /* Initialize neighbor table */
304   olsr_init_neighbor_table();
305
306   /* Initialize routing table */
307   olsr_init_routing_table();
308
309   /* Initialize two hop table */
310   olsr_init_two_hop_table();
311
312   /* Initialize old route table */
313   olsr_init_old_table();
314
315   /* Initialize topology */
316   olsr_init_tc();
317
318   /* Initialize mpr selector table */
319   olsr_init_mprs_set();
320
321   /* Initialize MID set */
322   olsr_init_mid_set();
323
324   /* Initialize HNA set */
325   olsr_init_hna_set();
326
327   /* Initialize ProcessChanges list */
328   ptf_list = NULL;
329   
330 }
331
332
333
334
335
336
337 /**
338  *Check if a message is to be forwarded and forward
339  *it if necessary.
340  *
341  *@param m the OLSR message recieved
342  *@param originator the originator of this message
343  *@param seqno the seqno of the message
344  *
345  *@returns positive if forwarded
346  */
347 int
348 olsr_forward_message(union olsr_message *m, 
349                      union olsr_ip_addr *originator, 
350                      olsr_u16_t seqno,
351                      struct interface *in_if, 
352                      union olsr_ip_addr *from_addr)
353 {
354   union olsr_ip_addr *src;
355   struct neighbor_entry *neighbor;
356   int msgsize;
357   struct interface *ifn;
358
359
360   if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
361     {
362 #ifdef DEBUG
363       olsr_printf(3, "Message already forwarded!\n");
364 #endif
365       return 0;
366     }
367
368   /* Lookup sender address */
369   if(!(src = mid_lookup_main_addr(from_addr)))
370     src = from_addr;
371
372
373   if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
374     return 0;
375
376   if(neighbor->status != SYM)
377     return 0;
378
379   /* Update duplicate table interface */
380   olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
381
382   
383   /* Check MPR */
384   if(olsr_lookup_mprs_set(src) == NULL)
385     {
386 #ifdef DEBUG
387       olsr_printf(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src));
388 #endif
389       return 0;
390     }
391
392
393   /* Treat TTL hopcnt */
394   if(olsr_cnf->ip_version == AF_INET)
395     {
396       /* IPv4 */
397       m->v4.hopcnt++;
398       m->v4.ttl--; 
399     }
400   else
401     {
402       /* IPv6 */
403       m->v6.hopcnt++;
404       m->v6.ttl--; 
405     }
406
407
408
409   /* Update dup forwarded */
410   olsr_set_dup_forward(originator, seqno);
411
412   /* Update packet data */
413
414
415   msgsize = ntohs(m->v4.olsr_msgsize);
416
417   /* looping trough interfaces */
418   for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
419     { 
420       if(net_output_pending(ifn))
421         {
422           /*
423            * Check if message is to big to be piggybacked
424            */
425           if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
426             {
427               /* Send */
428               net_output(ifn);
429               /* Buffer message */
430               set_buffer_timer(ifn);
431               
432               if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
433                 {
434                   olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
435                   olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
436                 }
437
438             }
439         }
440       
441       else
442         {
443           /* No forwarding pending */
444           set_buffer_timer(ifn);
445           
446           if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
447             {
448               olsr_printf(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
449               olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
450             }
451         }
452     }
453
454   return 1;
455
456 }
457
458
459 void
460 set_buffer_timer(struct interface *ifn)
461 {
462   float jitter;
463   struct timeval jittertimer;
464       
465   /* Set timer */
466   jitter = (float) random()/RAND_MAX;
467   jitter *= max_jitter;
468
469   olsr_init_timer((olsr_u32_t) (jitter*1000), &jittertimer);
470
471   timeradd(&now, &jittertimer, &fwdtimer[ifn->if_nr]);
472
473 }
474
475
476
477 void
478 olsr_init_willingness()
479 {
480   if(olsr_cnf->willingness_auto)
481     olsr_register_scheduler_event(&olsr_update_willingness, NULL, will_int, will_int, NULL);
482 }
483
484 void
485 olsr_update_willingness(void *foo)
486 {
487   int tmp_will;
488
489   tmp_will = olsr_cnf->willingness;
490
491   /* Re-calculate willingness */
492   olsr_cnf->willingness = olsr_calculate_willingness();
493
494   if(tmp_will != olsr_cnf->willingness)
495     {
496       olsr_printf(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
497     }
498 }
499
500
501 /**
502  *Calculate this nodes willingness to act as a MPR
503  *based on either a fixed value or the power status
504  *of the node using APM
505  *
506  *@return a 8bit value from 0-7 representing the willingness
507  */
508
509 olsr_u8_t
510 olsr_calculate_willingness()
511 {
512   struct olsr_apm_info ainfo;
513
514   /* If fixed willingness */
515   if(!olsr_cnf->willingness_auto)
516     return olsr_cnf->willingness;
517
518 #warning CHANGES IN THE apm INTERFACE(0.4.8)!
519
520   if(apm_read(&ainfo) < 1)
521     return WILL_DEFAULT;
522
523   apm_printinfo(&ainfo);
524
525   /* If AC powered */
526   if(ainfo.ac_line_status == OLSR_AC_POWERED)
527     return 6;
528
529   /* If battery powered 
530    *
531    * juice > 78% will: 3
532    * 78% > juice > 26% will: 2
533    * 26% > juice will: 1
534    */
535   return (ainfo.battery_percentage / 26);
536 }
537
538
539
540 /**
541  *Termination function to be called whenever a error occures
542  *that requires the daemon to terminate
543  *
544  *@param msg the message to write to the syslog and possibly stdout
545  */
546
547 void
548 olsr_exit(const char *msg, int val)
549 {
550   olsr_printf(1, "OLSR EXIT: %s\n", msg);
551   olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
552   fflush(stdout);
553   exit_value = val;
554
555   raise(SIGTERM);
556 }
557
558
559 /**
560  *Wrapper for malloc(3) that does error-checking
561  *
562  *@param size the number of bytes to allocalte
563  *@param caller a string identifying the caller for
564  *use in error messaging
565  *
566  *@return a void pointer to the memory allocated
567  */
568 void *
569 olsr_malloc(size_t size, const char *id)
570 {
571   void *ptr;
572
573   if((ptr = malloc(size)) == 0) 
574     {
575       olsr_printf(1, "OUT OF MEMORY: %s\n", strerror(errno));
576       olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
577       olsr_exit((char *)id, EXIT_FAILURE);
578     }
579   return ptr;
580 }
581
582
583 /**
584  *Wrapper for printf that prints to a specific
585  *debuglevel upper limit
586  *
587  */
588
589 inline int
590 olsr_printf(int loglevel, char *format, ...)
591 {
592   va_list arglist;
593
594   if(loglevel <= olsr_cnf->debug_level)
595     {
596
597       if(stdout_pulse_set)
598         {
599           printf("\b");
600           stdout_pulse_set = OLSR_FALSE;
601         }
602
603       va_start(arglist, format);
604       
605       vprintf(format, arglist);
606       
607       va_end(arglist);
608     }
609
610
611   return 0;
612 }