From nobody Sat May 18 22:15:09 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1534997730588788.9273555304225; Wed, 22 Aug 2018 21:15:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 57815308429C; Thu, 23 Aug 2018 04:15:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 257B92E04B; Thu, 23 Aug 2018 04:15:28 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id C7F9F4BB75; Thu, 23 Aug 2018 04:15:27 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w7N4FQkk006464 for ; Thu, 23 Aug 2018 00:15:27 -0400 Received: by smtp.corp.redhat.com (Postfix) id CB4512E04C; Thu, 23 Aug 2018 04:15:26 +0000 (UTC) Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.42]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C3B532E04B for ; Thu, 23 Aug 2018 04:15:24 +0000 (UTC) Received: from m50210.mail.qiye.163.com (m50210.mail.qiye.163.com [123.125.50.210]) by mx1.redhat.com (Postfix) with ESMTP id 4FB603082120 for ; Thu, 23 Aug 2018 04:15:18 +0000 (UTC) Received: from localhost.localdomain (unknown [58.56.27.130]) by smtp6 (Coremail) with SMTP id RNOowEBJ3EHTNH5bAxEjAQ--.91S2; Thu, 23 Aug 2018 12:15:15 +0800 (CST) From: Shi Lei To: libvir-list@redhat.com Date: Thu, 23 Aug 2018 12:15:08 +0800 Message-Id: <1534997708-15596-1-git-send-email-shi_lei@massclouds.com> X-CM-TRANSID: RNOowEBJ3EHTNH5bAxEjAQ--.91S2 X-Coremail-Antispam: 1Uf129KBjvJXoW3tFy7GrW8AF18Kr1xXF4kCrg_yoWkGF4fpF 1akas7JFWkJr1xZFZFvFyUGFyavrnrWr45G3y8uan2ya1fAFy5Xr129r1FvayfAr93JryF yF1Y9Fy8Cw4rXaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07j0oGdUUUUU= X-Originating-IP: [58.56.27.130] X-CM-SenderInfo: pvklsz1hl6ztxvvfz0xxgvhudrp/1tbifgGrT1rpNCiW5gABsF X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 212 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 23 Aug 2018 04:15:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 23 Aug 2018 04:15:21 +0000 (UTC) for IP:'123.125.50.210' DOMAIN:'m50210.mail.qiye.163.com' HELO:'m50210.mail.qiye.163.com' FROM:'shi_lei@massclouds.com' RCPT:'' X-RedHat-Spam-Score: -0.01 (RCVD_IN_DNSWL_NONE) 123.125.50.210 m50210.mail.qiye.163.com 123.125.50.210 m50210.mail.qiye.163.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.42 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Thu, 23 Aug 2018 04:15:29 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate and virNetDevBridgeCreate. Signed-off-by: Shi Lei --- 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; =20 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 =3D "bridge"; - struct nlmsgerr *err; - struct ifinfomsg ifinfo =3D { .ifi_family =3D AF_UNSPEC }; - unsigned int recvbuflen; - struct nlattr *linkinfo; - VIR_AUTOPTR(virNetlinkMsg) nl_msg =3D NULL; - VIR_AUTOFREE(struct nlmsghdr *) resp =3D NULL; + int error =3D 0; =20 - nl_msg =3D 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 =3D 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 =3D=3D NULL) - goto malformed_resp; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err =3D (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 =3D=3D -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 =3D=3D -EOPNOTSUPP) { + /* fallback to ioctl if netlink doesn't support creating bridg= es */ + return virNetDevBridgeCreateWithIoctl(brname); } - break; +# endif + virReportSystemError(-error, _("error creating bridge interface %s= "), + brname); =20 - case NLMSG_DONE: - break; - default: - goto malformed_resp; + return -1; } =20 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; } =20 =20 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) } =20 =20 +static int +virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque) +{ + const uint32_t *mode =3D (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 =3D 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 =3D -1; - struct nlmsgerr *err; - struct ifinfomsg ifinfo =3D { .ifi_family =3D 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 =3D NULL; - - if (virNetDevGetIndex(srcdev, &ifindex) < 0) - return -1; - + int error =3D 0; *retry =3D 0; =20 - nl_msg =3D 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; =20 - if (!(linkinfo =3D 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 =3D 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 =3D=3D NULL) - goto malformed_resp; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err =3D (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 =3D=3D -EEXIST) *retry =3D 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; =20 - default: - goto malformed_resp; + return -1; } =20 - rc =3D 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; } =20 /** 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, =20 =20 /** + * 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 =3D { .ifi_family =3D AF_UNSPEC }; + VIR_AUTOPTR(virNetlinkMsg) nl_msg =3D NULL; + VIR_AUTOFREE(struct nlmsghdr *) resp =3D NULL; + + *error =3D 0; + + nl_msg =3D 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 =3D 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 =3D=3D NULL) + goto malformed_resp; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err =3D (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error < 0) { + *error =3D 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); =20 +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); =20 int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallba= ck); --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list