platform: add support for bridge vlans

This commit is contained in:
Beniamino Galvani 2019-03-16 17:22:35 +01:00
parent be2fbd0c69
commit fafde171ea
3 changed files with 121 additions and 1 deletions

View file

@ -29,6 +29,7 @@
#include <linux/fib_rules.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/if_bridge.h>
#include <linux/if_link.h>
#include <linux/if_tun.h>
#include <linux/if_tunnel.h>
@ -277,6 +278,14 @@ struct _ifla_vf_vlan_info {
/*****************************************************************************/
/* Appeared in in kernel 4.0 dated April 12, 2015 */
#ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN
#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1 << 3) /* VLAN is start of vlan range */
#define BRIDGE_VLAN_INFO_RANGE_END (1 << 4) /* VLAN is end of vlan range */
#endif
/*****************************************************************************/
typedef enum {
INFINIBAND_ACTION_CREATE_CHILD,
INFINIBAND_ACTION_DELETE_CHILD,
@ -3858,7 +3867,7 @@ _nl_msg_new_link_full (int nlmsg_type,
.ifi_index = ifindex,
};
nm_assert (NM_IN_SET (nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK));
nm_assert (NM_IN_SET (nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK));
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
@ -6781,6 +6790,67 @@ nla_put_failure:
g_return_val_if_reached (FALSE);
}
static gboolean
link_set_bridge_vlans (NMPlatform *platform,
int ifindex,
gboolean on_master,
const NMPlatformBridgeVlan *const *vlans)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
struct nlattr *list;
struct bridge_vlan_info vinfo = { };
guint i;
nlmsg = _nl_msg_new_link_full (vlans ? RTM_SETLINK : RTM_DELLINK,
0,
ifindex,
NULL,
AF_BRIDGE,
0,
0);
if (!nlmsg)
g_return_val_if_reached (-NME_BUG);
if (!(list = nla_nest_start (nlmsg, IFLA_AF_SPEC)))
goto nla_put_failure;
NLA_PUT_U16 (nlmsg,
IFLA_BRIDGE_FLAGS,
on_master ? BRIDGE_FLAGS_MASTER : BRIDGE_FLAGS_SELF);
if (vlans) {
/* Add VLANs */
for (i = 0; vlans[i]; i++) {
const NMPlatformBridgeVlan *vlan = vlans[i];
vinfo.vid = vlan->vid;
vinfo.flags = 0;
if (vlan->untagged)
vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
if (vlan->pvid)
vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo);
}
} else {
/* Flush existing VLANs */
vinfo.vid = 1;
vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo);
vinfo.vid = 4094;
vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo);
}
nla_nest_end (nlmsg, list);
return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0);
nla_put_failure:
g_return_val_if_reached (FALSE);
}
static char *
link_get_physical_port_id (NMPlatform *platform, int ifindex)
{
@ -8921,6 +8991,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_set_name = link_set_name;
platform_class->link_set_sriov_params = link_set_sriov_params;
platform_class->link_set_sriov_vfs = link_set_sriov_vfs;
platform_class->link_set_bridge_vlans = link_set_bridge_vlans;
platform_class->link_get_physical_port_id = link_get_physical_port_id;
platform_class->link_get_dev_id = link_get_dev_id;

View file

@ -1518,6 +1518,28 @@ nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformV
return klass->link_set_sriov_vfs (self, ifindex, vfs);
}
gboolean
nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans)
{
guint i;
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
_LOG3D ("link: %s bridge VLANs on %s",
vlans ? "setting" : "clearing",
on_master ? "master" : "self");
if (vlans) {
for (i = 0; vlans[i]; i++) {
const NMPlatformBridgeVlan *vlan = vlans[i];
_LOG3D ("link: bridge VLAN %s", nm_platform_bridge_vlan_to_string (vlan, NULL, 0));
}
}
return klass->link_set_bridge_vlans (self, ifindex, on_master, vlans);
}
/**
* nm_platform_link_set_up:
* @self: platform instance
@ -6506,6 +6528,24 @@ nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len)
return buf;
}
const char *
nm_platform_bridge_vlan_to_string (const NMPlatformBridgeVlan *vlan, char *buf, gsize len)
{
if (!nm_utils_to_string_buffer_init_null (vlan, &buf, &len))
return buf;
g_snprintf (buf, len,
"%u"
"%s"
"%s",
vlan->vid,
vlan->pvid ? " PVID" : "",
vlan->untagged ? " untagged" : "");
return buf;
}
void
nm_platform_link_hash_update (const NMPlatformLink *obj, NMHashState *h)
{

View file

@ -670,6 +670,12 @@ typedef struct {
gint8 trust;
} NMPlatformVF;
typedef struct {
guint16 vid;
bool untagged:1;
bool pvid:1;
} NMPlatformBridgeVlan;
typedef struct {
in_addr_t local;
in_addr_t remote;
@ -893,6 +899,7 @@ typedef struct {
gboolean (*link_set_name) (NMPlatform *, int ifindex, const char *name);
gboolean (*link_set_sriov_params) (NMPlatform *, int ifindex, guint num_vfs, int autoprobe);
gboolean (*link_set_sriov_vfs) (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
gboolean (*link_set_bridge_vlans) (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
guint (*link_get_dev_id) (NMPlatform *, int ifindex);
@ -1326,6 +1333,7 @@ int nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name);
gboolean nm_platform_link_set_sriov_params (NMPlatform *self, int ifindex, guint num_vfs, int autoprobe);
gboolean nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
gboolean nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
char *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex);
guint nm_platform_link_get_dev_id (NMPlatform *self, int ifindex);
@ -1585,6 +1593,7 @@ const char *nm_platform_routing_rule_to_string (const NMPlatformRoutingRule *rou
const char *nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len);
const char *nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsize len);
const char *nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len);
const char *nm_platform_bridge_vlan_to_string (const NMPlatformBridgeVlan *vlan, char *buf, gsize len);
const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
const NMVlanQosMapping *map,