mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-08-24 09:49:59 +03:00
util: add netlink bridge vlan filtering
Enable capability to add and remove vlan filters for a standard linux bridge using netlink. New function virNetlinkBridgeVlanFilterSet can be used to add or remove a vlan filter to a given bridge interface. Signed-off-by: Leigh Brown <leigh@solinno.co.uk> Reviewed-by: Laine Stump <laine@redhat.com>
This commit is contained in:
@ -701,6 +701,72 @@ virNetlinkDelLink(const char *ifname, virNetlinkTalkFallback fallback)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virNetlinkBridgeVlanFilterSet:
|
||||||
|
*
|
||||||
|
* @ifname: name of the link
|
||||||
|
* @cmd: netlink command, either RTM_SETLINK or RTM_DELLINK
|
||||||
|
* @flags: flags to use when adding the vlan filter
|
||||||
|
* @vid: vlan id to add or remove
|
||||||
|
* @error: netlink error code
|
||||||
|
*
|
||||||
|
* Add or remove a vlan filter from an interface associated with a
|
||||||
|
* bridge.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on error. Additionally, if the @error is
|
||||||
|
* non-zero, then a netlink failure occurred, but no error message
|
||||||
|
* is generated leaving it up to the caller to handle the condition.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virNetlinkBridgeVlanFilterSet(const char *ifname,
|
||||||
|
int cmd,
|
||||||
|
const unsigned short flags,
|
||||||
|
const short vid,
|
||||||
|
int *error)
|
||||||
|
{
|
||||||
|
struct ifinfomsg ifm = { .ifi_family = PF_BRIDGE };
|
||||||
|
struct bridge_vlan_info vinfo = { .flags = flags, .vid = vid };
|
||||||
|
struct nlattr *afspec = NULL;
|
||||||
|
g_autoptr(virNetlinkMsg) nl_msg = NULL;
|
||||||
|
g_autofree struct nlmsghdr *resp = NULL;
|
||||||
|
unsigned int resp_len = 0;
|
||||||
|
|
||||||
|
*error = 0;
|
||||||
|
|
||||||
|
if (vid < 1 || vid > 4095) {
|
||||||
|
virReportError(ERANGE, _("vlanid out of range: %1$d"), vid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(cmd == RTM_SETLINK || cmd == RTM_DELLINK)) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid vlan filter command %1$d"), cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virNetDevGetIndex(ifname, &ifm.ifi_index) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nl_msg = virNetlinkMsgNew(cmd, NLM_F_REQUEST);
|
||||||
|
|
||||||
|
NETLINK_MSG_APPEND(nl_msg, sizeof(ifm), &ifm);
|
||||||
|
|
||||||
|
NETLINK_MSG_NEST_START(nl_msg, afspec, IFLA_AF_SPEC);
|
||||||
|
NETLINK_MSG_PUT(nl_msg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo);
|
||||||
|
NETLINK_MSG_NEST_END(nl_msg, afspec);
|
||||||
|
|
||||||
|
if (virNetlinkTalk(ifname, nl_msg, 0, 0, &resp, &resp_len, error, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (resp->nlmsg_type != NLMSG_ERROR && resp->nlmsg_type != NLMSG_DONE) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("malformed netlink response message"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virNetlinkGetNeighbor:
|
* virNetlinkGetNeighbor:
|
||||||
*
|
*
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#if defined(WITH_LIBNL)
|
#if defined(WITH_LIBNL)
|
||||||
|
|
||||||
# include <netlink/msg.h>
|
# include <netlink/msg.h>
|
||||||
|
# include <linux/if_bridge.h>
|
||||||
|
|
||||||
typedef struct nl_msg virNetlinkMsg;
|
typedef struct nl_msg virNetlinkMsg;
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetlinkMsg, nlmsg_free);
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetlinkMsg, nlmsg_free);
|
||||||
@ -76,6 +77,12 @@ typedef int (*virNetlinkTalkFallback)(const char *ifname);
|
|||||||
|
|
||||||
int virNetlinkDelLink(const char *ifname, virNetlinkTalkFallback fallback);
|
int virNetlinkDelLink(const char *ifname, virNetlinkTalkFallback fallback);
|
||||||
|
|
||||||
|
int virNetlinkBridgeVlanFilterSet(const char *ifname,
|
||||||
|
int cmd,
|
||||||
|
const unsigned short flags,
|
||||||
|
const short vid,
|
||||||
|
int *error);
|
||||||
|
|
||||||
int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen);
|
int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen);
|
||||||
|
|
||||||
int virNetlinkDumpLink(const char *ifname, int ifindex,
|
int virNetlinkDumpLink(const char *ifname, int ifindex,
|
||||||
|
Reference in New Issue
Block a user