Testing
[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.10 2004/09/21 19:06:56 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 #include "scheduler.h"
40 #include "generate_msg.h"
41 #include "apm.h"
42
43 #include <stdarg.h>
44 #include <signal.h>
45
46
47 /**
48  *Checks if a timer has timed out.
49  */
50
51
52 /**
53  *Initiates a "timer", wich is a timeval structure,
54  *with the value given in time_value.
55  *@param time_value the value to initialize the timer with
56  *@param hold_timer the timer itself
57  *@return nada
58  */
59 inline void
60 olsr_init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
61
62   olsr_u16_t  time_value_sec;
63   olsr_u16_t  time_value_msec;
64
65   time_value_sec = time_value/1000;
66   time_value_msec = time_value-(time_value_sec*1000);
67
68   hold_timer->tv_sec = time_value_sec;
69   hold_timer->tv_usec = time_value_msec*1000;   
70 }
71
72
73
74
75
76 /**
77  *Generaties a timestamp a certain number of milliseconds
78  *into the future.
79  *
80  *@param time_value how many milliseconds from now
81  *@param hold_timer the timer itself
82  *@return nada
83  */
84 inline void
85 olsr_get_timestamp(olsr_u32_t delay, struct timeval *hold_timer)
86
87   hold_timer->tv_sec = now.tv_sec + delay / 1000;
88   hold_timer->tv_usec = now.tv_usec + (delay % 1000) * 1000;
89   
90   if (hold_timer->tv_usec > 1000000)
91     {
92       hold_timer->tv_sec++;
93       hold_timer->tv_usec -= 1000000;
94     }
95 }
96
97
98
99 /**
100  *Initialize the message sequence number as a random value
101  */
102 void
103 init_msg_seqno()
104 {
105   message_seqno = random() & 0xFFFF;
106 }
107
108 /**
109  * Get and increment the message sequence number
110  *
111  *@return the seqno
112  */
113 inline olsr_u16_t
114 get_msg_seqno()
115 {
116   return message_seqno++;
117 }
118
119
120 void
121 register_pcf(int (*f)(int, int, int))
122 {
123   struct pcf *new_pcf;
124
125   olsr_printf(1, "Registering pcf function\n");
126
127   new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
128
129   new_pcf->function = f;
130   new_pcf->next = pcf_list;
131   pcf_list = new_pcf;
132
133 }
134
135
136 /**
137  *Process changes in neighborhood or/and topology.
138  *Re-calculates the neighborhooh/topology if there
139  *are any updates - then calls the right functions to
140  *update the routing table.
141  *@return 0
142  */
143 inline void
144 olsr_process_changes()
145 {
146
147   struct pcf *tmp_pc_list;
148
149 #ifdef DEBUG
150   if(changes_neighborhood)
151     olsr_printf(3, "CHANGES IN NEIGHBORHOOD\n");
152   if(changes_topology)
153     olsr_printf(3, "CHANGES IN TOPOLOGY\n");
154   if(changes_hna)
155     olsr_printf(3, "CHANGES IN HNA\n");  
156 #endif
157
158   if(!changes_neighborhood &&
159      !changes_topology &&
160      !changes_hna)
161     return;
162
163   if(changes_neighborhood)
164     {
165       /* Calculate new mprs, HNA and routing table */
166       olsr_calculate_mpr();
167       olsr_calculate_routing_table();
168       olsr_calculate_hna_routes();
169
170       goto process_pcf;  
171     }
172   
173   if(changes_topology)
174     {
175       /* calculate the routing table and HNA */
176       olsr_calculate_routing_table();
177       olsr_calculate_hna_routes();
178
179       goto process_pcf;  
180     }
181
182   if(changes_hna)
183     {
184       /* Update HNA routes */
185       olsr_calculate_hna_routes();
186
187       goto process_pcf;
188     }
189   
190  process_pcf:
191
192   for(tmp_pc_list = pcf_list; 
193       tmp_pc_list != NULL;
194       tmp_pc_list = tmp_pc_list->next)
195     {
196       tmp_pc_list->function(changes_neighborhood,
197                             changes_topology,
198                             changes_hna);
199     }
200
201   changes_neighborhood = DOWN;
202   changes_topology = DOWN;
203   changes_hna = DOWN;
204
205
206   return;
207 }
208
209
210
211
212
213 /**
214  *Initialize all the tables used(neighbor,
215  *topology, MID,  HNA, MPR, dup).
216  *Also initalizes other variables
217  */
218 void
219 olsr_init_tables()
220 {
221   
222   changes_topology = DOWN;
223   changes_neighborhood = DOWN;
224   changes_hna = DOWN;
225
226   /* Initialize link set */
227   olsr_init_link_set();
228
229   /* Initialize duplicate table */
230   olsr_init_duplicate_table();
231
232   /* Initialize neighbor table */
233   olsr_init_neighbor_table();
234
235   /* Initialize routing table */
236   olsr_init_routing_table();
237
238   /* Initialize two hop table */
239   olsr_init_two_hop_table();
240
241   /* Initialize old route table */
242   olsr_init_old_table();
243
244   /* Initialize topology */
245   olsr_init_tc();
246
247   /* Initialize mpr selector table */
248   olsr_init_mprs_set();
249
250   /* Initialize MID set */
251   olsr_init_mid_set();
252
253   /* Initialize HNA set */
254   olsr_init_hna_set();
255
256   /* Initialize ProcessChanges list */
257   ptf_list = NULL;
258   
259 }
260
261
262
263
264
265
266 /**
267  *Check if a message is to be forwarded and forward
268  *it if necessary.
269  *
270  *@param m the OLSR message recieved
271  *@param originator the originator of this message
272  *@param seqno the seqno of the message
273  *
274  *@returns positive if forwarded
275  */
276 int
277 olsr_forward_message(union olsr_message *m, 
278                      union olsr_ip_addr *originator, 
279                      olsr_u16_t seqno,
280                      struct interface *in_if, 
281                      union olsr_ip_addr *from_addr)
282 {
283   union olsr_ip_addr *src;
284   struct neighbor_entry *neighbor;
285   int msgsize;
286
287
288   if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
289     {
290 #ifdef DEBUG
291       olsr_printf(3, "Message already forwarded!\n");
292 #endif
293       return 0;
294     }
295
296   /* Lookup sender address */
297   if(!(src = mid_lookup_main_addr(from_addr)))
298     src = from_addr;
299
300
301   if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
302     return 0;
303
304   if(neighbor->status != SYM)
305     return 0;
306
307   /* Update duplicate table interface */
308   olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
309
310   
311   /* Check MPR */
312   if(olsr_lookup_mprs_set(src) == NULL)
313     {
314 #ifdef DEBUG
315       olsr_printf(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src));
316 #endif
317       return 0;
318     }
319
320
321   /* Treat TTL hopcnt */
322   if(ipversion == AF_INET)
323     {
324       /* IPv4 */
325       m->v4.hopcnt++;
326       m->v4.ttl--; 
327     }
328   else
329     {
330       /* IPv6 */
331       m->v6.hopcnt++;
332       m->v6.ttl--; 
333     }
334
335
336
337   /* Update dup forwarded */
338   olsr_set_dup_forward(originator, seqno);
339
340   /* Update packet data */
341
342
343   msgsize = ntohs(m->v4.olsr_msgsize);
344
345   if(net_fwd_pending())
346     {
347       /*
348        * Check if message is to big to be piggybacked
349        */
350       if(net_fwdbuffer_push(m, msgsize) != msgsize)
351         {
352           olsr_printf(1, "Forwardbuffer full(%d + %d) - flushing!\n", fwdsize, msgsize);
353           
354           /* Send */
355           net_forward();
356           
357           /* Buffer message */
358           buffer_forward(m, msgsize);
359         }
360       else
361         {
362 #ifdef DEBUG
363           olsr_printf(3, "Piggybacking message - buffer: %d msg: %d\n", fwdsize, msgsize);
364 #endif
365           /* piggyback message to outputbuffer */
366         }
367     }
368
369   else
370     {
371       /* No forwarding pending */
372       buffer_forward(m, msgsize);
373     }
374
375   return 1;
376
377 }
378
379
380
381 int
382 buffer_forward(union olsr_message *m, olsr_u16_t msgsize)
383 {
384   float jitter;
385   struct timeval jittertimer;
386       
387   /* Set timer */
388   jitter = (float) random()/RAND_MAX;
389   jitter *= max_jitter;
390
391   olsr_init_timer((olsr_u32_t) (jitter*1000), &jittertimer);
392   
393   timeradd(&now, &jittertimer, &fwdtimer);
394   
395   
396 #ifdef DEBUG
397   olsr_printf(3, "Adding jitter for forwarding: %f size: %d\n", jitter, fwdsize);
398 #endif
399
400   /* Copy message to outputbuffer */
401   if(net_fwdbuffer_push(m, msgsize) != msgsize)
402     {
403       olsr_printf(1, "Received message to big to be forwarded(%d bytes)!", msgsize);
404       olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded(%d bytes)!", msgsize);
405       fwdtimer = now;
406     }
407
408   return 1;
409 }
410
411
412
413 void
414 olsr_init_willingness()
415 {
416   if(!willingness_set)
417     olsr_register_scheduler_event(&olsr_update_willingness, will_int, will_int, NULL);
418 }
419
420 void
421 olsr_update_willingness()
422 {
423   int tmp_will;
424
425   tmp_will = my_willingness;
426
427   /* Re-calculate willingness */
428   my_willingness = olsr_calculate_willingness();
429
430   if(tmp_will != my_willingness)
431     {
432       olsr_printf(1, "Local willingness updated: old %d new %d\n", tmp_will, my_willingness);
433     }
434 }
435
436
437 /**
438  *Calculate this nodes willingness to act as a MPR
439  *based on either a fixed value or the power status
440  *of the node using APM
441  *
442  *@return a 8bit value from 0-7 representing the willingness
443  */
444
445 olsr_u8_t
446 olsr_calculate_willingness()
447 {
448   struct olsr_apm_info ainfo;
449
450   /* If fixed willingness */
451   if(willingness_set)
452     return my_willingness;
453
454 #warning CHANGES IN THE apm INTERFACE(0.4.8)!
455
456   if(apm_read(&ainfo) < 1)
457     return WILL_DEFAULT;
458
459   apm_printinfo(&ainfo);
460
461   /* If AC powered */
462   if(ainfo.ac_line_status == OLSR_AC_POWERED)
463     return 6;
464
465   /* If battery powered 
466    *
467    * juice > 78% will: 3
468    * 78% > juice > 26% will: 2
469    * 26% > juice will: 1
470    */
471   return (ainfo.battery_percentage / 26);
472 }
473
474
475
476 /**
477  *Termination function to be called whenever a error occures
478  *that requires the daemon to terminate
479  *
480  *@param msg the message to write to the syslog and possibly stdout
481  */
482
483 void
484 olsr_exit(const char *msg, int val)
485 {
486   olsr_printf(1, "OLSR EXIT: %s\n", msg);
487   olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
488   fflush(stdout);
489   exit_value = val;
490
491   raise(SIGTERM);
492 }
493
494
495 /**
496  *Wrapper for malloc(3) that does error-checking
497  *
498  *@param size the number of bytes to allocalte
499  *@param caller a string identifying the caller for
500  *use in error messaging
501  *
502  *@return a void pointer to the memory allocated
503  */
504 void *
505 olsr_malloc(size_t size, const char *id)
506 {
507   void *ptr;
508
509   if((ptr = malloc(size)) == 0) 
510     {
511       olsr_printf(1, "OUT OF MEMORY: %s\n", strerror(errno));
512       olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
513       olsr_exit((char *)id, EXIT_FAILURE);
514     }
515   return ptr;
516 }
517
518
519 /**
520  *Wrapper for printf that prints to a specific
521  *debuglevel upper limit
522  *
523  */
524
525 inline int
526 olsr_printf(int loglevel, char *format, ...)
527 {
528   va_list arglist;
529
530   va_start(arglist, format);
531
532   if(loglevel <= debug_level)
533     {
534       vprintf(format, arglist);
535     }
536
537   va_end(arglist);
538
539   return 0;
540 }