34790260edc1ce24ca4c6e6a74bca229d063ab33
[olsrd.git] / src / scheduler.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
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 
15  *   distribution.
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.
19  *
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.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
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.
38  *
39  * $Id: scheduler.c,v 1.21 2004/11/21 11:28:56 kattemat Exp $
40  */
41
42
43 #include "defs.h"
44 #include "scheduler.h"
45 #include "tc_set.h"
46 #include "link_set.h"
47 #include "duplicate_set.h"
48 #include "mpr_selector_set.h"
49 #include "mid_set.h"
50 #include "mpr.h"
51 #include "olsr.h"
52 #include "build_msg.h"
53
54
55 static float pollrate;
56 olsr_bool want_neigh;
57
58
59 /**
60  *Main scheduler event loop. Polls at every
61  *sched_poll_interval and calls all functions
62  *that are timed out or that are triggered.
63  *Also calls the olsr_process_changes()
64  *function at every poll.
65  *
66  *
67  *@return nada
68  */
69
70 void
71 scheduler()
72 {
73   struct timespec remainder_spec;
74   struct timespec sleeptime_spec;
75
76   /*
77    *Used to calculate sleep time
78    */
79   struct timeval start_of_loop;
80   struct timeval end_of_loop;
81   struct timeval time_used;
82   struct timeval interval;
83   struct timeval sleeptime_val;
84
85   olsr_u32_t interval_usec;
86
87   struct event_entry *entry;
88   struct timeout_entry *time_out_entry;
89
90   struct interface *ifn;
91  
92   pollrate = olsr_cnf->pollrate;
93
94   interval_usec = (olsr_u32_t)(pollrate * 1000000);
95
96   interval.tv_sec = interval_usec / 1000000;
97   interval.tv_usec = interval_usec % 1000000;
98
99   olsr_printf(1, "Scheduler started - polling every %0.2f seconds\n", pollrate);
100
101   olsr_printf(3, "Max jitter is %f\n\n", max_jitter);
102
103
104
105   /* Main scheduler event loop */
106
107   for(;;)
108     {
109
110       gettimeofday(&start_of_loop, NULL);
111
112       /* Update the global timestamp */
113       gettimeofday(&now, NULL);
114       nowtm = gmtime((time_t *)&now.tv_sec);
115
116       while (nowtm == NULL)
117         {
118           nowtm = gmtime((time_t *)&now.tv_sec);
119         }
120
121
122       /* Run timout functions (before packet generation) */
123
124       time_out_entry = timeout_functions;
125       
126       while(time_out_entry)
127         {
128           time_out_entry->function();
129           time_out_entry = time_out_entry->next;
130         }
131
132       /* Update */
133       
134       olsr_process_changes();
135
136
137       /* Check for changes in topology */
138
139       if (changes || want_neigh)
140         {
141           // if the MPR selector might have been updated, we have to print
142           // the updated neighbour table, as it now contains an "MPRS" column
143
144           olsr_print_neighbor_table();
145
146           want_neigh = OLSR_FALSE;
147         }
148
149       if(changes)
150         {
151           olsr_printf(3, "ANSN UPDATED %d\n\n", ansn);
152           ansn++;
153 #warning changes is set to OLSR_FALSE in scheduler now
154           changes = OLSR_FALSE;
155         }
156
157
158       /* Check scheduled events */
159
160       entry = event_functions;
161
162       /* UPDATED - resets timer upon triggered execution */
163       while(entry)
164         {
165           entry->since_last += pollrate;
166
167           /* Timed out */
168           if((entry->since_last > entry->interval) ||
169              /* Triggered */
170              ((entry->trigger != NULL) &&
171               (*(entry->trigger) == 1)))
172             {
173               /* Run scheduled function */
174               entry->function(entry->param);
175
176               /* Set jitter */
177               entry->since_last = (float) random()/RAND_MAX;
178               entry->since_last *= max_jitter;
179               
180               /* Reset trigger */
181               if(entry->trigger != NULL)
182                 *(entry->trigger) = 0;
183               
184               //olsr_printf(3, "Since_last jitter: %0.2f\n", entry->since_last);
185
186             }
187
188           entry = entry->next;
189         }
190
191
192
193       /* looping trough interfaces and emmittin pending data */
194       for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
195         { 
196           if(net_output_pending(ifn) && TIMED_OUT(&fwdtimer[ifn->if_nr])) 
197             net_output(ifn);
198         }
199
200
201       gettimeofday(&end_of_loop, NULL);
202
203       timersub(&end_of_loop, &start_of_loop, &time_used);
204
205
206       //printf("Time to sleep: %ld\n", sleeptime.tv_nsec);
207       //printf("Time used: %ld\n", time_used.tv_usec/1000);
208
209       if(timercmp(&time_used, &interval, <))
210         {
211           timersub(&interval, &time_used, &sleeptime_val);
212           
213           // printf("sleeptime_val = %u.%06u\n",
214           //        sleeptime_val.tv_sec, sleeptime_val.tv_usec);
215           
216           sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
217           sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * 1000;
218           
219           while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
220             sleeptime_spec = remainder_spec;
221         }
222       
223     }//end for
224 }
225
226
227 /*
228  *
229  *@param initial how long utnil the first generation
230  *@param trigger pointer to a boolean indicating that
231  *this function should be triggered immediatley
232  */
233 int
234 olsr_register_scheduler_event(void (*event_function)(void *), 
235                               void *par,
236                               float interval, 
237                               float initial, 
238                               olsr_u8_t *trigger)
239 {
240   struct event_entry *new_entry;
241
242   olsr_printf(3, "Scheduler event registered int: %0.2f\n", interval);
243
244   /* check that this entry is not added already */
245   new_entry = event_functions;
246   while(new_entry)
247     {
248       if((new_entry->function == event_function) &&
249          (new_entry->param == par) &&
250          (new_entry->trigger == trigger) &&
251          (new_entry->interval == interval))
252         {
253           fprintf(stderr, "Register scheduler event: Event alread registered!\n");
254           olsr_syslog(OLSR_LOG_ERR, "Register scheduler event: Event alread registered!\n");
255           return 0;
256         }
257       new_entry = new_entry->next;
258     }
259
260   new_entry = olsr_malloc(sizeof(struct event_entry), "add scheduler event");
261
262   new_entry->function = event_function;
263   new_entry->param = par;
264   new_entry->interval = interval;
265   new_entry->since_last = interval - initial;
266   new_entry->next = event_functions;
267   new_entry->trigger = trigger;
268
269   event_functions = new_entry;
270
271   return 1;
272 }
273
274
275
276 /*
277  *
278  *@param initial how long utnil the first generation
279  *@param trigger pointer to a boolean indicating that
280  *this function should be triggered immediatley
281  */
282 int
283 olsr_remove_scheduler_event(void (*event_function)(void *), 
284                             void *par,
285                             float interval, 
286                             float initial, 
287                             olsr_u8_t *trigger)
288 {
289   struct event_entry *entry, *prev;
290
291   prev = NULL;
292   entry = event_functions;
293
294   while(entry)
295     {
296       if((entry->function == event_function) &&
297          (entry->param == par) &&
298          (entry->trigger == trigger) &&
299          (entry->interval == interval))
300         {
301           if(entry == event_functions)
302             {
303               event_functions = entry->next;
304             }
305           else
306             {
307               prev->next = entry->next;
308             }
309           return 1;
310         }
311
312       prev = entry;
313       entry = entry->next;
314     }
315
316   return 0;
317 }
318
319
320 int
321 olsr_register_timeout_function(void (*time_out_function)(void))
322 {
323   struct timeout_entry *new_entry;
324
325   /* check that this entry is not added already */
326   new_entry = timeout_functions;
327   while(new_entry)
328     {
329       if(new_entry->function == time_out_function)
330         {
331           fprintf(stderr, "Register scheduler timeout: Event alread registered!\n");
332           olsr_syslog(OLSR_LOG_ERR, "Register scheduler timeout: Event alread registered!\n");
333           return 0;
334         }
335       new_entry = new_entry->next;
336     }
337
338   new_entry = olsr_malloc(sizeof(struct timeout_entry), "scheduler add timeout");
339
340   new_entry->function = time_out_function;
341   new_entry->next = timeout_functions;
342
343   timeout_functions = new_entry;
344
345   return 1;
346 }
347
348
349
350 int
351 olsr_remove_timeout_function(void (*time_out_function)(void))
352 {
353   struct timeout_entry *entry, *prev;
354
355   /* check that this entry is not added already */
356   entry = timeout_functions;
357   prev = NULL;
358
359   while(entry)
360     {
361       if(entry->function == time_out_function)
362         {
363           if(entry == timeout_functions)
364             {
365               timeout_functions = entry->next;
366             }
367           else
368             {
369               prev->next = entry->next;
370             }
371           free(entry);
372           return 1;
373         }
374       prev = entry;
375       entry = entry->next;
376     }
377
378   return 0;
379 }
380