mirror of
https://github.com/systemd/systemd.git
synced 2025-12-02 12:24:18 +03:00
Merge pull request #10988 from ssahani/IFLA_BRPORT_MCAST_TO_UCAST
networkd: bridge add support to configure multicast_to_unicast
This commit is contained in:
@@ -1729,6 +1729,15 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>MulticastToUnicast=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. Multicast to unicast works on top of the multicast snooping feature of
|
||||
the bridge. Which means unicast copies are only delivered to hosts which are interested in it.
|
||||
When unset, the kernel's default will be used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>HairPin=</varname></term>
|
||||
<listitem>
|
||||
|
||||
@@ -423,6 +423,29 @@ static const struct NLType rtnl_prot_info_bridge_port_types[] = {
|
||||
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ROOT_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BRIDGE_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_DESIGNATED_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_DESIGNATED_COST] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NO] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_CONFIG_PENDING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MESSAGE_AGE_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_HOLD_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FLUSH] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PAD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_VLAN_TUNNEL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ISOLATED] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BACKUP_PORT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_prot_info_type_systems[] = {
|
||||
|
||||
@@ -1421,7 +1421,12 @@ static int link_set_bridge(Link *link) {
|
||||
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
|
||||
}
|
||||
|
||||
if (link->network->multicast_to_unicast >= 0) {
|
||||
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
|
||||
}
|
||||
|
||||
if (link->network->cost != 0) {
|
||||
@@ -1429,6 +1434,7 @@ static int link_set_bridge(Link *link) {
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
|
||||
}
|
||||
|
||||
if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
|
||||
r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
|
||||
if (r < 0)
|
||||
|
||||
@@ -163,6 +163,7 @@ Bridge.HairPin, config_parse_tristate,
|
||||
Bridge.FastLeave, config_parse_tristate, 0, offsetof(Network, fast_leave)
|
||||
Bridge.AllowPortToBeRoot, config_parse_tristate, 0, offsetof(Network, allow_port_to_be_root)
|
||||
Bridge.UnicastFlood, config_parse_tristate, 0, offsetof(Network, unicast_flood)
|
||||
Bridge.MulticastToUnicast, config_parse_tristate, 0, offsetof(Network, multicast_to_unicast)
|
||||
Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority)
|
||||
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
|
||||
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
|
||||
|
||||
@@ -163,6 +163,7 @@ int network_load_one(Manager *manager, const char *filename) {
|
||||
.fast_leave = -1,
|
||||
.allow_port_to_be_root = -1,
|
||||
.unicast_flood = -1,
|
||||
.multicast_to_unicast = -1,
|
||||
.priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
|
||||
|
||||
.lldp_mode = LLDP_MODE_ROUTERS_ONLY,
|
||||
|
||||
@@ -183,6 +183,7 @@ struct Network {
|
||||
int fast_leave;
|
||||
int allow_port_to_be_root;
|
||||
int unicast_flood;
|
||||
int multicast_to_unicast;
|
||||
uint32_t cost;
|
||||
uint16_t priority;
|
||||
|
||||
|
||||
@@ -9,3 +9,4 @@ Cost=400
|
||||
HairPin = true
|
||||
FastLeave = true
|
||||
UnicastFlood = true
|
||||
MulticastToUnicast = true
|
||||
|
||||
@@ -6,6 +6,7 @@ UnicastFlood=
|
||||
FastLeave=
|
||||
Priority=
|
||||
AllowPortToBeRoot=
|
||||
MulticastToUnicast=
|
||||
[Match]
|
||||
KernelVersion=
|
||||
Type=
|
||||
|
||||
@@ -417,6 +417,7 @@ Group=
|
||||
GroupForwardMask=
|
||||
GroupPolicyExtension=
|
||||
HairPin=
|
||||
MulticastToUnicast=
|
||||
HelloTimeSec=
|
||||
HomeAddress=
|
||||
Host=
|
||||
|
||||
@@ -9,3 +9,4 @@ Cost=400
|
||||
HairPin = true
|
||||
FastLeave = true
|
||||
UnicastFlood = true
|
||||
MulticastToUnicast = true
|
||||
|
||||
@@ -61,6 +61,15 @@ class Utilities():
|
||||
with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
|
||||
return f.readline().strip()
|
||||
|
||||
def read_bridge_port_attr(self, bridge, link, attribute):
|
||||
|
||||
path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
|
||||
path_port = 'lower_' + link + '/brport'
|
||||
path = os.path.join(path_bridge, path_port)
|
||||
|
||||
with open(os.path.join(path, attribute)) as f:
|
||||
return f.readline().strip()
|
||||
|
||||
def link_exits(self, link):
|
||||
return os.path.exists(os.path.join('/sys/class/net', link))
|
||||
|
||||
@@ -735,10 +744,15 @@ class NetworkdNetWorkBrideTests(unittest.TestCase, Utilities):
|
||||
|
||||
output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertRegex(output, 'cost 400')
|
||||
self.assertRegex(output, 'hairpin on')
|
||||
self.assertRegex(output, 'flood on')
|
||||
self.assertRegex(output, 'fastleave on')
|
||||
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
|
||||
|
||||
# CONFIG_BRIDGE_IGMP_SNOOPING=y
|
||||
if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
|
||||
|
||||
class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
|
||||
links = ['veth99']
|
||||
|
||||
Reference in New Issue
Block a user