aboutsummaryrefslogtreecommitdiff
path: root/net/tap.c
diff options
context:
space:
mode:
authorAlexey Kirillov <lekiravi@yandex-team.ru>2021-03-03 12:59:06 +0300
committerJason Wang <jasowang@redhat.com>2021-03-15 16:41:22 +0800
commitd32ad10a14d46dfe9304e3ed5858a11dcd5c71a0 (patch)
treee56aaddf5e86dd29209ce958e94c0d91ad950778 /net/tap.c
parent3aa1b7af0f5fbfdf1b4759658e1445bda680b40d (diff)
downloadqemu-d32ad10a14d46dfe9304e3ed5858a11dcd5c71a0.zip
qemu-d32ad10a14d46dfe9304e3ed5858a11dcd5c71a0.tar.gz
qemu-d32ad10a14d46dfe9304e3ed5858a11dcd5c71a0.tar.bz2
qapi: net: Add query-netdev command
The query-netdev command is used to get the configuration of the current network device backends (netdevs). This is the QMP analog of the HMP command "info network" but only for netdevs (i.e. excluding NIC and hubports). The query-netdev command returns an array of objects of the NetdevInfo type, which are an extension of Netdev type. It means that response can be used for netdev-add after small modification. This can be useful for recreate the same netdev configuration. Information about the network device is filled in when it is created or modified and is available through the NetClientState->stored_config. Signed-off-by: Alexey Kirillov <lekiravi@yandex-team.ru> Acked-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'net/tap.c')
-rw-r--r--net/tap.c103
1 files changed, 98 insertions, 5 deletions
diff --git a/net/tap.c b/net/tap.c
index b751285..8041245 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -590,6 +590,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
const char *helper, *br;
TAPState *s;
int fd, vnet_hdr;
+ NetdevBridgeOptions *stored;
assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
bridge = &netdev->u.bridge;
@@ -609,6 +610,21 @@ int net_init_bridge(const Netdev *netdev, const char *name,
}
s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
+ /* Store startup parameters */
+ s->nc.stored_config = g_new0(NetdevInfo, 1);
+ s->nc.stored_config->type = NET_BACKEND_BRIDGE;
+ stored = &s->nc.stored_config->u.bridge;
+
+ if (br) {
+ stored->has_br = true;
+ stored->br = g_strdup(br);
+ }
+
+ if (helper) {
+ stored->has_helper = true;
+ stored->helper = g_strdup(helper);
+ }
+
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
br);
@@ -656,11 +672,13 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
const char *model, const char *name,
const char *ifname, const char *script,
const char *downscript, const char *vhostfdname,
- int vnet_hdr, int fd, Error **errp)
+ int vnet_hdr, int fd, NetdevInfo **common_stored,
+ Error **errp)
{
Error *err = NULL;
TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
int vhostfd;
+ NetdevTapOptions *stored;
tap_set_sndbuf(s->fd, tap, &err);
if (err) {
@@ -668,12 +686,65 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
return;
}
+ /* Store startup parameters */
+ if (!*common_stored) {
+ *common_stored = g_new0(NetdevInfo, 1);
+ (*common_stored)->type = NET_BACKEND_TAP;
+ s->nc.stored_config = *common_stored;
+ }
+ stored = &(*common_stored)->u.tap;
+
+ if (tap->has_sndbuf && !stored->has_sndbuf) {
+ stored->has_sndbuf = true;
+ stored->sndbuf = tap->sndbuf;
+ }
+
+ if (vnet_hdr && !stored->has_vnet_hdr) {
+ stored->has_vnet_hdr = true;
+ stored->vnet_hdr = true;
+ }
+
if (tap->has_fd || tap->has_fds) {
+ if (!stored->has_fds) {
+ stored->has_fds = true;
+ stored->fds = g_strdup_printf("%d", fd);
+ } else {
+ char *tmp_s = stored->fds;
+ stored->fds = g_strdup_printf("%s:%d", stored->fds, fd);
+ g_free(tmp_s);
+ }
+
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
} else if (tap->has_helper) {
+ if (!stored->has_helper) {
+ stored->has_helper = true;
+ stored->helper = g_strdup(tap->helper);
+ }
+
+ if (!stored->has_br) {
+ stored->has_br = true;
+ stored->br = tap->has_br ? g_strdup(tap->br) :
+ g_strdup(DEFAULT_BRIDGE_INTERFACE);
+ }
+
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s",
tap->helper);
} else {
+ if (ifname && !stored->has_ifname) {
+ stored->has_ifname = true;
+ stored->ifname = g_strdup(ifname);
+ }
+
+ if (script && !stored->has_script) {
+ stored->has_script = true;
+ stored->script = g_strdup(script);
+ }
+
+ if (downscript && !stored->has_downscript) {
+ stored->has_downscript = true;
+ stored->downscript = g_strdup(downscript);
+ }
+
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"ifname=%s,script=%s,downscript=%s", ifname, script,
downscript);
@@ -689,9 +760,20 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
VhostNetOptions options;
+ stored->has_vhost = true;
+ stored->vhost = true;
+
+ if (tap->has_vhostforce && tap->vhostforce) {
+ stored->has_vhostforce = true;
+ stored->vhostforce = true;
+ }
+
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
options.net_backend = &s->nc;
if (tap->has_poll_us) {
+ stored->has_poll_us = true;
+ stored->poll_us = tap->poll_us;
+
options.busyloop_timeout = tap->poll_us;
} else {
options.busyloop_timeout = 0;
@@ -731,6 +813,15 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
}
options.opaque = (void *)(uintptr_t)vhostfd;
+ if (!stored->has_vhostfds) {
+ stored->has_vhostfds = true;
+ stored->vhostfds = g_strdup_printf("%d", vhostfd);
+ } else {
+ char *tmp_s = stored->vhostfds;
+ stored->vhostfds = g_strdup_printf("%s:%d", stored->fds, vhostfd);
+ g_free(tmp_s);
+ }
+
s->vhost_net = vhost_net_init(&options);
if (!s->vhost_net) {
if (tap->has_vhostforce && tap->vhostforce) {
@@ -783,6 +874,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
const char *vhostfdname;
char ifname[128];
int ret = 0;
+ NetdevInfo *common_stored = NULL; /* will store configuration */
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
tap = &netdev->u.tap;
@@ -829,7 +921,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
net_init_tap_one(tap, peer, "tap", name, NULL,
script, downscript,
- vhostfdname, vnet_hdr, fd, &err);
+ vhostfdname, vnet_hdr, fd, &common_stored, &err);
if (err) {
error_propagate(errp, err);
close(fd);
@@ -892,7 +984,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
net_init_tap_one(tap, peer, "tap", name, ifname,
script, downscript,
tap->has_vhostfds ? vhost_fds[i] : NULL,
- vnet_hdr, fd, &err);
+ vnet_hdr, fd, &common_stored, &err);
if (err) {
error_propagate(errp, err);
ret = -1;
@@ -935,7 +1027,7 @@ free_fail:
net_init_tap_one(tap, peer, "bridge", name, ifname,
script, downscript, vhostfdname,
- vnet_hdr, fd, &err);
+ vnet_hdr, fd, &common_stored, &err);
if (err) {
error_propagate(errp, err);
close(fd);
@@ -981,7 +1073,8 @@ free_fail:
net_init_tap_one(tap, peer, "tap", name, ifname,
i >= 1 ? "no" : script,
i >= 1 ? "no" : downscript,
- vhostfdname, vnet_hdr, fd, &err);
+ vhostfdname, vnet_hdr, fd,
+ &common_stored, &err);
if (err) {
error_propagate(errp, err);
close(fd);