mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
util: netlink: Use virNetlinkNewLink helper to simplify virNetDev*Create
This patch simplifies virNetDevBridgeCreate and virNetDevMacVLanCreate functions by making use of the virNetlinkNewLink helper. Signed-off-by: Shi Lei <shi_lei@massclouds.com> Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
b6ba2b961a
commit
ffd31684be
@ -416,78 +416,23 @@ int
|
|||||||
virNetDevBridgeCreate(const char *brname)
|
virNetDevBridgeCreate(const char *brname)
|
||||||
{
|
{
|
||||||
/* use a netlink RTM_NEWLINK message to create the bridge */
|
/* use a netlink RTM_NEWLINK message to create the bridge */
|
||||||
const char *type = "bridge";
|
int error = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
|
if (virNetlinkNewLink(brname, "bridge", NULL, &error) < 0) {
|
||||||
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 defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
# if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
||||||
if (err->error == -EOPNOTSUPP) {
|
if (error == -EOPNOTSUPP) {
|
||||||
/* fallback to ioctl if netlink doesn't support creating
|
/* fallback to ioctl if netlink doesn't support creating bridges */
|
||||||
* bridges
|
return virNetDevBridgeCreateWithIoctl(brname);
|
||||||
*/
|
|
||||||
return virNetDevBridgeCreateWithIoctl(brname);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
virReportSystemError(-err->error,
|
|
||||||
_("error creating bridge interface %s"),
|
|
||||||
brname);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
break;
|
# endif
|
||||||
|
if (error < 0)
|
||||||
|
virReportSystemError(-error, _("error creating bridge interface %s"),
|
||||||
|
brname);
|
||||||
|
|
||||||
case NLMSG_DONE:
|
return -1;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto malformed_resp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,113 +307,33 @@ virNetDevMacVLanCreate(const char *ifname,
|
|||||||
uint32_t macvlan_mode,
|
uint32_t macvlan_mode,
|
||||||
int *retry)
|
int *retry)
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int error = 0;
|
||||||
struct nlmsgerr *err;
|
int ifindex = 0;
|
||||||
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
|
virNetlinkNewLinkData data = {
|
||||||
int ifindex;
|
.macvlan_mode = &macvlan_mode,
|
||||||
unsigned int recvbuflen;
|
.mac = macaddress,
|
||||||
struct nl_msg *nl_msg;
|
};
|
||||||
struct nlattr *linkinfo, *info_data;
|
|
||||||
char macstr[VIR_MAC_STRING_BUFLEN];
|
*retry = 0;
|
||||||
VIR_AUTOFREE(struct nlmsghdr *) resp = NULL;
|
|
||||||
|
|
||||||
if (virNetDevGetIndex(srcdev, &ifindex) < 0)
|
if (virNetDevGetIndex(srcdev, &ifindex) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*retry = 0;
|
data.ifindex = &ifindex;
|
||||||
|
if (virNetlinkNewLink(ifname, type, &data, &error) < 0) {
|
||||||
nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
|
char macstr[VIR_MAC_STRING_BUFLEN];
|
||||||
NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
|
if (error == -EEXIST)
|
||||||
if (!nl_msg) {
|
|
||||||
virReportOOMError();
|
|
||||||
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:
|
|
||||||
*retry = 1;
|
*retry = 1;
|
||||||
goto cleanup;
|
else if (error < 0)
|
||||||
|
virReportSystemError(-error,
|
||||||
default:
|
|
||||||
virReportSystemError(-err->error,
|
|
||||||
_("error creating %s interface %s@%s (%s)"),
|
_("error creating %s interface %s@%s (%s)"),
|
||||||
type, ifname, srcdev,
|
type, ifname, srcdev,
|
||||||
virMacAddrFormat(macaddress, macstr));
|
virMacAddrFormat(macaddress, macstr));
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NLMSG_DONE:
|
return -1;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto malformed_resp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = 0;
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user