/[dynamips]/upstream/dynamips-0.2.6-RC2/net_io_bridge.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/dynamips-0.2.6-RC2/net_io_bridge.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Sat Oct 6 16:05:34 2007 UTC (14 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 8951 byte(s)
dynamips-0.2.6-RC2

1 dpavlin 1 /*
2     * Cisco 7200 (Predator) simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * NetIO bridges.
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12     #include <pthread.h>
13     #include <errno.h>
14     #include <sys/select.h>
15     #include <sys/time.h>
16     #include <sys/types.h>
17    
18     #include "utils.h"
19     #include "registry.h"
20     #include "net_io.h"
21     #include "net_io_bridge.h"
22    
23     #define PKT_MAX_SIZE 2048
24    
25     /* Receive a packet */
26     static int netio_bridge_recv_pkt(netio_desc_t *nio,u_char *pkt,ssize_t pkt_len,
27     netio_bridge_t *t)
28     {
29     int i;
30    
31     NETIO_BRIDGE_LOCK(t);
32    
33     for(i=0;i<NETIO_BRIDGE_MAX_NIO;i++)
34     if ((t->nio[i] != NULL) && (t->nio[i] != nio))
35     netio_send(t->nio[i],pkt,pkt_len);
36    
37     NETIO_BRIDGE_UNLOCK(t);
38     return(0);
39     }
40    
41     /* Acquire a reference to NetIO bridge from the registry (inc ref count) */
42     netio_desc_t *netio_bridge_acquire(char *name)
43     {
44     return(registry_find(name,OBJ_TYPE_NIO_BRIDGE));
45     }
46    
47     /* Release a NetIO bridge (decrement reference count) */
48     int netio_bridge_release(char *name)
49     {
50     return(registry_unref(name,OBJ_TYPE_NIO_BRIDGE));
51     }
52    
53     /* Create a virtual bridge */
54     netio_bridge_t *netio_bridge_create(char *name)
55     {
56     netio_bridge_t *t;
57    
58     /* Allocate a new bridge structure */
59     if (!(t = malloc(sizeof(*t))))
60     return NULL;
61    
62     memset(t,0,sizeof(*t));
63     pthread_mutex_init(&t->lock,NULL);
64    
65     if (!(t->name = strdup(name)))
66     goto err_name;
67    
68     /* Record this object in registry */
69     if (registry_add(t->name,OBJ_TYPE_NIO_BRIDGE,t) == -1) {
70     fprintf(stderr,"netio_bridge_create: unable to register bridge '%s'\n",
71     name);
72     goto err_reg;
73     }
74    
75     return t;
76    
77     err_reg:
78     free(t->name);
79     err_name:
80     free(t);
81     return NULL;
82     }
83    
84     /* Add a NetIO descriptor to a virtual bridge */
85     int netio_bridge_add_netio(netio_bridge_t *t,char *nio_name)
86     {
87     netio_desc_t *nio;
88     int i;
89    
90     NETIO_BRIDGE_LOCK(t);
91    
92     /* Try to find a free slot in the NIO array */
93     for(i=0;i<NETIO_BRIDGE_MAX_NIO;i++)
94     if (t->nio[i] == NULL)
95     break;
96    
97     /* No free slot found ... */
98     if (i == NETIO_BRIDGE_MAX_NIO)
99     goto error;
100    
101     /* Acquire the NIO descriptor and increment its reference count */
102     if (!(nio = netio_acquire(nio_name)))
103     goto error;
104    
105     t->nio[i] = nio;
106     netio_rxl_add(nio,(netio_rx_handler_t)netio_bridge_recv_pkt,t,NULL);
107     NETIO_BRIDGE_UNLOCK(t);
108     return(0);
109    
110     error:
111     NETIO_BRIDGE_UNLOCK(t);
112     return(-1);
113     }
114    
115     /* Free resources used by a NIO in a bridge */
116     static void netio_bridge_free_nio(netio_desc_t *nio)
117     {
118     netio_rxl_remove(nio);
119     netio_release(nio->name);
120     }
121    
122     /* Remove a NetIO descriptor from a virtual bridge */
123     int netio_bridge_remove_netio(netio_bridge_t *t,char *nio_name)
124     {
125     netio_desc_t *nio;
126     int i;
127    
128     NETIO_BRIDGE_LOCK(t);
129    
130     if (!(nio = registry_exists(nio_name,OBJ_TYPE_NIO)))
131     goto error;
132    
133     /* Try to find the NIO in the NIO array */
134     for(i=0;i<NETIO_BRIDGE_MAX_NIO;i++)
135     if (t->nio[i] == nio)
136     break;
137    
138     if (i == NETIO_BRIDGE_MAX_NIO)
139     goto error;
140    
141     /* Remove the NIO from the RX multiplexer */
142     netio_bridge_free_nio(t->nio[i]);
143     t->nio[i] = NULL;
144    
145     NETIO_BRIDGE_UNLOCK(t);
146     return(0);
147    
148     error:
149     NETIO_BRIDGE_UNLOCK(t);
150     return(-1);
151     }
152    
153     /* Save the configuration of a bridge */
154     void netio_bridge_save_config(netio_bridge_t *t,FILE *fd)
155     {
156     int i;
157    
158     fprintf(fd,"nio_bridge create %s\n",t->name);
159    
160     for(i=0;i<NETIO_BRIDGE_MAX_NIO;i++)
161     fprintf(fd,"nio_bridge add_nio %s %s\n",t->name,t->nio[i]->name);
162    
163     fprintf(fd,"\n");
164     }
165    
166     /* Save configurations of all NIO bridges */
167     static void netio_bridge_reg_save_config(registry_entry_t *entry,
168     void *opt,int *err)
169     {
170     netio_bridge_save_config((netio_bridge_t *)entry->data,(FILE *)opt);
171     }
172    
173     void netio_bridge_save_config_all(FILE *fd)
174     {
175     registry_foreach_type(OBJ_TYPE_NIO_BRIDGE,netio_bridge_reg_save_config,
176     fd,NULL);
177     }
178    
179     /* Free resources used by a NIO bridge */
180     static int netio_bridge_free(void *data,void *arg)
181     {
182     netio_bridge_t *t = data;
183     int i;
184    
185     NETIO_BRIDGE_LOCK(t);
186    
187     for(i=0;i<NETIO_BRIDGE_MAX_NIO;i++) {
188     if (!t->nio[i])
189     continue;
190    
191     netio_bridge_free_nio(t->nio[i]);
192     }
193    
194     NETIO_BRIDGE_UNLOCK(t);
195     free(t->name);
196     free(t);
197     return(TRUE);
198     }
199    
200     /* Delete a virtual bridge */
201     int netio_bridge_delete(char *name)
202     {
203     return(registry_delete_if_unused(name,OBJ_TYPE_NIO_BRIDGE,
204     netio_bridge_free,NULL));
205     }
206    
207     /* Delete all virtual bridges */
208     int netio_bridge_delete_all(void)
209     {
210     return(registry_delete_type(OBJ_TYPE_NIO_BRIDGE,netio_bridge_free,NULL));
211     }
212    
213     /* Create a new interface */
214     static int netio_bridge_cfg_create_if(netio_bridge_t *t,
215     char **tokens,int count)
216     {
217     netio_desc_t *nio = NULL;
218     int nio_type;
219    
220     nio_type = netio_get_type(tokens[1]);
221     switch(nio_type) {
222     case NETIO_TYPE_UNIX:
223     if (count != 4) {
224     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
225     "for UNIX NIO\n");
226     break;
227     }
228    
229     nio = netio_desc_create_unix(tokens[0],tokens[2],tokens[3]);
230     break;
231    
232     case NETIO_TYPE_TAP:
233     if (count != 3) {
234     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
235     "for TAP NIO\n");
236     break;
237     }
238    
239     nio = netio_desc_create_tap(tokens[0],tokens[2]);
240     break;
241    
242     case NETIO_TYPE_UDP:
243     if (count != 5) {
244     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
245     "for UDP NIO\n");
246     break;
247     }
248    
249     nio = netio_desc_create_udp(tokens[0],atoi(tokens[2]),
250     tokens[3],atoi(tokens[4]));
251     break;
252    
253     case NETIO_TYPE_TCP_CLI:
254     if (count != 4) {
255     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
256     "for TCP CLI NIO\n");
257     break;
258     }
259    
260     nio = netio_desc_create_tcp_cli(tokens[0],tokens[2],tokens[3]);
261     break;
262    
263     case NETIO_TYPE_TCP_SER:
264     if (count != 3) {
265     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
266     "for TCP SER NIO\n");
267     break;
268     }
269    
270     nio = netio_desc_create_tcp_ser(tokens[0],tokens[2]);
271     break;
272    
273     #ifdef GEN_ETH
274     case NETIO_TYPE_GEN_ETH:
275     if (count != 3) {
276     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
277     "for Generic Ethernet NIO\n");
278     break;
279     }
280    
281     nio = netio_desc_create_geneth(tokens[0],tokens[2]);
282     break;
283     #endif
284    
285     #ifdef LINUX_ETH
286     case NETIO_TYPE_LINUX_ETH:
287     if (count != 3) {
288     fprintf(stderr,"NETIO_BRIDGE: invalid number of arguments "
289     "for Linux Ethernet NIO\n");
290     break;
291     }
292    
293     nio = netio_desc_create_lnxeth(tokens[0],tokens[2]);
294     break;
295     #endif
296    
297     default:
298     fprintf(stderr,"NETIO_BRIDGE: unknown/invalid NETIO type '%s'\n",
299     tokens[1]);
300     }
301    
302     if (!nio) {
303     fprintf(stderr,"NETIO_BRIDGE: unable to create NETIO descriptor\n");
304     return(-1);
305     }
306    
307     if (netio_bridge_add_netio(t,tokens[0]) == -1) {
308     fprintf(stderr,"NETIO_BRIDGE: unable to add NETIO descriptor.\n");
309     netio_release(nio->name);
310     return(-1);
311     }
312    
313     netio_release(nio->name);
314     return(0);
315     }
316    
317     #define NETIO_BRIDGE_MAX_TOKENS 16
318    
319     /* Handle a configuration line */
320     static int netio_bridge_handle_cfg_line(netio_bridge_t *t,char *str)
321     {
322     char *tokens[NETIO_BRIDGE_MAX_TOKENS];
323     int count;
324    
325     if ((count = m_strsplit(str,':',tokens,NETIO_BRIDGE_MAX_TOKENS)) <= 2)
326     return(-1);
327    
328     return(netio_bridge_cfg_create_if(t,tokens,count));
329     }
330    
331     /* Read a configuration file */
332     static int netio_bridge_read_cfg_file(netio_bridge_t *t,char *filename)
333     {
334     char buffer[1024],*ptr;
335     FILE *fd;
336    
337     if (!(fd = fopen(filename,"r"))) {
338     perror("fopen");
339     return(-1);
340     }
341    
342     while(!feof(fd)) {
343     if (!fgets(buffer,sizeof(buffer),fd))
344     break;
345    
346     /* skip comments and end of line */
347     if ((ptr = strpbrk(buffer,"#\r\n")) != NULL)
348     *ptr = 0;
349    
350     /* analyze non-empty lines */
351     if (strchr(buffer,':'))
352     netio_bridge_handle_cfg_line(t,buffer);
353     }
354    
355     fclose(fd);
356     return(0);
357     }
358    
359     /* Start a virtual bridge */
360     int netio_bridge_start(char *filename)
361     {
362     netio_bridge_t *t;
363    
364     if (!(t = netio_bridge_create("default"))) {
365     fprintf(stderr,"NETIO_BRIDGE: unable to create virtual fabric table.\n");
366     return(-1);
367     }
368    
369     if (netio_bridge_read_cfg_file(t,filename) == -1) {
370     fprintf(stderr,"NETIO_BRIDGE: unable to parse configuration file.\n");
371     return(-1);
372     }
373    
374     netio_bridge_release("default");
375     return(0);
376     }

  ViewVC Help
Powered by ViewVC 1.1.26