113 |
113 |
#include "qemu-config.h"
|
114 |
114 |
|
115 |
115 |
#include "slirp/libslirp.h"
|
116 |
|
#include "qemu-queue.h"
|
117 |
116 |
|
118 |
|
|
119 |
|
static VLANState *first_vlan;
|
|
117 |
static QTAILQ_HEAD(, VLANState) vlans;
|
120 |
118 |
|
121 |
119 |
/***********************************************************/
|
122 |
120 |
/* network device redirectors */
|
... | ... | |
287 |
285 |
char buf[256];
|
288 |
286 |
int id = 0;
|
289 |
287 |
|
290 |
|
for (vlan = first_vlan; vlan; vlan = vlan->next) {
|
|
288 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
291 |
289 |
VLANClientState *vc;
|
292 |
290 |
|
293 |
|
for (vc = vlan->first_client; vc; vc = vc->next)
|
294 |
|
if (vc != vc1 && strcmp(vc->model, model) == 0)
|
|
291 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
|
292 |
if (vc != vc1 && strcmp(vc->model, model) == 0) {
|
295 |
293 |
id++;
|
|
294 |
}
|
|
295 |
}
|
296 |
296 |
}
|
297 |
297 |
|
298 |
298 |
snprintf(buf, sizeof(buf), "%s.%d", model, id);
|
... | ... | |
309 |
309 |
NetCleanup *cleanup,
|
310 |
310 |
void *opaque)
|
311 |
311 |
{
|
312 |
|
VLANClientState *vc, **pvc;
|
|
312 |
VLANClientState *vc;
|
|
313 |
|
313 |
314 |
vc = qemu_mallocz(sizeof(VLANClientState));
|
|
315 |
|
314 |
316 |
vc->model = qemu_strdup(model);
|
315 |
317 |
if (name)
|
316 |
318 |
vc->name = qemu_strdup(name);
|
... | ... | |
321 |
323 |
vc->receive_iov = receive_iov;
|
322 |
324 |
vc->cleanup = cleanup;
|
323 |
325 |
vc->opaque = opaque;
|
|
326 |
|
324 |
327 |
vc->vlan = vlan;
|
|
328 |
QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
|
325 |
329 |
|
326 |
|
vc->next = NULL;
|
327 |
|
pvc = &vlan->first_client;
|
328 |
|
while (*pvc != NULL)
|
329 |
|
pvc = &(*pvc)->next;
|
330 |
|
*pvc = vc;
|
331 |
330 |
return vc;
|
332 |
331 |
}
|
333 |
332 |
|
334 |
333 |
void qemu_del_vlan_client(VLANClientState *vc)
|
335 |
334 |
{
|
336 |
|
VLANClientState **pvc = &vc->vlan->first_client;
|
|
335 |
QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
|
337 |
336 |
|
338 |
|
while (*pvc != NULL)
|
339 |
|
if (*pvc == vc) {
|
340 |
|
*pvc = vc->next;
|
341 |
|
if (vc->cleanup) {
|
342 |
|
vc->cleanup(vc);
|
343 |
|
}
|
344 |
|
qemu_free(vc->name);
|
345 |
|
qemu_free(vc->model);
|
346 |
|
qemu_free(vc);
|
347 |
|
break;
|
348 |
|
} else
|
349 |
|
pvc = &(*pvc)->next;
|
|
337 |
if (vc->cleanup) {
|
|
338 |
vc->cleanup(vc);
|
|
339 |
}
|
|
340 |
|
|
341 |
qemu_free(vc->name);
|
|
342 |
qemu_free(vc->model);
|
|
343 |
qemu_free(vc);
|
350 |
344 |
}
|
351 |
345 |
|
352 |
346 |
VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
|
353 |
347 |
{
|
354 |
|
VLANClientState **pvc = &vlan->first_client;
|
|
348 |
VLANClientState *vc;
|
355 |
349 |
|
356 |
|
while (*pvc != NULL)
|
357 |
|
if ((*pvc)->opaque == opaque)
|
358 |
|
return *pvc;
|
359 |
|
else
|
360 |
|
pvc = &(*pvc)->next;
|
|
350 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
|
351 |
if (vc->opaque == opaque) {
|
|
352 |
return vc;
|
|
353 |
}
|
|
354 |
}
|
361 |
355 |
|
362 |
356 |
return NULL;
|
363 |
357 |
}
|
... | ... | |
375 |
369 |
return NULL;
|
376 |
370 |
}
|
377 |
371 |
|
378 |
|
for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
|
372 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
379 |
373 |
if (!strcmp(vc->name, client_str)) {
|
380 |
374 |
break;
|
381 |
375 |
}
|
... | ... | |
393 |
387 |
VLANState *vlan = sender->vlan;
|
394 |
388 |
VLANClientState *vc;
|
395 |
389 |
|
396 |
|
for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
|
390 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
397 |
391 |
if (vc == sender) {
|
398 |
392 |
continue;
|
399 |
393 |
}
|
... | ... | |
414 |
408 |
|
415 |
409 |
sender->vlan->delivering = 1;
|
416 |
410 |
|
417 |
|
for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
|
|
411 |
QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
|
418 |
412 |
ssize_t len;
|
419 |
413 |
|
420 |
414 |
if (vc == sender) {
|
... | ... | |
557 |
551 |
|
558 |
552 |
sender->vlan->delivering = 1;
|
559 |
553 |
|
560 |
|
for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
|
|
554 |
QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
|
561 |
555 |
ssize_t len;
|
562 |
556 |
|
563 |
557 |
if (vc == sender) {
|
... | ... | |
2305 |
2299 |
/* find or alloc a new VLAN */
|
2306 |
2300 |
VLANState *qemu_find_vlan(int id, int allocate)
|
2307 |
2301 |
{
|
2308 |
|
VLANState **pvlan, *vlan;
|
2309 |
|
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
2310 |
|
if (vlan->id == id)
|
|
2302 |
VLANState *vlan;
|
|
2303 |
|
|
2304 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
|
2305 |
if (vlan->id == id) {
|
2311 |
2306 |
return vlan;
|
|
2307 |
}
|
2312 |
2308 |
}
|
|
2309 |
|
2313 |
2310 |
if (!allocate) {
|
2314 |
2311 |
return NULL;
|
2315 |
2312 |
}
|
|
2313 |
|
2316 |
2314 |
vlan = qemu_mallocz(sizeof(VLANState));
|
2317 |
2315 |
vlan->id = id;
|
|
2316 |
QTAILQ_INIT(&vlan->clients);
|
2318 |
2317 |
QTAILQ_INIT(&vlan->send_queue);
|
2319 |
|
vlan->next = NULL;
|
2320 |
|
pvlan = &first_vlan;
|
2321 |
|
while (*pvlan != NULL)
|
2322 |
|
pvlan = &(*pvlan)->next;
|
2323 |
|
*pvlan = vlan;
|
|
2318 |
|
|
2319 |
QTAILQ_INSERT_TAIL(&vlans, vlan, next);
|
|
2320 |
|
2324 |
2321 |
return vlan;
|
2325 |
2322 |
}
|
2326 |
2323 |
|
... | ... | |
3118 |
3115 |
void do_info_network(Monitor *mon)
|
3119 |
3116 |
{
|
3120 |
3117 |
VLANState *vlan;
|
3121 |
|
VLANClientState *vc;
|
3122 |
3118 |
|
3123 |
|
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
|
3119 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
|
3120 |
VLANClientState *vc;
|
|
3121 |
|
3124 |
3122 |
monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
|
3125 |
|
for(vc = vlan->first_client; vc != NULL; vc = vc->next)
|
|
3123 |
|
|
3124 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
3126 |
3125 |
monitor_printf(mon, " %s: %s\n", vc->name, vc->info_str);
|
|
3126 |
}
|
3127 |
3127 |
}
|
3128 |
3128 |
}
|
3129 |
3129 |
|
... | ... | |
3134 |
3134 |
const char *name = qdict_get_str(qdict, "name");
|
3135 |
3135 |
const char *up_or_down = qdict_get_str(qdict, "up_or_down");
|
3136 |
3136 |
|
3137 |
|
for (vlan = first_vlan; vlan != NULL; vlan = vlan->next)
|
3138 |
|
for (vc = vlan->first_client; vc != NULL; vc = vc->next)
|
3139 |
|
if (strcmp(vc->name, name) == 0)
|
|
3137 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
|
3138 |
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
|
3139 |
if (strcmp(vc->name, name) == 0) {
|
3140 |
3140 |
goto done;
|
|
3141 |
}
|
|
3142 |
}
|
|
3143 |
}
|
3141 |
3144 |
done:
|
3142 |
3145 |
|
3143 |
3146 |
if (!vc) {
|
... | ... | |
3161 |
3164 |
{
|
3162 |
3165 |
VLANState *vlan;
|
3163 |
3166 |
|
3164 |
|
/* close network clients */
|
3165 |
|
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
3166 |
|
VLANClientState *vc = vlan->first_client;
|
3167 |
|
|
3168 |
|
while (vc) {
|
3169 |
|
VLANClientState *next = vc->next;
|
|
3167 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
|
3168 |
VLANClientState *vc, *next_vc;
|
3170 |
3169 |
|
|
3170 |
QTAILQ_FOREACH_SAFE(vc, &vlan->clients, next, next_vc) {
|
3171 |
3171 |
qemu_del_vlan_client(vc);
|
3172 |
|
|
3173 |
|
vc = next;
|
3174 |
3172 |
}
|
3175 |
3173 |
}
|
3176 |
3174 |
}
|
... | ... | |
3179 |
3177 |
{
|
3180 |
3178 |
VLANState *vlan;
|
3181 |
3179 |
|
3182 |
|
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
|
3180 |
QTAILQ_FOREACH(vlan, &vlans, next) {
|
3183 |
3181 |
if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
|
3184 |
3182 |
continue;
|
3185 |
3183 |
if (vlan->nb_guest_devs == 0)
|
... | ... | |
3206 |
3204 |
#endif
|
3207 |
3205 |
}
|
3208 |
3206 |
|
|
3207 |
QTAILQ_INIT(&vlans);
|
|
3208 |
|
3209 |
3209 |
if (qemu_opts_foreach(&qemu_net_opts, net_init_client, NULL, 1) == -1) {
|
3210 |
3210 |
return -1;
|
3211 |
3211 |
}
|