]> git.proxmox.com Git - mirror_qemu.git/blame - net/net.c
net: Update MemReentrancyGuard for NIC
[mirror_qemu.git] / net / net.c
CommitLineData
63a01ef8
AL
1/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
e688df6b 24
2744d920 25#include "qemu/osdep.h"
d40cdb10 26
1422e32d 27#include "net/net.h"
fd9400b3
PB
28#include "clients.h"
29#include "hub.h"
a27bd6c7 30#include "hw/qdev-properties.h"
1422e32d 31#include "net/slirp.h"
d60b20cf 32#include "net/eth.h"
fd9400b3 33#include "util.h"
a245fc18 34
83c9089e 35#include "monitor/monitor.h"
f348b6d1 36#include "qemu/help_option.h"
9af23989 37#include "qapi/qapi-commands-net.h"
f9bb0c1f 38#include "qapi/qapi-visit-net.h"
452fcdbc 39#include "qapi/qmp/qdict.h"
cc7a8ea7 40#include "qapi/qmp/qerror.h"
d49b6836 41#include "qemu/error-report.h"
1de7afc9 42#include "qemu/sockets.h"
f348b6d1 43#include "qemu/cutils.h"
1de7afc9 44#include "qemu/config-file.h"
856dfd8a 45#include "qemu/ctype.h"
27eb3722 46#include "qemu/id.h"
1de7afc9 47#include "qemu/iov.h"
ad6f932f 48#include "qemu/qemu-print.h"
6a1751b7 49#include "qemu/main-loop.h"
922a01a0 50#include "qemu/option.h"
5166fe0a 51#include "qemu/keyval.h"
e688df6b 52#include "qapi/error.h"
6687b79d 53#include "qapi/opts-visitor.h"
54d31236 54#include "sysemu/runstate.h"
0c7af1a7 55#include "net/colo-compare.h"
fdccce45 56#include "net/filter.h"
aa9156f4 57#include "qapi/string-output-visitor.h"
f3eedcdd 58#include "qapi/qobject-input-visitor.h"
511d2b14 59
2944e4ec
SW
60/* Net bridge is currently not supported for W32. */
61#if !defined(_WIN32)
62# define CONFIG_NET_BRIDGE
63#endif
64
ca77d85e 65static VMChangeStateEntry *net_change_state_entry;
ae71d13d 66NetClientStateList net_clients;
63a01ef8 67
f3eedcdd
LV
68typedef struct NetdevQueueEntry {
69 Netdev *nd;
70 Location loc;
71 QSIMPLEQ_ENTRY(NetdevQueueEntry) entry;
72} NetdevQueueEntry;
73
74typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
75
76static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
77
63a01ef8
AL
78/***********************************************************/
79/* network device redirectors */
80
30e4226b
LV
81int convert_host_port(struct sockaddr_in *saddr, const char *host,
82 const char *port, Error **errp)
63a01ef8 83{
63a01ef8 84 struct hostent *he;
30e4226b
LV
85 const char *r;
86 long p;
63a01ef8 87
59292384
PM
88 memset(saddr, 0, sizeof(*saddr));
89
63a01ef8 90 saddr->sin_family = AF_INET;
30e4226b 91 if (host[0] == '\0') {
63a01ef8
AL
92 saddr->sin_addr.s_addr = 0;
93 } else {
30e4226b
LV
94 if (qemu_isdigit(host[0])) {
95 if (!inet_aton(host, &saddr->sin_addr)) {
bcd4dfd6 96 error_setg(errp, "host address '%s' is not a valid "
30e4226b
LV
97 "IPv4 address", host);
98 return -1;
bcd4dfd6 99 }
63a01ef8 100 } else {
30e4226b 101 he = gethostbyname(host);
bcd4dfd6 102 if (he == NULL) {
30e4226b
LV
103 error_setg(errp, "can't resolve host address '%s'", host);
104 return -1;
bcd4dfd6 105 }
63a01ef8
AL
106 saddr->sin_addr = *(struct in_addr *)he->h_addr;
107 }
108 }
30e4226b
LV
109 if (qemu_strtol(port, &r, 0, &p) != 0) {
110 error_setg(errp, "port number '%s' is invalid", port);
111 return -1;
112 }
113 saddr->sin_port = htons(p);
114 return 0;
115}
116
117int parse_host_port(struct sockaddr_in *saddr, const char *str,
118 Error **errp)
119{
120 gchar **substrings;
121 int ret;
122
123 substrings = g_strsplit(str, ":", 2);
124 if (!substrings || !substrings[0] || !substrings[1]) {
125 error_setg(errp, "host address '%s' doesn't contain ':' "
126 "separating host from port", str);
add99347
SG
127 ret = -1;
128 goto out;
bcd4dfd6 129 }
30e4226b
LV
130
131 ret = convert_host_port(saddr, substrings[0], substrings[1], errp);
add99347
SG
132
133out:
134 g_strfreev(substrings);
135 return ret;
63a01ef8
AL
136}
137
890ee6ab
SF
138char *qemu_mac_strdup_printf(const uint8_t *macaddr)
139{
140 return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
141 macaddr[0], macaddr[1], macaddr[2],
142 macaddr[3], macaddr[4], macaddr[5]);
143}
144
53b85d95
LV
145void qemu_set_info_str(NetClientState *nc, const char *fmt, ...)
146{
147 va_list ap;
148
149 va_start(ap, fmt);
150 vsnprintf(nc->info_str, sizeof(nc->info_str), fmt, ap);
151 va_end(ap);
152}
153
35277d14 154void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
7cb7434b 155{
53b85d95
LV
156 qemu_set_info_str(nc, "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
157 nc->model, macaddr[0], macaddr[1], macaddr[2],
158 macaddr[3], macaddr[4], macaddr[5]);
7cb7434b
AL
159}
160
2bc22a58
SZ
161static int mac_table[256] = {0};
162
163static void qemu_macaddr_set_used(MACAddr *macaddr)
164{
165 int index;
166
167 for (index = 0x56; index < 0xFF; index++) {
168 if (macaddr->a[5] == index) {
169 mac_table[index]++;
170 }
171 }
172}
173
174static void qemu_macaddr_set_free(MACAddr *macaddr)
175{
176 int index;
177 static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };
178
179 if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
180 return;
181 }
182 for (index = 0x56; index < 0xFF; index++) {
183 if (macaddr->a[5] == index) {
184 mac_table[index]--;
185 }
186 }
187}
188
189static int qemu_macaddr_get_free(void)
190{
191 int index;
192
193 for (index = 0x56; index < 0xFF; index++) {
194 if (mac_table[index] == 0) {
195 return index;
196 }
197 }
198
199 return -1;
200}
201
76d32cba
GH
202void qemu_macaddr_default_if_unset(MACAddr *macaddr)
203{
76d32cba 204 static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
2bc22a58
SZ
205 static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };
206
207 if (memcmp(macaddr, &zero, sizeof(zero)) != 0) {
208 if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
209 return;
210 } else {
211 qemu_macaddr_set_used(macaddr);
212 return;
213 }
214 }
76d32cba 215
76d32cba
GH
216 macaddr->a[0] = 0x52;
217 macaddr->a[1] = 0x54;
218 macaddr->a[2] = 0x00;
219 macaddr->a[3] = 0x12;
220 macaddr->a[4] = 0x34;
2bc22a58
SZ
221 macaddr->a[5] = qemu_macaddr_get_free();
222 qemu_macaddr_set_used(macaddr);
76d32cba
GH
223}
224
d33d93b2
SH
225/**
226 * Generate a name for net client
227 *
c963530a 228 * Only net clients created with the legacy -net option and NICs need this.
d33d93b2 229 */
35277d14 230static char *assign_name(NetClientState *nc1, const char *model)
676cff29 231{
35277d14 232 NetClientState *nc;
676cff29
AL
233 int id = 0;
234
35277d14
SH
235 QTAILQ_FOREACH(nc, &net_clients, next) {
236 if (nc == nc1) {
d33d93b2 237 continue;
5610c3aa 238 }
c963530a 239 if (strcmp(nc->model, model) == 0) {
53e51d85
MA
240 id++;
241 }
242 }
243
4bf2c138 244 return g_strdup_printf("%s.%d", model, id);
676cff29
AL
245}
246
f7860455
JW
247static void qemu_net_client_destructor(NetClientState *nc)
248{
249 g_free(nc);
250}
25c01bd1
JW
251static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
252 unsigned flags,
253 const struct iovec *iov,
254 int iovcnt,
255 void *opaque);
f7860455 256
18a1541a
JW
257static void qemu_net_client_setup(NetClientState *nc,
258 NetClientInfo *info,
259 NetClientState *peer,
260 const char *model,
f7860455 261 const char *name,
2f849dbd
JW
262 NetClientDestructor *destructor,
263 bool is_datapath)
63a01ef8 264{
35277d14
SH
265 nc->info = info;
266 nc->model = g_strdup(model);
45460d1a 267 if (name) {
35277d14 268 nc->name = g_strdup(name);
45460d1a 269 } else {
35277d14 270 nc->name = assign_name(nc, model);
45460d1a 271 }
5610c3aa 272
ab5f3f84
SH
273 if (peer) {
274 assert(!peer->peer);
35277d14
SH
275 nc->peer = peer;
276 peer->peer = nc;
d80b9fc6 277 }
35277d14 278 QTAILQ_INSERT_TAIL(&net_clients, nc, next);
63a01ef8 279
3e033a46 280 nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
f7860455 281 nc->destructor = destructor;
2f849dbd 282 nc->is_datapath = is_datapath;
fdccce45 283 QTAILQ_INIT(&nc->filters);
18a1541a
JW
284}
285
286NetClientState *qemu_new_net_client(NetClientInfo *info,
287 NetClientState *peer,
288 const char *model,
289 const char *name)
290{
291 NetClientState *nc;
292
293 assert(info->size >= sizeof(NetClientState));
294
295 nc = g_malloc0(info->size);
f7860455 296 qemu_net_client_setup(nc, info, peer, model, name,
2f849dbd
JW
297 qemu_net_client_destructor, true);
298
299 return nc;
300}
301
302NetClientState *qemu_new_net_control_client(NetClientInfo *info,
303 NetClientState *peer,
304 const char *model,
305 const char *name)
306{
307 NetClientState *nc;
308
309 assert(info->size >= sizeof(NetClientState));
310
311 nc = g_malloc0(info->size);
312 qemu_net_client_setup(nc, info, peer, model, name,
313 qemu_net_client_destructor, false);
18a1541a 314
35277d14 315 return nc;
63a01ef8
AL
316}
317
ebef2c09
MM
318NICState *qemu_new_nic(NetClientInfo *info,
319 NICConf *conf,
320 const char *model,
321 const char *name,
7d0fefdf 322 MemReentrancyGuard *reentrancy_guard,
ebef2c09
MM
323 void *opaque)
324{
1ceef9f2 325 NetClientState **peers = conf->peers.ncs;
ebef2c09 326 NICState *nic;
575a1c0e 327 int i, queues = MAX(1, conf->peers.queues);
ebef2c09 328
f394b2e2 329 assert(info->type == NET_CLIENT_DRIVER_NIC);
ebef2c09
MM
330 assert(info->size >= sizeof(NICState));
331
f6b26cf2
JW
332 nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
333 nic->ncs = (void *)nic + info->size;
ebef2c09 334 nic->conf = conf;
9050f976 335 nic->reentrancy_guard = reentrancy_guard,
ebef2c09
MM
336 nic->opaque = opaque;
337
f6b26cf2
JW
338 for (i = 0; i < queues; i++) {
339 qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
2f849dbd 340 NULL, true);
1ceef9f2
JW
341 nic->ncs[i].queue_index = i;
342 }
343
ebef2c09
MM
344 return nic;
345}
346
1ceef9f2
JW
347NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
348{
f6b26cf2 349 return nic->ncs + queue_index;
1ceef9f2
JW
350}
351
b356f76d
JW
352NetClientState *qemu_get_queue(NICState *nic)
353{
1ceef9f2 354 return qemu_get_subqueue(nic, 0);
b356f76d
JW
355}
356
cc1f0f45
JW
357NICState *qemu_get_nic(NetClientState *nc)
358{
1ceef9f2
JW
359 NetClientState *nc0 = nc - nc->queue_index;
360
f6b26cf2 361 return (NICState *)((void *)nc0 - nc->info->size);
cc1f0f45
JW
362}
363
364void *qemu_get_nic_opaque(NetClientState *nc)
365{
366 NICState *nic = qemu_get_nic(nc);
367
368 return nic->opaque;
369}
370
0165daae
CL
371NetClientState *qemu_get_peer(NetClientState *nc, int queue_index)
372{
373 assert(nc != NULL);
374 NetClientState *ncs = nc + queue_index;
375 return ncs->peer;
376}
377
b20c6b9e 378static void qemu_cleanup_net_client(NetClientState *nc)
63a01ef8 379{
35277d14 380 QTAILQ_REMOVE(&net_clients, nc, next);
63a01ef8 381
cc2a9043
AF
382 if (nc->info->cleanup) {
383 nc->info->cleanup(nc);
384 }
a083a89d 385}
5610c3aa 386
b20c6b9e 387static void qemu_free_net_client(NetClientState *nc)
a083a89d 388{
067404be
JK
389 if (nc->incoming_queue) {
390 qemu_del_net_queue(nc->incoming_queue);
a005d073 391 }
35277d14
SH
392 if (nc->peer) {
393 nc->peer->peer = NULL;
a083a89d 394 }
35277d14
SH
395 g_free(nc->name);
396 g_free(nc->model);
f7860455
JW
397 if (nc->destructor) {
398 nc->destructor(nc);
399 }
63a01ef8
AL
400}
401
b20c6b9e 402void qemu_del_net_client(NetClientState *nc)
a083a89d 403{
1ceef9f2
JW
404 NetClientState *ncs[MAX_QUEUE_NUM];
405 int queues, i;
fdccce45 406 NetFilterState *nf, *next;
1ceef9f2 407
f394b2e2 408 assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
7fb43911 409
1ceef9f2
JW
410 /* If the NetClientState belongs to a multiqueue backend, we will change all
411 * other NetClientStates also.
412 */
413 queues = qemu_find_net_clients_except(nc->name, ncs,
f394b2e2 414 NET_CLIENT_DRIVER_NIC,
1ceef9f2
JW
415 MAX_QUEUE_NUM);
416 assert(queues != 0);
417
fdccce45
YH
418 QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
419 object_unparent(OBJECT(nf));
420 }
421
a083a89d 422 /* If there is a peer NIC, delete and cleanup client, but do not free. */
f394b2e2 423 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
cc1f0f45 424 NICState *nic = qemu_get_nic(nc->peer);
a083a89d
MT
425 if (nic->peer_deleted) {
426 return;
427 }
428 nic->peer_deleted = true;
1ceef9f2
JW
429
430 for (i = 0; i < queues; i++) {
431 ncs[i]->peer->link_down = true;
432 }
433
35277d14
SH
434 if (nc->peer->info->link_status_changed) {
435 nc->peer->info->link_status_changed(nc->peer);
a083a89d 436 }
1ceef9f2
JW
437
438 for (i = 0; i < queues; i++) {
439 qemu_cleanup_net_client(ncs[i]);
440 }
441
a083a89d
MT
442 return;
443 }
444
1ceef9f2
JW
445 for (i = 0; i < queues; i++) {
446 qemu_cleanup_net_client(ncs[i]);
447 qemu_free_net_client(ncs[i]);
448 }
948ecf21
JW
449}
450
451void qemu_del_nic(NICState *nic)
452{
575a1c0e 453 int i, queues = MAX(nic->conf->peers.queues, 1);
1ceef9f2 454
2bc22a58
SZ
455 qemu_macaddr_set_free(&nic->conf->macaddr);
456
d2abc563
YB
457 for (i = 0; i < queues; i++) {
458 NetClientState *nc = qemu_get_subqueue(nic, i);
459 /* If this is a peer NIC and peer has already been deleted, free it now. */
460 if (nic->peer_deleted) {
461 qemu_free_net_client(nc->peer);
462 } else if (nc->peer) {
463 /* if there are RX packets pending, complete them */
464 qemu_purge_queued_packets(nc->peer);
1a609520
JK
465 }
466 }
1a609520 467
1ceef9f2
JW
468 for (i = queues - 1; i >= 0; i--) {
469 NetClientState *nc = qemu_get_subqueue(nic, i);
470
471 qemu_cleanup_net_client(nc);
472 qemu_free_net_client(nc);
473 }
f6b26cf2
JW
474
475 g_free(nic);
1a609520
JK
476}
477
57f9ef17
MM
478void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
479{
4e68f7a0 480 NetClientState *nc;
57f9ef17 481
94878994 482 QTAILQ_FOREACH(nc, &net_clients, next) {
f394b2e2 483 if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
1ceef9f2
JW
484 if (nc->queue_index == 0) {
485 func(qemu_get_nic(nc), opaque);
486 }
57f9ef17
MM
487 }
488 }
57f9ef17
MM
489}
490
d6085e3a 491bool qemu_has_ufo(NetClientState *nc)
1f55ac45 492{
d6085e3a 493 if (!nc || !nc->info->has_ufo) {
1f55ac45
VM
494 return false;
495 }
496
d6085e3a 497 return nc->info->has_ufo(nc);
1f55ac45
VM
498}
499
f03e0cf6
YB
500bool qemu_has_uso(NetClientState *nc)
501{
502 if (!nc || !nc->info->has_uso) {
503 return false;
504 }
505
506 return nc->info->has_uso(nc);
507}
508
d6085e3a 509bool qemu_has_vnet_hdr(NetClientState *nc)
1f55ac45 510{
d6085e3a 511 if (!nc || !nc->info->has_vnet_hdr) {
1f55ac45
VM
512 return false;
513 }
514
d6085e3a 515 return nc->info->has_vnet_hdr(nc);
1f55ac45
VM
516}
517
d6085e3a 518bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
1f55ac45 519{
d6085e3a 520 if (!nc || !nc->info->has_vnet_hdr_len) {
1f55ac45
VM
521 return false;
522 }
523
d6085e3a 524 return nc->info->has_vnet_hdr_len(nc, len);
1f55ac45
VM
525}
526
481c5232
AO
527bool qemu_get_using_vnet_hdr(NetClientState *nc)
528{
529 if (!nc || !nc->info->get_using_vnet_hdr) {
530 return false;
531 }
532
533 return nc->info->get_using_vnet_hdr(nc);
534}
535
d6085e3a 536void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
1f55ac45 537{
d6085e3a 538 if (!nc || !nc->info->using_vnet_hdr) {
1f55ac45
VM
539 return;
540 }
541
d6085e3a 542 nc->info->using_vnet_hdr(nc, enable);
1f55ac45
VM
543}
544
d6085e3a 545void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
2ab0ec31 546 int ecn, int ufo, int uso4, int uso6)
1f55ac45 547{
d6085e3a 548 if (!nc || !nc->info->set_offload) {
1f55ac45
VM
549 return;
550 }
551
2ab0ec31 552 nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo, uso4, uso6);
1f55ac45
VM
553}
554
481c5232
AO
555int qemu_get_vnet_hdr_len(NetClientState *nc)
556{
557 if (!nc || !nc->info->get_vnet_hdr_len) {
558 return 0;
559 }
560
561 return nc->info->get_vnet_hdr_len(nc);
562}
563
d6085e3a 564void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
1f55ac45 565{
d6085e3a 566 if (!nc || !nc->info->set_vnet_hdr_len) {
1f55ac45
VM
567 return;
568 }
569
d6b732e9 570 nc->vnet_hdr_len = len;
d6085e3a 571 nc->info->set_vnet_hdr_len(nc, len);
1f55ac45
VM
572}
573
c80cd6bb
GK
574int qemu_set_vnet_le(NetClientState *nc, bool is_le)
575{
e03b5686 576#if HOST_BIG_ENDIAN
c80cd6bb
GK
577 if (!nc || !nc->info->set_vnet_le) {
578 return -ENOSYS;
579 }
580
581 return nc->info->set_vnet_le(nc, is_le);
052bd52f
MT
582#else
583 return 0;
584#endif
c80cd6bb
GK
585}
586
587int qemu_set_vnet_be(NetClientState *nc, bool is_be)
588{
e03b5686 589#if HOST_BIG_ENDIAN
052bd52f
MT
590 return 0;
591#else
c80cd6bb
GK
592 if (!nc || !nc->info->set_vnet_be) {
593 return -ENOSYS;
594 }
595
596 return nc->info->set_vnet_be(nc, is_be);
052bd52f 597#endif
c80cd6bb
GK
598}
599
705df546
JW
600int qemu_can_receive_packet(NetClientState *nc)
601{
602 if (nc->receive_disabled) {
603 return 0;
604 } else if (nc->info->can_receive &&
605 !nc->info->can_receive(nc)) {
606 return 0;
607 }
608 return 1;
609}
610
4e68f7a0 611int qemu_can_send_packet(NetClientState *sender)
63a01ef8 612{
e1d64c08
HZ
613 int vm_running = runstate_is_running();
614
615 if (!vm_running) {
616 return 0;
617 }
618
a005d073 619 if (!sender->peer) {
d80b9fc6
MM
620 return 1;
621 }
622
705df546 623 return qemu_can_receive_packet(sender->peer);
63a01ef8
AL
624}
625
e64c770d
YH
626static ssize_t filter_receive_iov(NetClientState *nc,
627 NetFilterDirection direction,
628 NetClientState *sender,
629 unsigned flags,
630 const struct iovec *iov,
631 int iovcnt,
632 NetPacketSent *sent_cb)
633{
634 ssize_t ret = 0;
635 NetFilterState *nf = NULL;
636
25aaadf0
LZ
637 if (direction == NET_FILTER_DIRECTION_TX) {
638 QTAILQ_FOREACH(nf, &nc->filters, next) {
639 ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
640 iovcnt, sent_cb);
641 if (ret) {
642 return ret;
643 }
644 }
645 } else {
eae3eb3e 646 QTAILQ_FOREACH_REVERSE(nf, &nc->filters, next) {
25aaadf0
LZ
647 ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
648 iovcnt, sent_cb);
649 if (ret) {
650 return ret;
651 }
e64c770d
YH
652 }
653 }
654
655 return ret;
656}
657
658static ssize_t filter_receive(NetClientState *nc,
659 NetFilterDirection direction,
660 NetClientState *sender,
661 unsigned flags,
662 const uint8_t *data,
663 size_t size,
664 NetPacketSent *sent_cb)
665{
666 struct iovec iov = {
667 .iov_base = (void *)data,
668 .iov_len = size
669 };
670
671 return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb);
672}
673
35277d14 674void qemu_purge_queued_packets(NetClientState *nc)
8cad5516 675{
35277d14 676 if (!nc->peer) {
d80b9fc6 677 return;
9a6ecb30 678 }
d80b9fc6 679
067404be 680 qemu_net_queue_purge(nc->peer->incoming_queue, nc);
8cad5516
MM
681}
682
ca77d85e 683void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
e94667b9 684{
35277d14 685 nc->receive_disabled = 0;
9a6ecb30 686
f394b2e2 687 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
199ee608
LR
688 if (net_hub_flush(nc->peer)) {
689 qemu_notify_event();
690 }
199ee608 691 }
067404be 692 if (qemu_net_queue_flush(nc->incoming_queue)) {
987a9b48
PB
693 /* We emptied the queue successfully, signal to the IO thread to repoll
694 * the file descriptor (for tap, for example).
695 */
696 qemu_notify_event();
ca77d85e
MT
697 } else if (purge) {
698 /* Unable to empty the queue, purge remaining packets */
5fe19fb8 699 qemu_net_queue_purge(nc->incoming_queue, nc->peer);
987a9b48 700 }
e94667b9
MM
701}
702
ca77d85e
MT
703void qemu_flush_queued_packets(NetClientState *nc)
704{
705 qemu_flush_or_purge_queued_packets(nc, false);
706}
707
4e68f7a0 708static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
ca77d175
MM
709 unsigned flags,
710 const uint8_t *buf, int size,
711 NetPacketSent *sent_cb)
764a4d1d 712{
9a6ecb30 713 NetQueue *queue;
e64c770d 714 int ret;
436e5e53 715
63a01ef8 716#ifdef DEBUG_NET
d80b9fc6 717 printf("qemu_send_packet_async:\n");
b42581f5 718 qemu_hexdump(stdout, "net", buf, size);
63a01ef8 719#endif
f3b6c7fc 720
a005d073 721 if (sender->link_down || !sender->peer) {
9a6ecb30
MM
722 return size;
723 }
724
e64c770d
YH
725 /* Let filters handle the packet first */
726 ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
727 sender, flags, buf, size, sent_cb);
728 if (ret) {
729 return ret;
730 }
731
732 ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
733 sender, flags, buf, size, sent_cb);
734 if (ret) {
735 return ret;
736 }
737
067404be 738 queue = sender->peer->incoming_queue;
9a6ecb30 739
ca77d175
MM
740 return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
741}
742
4e68f7a0 743ssize_t qemu_send_packet_async(NetClientState *sender,
ca77d175
MM
744 const uint8_t *buf, int size,
745 NetPacketSent *sent_cb)
746{
747 return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
748 buf, size, sent_cb);
f3b6c7fc
MM
749}
750
625a526b 751ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
f3b6c7fc 752{
625a526b 753 return qemu_send_packet_async(nc, buf, size, NULL);
63a01ef8
AL
754}
755
705df546
JW
756ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
757{
758 if (!qemu_can_receive_packet(nc)) {
759 return 0;
760 }
761
762 return qemu_net_queue_receive(nc->incoming_queue, buf, size);
763}
764
765ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
766 int iovcnt)
767{
768 if (!qemu_can_receive_packet(nc)) {
769 return 0;
770 }
771
772 return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt);
773}
774
35277d14 775ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
ca77d175 776{
35277d14 777 return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
ca77d175
MM
778 buf, size, NULL);
779}
780
35277d14 781static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
fefe2a78 782 int iovcnt, unsigned flags)
fbe78f4f 783{
74044c8f 784 uint8_t *buf = NULL;
fefe2a78 785 uint8_t *buffer;
ce053661 786 size_t offset;
74044c8f 787 ssize_t ret;
fbe78f4f 788
fefe2a78
YH
789 if (iovcnt == 1) {
790 buffer = iov[0].iov_base;
791 offset = iov[0].iov_len;
792 } else {
47f9f158
PL
793 offset = iov_size(iov, iovcnt);
794 if (offset > NET_BUFSIZE) {
795 return -1;
796 }
797 buf = g_malloc(offset);
fefe2a78 798 buffer = buf;
47f9f158 799 offset = iov_to_buf(iov, iovcnt, 0, buf, offset);
fefe2a78 800 }
fbe78f4f 801
fefe2a78 802 if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
74044c8f 803 ret = nc->info->receive_raw(nc, buffer, offset);
fefe2a78 804 } else {
74044c8f 805 ret = nc->info->receive(nc, buffer, offset);
fefe2a78 806 }
74044c8f
PD
807
808 g_free(buf);
809 return ret;
fbe78f4f
AL
810}
811
25c01bd1
JW
812static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
813 unsigned flags,
814 const struct iovec *iov,
815 int iovcnt,
816 void *opaque)
9a6ecb30 817{
9050f976 818 MemReentrancyGuard *owned_reentrancy_guard;
35277d14 819 NetClientState *nc = opaque;
c67f5dc1 820 int ret;
9a6ecb30 821
1592a994 822
35277d14 823 if (nc->link_down) {
25c01bd1 824 return iov_size(iov, iovcnt);
9a6ecb30
MM
825 }
826
c67f5dc1
SH
827 if (nc->receive_disabled) {
828 return 0;
829 }
830
9050f976
AO
831 if (nc->info->type != NET_CLIENT_DRIVER_NIC ||
832 qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) {
833 owned_reentrancy_guard = NULL;
834 } else {
835 owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard;
836 owned_reentrancy_guard->engaged_in_io = true;
837 }
838
ca1ee3d6 839 if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
c67f5dc1 840 ret = nc->info->receive_iov(nc, iov, iovcnt);
9a6ecb30 841 } else {
fefe2a78 842 ret = nc_sendv_compat(nc, iov, iovcnt, flags);
c67f5dc1
SH
843 }
844
9050f976
AO
845 if (owned_reentrancy_guard) {
846 owned_reentrancy_guard->engaged_in_io = false;
847 }
848
c67f5dc1
SH
849 if (ret == 0) {
850 nc->receive_disabled = 1;
e94667b9 851 }
c67f5dc1
SH
852
853 return ret;
e94667b9
MM
854}
855
4e68f7a0 856ssize_t qemu_sendv_packet_async(NetClientState *sender,
f3b6c7fc
MM
857 const struct iovec *iov, int iovcnt,
858 NetPacketSent *sent_cb)
e94667b9 859{
9a6ecb30 860 NetQueue *queue;
25c01bd1 861 size_t size = iov_size(iov, iovcnt);
e64c770d 862 int ret;
9a6ecb30 863
25c01bd1
JW
864 if (size > NET_BUFSIZE) {
865 return size;
866 }
867
a005d073 868 if (sender->link_down || !sender->peer) {
25c01bd1 869 return size;
e94667b9
MM
870 }
871
e64c770d
YH
872 /* Let filters handle the packet first */
873 ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
874 QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
875 if (ret) {
876 return ret;
877 }
878
879 ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender,
880 QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
881 if (ret) {
882 return ret;
883 }
884
067404be 885 queue = sender->peer->incoming_queue;
9a6ecb30 886
c0b8e49c
MM
887 return qemu_net_queue_send_iov(queue, sender,
888 QEMU_NET_PACKET_FLAG_NONE,
889 iov, iovcnt, sent_cb);
fbe78f4f
AL
890}
891
f3b6c7fc 892ssize_t
35277d14 893qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
f3b6c7fc 894{
35277d14 895 return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
63a01ef8
AL
896}
897
4e68f7a0 898NetClientState *qemu_find_netdev(const char *id)
5869c4d5 899{
35277d14 900 NetClientState *nc;
5869c4d5 901
35277d14 902 QTAILQ_FOREACH(nc, &net_clients, next) {
f394b2e2 903 if (nc->info->type == NET_CLIENT_DRIVER_NIC)
85dde9a9 904 continue;
35277d14
SH
905 if (!strcmp(nc->name, id)) {
906 return nc;
5869c4d5
MM
907 }
908 }
909
910 return NULL;
911}
912
6c51ae73 913int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
f394b2e2 914 NetClientDriver type, int max)
6c51ae73
JW
915{
916 NetClientState *nc;
917 int ret = 0;
918
919 QTAILQ_FOREACH(nc, &net_clients, next) {
920 if (nc->info->type == type) {
921 continue;
922 }
40d19394 923 if (!id || !strcmp(nc->name, id)) {
6c51ae73
JW
924 if (ret < max) {
925 ncs[ret] = nc;
926 }
927 ret++;
928 }
929 }
930
931 return ret;
932}
933
7697079b
AL
934static int nic_get_free_idx(void)
935{
936 int index;
937
938 for (index = 0; index < MAX_NICS; index++)
939 if (!nd_table[index].used)
940 return index;
941 return -1;
942}
943
c6941b3b
TH
944GPtrArray *qemu_get_nic_models(const char *device_type)
945{
946 GPtrArray *nic_models = g_ptr_array_new();
947 GSList *list = object_class_get_list_sorted(device_type, false);
948
949 while (list) {
950 DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
951 TYPE_DEVICE);
952 GSList *next;
953 if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
954 dc->user_creatable) {
955 const char *name = object_class_get_name(list->data);
956 /*
957 * A network device might also be something else than a NIC, see
958 * e.g. the "rocker" device. Thus we have to look for the "netdev"
959 * property, too. Unfortunately, some devices like virtio-net only
960 * create this property during instance_init, so we have to create
961 * a temporary instance here to be able to check it.
962 */
963 Object *obj = object_new_with_class(OBJECT_CLASS(dc));
964 if (object_property_find(obj, "netdev")) {
965 g_ptr_array_add(nic_models, (gpointer)name);
966 }
967 object_unref(obj);
968 }
969 next = list->next;
970 g_slist_free_1(list);
971 list = next;
972 }
973 g_ptr_array_add(nic_models, NULL);
974
975 return nic_models;
976}
977
07caea31
MA
978int qemu_show_nic_models(const char *arg, const char *const *models)
979{
980 int i;
981
c8057f95 982 if (!arg || !is_help_option(arg)) {
07caea31 983 return 0;
c8057f95 984 }
07caea31 985
3b0cca8e 986 printf("Available NIC models:\n");
7b71e03a
TH
987 for (i = 0 ; models[i]; i++) {
988 printf("%s\n", models[i]);
989 }
07caea31
MA
990 return 1;
991}
992
d07f22c5
AL
993void qemu_check_nic_model(NICInfo *nd, const char *model)
994{
995 const char *models[2];
996
997 models[0] = model;
998 models[1] = NULL;
999
07caea31
MA
1000 if (qemu_show_nic_models(nd->model, models))
1001 exit(0);
1002 if (qemu_find_nic_model(nd, models, model) < 0)
1003 exit(1);
d07f22c5
AL
1004}
1005
07caea31
MA
1006int qemu_find_nic_model(NICInfo *nd, const char * const *models,
1007 const char *default_model)
d07f22c5 1008{
07caea31 1009 int i;
d07f22c5
AL
1010
1011 if (!nd->model)
7267c094 1012 nd->model = g_strdup(default_model);
d07f22c5 1013
07caea31
MA
1014 for (i = 0 ; models[i]; i++) {
1015 if (strcmp(nd->model, models[i]) == 0)
1016 return i;
d07f22c5
AL
1017 }
1018
6daf194d 1019 error_report("Unsupported NIC model: %s", nd->model);
07caea31 1020 return -1;
d07f22c5
AL
1021}
1022
cebea510 1023static int net_init_nic(const Netdev *netdev, const char *name,
a30ecde6 1024 NetClientState *peer, Error **errp)
f83c6e10
MM
1025{
1026 int idx;
1027 NICInfo *nd;
2456f36f
LE
1028 const NetLegacyNicOptions *nic;
1029
f394b2e2
EB
1030 assert(netdev->type == NET_CLIENT_DRIVER_NIC);
1031 nic = &netdev->u.nic;
f83c6e10
MM
1032
1033 idx = nic_get_free_idx();
1034 if (idx == -1 || nb_nics >= MAX_NICS) {
66308868 1035 error_setg(errp, "too many NICs");
f83c6e10
MM
1036 return -1;
1037 }
1038
1039 nd = &nd_table[idx];
1040
1041 memset(nd, 0, sizeof(*nd));
1042
7480874a 1043 if (nic->netdev) {
2456f36f 1044 nd->netdev = qemu_find_netdev(nic->netdev);
5869c4d5 1045 if (!nd->netdev) {
66308868 1046 error_setg(errp, "netdev '%s' not found", nic->netdev);
5869c4d5
MM
1047 return -1;
1048 }
1049 } else {
d33d93b2
SH
1050 assert(peer);
1051 nd->netdev = peer;
5869c4d5 1052 }
c64f50d1 1053 nd->name = g_strdup(name);
7480874a 1054 if (nic->model) {
2456f36f 1055 nd->model = g_strdup(nic->model);
f83c6e10 1056 }
7480874a 1057 if (nic->addr) {
2456f36f 1058 nd->devaddr = g_strdup(nic->addr);
f83c6e10
MM
1059 }
1060
7480874a 1061 if (nic->macaddr &&
2456f36f 1062 net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
66308868 1063 error_setg(errp, "invalid syntax for ethernet address");
f83c6e10
MM
1064 return -1;
1065 }
7480874a 1066 if (nic->macaddr &&
d60b20cf 1067 is_multicast_ether_addr(nd->macaddr.a)) {
66308868
MA
1068 error_setg(errp,
1069 "NIC cannot have multicast MAC address (odd 1st byte)");
d60b20cf
DK
1070 return -1;
1071 }
6eed1856 1072 qemu_macaddr_default_if_unset(&nd->macaddr);
f83c6e10 1073
2456f36f
LE
1074 if (nic->has_vectors) {
1075 if (nic->vectors > 0x7ffffff) {
66308868 1076 error_setg(errp, "invalid # of vectors: %"PRIu32, nic->vectors);
2456f36f
LE
1077 return -1;
1078 }
1079 nd->nvectors = nic->vectors;
1080 } else {
1081 nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
f83c6e10
MM
1082 }
1083
1084 nd->used = 1;
f83c6e10
MM
1085 nb_nics++;
1086
1087 return idx;
1088}
1089
6687b79d 1090
f394b2e2 1091static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
cebea510 1092 const Netdev *netdev,
6687b79d 1093 const char *name,
a30ecde6 1094 NetClientState *peer, Error **errp) = {
f394b2e2 1095 [NET_CLIENT_DRIVER_NIC] = net_init_nic,
ec302ffd 1096#ifdef CONFIG_SLIRP
f394b2e2 1097 [NET_CLIENT_DRIVER_USER] = net_init_slirp,
2944e4ec 1098#endif
f394b2e2
EB
1099 [NET_CLIENT_DRIVER_TAP] = net_init_tap,
1100 [NET_CLIENT_DRIVER_SOCKET] = net_init_socket,
5166fe0a
LV
1101 [NET_CLIENT_DRIVER_STREAM] = net_init_stream,
1102 [NET_CLIENT_DRIVER_DGRAM] = net_init_dgram,
dd51058d 1103#ifdef CONFIG_VDE
f394b2e2 1104 [NET_CLIENT_DRIVER_VDE] = net_init_vde,
58952137
VM
1105#endif
1106#ifdef CONFIG_NETMAP
f394b2e2 1107 [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
dd51058d 1108#endif
cb039ef3
IM
1109#ifdef CONFIG_AF_XDP
1110 [NET_CLIENT_DRIVER_AF_XDP] = net_init_af_xdp,
1111#endif
2944e4ec 1112#ifdef CONFIG_NET_BRIDGE
f394b2e2 1113 [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
6687b79d 1114#endif
f394b2e2 1115 [NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
56f41de7 1116#ifdef CONFIG_VHOST_NET_USER
f394b2e2 1117 [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
03ce5744 1118#endif
1e0a84ea
CL
1119#ifdef CONFIG_VHOST_NET_VDPA
1120 [NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
1121#endif
015a33bd 1122#ifdef CONFIG_L2TPV3
f394b2e2 1123 [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
3fb69aa1 1124#endif
81ad2964
VY
1125#ifdef CONFIG_VMNET
1126 [NET_CLIENT_DRIVER_VMNET_HOST] = net_init_vmnet_host,
1127 [NET_CLIENT_DRIVER_VMNET_SHARED] = net_init_vmnet_shared,
1128 [NET_CLIENT_DRIVER_VMNET_BRIDGED] = net_init_vmnet_bridged,
1129#endif /* CONFIG_VMNET */
f83c6e10
MM
1130};
1131
6687b79d 1132
71830d84 1133static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
f83c6e10 1134{
4ef0defb 1135 NetClientState *peer = NULL;
831734cc 1136 NetClientState *nc;
f83c6e10 1137
5294e2c7 1138 if (is_netdev) {
857d2087 1139 if (netdev->type == NET_CLIENT_DRIVER_NIC ||
f394b2e2 1140 !net_client_init_fun[netdev->type]) {
7d0e12af
DB
1141 error_setg(errp, "network backend '%s' is not compiled into this binary",
1142 NetClientDriver_str(netdev->type));
f6b134ac
MM
1143 return -1;
1144 }
6687b79d 1145 } else {
71830d84 1146 if (netdev->type == NET_CLIENT_DRIVER_NONE) {
d139e9a6 1147 return 0; /* nothing to do */
1e81aba5 1148 }
7d0e12af
DB
1149 if (netdev->type == NET_CLIENT_DRIVER_HUBPORT) {
1150 error_setg(errp, "network backend '%s' is only supported with -netdev/-nic",
1151 NetClientDriver_str(netdev->type));
1152 return -1;
1153 }
1154
1155 if (!net_client_init_fun[netdev->type]) {
1156 error_setg(errp, "network backend '%s' is not compiled into this binary",
1157 NetClientDriver_str(netdev->type));
d139e9a6
SH
1158 return -1;
1159 }
f6b134ac 1160
af1a5c3e 1161 /* Do not add to a hub if it's a nic with a netdev= parameter. */
f394b2e2 1162 if (netdev->type != NET_CLIENT_DRIVER_NIC ||
7480874a 1163 !netdev->u.nic.netdev) {
af1a5c3e 1164 peer = net_hub_add_port(0, NULL, NULL);
a2dbe135 1165 }
4ef0defb 1166 }
6687b79d 1167
831734cc
MA
1168 nc = qemu_find_netdev(netdev->id);
1169 if (nc) {
1170 error_setg(errp, "Duplicate ID '%s'", netdev->id);
1171 return -1;
1172 }
1173
9d903f30 1174 if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
4ef0defb
SH
1175 /* FIXME drop when all init functions store an Error */
1176 if (errp && !*errp) {
f820af87 1177 error_setg(errp, "Device '%s' could not be initialized",
977c736f 1178 NetClientDriver_str(netdev->type));
f6b134ac 1179 }
4ef0defb 1180 return -1;
f6b134ac 1181 }
08712fcb
EB
1182
1183 if (is_netdev) {
08712fcb
EB
1184 nc = qemu_find_netdev(netdev->id);
1185 assert(nc);
1186 nc->is_netdev = true;
1187 }
1188
6687b79d
LE
1189 return 0;
1190}
1191
ad6f932f 1192void show_netdevs(void)
547203ea
TH
1193{
1194 int idx;
1195 const char *available_netdevs[] = {
1196 "socket",
5166fe0a
LV
1197 "stream",
1198 "dgram",
547203ea
TH
1199 "hubport",
1200 "tap",
1201#ifdef CONFIG_SLIRP
1202 "user",
1203#endif
1204#ifdef CONFIG_L2TPV3
1205 "l2tpv3",
1206#endif
1207#ifdef CONFIG_VDE
1208 "vde",
1209#endif
1210#ifdef CONFIG_NET_BRIDGE
1211 "bridge",
1212#endif
1213#ifdef CONFIG_NETMAP
1214 "netmap",
1215#endif
cb039ef3
IM
1216#ifdef CONFIG_AF_XDP
1217 "af-xdp",
1218#endif
547203ea
TH
1219#ifdef CONFIG_POSIX
1220 "vhost-user",
1bc211a1
CL
1221#endif
1222#ifdef CONFIG_VHOST_VDPA
1223 "vhost-vdpa",
81ad2964
VY
1224#endif
1225#ifdef CONFIG_VMNET
1226 "vmnet-host",
1227 "vmnet-shared",
1228 "vmnet-bridged",
547203ea
TH
1229#endif
1230 };
1231
ad6f932f 1232 qemu_printf("Available netdev backend types:\n");
547203ea 1233 for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
ad6f932f 1234 qemu_printf("%s\n", available_netdevs[idx]);
547203ea
TH
1235 }
1236}
f6b134ac 1237
aa09a485 1238static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
6687b79d 1239{
c1112b2d 1240 gchar **substrings = NULL;
71830d84 1241 Netdev *object = NULL;
6687b79d 1242 int ret = -1;
09204eac 1243 Visitor *v = opts_visitor_new(opts);
f83c6e10 1244
0a4a1512 1245 /* Parse convenience option format ipv6-net=fec0::0[/64] */
ad6f932f 1246 const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
7aac531e 1247
ad6f932f
PB
1248 if (ip6_net) {
1249 char *prefix_addr;
1250 unsigned long prefix_len = 64; /* Default 64bit prefix length. */
c1112b2d 1251
ad6f932f
PB
1252 substrings = g_strsplit(ip6_net, "/", 2);
1253 if (!substrings || !substrings[0]) {
1254 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
1255 "a valid IPv6 prefix");
1256 goto out;
1257 }
c1112b2d 1258
ad6f932f 1259 prefix_addr = substrings[0];
7aac531e 1260
ad6f932f
PB
1261 /* Handle user-specified prefix length. */
1262 if (substrings[1] &&
1263 qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
1264 {
0a4a1512
MA
1265 error_setg(errp,
1266 "parameter 'ipv6-net' expects a number after '/'");
ad6f932f 1267 goto out;
7aac531e 1268 }
ad6f932f
PB
1269
1270 qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
1271 qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
1272 &error_abort);
1273 qemu_opt_unset(opts, "ipv6-net");
7aac531e
YB
1274 }
1275
71830d84
TH
1276 /* Create an ID for -net if the user did not specify one */
1277 if (!is_netdev && !qemu_opts_id(opts)) {
27eb3722 1278 qemu_opts_set_id(opts, id_generate(ID_NET));
f83c6e10
MM
1279 }
1280
14217038
MA
1281 if (visit_type_Netdev(v, NULL, &object, errp)) {
1282 ret = net_client_init1(object, is_netdev, errp);
6687b79d
LE
1283 }
1284
71830d84 1285 qapi_free_Netdev(object);
6687b79d 1286
21c520d0 1287out:
c1112b2d 1288 g_strfreev(substrings);
09204eac 1289 visit_free(v);
6687b79d 1290 return ret;
f83c6e10
MM
1291}
1292
928059a3
LC
1293void netdev_add(QemuOpts *opts, Error **errp)
1294{
0e55c381 1295 net_client_init(opts, true, errp);
928059a3
LC
1296}
1297
db2a380c 1298void qmp_netdev_add(Netdev *netdev, Error **errp)
ae82d324 1299{
e73b4317
PB
1300 if (!id_wellformed(netdev->id)) {
1301 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
1302 return;
1303 }
1304
08712fcb 1305 net_client_init1(netdev, true, errp);
ae82d324
MA
1306}
1307
5f964155 1308void qmp_netdev_del(const char *id, Error **errp)
ae82d324 1309{
35277d14 1310 NetClientState *nc;
831734cc 1311 QemuOpts *opts;
ae82d324 1312
35277d14
SH
1313 nc = qemu_find_netdev(id);
1314 if (!nc) {
75158ebb
MA
1315 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1316 "Device '%s' not found", id);
5f964155 1317 return;
ae82d324 1318 }
5f964155 1319
08712fcb 1320 if (!nc->is_netdev) {
645c9496
SH
1321 error_setg(errp, "Device '%s' is not a netdev", id);
1322 return;
1323 }
1324
b20c6b9e 1325 qemu_del_net_client(nc);
831734cc
MA
1326
1327 /*
1328 * Wart: we need to delete the QemuOpts associated with netdevs
1329 * created via CLI or HMP, to avoid bogus "Duplicate ID" errors in
1330 * HMP netdev_add.
1331 */
1332 opts = qemu_opts_find(qemu_find_opts("netdev"), id);
1333 if (opts) {
1334 qemu_opts_del(opts);
1335 }
ae82d324
MA
1336}
1337
aa9156f4
HZ
1338static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
1339{
1340 char *str;
1341 ObjectProperty *prop;
1342 ObjectPropertyIterator iter;
3b098d56 1343 Visitor *v;
aa9156f4
HZ
1344
1345 /* generate info str */
1346 object_property_iter_init(&iter, OBJECT(nf));
1347 while ((prop = object_property_iter_next(&iter))) {
1348 if (!strcmp(prop->name, "type")) {
1349 continue;
1350 }
3b098d56 1351 v = string_output_visitor_new(false, &str);
5325cc34 1352 object_property_get(OBJECT(nf), prop->name, v, NULL);
3b098d56
EB
1353 visit_complete(v, &str);
1354 visit_free(v);
aa9156f4
HZ
1355 monitor_printf(mon, ",%s=%s", prop->name, str);
1356 g_free(str);
1357 }
1358 monitor_printf(mon, "\n");
1359}
1360
1a859593 1361void print_net_client(Monitor *mon, NetClientState *nc)
44e798d3 1362{
a4960f52
YH
1363 NetFilterState *nf;
1364
1ceef9f2
JW
1365 monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
1366 nc->queue_index,
977c736f 1367 NetClientDriver_str(nc->info->type),
56e6f594 1368 nc->info_str);
a4960f52
YH
1369 if (!QTAILQ_EMPTY(&nc->filters)) {
1370 monitor_printf(mon, "filters:\n");
1371 }
1372 QTAILQ_FOREACH(nf, &nc->filters, next) {
7a309cc9
MA
1373 monitor_printf(mon, " - %s: type=%s",
1374 object_get_canonical_path_component(OBJECT(nf)),
aa9156f4
HZ
1375 object_get_typename(OBJECT(nf)));
1376 netfilter_print_info(mon, nf);
a4960f52 1377 }
44e798d3
JK
1378}
1379
7480874a 1380RxFilterInfoList *qmp_query_rx_filter(const char *name, Error **errp)
b1be4280
AK
1381{
1382 NetClientState *nc;
95b3a8c8 1383 RxFilterInfoList *filter_list = NULL, **tail = &filter_list;
b1be4280
AK
1384
1385 QTAILQ_FOREACH(nc, &net_clients, next) {
b1be4280
AK
1386 RxFilterInfo *info;
1387
7480874a 1388 if (name && strcmp(nc->name, name) != 0) {
b1be4280
AK
1389 continue;
1390 }
1391
1392 /* only query rx-filter information of NIC */
f394b2e2 1393 if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
7480874a 1394 if (name) {
b1be4280 1395 error_setg(errp, "net client(%s) isn't a NIC", name);
e9d635ea 1396 assert(!filter_list);
9083da1d 1397 return NULL;
b1be4280
AK
1398 }
1399 continue;
1400 }
1401
5320c2ca
VY
1402 /* only query information on queue 0 since the info is per nic,
1403 * not per queue
1404 */
1405 if (nc->queue_index != 0)
1406 continue;
1407
b1be4280
AK
1408 if (nc->info->query_rx_filter) {
1409 info = nc->info->query_rx_filter(nc);
95b3a8c8 1410 QAPI_LIST_APPEND(tail, info);
7480874a 1411 } else if (name) {
b1be4280
AK
1412 error_setg(errp, "net client(%s) doesn't support"
1413 " rx-filter querying", name);
e9d635ea 1414 assert(!filter_list);
9083da1d 1415 return NULL;
b1be4280 1416 }
638fb141 1417
7480874a 1418 if (name) {
638fb141
MA
1419 break;
1420 }
b1be4280
AK
1421 }
1422
7480874a 1423 if (filter_list == NULL && name) {
b1be4280
AK
1424 error_setg(errp, "invalid net client name: %s", name);
1425 }
1426
1427 return filter_list;
1428}
1429
5fbba3d6
ZC
1430void colo_notify_filters_event(int event, Error **errp)
1431{
1432 NetClientState *nc;
1433 NetFilterState *nf;
1434 NetFilterClass *nfc = NULL;
1435 Error *local_err = NULL;
1436
1437 QTAILQ_FOREACH(nc, &net_clients, next) {
1438 QTAILQ_FOREACH(nf, &nc->filters, next) {
1439 nfc = NETFILTER_GET_CLASS(OBJECT(nf));
1440 nfc->handle_event(nf, event, &local_err);
1441 if (local_err) {
1442 error_propagate(errp, local_err);
1443 return;
1444 }
1445 }
1446 }
1447}
1448
4b37156c 1449void qmp_set_link(const char *name, bool up, Error **errp)
436e5e53 1450{
1ceef9f2
JW
1451 NetClientState *ncs[MAX_QUEUE_NUM];
1452 NetClientState *nc;
1453 int queues, i;
436e5e53 1454
1ceef9f2 1455 queues = qemu_find_net_clients_except(name, ncs,
f394b2e2 1456 NET_CLIENT_DRIVER__MAX,
1ceef9f2
JW
1457 MAX_QUEUE_NUM);
1458
1459 if (queues == 0) {
75158ebb
MA
1460 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1461 "Device '%s' not found", name);
4b37156c 1462 return;
436e5e53 1463 }
1ceef9f2 1464 nc = ncs[0];
436e5e53 1465
1ceef9f2
JW
1466 for (i = 0; i < queues; i++) {
1467 ncs[i]->link_down = !up;
1468 }
436e5e53 1469
35277d14
SH
1470 if (nc->info->link_status_changed) {
1471 nc->info->link_status_changed(nc);
665a3b07 1472 }
ab1cbe1c 1473
02d38fcb
VY
1474 if (nc->peer) {
1475 /* Change peer link only if the peer is NIC and then notify peer.
1476 * If the peer is a HUBPORT or a backend, we do not change the
1477 * link status.
1478 *
af1a5c3e 1479 * This behavior is compatible with qemu hubs where there could be
02d38fcb
VY
1480 * multiple clients that can still communicate with each other in
1481 * disconnected mode. For now maintain this compatibility.
1482 */
f394b2e2 1483 if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
02d38fcb
VY
1484 for (i = 0; i < queues; i++) {
1485 ncs[i]->peer->link_down = !up;
1486 }
1487 }
1488 if (nc->peer->info->link_status_changed) {
1489 nc->peer->info->link_status_changed(nc->peer);
1490 }
ab1cbe1c 1491 }
436e5e53
AL
1492}
1493
538f0497 1494static void net_vm_change_state_handler(void *opaque, bool running,
ca77d85e
MT
1495 RunState state)
1496{
625de449
FZ
1497 NetClientState *nc;
1498 NetClientState *tmp;
ca77d85e 1499
625de449
FZ
1500 QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
1501 if (running) {
1502 /* Flush queued packets and wake up backends. */
1503 if (nc->peer && qemu_can_send_packet(nc)) {
1504 qemu_flush_queued_packets(nc->peer);
1505 }
1506 } else {
1507 /* Complete all queued packets, to guarantee we don't modify
1508 * state later when VM is not running.
1509 */
ca77d85e
MT
1510 qemu_flush_or_purge_queued_packets(nc, true);
1511 }
1512 }
1513}
1514
63a01ef8
AL
1515void net_cleanup(void)
1516{
1ceef9f2 1517 NetClientState *nc;
577c4af9 1518
0c7af1a7
RL
1519 /*cleanup colo compare module for COLO*/
1520 colo_compare_cleanup();
1521
1ceef9f2
JW
1522 /* We may del multiple entries during qemu_del_net_client(),
1523 * so QTAILQ_FOREACH_SAFE() is also not safe here.
1524 */
1525 while (!QTAILQ_EMPTY(&net_clients)) {
1526 nc = QTAILQ_FIRST(&net_clients);
f394b2e2 1527 if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
948ecf21
JW
1528 qemu_del_nic(qemu_get_nic(nc));
1529 } else {
1530 qemu_del_net_client(nc);
1531 }
577c4af9 1532 }
ca77d85e
MT
1533
1534 qemu_del_vm_change_state_handler(net_change_state_entry);
63a01ef8
AL
1535}
1536
668680f7 1537void net_check_clients(void)
63a01ef8 1538{
35277d14 1539 NetClientState *nc;
48e2faf2 1540 int i;
63a01ef8 1541
81017645 1542 net_hub_check_clients();
ac60cc18 1543
35277d14
SH
1544 QTAILQ_FOREACH(nc, &net_clients, next) {
1545 if (!nc->peer) {
8297be80 1546 warn_report("%s %s has no peer",
b62e39b4
AF
1547 nc->info->type == NET_CLIENT_DRIVER_NIC
1548 ? "nic" : "netdev",
1549 nc->name);
efe32fdd
MA
1550 }
1551 }
48e2faf2
PM
1552
1553 /* Check that all NICs requested via -net nic actually got created.
1554 * NICs created via -device don't need to be checked here because
1555 * they are always instantiated.
1556 */
1557 for (i = 0; i < MAX_NICS; i++) {
1558 NICInfo *nd = &nd_table[i];
1559 if (nd->used && !nd->instantiated) {
8297be80
AF
1560 warn_report("requested NIC (%s, model %s) "
1561 "was not created (not supported by this machine?)",
1562 nd->name ? nd->name : "anonymous",
1563 nd->model ? nd->model : "unspecified");
48e2faf2
PM
1564 }
1565 }
63a01ef8 1566}
dc1c9fe8 1567
28d0de7a 1568static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
dc1c9fe8 1569{
34f708b0 1570 return net_client_init(opts, false, errp);
f6b134ac
MM
1571}
1572
28d0de7a 1573static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
f6b134ac 1574{
ad6f932f
PB
1575 const char *type = qemu_opt_get(opts, "type");
1576
1577 if (type && is_help_option(type)) {
1578 show_netdevs();
1579 exit(0);
1580 }
34f708b0 1581 return net_client_init(opts, true, errp);
dc1c9fe8 1582}
4559a1db 1583
78cd6f7b
TH
1584/* For the convenience "--nic" parameter */
1585static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
1586{
1587 char *mac, *nd_id;
1588 int idx, ret;
1589 NICInfo *ni;
1590 const char *type;
1591
1592 type = qemu_opt_get(opts, "type");
27c81924
TH
1593 if (type) {
1594 if (g_str_equal(type, "none")) {
1595 return 0; /* Nothing to do, default_net is cleared in vl.c */
1596 }
1597 if (is_help_option(type)) {
1598 GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
1599 show_netdevs();
1600 printf("\n");
1601 qemu_show_nic_models(type, (const char **)nic_models->pdata);
1602 g_ptr_array_free(nic_models, true);
1603 exit(0);
1604 }
78cd6f7b
TH
1605 }
1606
1607 idx = nic_get_free_idx();
1608 if (idx == -1 || nb_nics >= MAX_NICS) {
1609 error_setg(errp, "no more on-board/default NIC slots available");
4559a1db
LC
1610 return -1;
1611 }
1612
78cd6f7b
TH
1613 if (!type) {
1614 qemu_opt_set(opts, "type", "user", &error_abort);
1615 }
1616
1617 ni = &nd_table[idx];
1618 memset(ni, 0, sizeof(*ni));
1619 ni->model = qemu_opt_get_del(opts, "model");
1620
1621 /* Create an ID if the user did not specify one */
1622 nd_id = g_strdup(qemu_opts_id(opts));
1623 if (!nd_id) {
27eb3722 1624 nd_id = id_generate(ID_NET);
78cd6f7b
TH
1625 qemu_opts_set_id(opts, nd_id);
1626 }
1627
1628 /* Handle MAC address */
1629 mac = qemu_opt_get_del(opts, "mac");
1630 if (mac) {
1631 ret = net_parse_macaddr(ni->macaddr.a, mac);
1632 g_free(mac);
1633 if (ret) {
1634 error_setg(errp, "invalid syntax for ethernet address");
9d946191 1635 goto out;
78cd6f7b
TH
1636 }
1637 if (is_multicast_ether_addr(ni->macaddr.a)) {
1638 error_setg(errp, "NIC cannot have multicast MAC address");
9d946191
TH
1639 ret = -1;
1640 goto out;
78cd6f7b
TH
1641 }
1642 }
1643 qemu_macaddr_default_if_unset(&ni->macaddr);
1644
1645 ret = net_client_init(opts, true, errp);
1646 if (ret == 0) {
1647 ni->netdev = qemu_find_netdev(nd_id);
1648 ni->used = true;
1649 nb_nics++;
1650 }
1651
9d946191 1652out:
78cd6f7b 1653 g_free(nd_id);
4559a1db 1654 return ret;
dc1c9fe8
MM
1655}
1656
f3eedcdd
LV
1657static void netdev_init_modern(void)
1658{
1659 while (!QSIMPLEQ_EMPTY(&nd_queue)) {
1660 NetdevQueueEntry *nd = QSIMPLEQ_FIRST(&nd_queue);
1661
1662 QSIMPLEQ_REMOVE_HEAD(&nd_queue, entry);
1663 loc_push_restore(&nd->loc);
1664 net_client_init1(nd->nd, true, &error_fatal);
1665 loc_pop(&nd->loc);
1666 qapi_free_Netdev(nd->nd);
1667 g_free(nd);
1668 }
1669}
1670
d63ef17b 1671void net_init_clients(void)
dc1c9fe8 1672{
ca77d85e
MT
1673 net_change_state_entry =
1674 qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
1675
94878994 1676 QTAILQ_INIT(&net_clients);
5610c3aa 1677
f3eedcdd
LV
1678 netdev_init_modern();
1679
d63ef17b
LV
1680 qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
1681 &error_fatal);
78cd6f7b 1682
d63ef17b
LV
1683 qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL,
1684 &error_fatal);
dc1c9fe8 1685
d63ef17b
LV
1686 qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL,
1687 &error_fatal);
dc1c9fe8
MM
1688}
1689
f3eedcdd
LV
1690/*
1691 * Does this -netdev argument use modern rather than traditional syntax?
1692 * Modern syntax is to be parsed with netdev_parse_modern().
1693 * Traditional syntax is to be parsed with net_client_parse().
1694 */
73071f19 1695bool netdev_is_modern(const char *optstr)
f3eedcdd 1696{
5166fe0a
LV
1697 QemuOpts *opts;
1698 bool is_modern;
1699 const char *type;
1700 static QemuOptsList dummy_opts = {
1701 .name = "netdev",
1702 .implied_opt_name = "type",
1703 .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
1704 .desc = { { } },
1705 };
1706
73071f19 1707 if (optstr[0] == '{') {
5166fe0a
LV
1708 /* This is JSON, which means it's modern syntax */
1709 return true;
1710 }
1711
1712 opts = qemu_opts_create(&dummy_opts, NULL, false, &error_abort);
73071f19 1713 qemu_opts_do_parse(opts, optstr, dummy_opts.implied_opt_name,
5166fe0a
LV
1714 &error_abort);
1715 type = qemu_opt_get(opts, "type");
1716 is_modern = !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram");
1717
1718 qemu_opts_reset(&dummy_opts);
1719
1720 return is_modern;
f3eedcdd
LV
1721}
1722
1723/*
1724 * netdev_parse_modern() uses modern, more expressive syntax than
1725 * net_client_parse(), but supports only the -netdev option.
1726 * netdev_parse_modern() appends to @nd_queue, whereas net_client_parse()
1727 * appends to @qemu_netdev_opts.
1728 */
73071f19 1729void netdev_parse_modern(const char *optstr)
f3eedcdd
LV
1730{
1731 Visitor *v;
1732 NetdevQueueEntry *nd;
1733
73071f19 1734 v = qobject_input_visitor_new_str(optstr, "type", &error_fatal);
f3eedcdd
LV
1735 nd = g_new(NetdevQueueEntry, 1);
1736 visit_type_Netdev(v, NULL, &nd->nd, &error_fatal);
1737 visit_free(v);
1738 loc_save(&nd->loc);
1739
1740 QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry);
1741}
1742
73071f19 1743void net_client_parse(QemuOptsList *opts_list, const char *optstr)
dc1c9fe8 1744{
73071f19 1745 if (!qemu_opts_parse_noisily(opts_list, optstr, true)) {
21fccb2c 1746 exit(1);
dc1c9fe8 1747 }
dc1c9fe8 1748}
7fc8d918
JW
1749
1750/* From FreeBSD */
1751/* XXX: optimize */
eaba8f34 1752uint32_t net_crc32(const uint8_t *p, int len)
7fc8d918
JW
1753{
1754 uint32_t crc;
1755 int carry, i, j;
1756 uint8_t b;
1757
1758 crc = 0xffffffff;
eaba8f34
MCA
1759 for (i = 0; i < len; i++) {
1760 b = *p++;
7fc8d918
JW
1761 for (j = 0; j < 8; j++) {
1762 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
1763 crc <<= 1;
1764 b >>= 1;
1765 if (carry) {
eaba8f34 1766 crc = ((crc ^ POLYNOMIAL_BE) | carry);
7fc8d918
JW
1767 }
1768 }
1769 }
eaba8f34
MCA
1770
1771 return crc;
1772}
1773
f1a7deb9
MCA
1774uint32_t net_crc32_le(const uint8_t *p, int len)
1775{
1776 uint32_t crc;
1777 int carry, i, j;
1778 uint8_t b;
1779
1780 crc = 0xffffffff;
1781 for (i = 0; i < len; i++) {
1782 b = *p++;
1783 for (j = 0; j < 8; j++) {
1784 carry = (crc & 0x1) ^ (b & 0x01);
1785 crc >>= 1;
1786 b >>= 1;
1787 if (carry) {
1788 crc ^= POLYNOMIAL_LE;
1789 }
1790 }
1791 }
1792
1793 return crc;
1794}
1795
4d454574
PB
1796QemuOptsList qemu_netdev_opts = {
1797 .name = "netdev",
1798 .implied_opt_name = "type",
1799 .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
78cd6f7b
TH
1800 .desc = {
1801 /*
1802 * no elements => accept any params
1803 * validation will happen later
1804 */
1805 { /* end of list */ }
1806 },
1807};
1808
1809QemuOptsList qemu_nic_opts = {
1810 .name = "nic",
1811 .implied_opt_name = "type",
1812 .head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head),
4d454574
PB
1813 .desc = {
1814 /*
1815 * no elements => accept any params
1816 * validation will happen later
1817 */
1818 { /* end of list */ }
1819 },
1820};
1821
1822QemuOptsList qemu_net_opts = {
1823 .name = "net",
1824 .implied_opt_name = "type",
1825 .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
1826 .desc = {
1827 /*
1828 * no elements => accept any params
1829 * validation will happen later
1830 */
1831 { /* end of list */ }
1832 },
1833};
16a3df40
ZC
1834
1835void net_socket_rs_init(SocketReadState *rs,
3cde5ea2
ZC
1836 SocketReadStateFinalize *finalize,
1837 bool vnet_hdr)
16a3df40
ZC
1838{
1839 rs->state = 0;
3cde5ea2 1840 rs->vnet_hdr = vnet_hdr;
16a3df40
ZC
1841 rs->index = 0;
1842 rs->packet_len = 0;
3cde5ea2 1843 rs->vnet_hdr_len = 0;
16a3df40
ZC
1844 memset(rs->buf, 0, sizeof(rs->buf));
1845 rs->finalize = finalize;
1846}
1847
1848/*
1849 * Returns
e9e0a585
ZC
1850 * 0: success
1851 * -1: error occurs
16a3df40
ZC
1852 */
1853int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
1854{
1855 unsigned int l;
1856
1857 while (size > 0) {
3cde5ea2
ZC
1858 /* Reassemble a packet from the network.
1859 * 0 = getting length.
1860 * 1 = getting vnet header length.
1861 * 2 = getting data.
1862 */
1863 switch (rs->state) {
16a3df40
ZC
1864 case 0:
1865 l = 4 - rs->index;
1866 if (l > size) {
1867 l = size;
1868 }
1869 memcpy(rs->buf + rs->index, buf, l);
1870 buf += l;
1871 size -= l;
1872 rs->index += l;
1873 if (rs->index == 4) {
1874 /* got length */
1875 rs->packet_len = ntohl(*(uint32_t *)rs->buf);
1876 rs->index = 0;
3cde5ea2
ZC
1877 if (rs->vnet_hdr) {
1878 rs->state = 1;
1879 } else {
1880 rs->state = 2;
1881 rs->vnet_hdr_len = 0;
1882 }
16a3df40
ZC
1883 }
1884 break;
1885 case 1:
3cde5ea2
ZC
1886 l = 4 - rs->index;
1887 if (l > size) {
1888 l = size;
1889 }
1890 memcpy(rs->buf + rs->index, buf, l);
1891 buf += l;
1892 size -= l;
1893 rs->index += l;
1894 if (rs->index == 4) {
1895 /* got vnet header length */
1896 rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf);
1897 rs->index = 0;
1898 rs->state = 2;
1899 }
1900 break;
1901 case 2:
16a3df40
ZC
1902 l = rs->packet_len - rs->index;
1903 if (l > size) {
1904 l = size;
1905 }
1906 if (rs->index + l <= sizeof(rs->buf)) {
1907 memcpy(rs->buf + rs->index, buf, l);
1908 } else {
1909 fprintf(stderr, "serious error: oversized packet received,"
1910 "connection terminated.\n");
1911 rs->index = rs->state = 0;
1912 return -1;
1913 }
1914
1915 rs->index += l;
1916 buf += l;
1917 size -= l;
1918 if (rs->index >= rs->packet_len) {
1919 rs->index = 0;
1920 rs->state = 0;
e79cd406
DB
1921 assert(rs->finalize);
1922 rs->finalize(rs);
16a3df40
ZC
1923 }
1924 break;
1925 }
1926 }
e9e0a585
ZC
1927
1928 assert(size == 0);
16a3df40
ZC
1929 return 0;
1930}