return 0;
}
+#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
+
+int link_update_bridge_vlan(Link *link, sd_netlink_message *m) {
+ _cleanup_free_ void *data = NULL;
+ size_t len;
+ uint16_t begin = UINT16_MAX;
+ int r, family;
+
+ assert(link);
+ assert(m);
+
+ r = sd_rtnl_message_get_family(m, &family);
+ if (r < 0)
+ return r;
+
+ if (family != AF_BRIDGE)
+ return 0;
+
+ r = sd_netlink_message_read_data(m, IFLA_AF_SPEC, &len, &data);
+ if (r == -ENODATA)
+ return 0;
+ if (r < 0)
+ return r;
+
+ memzero(link->bridge_vlan_bitmap, sizeof(link->bridge_vlan_bitmap));
+
+ for (struct rtattr *rta = data; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+ struct bridge_vlan_info *p;
+
+ if (RTA_TYPE(rta) != IFLA_BRIDGE_VLAN_INFO)
+ continue;
+ if (RTA_PAYLOAD(rta) != sizeof(struct bridge_vlan_info))
+ continue;
+
+ p = RTA_DATA(rta);
+
+ if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_RANGE_BEGIN)) {
+ begin = p->vid;
+ continue;
+ }
+
+ if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_RANGE_END)) {
+ for (uint16_t k = begin; k <= p->vid; k++)
+ set_bit(k, link->bridge_vlan_bitmap);
+
+ begin = UINT16_MAX;
+ continue;
+ }
+
+ if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_PVID)) {
+ link->bridge_vlan_pvid = p->vid;
+ link->bridge_vlan_pvid_is_untagged = FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_UNTAGGED);
+ }
+
+ set_bit(p->vid, link->bridge_vlan_bitmap);
+ begin = UINT16_MAX;
+ }
+
+ return 0;
+}
+
void network_adjust_bridge_vlan(Network *network) {
assert(network);
int bridge_vlan_set_message(Link *link, sd_netlink_message *m);
+int link_update_bridge_vlan(Link *link, sd_netlink_message *m);
+
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id_range);
#include "networkd-address.h"
#include "networkd-bridge-fdb.h"
#include "networkd-bridge-mdb.h"
+#include "networkd-bridge-vlan.h"
#include "networkd-can.h"
#include "networkd-dhcp-prefix-delegation.h"
#include "networkd-dhcp-server.h"
if (r < 0)
return r;
+ r = link_update_bridge_vlan(link, message);
+ if (r < 0)
+ return r;
+
return needs_reconfigure;
}
.ifname = TAKE_PTR(ifname),
.kind = TAKE_PTR(kind),
+ .bridge_vlan_pvid = UINT16_MAX,
+
.ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
.state_file = TAKE_PTR(state_file),
#include "log-link.h"
#include "netif-util.h"
#include "network-util.h"
+#include "networkd-bridge-vlan.h"
#include "networkd-ipv6ll.h"
#include "networkd-util.h"
#include "ordered-set.h"
sd_device *dev;
char *driver;
+ /* bridge vlan */
+ uint16_t bridge_vlan_pvid;
+ bool bridge_vlan_pvid_is_untagged;
+ uint32_t bridge_vlan_bitmap[BRIDGE_VLAN_BITMAP_LEN];
+
/* to prevent multiple ethtool calls */
bool ethtool_driver_read;
bool ethtool_permanent_hw_addr_read;
if (r < 0)
return r;
+ r = manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
+ if (r < 0)
+ return r;
+
+ req = sd_netlink_message_unref(req);
+
+ r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
+ if (r < 0)
+ return r;
+
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
}