[libvirt] [PATCHv2 0/3] network: new network forward mode 'vlan'
by Shi Lei
Hi, everyone!
This patch supports VLan by '8021q' kernel module
other than by OVS. The way of '8021q' is simpler and more robust.
Mode 'vlan' is like mode 'route' except these major differences:
- mode 'vlan' inserts a vlan-device between the specified host's
interface and the internal bridge. The vlan-device is based on
'8021q' kernel module.
- mode 'vlan' has no routed iptables rules but has other common
iptables rules
It can simplify the work of management apps whose developers want to
implement VLan but don't want to introduce OVS into their project.
Thank John for his comments in v1. v1 here:
https://www.redhat.com/archives/libvir-list/2018-July/msg00331.html
since v1:
- Change docs/formatnetwork.html.in
- Change docs/schemas/network.rng
- Add tests/networkxml2*
- Other code fixes
Besides, I have post two patches followed by John's suggestions.
- Replace 'if' type conditions with 'switch' for VIR_NETWORK_FORWARD_*
https://www.redhat.com/archives/libvir-list/2018-July/msg01537.html
This has been accepted.
- Introduce timeout mode for virKModLoad to solve the potential problem
of the 'strange delay' when loading '8021q' module
https://www.redhat.com/archives/libvir-list/2018-August/msg00605.html
This has been rejected and I don't know wether I should continue to
solve this problem. Now I just check the INIT process code of '8021q'
module and I think this module should not cause delay now. The loading
time of '8021q' by virKModLoad on my PC is about 30 milliseconds.
Shi Lei (3):
add functions: load 8021q module, create/destroy vlan-dev
support new forward mode 'vlan' for virtual network
tests and docs for new forward mode 'vlan'
configure.ac | 6 +
docs/formatnetwork.html.in | 27 ++-
docs/schemas/network.rng | 1 +
src/conf/domain_conf.c | 1 +
src/conf/network_conf.c | 24 ++-
src/conf/network_conf.h | 1 +
src/conf/virnetworkobj.c | 1 +
src/esx/esx_network_driver.c | 1 +
src/libvirt_private.syms | 4 +
src/network/bridge_driver.c | 55 +++++-
src/qemu/qemu_process.c | 1 +
src/util/virnetdev.c | 203 +++++++++++++++++++++
src/util/virnetdev.h | 18 ++
tests/networkxml2confdata/vlan-network.conf | 16 ++
tests/networkxml2confdata/vlan-network.xml | 13 ++
tests/networkxml2conftest.c | 1 +
.../vlan-network-multi-vlan-tag.xml | 11 ++
.../vlan-network-no-forward-dev.xml | 10 +
tests/networkxml2xmlin/vlan-network-with-dhcp.xml | 15 ++
tests/networkxml2xmlin/vlan-network.xml | 10 +
tests/networkxml2xmlout/vlan-network-with-dhcp.xml | 17 ++
tests/networkxml2xmlout/vlan-network.xml | 12 ++
tests/networkxml2xmltest.c | 5 +
23 files changed, 448 insertions(+), 5 deletions(-)
create mode 100644 tests/networkxml2confdata/vlan-network.conf
create mode 100644 tests/networkxml2confdata/vlan-network.xml
create mode 100644 tests/networkxml2xmlin/vlan-network-multi-vlan-tag.xml
create mode 100644 tests/networkxml2xmlin/vlan-network-no-forward-dev.xml
create mode 100644 tests/networkxml2xmlin/vlan-network-with-dhcp.xml
create mode 100644 tests/networkxml2xmlin/vlan-network.xml
create mode 100644 tests/networkxml2xmlout/vlan-network-with-dhcp.xml
create mode 100644 tests/networkxml2xmlout/vlan-network.xml
--
2.7.4
6 years, 3 months
[libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
by Shi Lei
This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate
and virNetDevBridgeCreate.
Signed-off-by: Shi Lei <shi_lei(a)massclouds.com>
---
src/libvirt_private.syms | 1 +
src/util/virnetdevbridge.c | 73 +++--------------------
src/util/virnetdevmacvlan.c | 137 ++++++++++++++------------------------------
src/util/virnetlink.c | 104 +++++++++++++++++++++++++++++++++
src/util/virnetlink.h | 8 +++
5 files changed, 164 insertions(+), 159 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 47ea35f..23931ba 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2439,6 +2439,7 @@ virNetlinkEventServiceStop;
virNetlinkEventServiceStopAll;
virNetlinkGetErrorCode;
virNetlinkGetNeighbor;
+virNetlinkNewLink;
virNetlinkShutdown;
virNetlinkStartup;
diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c
index bc377b5..1f5b37e 100644
--- a/src/util/virnetdevbridge.c
+++ b/src/util/virnetdevbridge.c
@@ -417,77 +417,22 @@ virNetDevBridgeCreate(const char *brname)
{
/* use a netlink RTM_NEWLINK message to create the bridge */
const char *type = "bridge";
- struct nlmsgerr *err;
- struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
- unsigned int recvbuflen;
- struct nlattr *linkinfo;
- VIR_AUTOPTR(virNetlinkMsg) nl_msg = NULL;
- VIR_AUTOFREE(struct nlmsghdr *) resp = NULL;
+ int error = 0;
- nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
- if (!nl_msg) {
- virReportOOMError();
- return -1;
- }
-
- if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
- goto buffer_too_small;
- if (nla_put(nl_msg, IFLA_IFNAME, strlen(brname)+1, brname) < 0)
- goto buffer_too_small;
- if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO)))
- goto buffer_too_small;
- if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0)
- goto buffer_too_small;
- nla_nest_end(nl_msg, linkinfo);
-
- if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
- NETLINK_ROUTE, 0) < 0) {
- return -1;
- }
-
- if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
- goto malformed_resp;
-
- switch (resp->nlmsg_type) {
- case NLMSG_ERROR:
- err = (struct nlmsgerr *)NLMSG_DATA(resp);
- if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
- goto malformed_resp;
-
- if (err->error < 0) {
+ if (virNetlinkNewLink(NULL, brname, NULL, type, NULL, NULL, &error) < 0) {
# if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
- if (err->error == -EOPNOTSUPP) {
- /* fallback to ioctl if netlink doesn't support creating
- * bridges
- */
- return virNetDevBridgeCreateWithIoctl(brname);
- }
-# endif
-
- virReportSystemError(-err->error,
- _("error creating bridge interface %s"),
- brname);
- return -1;
+ if (error == -EOPNOTSUPP) {
+ /* fallback to ioctl if netlink doesn't support creating bridges */
+ return virNetDevBridgeCreateWithIoctl(brname);
}
- break;
+# endif
+ virReportSystemError(-error, _("error creating bridge interface %s"),
+ brname);
- case NLMSG_DONE:
- break;
- default:
- goto malformed_resp;
+ return -1;
}
return 0;
-
- malformed_resp:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("malformed netlink response message"));
- return -1;
- buffer_too_small:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("allocated netlink buffer is too small"));
- return -1;
}
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index 2035b1f..1629add 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -283,6 +283,37 @@ virNetDevMacVLanReleaseName(const char *name)
}
+static int
+virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque)
+{
+ const uint32_t *mode = (const uint32_t *) opaque;
+ if (!nl_msg || !opaque) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("nl_msg %p or opaque %p is NULL"),
+ nl_msg, opaque);
+ return -1;
+ }
+
+ if (*mode > 0) {
+ struct nlattr *info_data;
+ if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA)))
+ goto buffer_too_small;
+
+ if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(*mode), mode) < 0)
+ goto buffer_too_small;
+
+ nla_nest_end(nl_msg, info_data);
+ }
+
+ return 0;
+
+ buffer_too_small:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("allocated netlink buffer is too small"));
+ return -1;
+}
+
+
/**
* virNetDevMacVLanCreate:
*
@@ -307,113 +338,29 @@ virNetDevMacVLanCreate(const char *ifname,
uint32_t macvlan_mode,
int *retry)
{
- int rc = -1;
- struct nlmsgerr *err;
- struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
int ifindex;
- unsigned int recvbuflen;
- struct nl_msg *nl_msg;
- struct nlattr *linkinfo, *info_data;
- char macstr[VIR_MAC_STRING_BUFLEN];
- VIR_AUTOFREE(struct nlmsghdr *) resp = NULL;
-
- if (virNetDevGetIndex(srcdev, &ifindex) < 0)
- return -1;
-
+ int error = 0;
*retry = 0;
- nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
- if (!nl_msg) {
- virReportOOMError();
+ if (virNetDevGetIndex(srcdev, &ifindex) < 0)
return -1;
- }
-
- if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
- goto buffer_too_small;
-
- if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0)
- goto buffer_too_small;
-
- if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0)
- goto buffer_too_small;
-
- if (ifname &&
- nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
- goto buffer_too_small;
- if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO)))
- goto buffer_too_small;
-
- if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0)
- goto buffer_too_small;
-
- if (macvlan_mode > 0) {
- if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA)))
- goto buffer_too_small;
-
- if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode),
- &macvlan_mode) < 0)
- goto buffer_too_small;
-
- nla_nest_end(nl_msg, info_data);
- }
-
- nla_nest_end(nl_msg, linkinfo);
-
- if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
- NETLINK_ROUTE, 0) < 0) {
- goto cleanup;
- }
-
- if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
- goto malformed_resp;
-
- switch (resp->nlmsg_type) {
- case NLMSG_ERROR:
- err = (struct nlmsgerr *)NLMSG_DATA(resp);
- if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
- goto malformed_resp;
-
- switch (err->error) {
-
- case 0:
- break;
-
- case -EEXIST:
+ if (virNetlinkNewLink(&ifindex, ifname, macaddress, type,
+ virNetDevMacVLanCreateCallback, &macvlan_mode,
+ &error) < 0) {
+ char macstr[VIR_MAC_STRING_BUFLEN];
+ if (error == -EEXIST)
*retry = 1;
- goto cleanup;
-
- default:
- virReportSystemError(-err->error,
+ else
+ virReportSystemError(-error,
_("error creating %s interface %s@%s (%s)"),
type, ifname, srcdev,
virMacAddrFormat(macaddress, macstr));
- goto cleanup;
- }
- break;
-
- case NLMSG_DONE:
- break;
- default:
- goto malformed_resp;
+ return -1;
}
- rc = 0;
- cleanup:
- nlmsg_free(nl_msg);
- return rc;
-
- malformed_resp:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("malformed netlink response message"));
- goto cleanup;
-
- buffer_too_small:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("allocated netlink buffer is too small"));
- goto cleanup;
+ return 0;
}
/**
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index 8f06446..817e347 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -489,6 +489,110 @@ virNetlinkDumpLink(const char *ifname, int ifindex,
/**
+ * virNetlinkNewLink:
+ *
+ * @ifindex: The index for the 'link' device
+ * @ifname: The name of the link
+ * @mac: The MAC address of the device
+ * @type: The type of device, i.e., "bridge", "macvtap", "macvlan"
+ * @cb: The callback for filling in IFLA_INFO_DATA for this type
+ * @opaque: opaque for the callback
+ * @error: for retrieving error code
+ *
+ * Create a network "link" (aka interface aka device) with the given
+ * args. This works for many different types of network devices,
+ * including macvtap and bridges.
+ *
+ * Returns 0 on success, -1 on fatal error.
+ */
+int
+virNetlinkNewLink(const int *ifindex,
+ const char *ifname,
+ const virMacAddr *mac,
+ const char *type,
+ virNetlinkNewLinkCallback cb,
+ const void *opaque,
+ int *error)
+{
+ struct nlmsgerr *err;
+ struct nlattr *linkinfo;
+ unsigned int buflen;
+ struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
+ VIR_AUTOPTR(virNetlinkMsg) nl_msg = NULL;
+ VIR_AUTOFREE(struct nlmsghdr *) resp = NULL;
+
+ *error = 0;
+
+ nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
+ NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
+ if (!nl_msg) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
+ goto buffer_too_small;
+
+ if (ifindex && nla_put_u32(nl_msg, IFLA_LINK, *ifindex) < 0)
+ goto buffer_too_small;
+
+ if (mac && nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, mac) < 0)
+ goto buffer_too_small;
+
+ if (ifname && nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
+ goto buffer_too_small;
+
+ if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO)))
+ goto buffer_too_small;
+
+ if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0)
+ goto buffer_too_small;
+
+ if (cb && cb(nl_msg, opaque) < 0)
+ return -1;
+
+ nla_nest_end(nl_msg, linkinfo);
+
+ if (virNetlinkCommand(nl_msg, &resp, &buflen, 0, 0, NETLINK_ROUTE, 0) < 0)
+ return -1;
+
+ if (buflen < NLMSG_LENGTH(0) || resp == NULL)
+ goto malformed_resp;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error < 0) {
+ *error = err->error;
+ return -1;
+ }
+ break;
+
+ case NLMSG_DONE:
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ return 0;
+
+ malformed_resp:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ return -1;
+
+ buffer_too_small:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("allocated netlink buffer is too small"));
+ return -1;
+}
+
+
+/**
* virNetlinkDelLink:
*
* @ifname: Name of the link
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 1e1e616..195c7bb 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -65,6 +65,14 @@ int virNetlinkDumpCommand(struct nl_msg *nl_msg,
unsigned int protocol, unsigned int groups,
void *opaque);
+typedef int (*virNetlinkNewLinkCallback)(struct nl_msg *nl_msg,
+ const void *opaque);
+
+int virNetlinkNewLink(const int *ifindex, const char *ifname,
+ const virMacAddr *macaddress, const char *type,
+ virNetlinkNewLinkCallback cb, const void *opaque,
+ int *error);
+
typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);
--
2.7.4
6 years, 3 months
[libvirt] [PATCH v3 0/2] Add .domainGetHostname() support for QEMU driver.
by Julio Faracco
This serie adds a new function into QEMU Guest Agent handlers to use
the QEMU command 'guest-get-host-name' to retrieve the domain hostname.
This approach requires QEMU-GA running inside the guest, but it is the
fastest and easiest way to get this info.
Julio Faracco (2):
qemu: implementing qemuAgentGetHostname() function.
qemu: adding domainGetHostname support for QEMU.
src/qemu/qemu_agent.c | 39 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 4 ++++
src/qemu/qemu_driver.c | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+)
--
2.17.1
6 years, 3 months