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

Linux Cross Reference
cvs/emstar/link/liblink/link_multi.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 /*
 33  * Library for using multiple links from a single class
 34  *
 35  * $Id: link_multi.c,v 1.8 2005-09-25 06:08:45 girod Exp $
 36  */
 37 
 38 char link_multi_cvsid[] = "$Id: link_multi.c,v 1.8 2005-09-25 06:08:45 girod Exp $";
 39 
 40 #include <stdio.h>
 41 #include <stdlib.h>
 42 #include <sys/types.h>
 43 #include <sys/stat.h>
 44 #include <fcntl.h>
 45 #include <time.h>
 46 
 47 #include "liblink_i.h"
 48 #include "link_multi.h"
 49 #include "neighbor.h"
 50 #include "libdev/directory_client.h"
 51 
 52 struct _lu_multi_link {
 53   QUEUE_ELEMENT_DECL(_,struct _lu_multi_link);
 54 
 55   /* link listener state */
 56   char *link_name;
 57   int index;
 58   lu_context_t *lu;
 59 
 60   /* user data */
 61   void *data;
 62 
 63   /* neighbor listener state */
 64   status_client_context_t *neighbors;
 65   neighbor_t *curr_list;
 66 
 67   lu_multi_context_t *parent;
 68 };
 69 
 70 struct _lu_multi_context {
 71   lu_multi_opts_t opts;
 72   dir_event_ctx_t *class_dir;
 73   int warned;
 74   QUEUE_DECL(links,struct _lu_multi_link);
 75   struct _lu_multi_context **ref;
 76 };
 77 
 78 
 79 QUEUE_INLINE_INSTANTIATIONS(lum_links,_,links,lu_multi_link_t,lu_multi_context_t);
 80 QUEUE_FUNCTION_INSTANTIATIONS(lum_links,_,links,lu_multi_link_t,lu_multi_context_t);
 81 
 82 
 83 lu_multi_link_t *lu_multi_links_top(lu_multi_context_t *lu)
 84 {
 85   return lum_links_top(lu);
 86 }
 87 
 88 
 89 lu_multi_link_t *lu_multi_links_next(lu_multi_link_t *ptr)
 90 {
 91   return lum_links_next(ptr);
 92 }
 93 
 94 
 95 int lu_multi_links_qlen(lu_multi_context_t *lu)
 96 {
 97   return lum_links_qlen(lu);
 98 }
 99 
