~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/routing/geo-linkstate/gls_nblist.c


  1 /*
  2  *
  3  * Copyright (c) 2003 The Regents of the University of California.  All 
  4  * 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  *
 13  * - Neither the name of the University nor the names of its
 14  *   contributors may be used to endorse or promote products derived
 15  *   from this software without specific prior written permission.
 16  *
 17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 20  * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  *
 29  */
 30  
 31 
 32 #include "common.h"
 33 #include "gls_i.h"
 34 #include "gls_nblist.h"
 35 #include "hash.h"
 36 #include "dijkstra.h"
 37 
 38 extern node_id_t my_node_id;
 39 extern loc_t my_loc;
 40 
 41 /* what's the upper bound on how often we wake up and send updates 
 42  * (it's specified in milliseconds) */
 43 #define INTER_UPDATE_INTERVAL_MSEC 500
 44 
 45 #define MY_LOG_LEVEL LOG_DEBUG(4)
 46 //#define MY_LOG_LEVEL LOG_NOTICE
 47 
 48 /******************* Utility Functions **********************/
 49 
 50 /* static void */
 51 /* print_nb_list(int count, neighbor_t *nb_list, buf_t *b) */
 52 /* { */
 53 /*   int i; */
 54 
 55 /*   assert(count);assert(nb_list);assert(b); */
 56 
 57 /*   bufprintf(b,"NeighborList(%d):",nb_list[i].node_id); */
 58   
 59 /*   for (i = 0; i < count; i++) { */
 60     
 61     /* Process only ACTIVE neighbors */
 62 /*     if (nb_list[i].state == ACTIVE) { */
 63 /*       bufprintf(b,":%d ",nb_list[i].node_id); */
 64 /*     } */
 65 /*   } */
 66 /* } */
 67 
 68 
 69 static GSList *
 70 get_active_nbr_glist(int count, neighbor_t *nb_list)
 71 {
 72   int i;
 73   GSList *neighborlist = NULL;
 74   gls_neighbor_t *n;
 75 
 76   assert(count);
 77   assert(nb_list);
 78         
 79   for (i = 0; i < count; i++) {
 80 
 81     /* Process only ACTIVE neighbors */
 82     if (nb_list[i].state == ACTIVE) {
 83 
 84       /* allocate memory for n */
 85       n = g_malloc0(sizeof(struct neighbor));
 86 
 87       elog(MY_LOG_LEVEL, "ACTIVE nbr: %d",nb_list[i].node_id);
 88 
 89       /* make a copy of the neighbor element */
 90       n->id = nb_list[i].node_id;
 91       /* and set its default weight */
 92       n->weight = 1;
 93       /* and its interface */
 94 /*       n->if_id = nb_list[i].if_id; */
 95 
 96       /* Prepend new element into neighborlist */
 97       neighborlist = g_slist_prepend(neighborlist, (gpointer)n);
 98     }
 99   }
100 
101   return neighborlist;
102 }
103 
104 
105 static gboolean
106 remove_neighbor(gpointer key, gpointer value, gpointer user_data)
107 {
108   assert(value);
109   /* destroy function is going to be called if this function is called by
110    * g_hash_table_foreach_remove, and it won't be called if
111    * g_hash_table_foreach_steal is called */
112   return TRUE;
113 }
114 
115 /******************* End Utility Functions **********************/
116 
117 
118 /* Convert nb_list to struct update.
119  * Does not allocate anything and returns NULL on errors 
120  */
121 static struct update *
122 get_nbr_update(node_id_t id, loc_t loc, GSList *nb_gslist)
123 {
124   struct update *u = NULL;
125   buf_t *b = buf_new();
126 
127   /* allocate update structure. 'g_malloc' aborts prog. on failure */
128   u = g_malloc0(sizeof(struct update));
129 
130   /* Assign id of node whose nb_list is being processed */
131   u->id  = id;
132         
133   /* Update location info for node "id" */
134   u->geo_update_present = TRUE;
135   u->geo.x = loc_trunc(loc.x);
136   u->geo.y = loc_trunc(loc.y);
137 
138   /* no udp update */
139   u->udp_update_present = FALSE;
140 
141   /* initialize a list of neighbors to NULL */
142   u->neighbors = nb_gslist;
143 
144   elog(MY_LOG_LEVEL, "id:%d loc.x:%f loc.y:%f ", 
145        id, loc.x, loc.y);
146         
147 /*   print_nb_list (count, nb_list, b); */
148 /*   elog (MY_LOG_LEVEL, "\n%s",b->buf); */
149   
150   buf_free(b);
151 
152 
153   return u;
154 }
155 
156 static void 
157 apply_update(struct update *u, struct routedev_info *tables)
158 {
159   gls_neighbor_t *n;
160   GSList *cur;
161   struct nodeconf *nodecfg;
162   gboolean insert_udp = TRUE;
163   gboolean insert_geo = TRUE;
164 
165   assert(u);
166   assert(tables);
167   assert(tables->nodeid);
168   assert(tables->geo);
169   assert(tables->udp);
170 
171   /* check if the node is present in nodeid table. If it isn't, we add it to
172    * all tables, since having a node present in nodeid table ensures it is
173    * present in other tables as well */
174   if ((nodecfg = g_hash_table_lookup(tables->nodeid, & u->id))) /* ... yep */
175     {
176 
177       elog(MY_LOG_LEVEL, "Node %d PRESENT in tables->nodeid",u->id);
178       
179       /* check to make sure udp information did not change. If it did, remove
180        * the old udp table entry, and enter new one */
181       if (  (u->udp_update_present)
182             && (  (nodecfg->udp.ip.s_addr != u->udp.ip.s_addr)
183                   || (nodecfg->udp.port      != u->udp.port)))
184         {
185           /* if present, pointer to node will be removed from the udp table */
186           g_hash_table_remove(tables->udp, & nodecfg->udp);
187         }
188       else
189         {
190           /* we don't remove nodecfg->udp, so no need to re-insert it */
191           insert_udp = FALSE;
192         }
193 
194       /* check to make sure geo information did not change. If it did, remove
195        * the old geo entry and, and enter new one */
196       if (  (u->geo_update_present)
197             && (  (nodecfg->geo.x != u->geo.x)
198                   || (nodecfg->geo.y != u->geo.y)))
199         {
200           /* if present, pointer to node will be removed from geo table */
201           g_hash_table_remove(tables->geo, & nodecfg->geo);
202         }
203       else
204         {
205           /* we don't remove nodecfg->geo, so no need to re-insert it */
206           insert_geo = FALSE;
207         }
208 
209       /* it is easier to remove/reenter neighbors, then to try to figure out
210        * if they have changed. Also, it would probably be a little more
211        * efficient to destroy/recreate table, as opposed to not destroying a
212        * table, but removing all elements. However, then we'd have an extra
213        * place where we create this neighborlist table, and that would not be
214        * good - more places to keep track of if something changes */
215       g_hash_table_foreach_remove(nodecfg->neighbor_list, remove_neighbor , 
216                                   NULL);
217     }
218   else  /* node for which we received an update is not present in table */
219     {
220 
221       elog(MY_LOG_LEVEL, "Node%d INSERTED in tables->nodeid",u->id);
222 
223       /* allocate a node */
224       nodecfg = g_new0(struct nodeconf, 1);
225       /* initialize our structure */
226       init_nodeconf(nodecfg);
227 
228       /* set structure fields, which are different from the defaults */
229       nodecfg->id = u->id;
230 
231       /* add the node to nodeid table */
232       g_hash_table_insert(tables->nodeid, &(nodecfg->id), nodecfg);
233     }
234 
235   /* store updated udp/geo info, since either the key has changed, or this is
236    * a new addition (if updated information was present, of course) */
237   if ((u->udp_update_present) && (insert_udp))
238     {
239       /* update udp information */
240       nodecfg->udp = u->udp;
241       /* make sure we can find this node by its udp info */
242       g_hash_table_insert(tables->udp, & nodecfg->udp, nodecfg);
243     }
244 
245   if ((u->geo_update_present) && (insert_geo))
246     {
247       elog (MY_LOG_LEVEL, "Updating GEO with address NODEID:%d LOC:%2.2f,%2.2f",
248             u->id, 0.0, 0.0);//u->geo.x, u->geo.y);
249       /* update geo information */
250       nodecfg->geo = u->geo;
251       /* make sure we can find this node by it's geo information */
252       g_hash_table_insert(tables->geo, & nodecfg->geo, nodecfg);
253     }
254 
255   /* either re-add, or newly-add neighbors (depending on whether the node was
256    * found in the table or not) */
257   for (cur = u->neighbors; cur; cur = g_slist_next(cur))
258     {
259       assert(cur->data);
260 
261       n = g_new0(gls_neighbor_t, 1);
262       n->id     = ((gls_neighbor_t *)cur->data)->id;
263       //      n->if_id = ((gls_neighbor_t *)cur->data)->if_id;
264       n->weight = ((gls_neighbor_t *)cur->data)->weight;
265       g_hash_table_insert(nodecfg->neighbor_list, &(n->id), n);
266     }
267 }
268 
269 static int 
270 recompute_timer(void *data, int interval, g_event_t *event)
271 {
272   gpointer tofree;
273   struct update *u;
274   gls_state_t *args = (gls_state_t *)data;
275 
276   assert(event);
277   assert(data);
278   assert(args);
279 
280   elog (MY_LOG_LEVEL, "Enter");
281 
282   /* the timer would only go off for us to process updates, so there must be
283    * some... */
284   assert(args->updates);
285   /* tables must've been created by now (they could be empty, but they must
286    * exist) */
287   assert(args->info);
288   /* note, that since routing table is dynamically
289    * allocated/deallocated/reallocated when we run dijkstra, it may not exist
290    * until compute_routing_table is run */
291   assert(args->info->nodeid);
292   assert(args->info->geo);
293   assert(args->info->udp);
294 
295   /* loop through updates */
296   while(! g_queue_is_empty(args->updates))
297     {
298       /* get next update from the head. we checked for g_queue_is_empty, so
299        * should never return NULL  */
300       u = g_queue_pop_head(args->updates);
301       assert(u);
302 
303       /* apply update, but don't recompute a routing table just yet */
304       apply_update(u, args->info);
305 
306       /* 
307        * done with this update - destroy it
308        */
309 
310       /* first, destroy the neighbors (we could've instead opted for not
311        * removing neighbors here, and simply stored them in the neighborlist
312        * during apply_update (as opposed to making copies there). This,
313        * however, seems a little cleaner. If performance is an issue, we could
314        * change that later */
315       while (u->neighbors)
316         {
317           /* once unlinked, we'll free this (that's the neighbor struct). we
318            * don't do it now, since g_slist_remove will be referencing 'data'
319            * pointer, and we don't want it to reference freed memory */
320           tofree = u->neighbors->data;
321           /* g_slist_remove removes the first element matching data. Since
322            * we're always @head of the list, we'll remove the element at the
323            * head and return a new list start) */
324           u->neighbors = g_slist_remove(u->neighbors, u->neighbors->data);
325           /* now free the data */
326           g_free(tofree);
327         }
328 
329       /* now, destroy the update structure */
330       g_free(u);
331     }
332 
333   /* destroy the timer (we don't need to keep firing if no more updates are
334    * coming in) */
335   if (0 > (g_event_destroy(args->recompute_timer)))
336     {
337       printf("handle_updates: Error destroying a timer\n");
338       return EVENT_ERROR(-1);
339     }
340 
341   args->recompute_timer = NULL;
342 
343   /* reset the number of times we were overidden */
344   args->num_timer_resets = 0;
345 
346 
347   elog(MY_LOG_LEVEL, "Printing global table for %d",my_node_id);
348         
349   /* print the entire neighbor table for debugging */
350   print_global_table((args->info)->nodeid);
351 
352 
353   /* Finally, recompute the routing table itself */
354   compute_routing_table(args->info, args->nodecfg);
355 
356   elog(MY_LOG_LEVEL, "Printing ROUTING TABLE");
357 
358   print_routing_table((args->info)->rtable);
359 
360 
361 #if 0   /* run debug querries. works with route.conf.3 file */
362 
363   {
364     printf("----------------------------------------\n");
365     printf("DEBUG QUERRIES - lookup nexthop info\n");
366     printf("----------------------------------------\n");
367     run_debug_queries("0.0.0.0", 0, 0, 0, 0, args->info);
368     printf("----------------------------------------\n");
369     run_debug_queries("1.1.1.1", 1, 1, 1, 1, args->info);
370     printf("----------------------------------------\n");
371     run_debug_queries("2.2.2.2", 2, 2, 2, 2, args->info);
372     printf("----------------------------------------\n");
373     run_debug_queries("3.3.3.3", 3, 3, 3, 3, args->info);
374     printf("----------------------------------------\n");
375     run_debug_queries("4.4.4.4", 4, 4, 4, 4, args->info);
376     printf("----------------------------------------\n");
377   }
378 #endif
379 
380   return EVENT_RENEW;
381 }
382 
383 
384 /* neighbor_t *nb_list, int count, void *data */
385 static int
386 new_neighbor_update(node_id_t id, loc_t loc, 
387                     GSList *nb_gslist, gls_state_t *args)
388 {
389   gboolean start_recompute_timer = FALSE;
390   struct update *u;
391         
392   if ((u = get_nbr_update(id, loc, nb_gslist)))
393     {
394       /* append an update to the queue */
395       g_queue_push_tail(args->updates, (gpointer)u);
396 
397       if (args->recompute_timer) /* recompute timer is active */
398         {
399           /* do we want to reset it? We do if we haven't reset it more then
400            * allowed number of times. Otherwise, we just wait for the timer to
401            * go off and process the updates without interfering */
402           if (args->num_timer_resets < args->max_timer_resets)
403             {
404               start_recompute_timer = TRUE;
405               args->num_timer_resets ++;
406 
407               /* destroy the timer that's there now. That's because we dont
408                * have a way to stop/start timers */
409               if (0 > (g_event_destroy(args->recompute_timer)))
410                 {
411                   printf("handle_updates: Error destroying a timer\n");
412                   return EVENT_ERROR(-1);
413                 }
414 
415               args->recompute_timer = NULL;
416             }
417         }
418       else      /* recompute timer is not active */
419         {
420           /* we then start it. 'num_timer_resets' is not incremented, since
421            * we assume that the first time the timer is started, it does not
422            * count as reset */
423           start_recompute_timer = TRUE;
424         }
425 
426       /* if necessary, start the timer which will then go off and process the
427        * updates */
428       if (start_recompute_timer)
429         {
430           /* timer options */
431           g_event_opts_t timer_opts;
432 
433           memset(&timer_opts, 0, sizeof timer_opts);
434           timer_opts.event_name = "recompute timer";
435 
436           if (0 > g_timer_add(args->recompute_timer_sleeptime,
437                               recompute_timer,
438                               args,
439                               &timer_opts, 
440                               &args->recompute_timer))
441             {
442               printf("handle_updates: g_timer_add failed\n");
443               return EVENT_ERROR(-1);
444             }
445         }
446     }
447   else  /* unsuccessful at receiving an update */
448     {
449       printf("handle_updates: Error receiving an update\n");
450       return EVENT_RENEW;
451     }
452 
453   return EVENT_RENEW;
454 }
455 
456 /* Returns size of the allocated flood packet */
457 /* static void marshal_flood_pkt (char *pkt, int pkt_size, node_id_t id,  */
458 /*                             loc_t loc, int count,  */
459 /*                             neighbor_t *nb_list) */
460 /* { */
461 /*   flood_pkt_t *flood_pkt = (flood_pkt_t *) pkt; */
462 
463 /*   /\* Allocate flood packet *\/ */
464 /*   flood_pkt->id = id; */
465 /*   flood_pkt->loc = loc; */
466 /*   flood_pkt->count = count; */
467 
468 /*   /\*  Copy in the constant sized fields *\/ */
469 /*   memcpy(pkt, flood_pkt, sizeof(flood_pkt_t)); */
470   
471 /*   /\*  and the variable sized nb_list *\/ */
472 /*   memcpy(flood_pkt->nb_list, */
473 /*       (void *)nb_list, count * sizeof(neighbor_t)); */
474 /* } */
475 
476 static void marshall_gslist (gpointer data, gpointer user_data)
477 {
478   buf_t *buf = (buf_t *) user_data;
479   gls_neighbor_t *n = (gls_neighbor_t *)data;
480 
481   elog(MY_LOG_LEVEL, "Copying Nbr:%d Weight:%d", (int)n->id, (int)n->weight);
482   bufcpy(buf, n, sizeof(gls_neighbor_t));
483 }
484 
485 static int flood_send_nb_list_update(node_id_t id, loc_t loc,  
486                                      GSList *nb_gslist, gls_state_t *gls_state)
487 {
488 
489   buf_t *pkt_out = buf_new();
490   
491   /* Create our *outgoing* link header */
492   link_pkt_t link_hdr = {
493     dst: {
494       id: LINK_BROADCAST,
495     },
496     type: PKT_TYPE_FLOOD_GLS,
497   };
498 
499   flood_pkt_t flood_hdr;
500 
501   flood_hdr.id = id;
502   flood_hdr.loc = loc;
503   flood_hdr.count = g_slist_length(nb_gslist);
504 
505   if (flood_hdr.count > 0) {
506 
507     bufcpy(pkt_out, &link_hdr,  sizeof(link_hdr));
508     bufcpy(pkt_out, &flood_hdr,  sizeof(flood_hdr));
509 
510     /* copy each element of nb_gslist into the packet */
511     g_slist_foreach(nb_gslist, (GFunc) marshall_gslist, (gpointer)pkt_out);
512   
513     elog(MY_LOG_LEVEL, "count:%d",flood_hdr.count);
514 
515     /* now launch the packet! */
516     if (link_send(gls_state->flood_link, (link_pkt_t *)pkt_out->buf, pkt_out->len) < 0)
517       elog(LOG_ERR, "can't send on %s: %m", link_name(link_opts(gls_state->flood_link)));
518     else
519       elog(MY_LOG_LEVEL, "broadcast nb_list");
520 
521   }
522 
523   free(pkt_out);
524   return 1;
525 }
526 
527 static int
528 gls_flood_timer(void *data, int interval, g_event_t *event)
529 {
530   gls_state_t *gs = (gls_state_t *)data;
531   GSList *nb_gslist;
532 
533   /* set the number of holdoffs to 0 */
534   gs->num_holdoffs = 0;
535   
536   /* Convert the nb_list into a GSList*/
537   nb_gslist = get_active_nbr_glist(gs->nb_list_count,gs->nb_list);
538 
539   elog(LOG_DEBUG_0, "Flooding nb_list");
540   
541   /* send the neighbor list to the entire network */
542   flood_send_nb_list_update(my_node_id, my_loc,
543                             nb_gslist, gs);
544 
545   return TIMER_DONE;
546 }
547 
548 
549 /* Update routing tables when new nb_list is received */
550 static int
551 local_nb_list_update(neighbor_t *nb_list, int count, void *data) {
552   gls_state_t *gls_state = (gls_state_t *) data;
553   GSList *nb_gslist;
554 
555   elog(LOG_DEBUG_0, "got local neighbor list");
556 
557   /* free the previously stored nb_list and store the current one */
558   if (gls_state->nb_list != NULL) free (gls_state->nb_list);
559   gls_state->nb_list = nb_list;
560   gls_state->nb_list_count = count;
561 
562   /* Convert the nb_list into a GSList*/
563   nb_gslist = get_active_nbr_glist(count,nb_list);
564   
565   /* schedule our tables for updation with the new neighbor list */
566   new_neighbor_update(my_node_id, my_loc, nb_gslist,
567                       (gls_state_t *) data);
568 
569   /* Set timeout for apps to flood */
570   /* If number of holdoffs > predefined value, then dont reschedule */
571   if (g_timer_isset(gls_state->holdoff_timer_event) && 
572       gls_state->num_holdoffs<MAX_HOLDOFFS) {
573     /* increment the number of holdoffs */
574     gls_state->num_holdoffs++;
575     /* reschedule the timer */
576     if (g_timer_resched(gls_state->holdoff_timer_event, FLOOD_TIMEOUT) < 0) {
577       elog(LOG_CRIT,"gls_flood_timer: g_timer_resched failed");
578       exit(1);
579     }
580   } else {
581     gls_state->num_holdoffs = 0;
582     if (g_timer_add(FLOOD_TIMEOUT, gls_flood_timer,
583                     gls_state, NULL, &(gls_state->holdoff_timer_event)) < 0)
584       {
585         elog(LOG_CRIT,"gls_flood_timer: g_timer_add failed");
586         exit(1);
587       }
588   }
589 
590   return EVENT_RENEW;
591 }
592 
593 static
594 int flood_receive_nb_list_update(link_pkt_t *link_pkt, 
595                                  ssize_t data_len, link_context_t *link)
596 {
597   GSList *nb_gslist = NULL;
598   gls_neighbor_t *n;
599 
600   /* Extract gls_state */
601   gls_state_t *gls_state = (gls_state_t *) link_opts(link)->data;
602 
603   /* Extract flood_pkt from link_pkt */
604   flood_pkt_t *flood_pkt = (flood_pkt_t *) link_pkt->data;
605 
606   /* Extract gls_nb_list from flood data */
607   gls_neighbor_t *gls_nb_list = (gls_neighbor_t *) flood_pkt->gls_nb_list;
608 
609   int i;
610 
611   elog(LOG_DEBUG_0, "Received Flooded Neighbor List from %d: Count: %d",
612        flood_pkt->id, flood_pkt->count);
613 
614   /* generate GSList from gls_neighbor_t */
615   for (i=0; i<flood_pkt->count; i++) {
616     /* allocate memory for n */
617     n = g_malloc0(sizeof(gls_neighbor_t));
618 
619     *n = gls_nb_list[i];
620 
621     elog(MY_LOG_LEVEL, "Nbr[%d] = %d Weight=%d",
622          flood_pkt->id,(int)gls_nb_list[i].id,(int)gls_nb_list[i].weight);
623 
624     /* Prepend new element into neighborlist */
625     nb_gslist = g_slist_prepend(nb_gslist, (gpointer)n);
626   }
627   
628   elog(MY_LOG_LEVEL, "Received nbr_list from %d", flood_pkt->id);
629 
630   new_neighbor_update(flood_pkt->id, flood_pkt->loc, 
631                       nb_gslist, gls_state);
632 
633   free (link_pkt);
634 
635   return 1;
636 }
637 
638 /*
639  * Come up, process configuration file to determine node topology, and create a
640  * routing table. Idle away, waiting for clients' "next hop" requests, and
641  * respond to them. Operates as a 'ROUTE_ROUTEDEV_NAME' device (set in the
642  * gls_i.h)
643  */
644 void
645 gls_nblist_open(gls_state_t *gls_state)
646 {
647 
648   neighbor_opts_t  n_opts = {
649     link_opts: {
650       link_index: LINK_INDEX_AUTO
651     },
652     new_list: local_nb_list_update,
653     data: (void *) gls_state /* routing state */
654   };
655 
656   /* nbr flood config */
657   link_opts_t flood_link_opts = {
658     link_index: LINK_INDEX_AUTO,   /* use any available link */
659     pkt_type: PKT_TYPE_FLOOD_GLS,  /* only give us type */
660     dev_type: LINK_DEV_FLOOD,      /* flood device */
661     q_opts: {
662       outq_len: 10000,
663       inq_len: 10000,
664     },
665     receive: flood_receive_nb_list_update, /* call this func when packets arrive */
666     data: (void *) gls_state       /* routing state */
667   };
668 
669   /* Open a link to the neighborlist service
670    * We're only listening on this daemon, so dont save 
671    * link state.
672    */
673   if (g_neighbors(&n_opts, NULL) < 0) {
674     elog(LOG_CRIT, "couldn't open neighborlist %s: %m",
675          link_name(&n_opts.link_opts));
676     exit(1);
677   }
678   
679   /*
680    * Open the link-layer device for receiving nb_lists that were flooded 
681    * from other nodes. 
682    * Save link state for later use.
683    */
684   if (link_open(&flood_link_opts, &gls_state->flood_link) < 0) {
685     elog(LOG_CRIT, "can't open %s: %m", link_name(&flood_link_opts));
686     exit(1);
687   }
688 
689   elog(MY_LOG_LEVEL, "gls_nblist running");
690 }
691 
692 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.