/[dynamips]/upstream/dynamips-0.2.6-RC1/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

Contents of /upstream/dynamips-0.2.6-RC1/net_io_bridge.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Sat Oct 6 16:03:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 8951 byte(s)
import dynamips-0.2.6-RC1

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