100 
101 lu_context_t *lu_multi_link_get_lu(lu_multi_link_t *l)
102 {
103   if (l) return l->lu;
104   return NULL;
105 }
106 
107 
108 void *lu_multi_link_get_data(lu_multi_link_t *l)
109 {
110   if (l) return l->data;
111   return NULL;
112 }
113 
114 
115 void lu_multi_link_set_data(lu_multi_link_t *l, void *data)
116 {
117   if (l) l->data = data;
118 }
119 
120 
121 int lu_multi_link_get_index(lu_multi_link_t *l)
122 {
123   if (l) return l->index;
124   return -1;
125 }
126 
127 
128 char *lu_multi_link_get_name(lu_multi_link_t *l)
129 {
130   if (l) return l->link_name;
131   return NULL;
132 }
133 
134 
135 lu_multi_context_t *lu_multi_link_get_parent(lu_multi_link_t *l)
136 {
137   if (l) return l->parent;
138   return NULL;
139 }
140 
141 
142 void *lu_multi_get_data(lu_multi_context_t *lm)
143 {
144   if (lm) return lm->opts.lu_opts.opts.data;
145   return NULL;
146 }
147 
148 
149 
150 lu_multi_link_t *lu_multi_index_link(lu_multi_context_t *lu, int index)
151 {
152   lu_multi_link_t *l;
153   for (l=lum_links_top(lu); l; l=lum_links_next(l)) {
154     if (l->index == index) return l;
155   }
156   return NULL;
157 }
158 
159 
160 lu_multi_link_t *lu_multi_lookup_link(lu_multi_context_t *lu, const char *name)
161 {
162   lu_multi_link_t *l;
163   for (l=lum_links_top(lu); l; l=lum_links_next(l)) {
164     if (strcmp(name, l->link_name) == 0) return l;
165   }
166   return NULL;
167 }
168 
169 
170 static
171 int lum_receive(lu_context_t *lu, link_pkt_t *pkt, ssize_t data_len)
172 {
173   lu_multi_link_t *l = (lu_multi_link_t *)lu_data(lu);
174   pkt->link_index = l->index;
175 
176   if (l->parent->opts.receive) {
177     int status = l->parent->opts.receive(l, pkt, data_len);
178     if (status == EVENT_DONE) {
179       lu_multi_destroy(l->parent);
180       return EVENT_DONE;
181     }
182   }
183   else
184     free(pkt);
185   
186   return EVENT_RENEW;
187 }
188 
189 
190 static
191 int lum_status(lu_context_t *lu)
192 {
193   lu_multi_link_t *l = (lu_multi_link_t *)lu_data(lu);
194   
195   if (l->parent->opts.status_notify) 
196     l->parent->opts.status_notify(l->parent, l);
197   
198   return EVENT_RENEW;
199 }
200 
201 
202 static
203 int lum_neighbor_list(neighbor_t *nb_list, int count, void *data)
204 {
205   lu_multi_link_t *l = (lu_multi_link_t *)data;
206   if (l->curr_list) free(l->curr_list);
207   l->curr_list = nb_list;
208   if (l->parent->opts.neighbor_change)
209     l->parent->opts.neighbor_change(l->parent, l);
210   return EVENT_RENEW;
211 }
212 
213 
214 int lu_multi_if_to_node(lu_multi_context_t *lu, if_id_t if_id, node_id_t *node_id)
215 {
216   lu_multi_link_t *l;
217   int filled = 0;
218   for (l=lum_links_top(lu); l; l=lum_links_next(l)) {
219     if (l->curr_list) {
220       int i;
221       for (i=0; l->curr_list[i].node_id; i++)
222         if (l->curr_list[i].if_id == if_id) {
223           if (node_id) *node_id = l->curr_list[i].node_id;
224           if (l->curr_list[i].state == ACTIVE)
225             return 0;
226           filled = 1;
227         }                    
228     }
229   }
230   if (filled) return 1;
231   return -1;
232 }
233 
234 
235 int lu_multi_node_to_if(lu_multi_context_t *lu, node_id_t node_id, if_id_t *if_id, int *index)
236 {
237   lu_multi_link_t *l;
238   int filled = 0;
239   for (l=lum_links_top(lu); l; l=lum_links_next(l)) {
240     if (l->curr_list) {
241       int i;
242       for (i=0; l->curr_list[i].node_id; i++)
243         if (l->curr_list[i].node_id == node_id) {
244           if (index) *index = l->index;
245           if (if_id) *if_id = l->curr_list[i].if_id;
246           if (l->curr_list[i].state == ACTIVE)
247             return 0;
248           filled = 1;
249         }                    
250     }
251   }
252   if (filled) return 1;
253   return -1;
254 }
255 
256 
257 int lu_multi_link_get_conn(lu_multi_link_t *l, if_id_t if_id)
258 {
259   if (l->curr_list) {
260     int i;
261     for (i=0; l->curr_list[i].node_id; i++)
262       if (l->curr_list[i].if_id == if_id) {
263         return l->curr_list[i].conn_from;
264       }
265   }
266   return -1;
267 }
268 
269 
270 static
271 lu_multi_link_t *lu_multi_open_link(lu_multi_context_t *lu,
272                                     const char *link_name, int index, 
273                                     const char *neighbors_name)
274 {
275   lu_multi_link_t *l = g_new0(lu_multi_link_t,1);
276   lu_opts_t opts = lu->opts.lu_opts;
277   
278   l->link_name = strdup(link_name ? link_name : neighbors_name);
279   l->index = index;
280   l->parent = lu;
281   l->data = opts.opts.data;
282 
283   if (link_name) {
284     opts.opts.name = l->link_name;
285     opts.receive = lum_receive;
286     opts.status_notify = lum_status;
287     opts.opts.data = l;
288     
289     if (lu_open(&opts, &(l->lu)) < 0) {
290       elog(LOG_WARNING, "Unable to open link %s", l->link_name);
291       free(l);
292       return NULL;
293     }
294     elog(LOG_NOTICE, "Opened link %s, index %d, filter %d", 
295          l->link_name, index, opts.opts.pkt_type);
296   }
297     
298   if (link_name || neighbors_name) {
299     /* connect to neighbors service */
300     neighbor_opts_t n_opts = {
301       link_name: neighbors_name ? (char*)neighbors_name : l->link_name, 
302       new_list: lum_neighbor_list,
303       data: l,
304       no_init_crashproof:1
305     };
306     
307     if (g_neighbors(&n_opts, &(l->neighbors)) < 0) 
308       elog(LOG_WARNING, "Unable to connect to neighbors service on link %s",
309            n_opts.link_name);
310     else
311       elog(LOG_NOTICE, "Opened neighbors %s, index %d", n_opts.link_name, index);
312   }
313 
314   lum_links_push(lu, l);
315   return l;
316 }
317 
318 
319 static
320 int lum_dir_update(dir_event_ctx_t *dir) 
321 {
322   lu_multi_context_t *lu = remote_dir_event_data(dir);
323 
324   /* iterate thru the directory */
325   for (remote_dir_event_top(dir);
326        remote_dir_event_valid(dir);
327        remote_dir_event_next(dir)) {
328     
329     int num;
330     char *link = remote_dir_event_get_curr(dir, &num);
331     
332     /* look it up */
333     lu_multi_link_t *lu_client = lu_multi_index_link(lu, num);
334 
335     /* missing? create a new client */
336     if (lu_client == NULL) {
337       lu_multi_link_t *l = lu_multi_open_link(lu, link, num, link);
338       if (l && lu->opts.new_link)
339         lu->opts.new_link(lu, l);
340     }
341   }
342     
343   return EVENT_RENEW;
344 }
345 
346 
347 int lu_multi_get_if_id(lu_multi_context_t *lum, int interface, if_id_t *iid)
348 {
349   lu_multi_link_t *lu = lu_multi_index_link(lum, interface);
350   if (lu == NULL) elog(LOG_NOTICE, "Can't find interface index %d", interface);
351   else {
352     lu_context_t *lu2 = lu_multi_link_get_lu(lu);
353     if (lu2) return lu_get_if_id(lu2, iid);
354     elog(LOG_NOTICE, "Can't find interface index %d --2", interface);
355   }
356   return -1;
357 }
358 
359 
360 
361 int lu_multi_send(lu_multi_context_t *lm, int interface, link_pkt_t *pkt, ssize_t data_len)
362 {
363   lu_multi_link_t *lu = lu_multi_index_link(lm, interface);
364   if (lu)
365     return lu_send(lu_multi_link_get_lu(lu), pkt, data_len);
366   errno = ENODEV;
367   return -1;
368 }
369 
370 
371 void lu_multi_destroy(lu_multi_context_t *lu)
372 {
373   if (lu) {
374     lu_multi_link_t *l;
375 
376     if (lu->ref) *(lu->ref) = NULL;
377 
378     while ((l=lum_links_pop(lu))) {
379       lu_destroy(l->lu);
380       free(l->link_name);
381       free(l);
382     }
383 
384     remote_dir_event_destroy(lu->class_dir);
385     free(lu->opts.if_class);
386 
387     free(lu);
388   }
389 }
390 
391 
392 int lum_warning(void *data, int interval, g_event_t *ev)
393 {
394   lu_multi_context_t *lum = (lu_multi_context_t *)data;
395   if (lum_links_qlen(lum) > 0) {
396     if (lum->warned) 
397       elog(LOG_WARNING, "Got a link.. link_multi OK");
398     return TIMER_DONE;
399   }
400 
401   if (lum->warned < 3) 
402     elog(LOG_WARNING, "%sNO LINKS yet in class %s.. did you create any?",
403          lum->warned > 0 ? "Still " : "", 
404          lum->opts.if_class);
405   lum->warned++;
406 
407   return TIMER_RENEW;
408 }
409 
410 
411 int lu_open_multi(lu_multi_opts_t *opts, lu_multi_context_t **ref)
412 {
413   lu_multi_context_t *lu = g_new0(lu_multi_context_t,1);
414   char buf[128];
415   char *dir_name;
416 
417   sprintf(buf, "/dev/link/classes/%s", opts->if_class);
418   dir_name = sim_path(buf);
419 
420   lu->opts = *opts;
421   lu->opts.lu_opts.opts.name = NULL;
422   lu->opts.lu_opts.opts.if_class = NULL;
423   lu->opts.if_class = strdup(lu->opts.if_class);
424   lu->opts.neighbors_list = 
425     lu->opts.neighbors_list ? strdup(lu->opts.neighbors_list) : NULL;
426 
427   if (lu->opts.receive == NULL) 
428     elog(LOG_WARNING, "no packet receive handler specified");
429 
430   /* set ref now because callbacks may be invoked */
431   if (ref) {
432     if (*ref) {
433       elog(LOG_WARNING, "Destroying reference");
434       lu_multi_destroy(*ref);
435     }
436     *ref = lu;
437   }
438 
439   /* register for directory info */
440   if (remote_dir_event_new(dir_name, lum_dir_update, lu, &(lu->class_dir)) < 0) {
441     elog(LOG_WARNING, "Unable to open %s class direcotory", dir_name);
442     if (ref) *ref = NULL;
443     free(lu);
444     return -1;
445   }
446 
447   /* if neighbors devs specified process them now */
448   /* $$$ parse csv */
449   if (lu->opts.neighbors_list) {
450     lu_multi_open_link(lu, NULL, -1, lu->opts.neighbors_list);
451   }
452 
453   /* set timer to emit warning message if you forgot to have anything in your class.. */
454   if (!lu->opts.withhold_warning)
455     g_timer_add(10000, lum_warning, lu, NULL, NULL);
456 
457   return 0;
458 }
459 
460 
461 
462 

~ [ 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.