mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
util: use netlink to create bridge devices
Just as it is possible to delete a bridge device with the netlink RTM_DELLINK message, one can be created with the RTM_NEWLINK message. Because of differences in the format of the message, it's not as straightforward as with virNetlinkDelLink() to create a single utility function that can be used to create any type of interface, so the new netlink version of virNetDevBridgeCreate() does its own construction of the netlink message and calls virNetlinkCommand() itself. This doesn't provide any extra functionality, just provides symmetry with the previous commit. NB: We *could* alter the API of virNetDevBridgeCreate() to take a MAC address, and directly program that mac address into the bridge (by adding an IFLA_ADDRESS attribute, as is done in virNetDevMacVLanCreate()) rather than separately creating the "dummy tap" (e.g. virbr0-nic) to maintain a fixed mac address on the bridge, but the commit history of virnetdevbridge.c shows that the presence of this dummy tap is essential in some older versions of the kernel (between 2.6.39 and 3.1 or 3.2, possibly?) to proper operation of IPv6 DAD, and I don't want to take the chance of breaking something that I don't have the time/setup to test (my RHEL6 box is at kernel 2.6.32-544, and the next lowest kernel I have is 3.17)
This commit is contained in:
parent
09778e0908
commit
fc7b23db02
@ -395,7 +395,83 @@ virNetDevBridgePortSetUnicastFlood(const char *brname ATTRIBUTE_UNUSED,
|
|||||||
*
|
*
|
||||||
* Returns 0 in case of success or -1 on failure
|
* Returns 0 in case of success or -1 on failure
|
||||||
*/
|
*/
|
||||||
#if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
#if defined(__linux__) && defined(HAVE_LIBNL)
|
||||||
|
int virNetDevBridgeCreate(const char *brname)
|
||||||
|
{
|
||||||
|
/* use a netlink RTM_NEWLINK message to create the bridge */
|
||||||
|
const char *type = "bridge";
|
||||||
|
int rc = -1;
|
||||||
|
struct nlmsghdr *resp = NULL;
|
||||||
|
struct nlmsgerr *err;
|
||||||
|
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
|
||||||
|
unsigned int recvbuflen;
|
||||||
|
struct nl_msg *nl_msg;
|
||||||
|
struct nlattr *linkinfo;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
virReportSystemError(-err->error,
|
||||||
|
_("error creating bridge interface %s"),
|
||||||
|
brname);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NLMSG_DONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto malformed_resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
cleanup:
|
||||||
|
nlmsg_free(nl_msg);
|
||||||
|
VIR_FREE(resp);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
||||||
int virNetDevBridgeCreate(const char *brname)
|
int virNetDevBridgeCreate(const char *brname)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user