mirror of
https://github.com/systemd/systemd.git
synced 2024-10-27 10:25:37 +03:00
network: Add L3MasterDevice= into routing policy
This commit is contained in:
parent
12af3f1834
commit
4be1fc8443
@ -1629,6 +1629,18 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>L3MasterDevice=</varname></term>
|
||||
<listitem>
|
||||
<para>A boolean. Specifies whether the rule is to direct lookups to the tables associated with
|
||||
level 3 master devices (also known as Virtual Routing and Forwarding or VRF devices).
|
||||
For further details see <ulink url="https://docs.kernel.org/networking/vrf.html">
|
||||
Virtual Routing and Forwarding (VRF)</ulink>. Defaults to false.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SourcePort=</varname></term>
|
||||
<listitem>
|
||||
@ -1951,7 +1963,7 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
|
||||
<command>ip route show table <replaceable>num</replaceable></command>. If unset and
|
||||
<varname>Type=</varname> is <literal>local</literal>, <literal>broadcast</literal>,
|
||||
<literal>anycast</literal>, or <literal>nat</literal>, then <literal>local</literal> is used.
|
||||
In other cases, defaults to <literal>main</literal>.</para>
|
||||
In other cases, defaults to <literal>main</literal>. Ignored if <varname>L3MasterDevice=</varname> is true.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v230"/>
|
||||
</listitem>
|
||||
|
@ -180,6 +180,7 @@ RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule_ip
|
||||
RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0
|
||||
RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0
|
||||
RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0
|
||||
RoutingPolicyRule.L3MasterDevice, config_parse_routing_policy_rule_l3mdev, 0, 0
|
||||
RoutingPolicyRule.Family, config_parse_routing_policy_rule_family, 0, 0
|
||||
RoutingPolicyRule.User, config_parse_routing_policy_rule_uid_range, 0, 0
|
||||
RoutingPolicyRule.SuppressInterfaceGroup, config_parse_routing_policy_rule_suppress_ifgroup, 0, 0
|
||||
|
@ -164,6 +164,8 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
|
||||
in_addr_hash_func(&rule->from, rule->family, state);
|
||||
siphash24_compress_typesafe(rule->from_prefixlen, state);
|
||||
|
||||
siphash24_compress_boolean(rule->l3mdev, state);
|
||||
|
||||
in_addr_hash_func(&rule->to, rule->family, state);
|
||||
siphash24_compress_typesafe(rule->to_prefixlen, state);
|
||||
|
||||
@ -212,6 +214,10 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->l3mdev, b->l3mdev);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->to_prefixlen, b->to_prefixlen);
|
||||
if (r != 0)
|
||||
return r;
|
||||
@ -476,19 +482,19 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
|
||||
return r;
|
||||
}
|
||||
|
||||
if (rule->table < 256) {
|
||||
if (rule->l3mdev)
|
||||
r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
|
||||
else if (rule->table < 256)
|
||||
r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
else {
|
||||
r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rule->fwmark > 0) {
|
||||
r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
|
||||
@ -544,6 +550,12 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
|
||||
return r;
|
||||
}
|
||||
|
||||
if (rule->l3mdev) {
|
||||
r = sd_netlink_message_append_u8(m, FRA_L3MDEV, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (rule->suppress_prefixlen >= 0) {
|
||||
r = sd_netlink_message_append_u32(m, FRA_SUPPRESS_PREFIXLEN, (uint32_t) rule->suppress_prefixlen);
|
||||
if (r < 0)
|
||||
@ -853,20 +865,17 @@ int link_request_static_routing_policy_rules(Link *link) {
|
||||
|
||||
static const RoutingPolicyRule kernel_rules[] = {
|
||||
{ .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
|
||||
{ .family = AF_INET, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true },
|
||||
{ .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
|
||||
{ .family = AF_INET, .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
|
||||
{ .family = AF_INET6, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
|
||||
{ .family = AF_INET6, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true },
|
||||
{ .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, },
|
||||
};
|
||||
|
||||
static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) {
|
||||
assert(rule);
|
||||
|
||||
if (rule->l3mdev > 0)
|
||||
/* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
|
||||
* is set, it is safe to treat the rule as created by kernel. */
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < ELEMENTSOF(kernel_rules); i++)
|
||||
if (routing_policy_rule_equal(rule, &kernel_rules[i]))
|
||||
return true;
|
||||
@ -1016,11 +1025,13 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u8(message, FRA_L3MDEV, &tmp->l3mdev);
|
||||
uint8_t l3mdev = 0;
|
||||
r = sd_netlink_message_read_u8(message, FRA_L3MDEV, &l3mdev);
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
log_warning_errno(r, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
tmp->l3mdev = l3mdev != 0;
|
||||
|
||||
r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
@ -1502,6 +1513,44 @@ int config_parse_routing_policy_rule_invert(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_routing_policy_rule_l3mdev(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
|
||||
Network *network = userdata;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = routing_policy_rule_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule l3mdev, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->l3mdev = r;
|
||||
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_routing_policy_rule_family(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -1734,12 +1783,6 @@ static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
|
||||
/* rule->family can be AF_UNSPEC only when Family=both. */
|
||||
}
|
||||
|
||||
/* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
|
||||
* update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
|
||||
* added in the future. */
|
||||
if (rule->l3mdev > 0)
|
||||
assert_not_reached();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ typedef struct RoutingPolicyRule {
|
||||
|
||||
bool invert_rule;
|
||||
bool priority_set;
|
||||
bool l3mdev; /* FRA_L3MDEV */
|
||||
|
||||
uint8_t tos;
|
||||
uint8_t type;
|
||||
@ -29,7 +30,6 @@ typedef struct RoutingPolicyRule {
|
||||
uint8_t protocol; /* FRA_PROTOCOL */
|
||||
uint8_t to_prefixlen;
|
||||
uint8_t from_prefixlen;
|
||||
uint8_t l3mdev; /* FRA_L3MDEV */
|
||||
|
||||
uint32_t table;
|
||||
uint32_t fwmark;
|
||||
@ -80,6 +80,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_fwmark_mask);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_prefix);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_l3mdev);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
|
||||
|
@ -496,6 +496,7 @@ KernelVersion=
|
||||
Key=
|
||||
Kind=
|
||||
L2MissNotification=
|
||||
L3MasterDevice=
|
||||
L3MissNotification=
|
||||
LACPTransmitRate=
|
||||
LLDP=
|
||||
|
15
test/test-network/conf/25-fibrule-l3mdev.network
Normal file
15
test/test-network/conf/25-fibrule-l3mdev.network
Normal file
@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=test1
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
|
||||
[RoutingPolicyRule]
|
||||
Priority=1500
|
||||
L3MasterDevice=true
|
||||
|
||||
[RoutingPolicyRule]
|
||||
Priority=2000
|
||||
L3MasterDevice=true
|
||||
Type=unreachable
|
@ -199,6 +199,14 @@ def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
|
||||
|
||||
return f
|
||||
|
||||
def expectedFailureIfRoutingPolicyL3MasterDeviceIsNotAvailable():
|
||||
def f(func):
|
||||
rc = call_quiet('ip rule add not from 192.168.100.19 l3mdev')
|
||||
call_quiet('ip rule del not from 192.168.100.19 l3mdev')
|
||||
return func if rc == 0 else unittest.expectedFailure(func)
|
||||
|
||||
return f
|
||||
|
||||
def expectedFailureIfNexthopIsNotAvailable():
|
||||
def f(func):
|
||||
rc = call_quiet('ip nexthop list')
|
||||
@ -3106,6 +3114,17 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, 'tcp')
|
||||
self.assertRegex(output, 'lookup 7')
|
||||
|
||||
@expectedFailureIfRoutingPolicyL3MasterDeviceIsNotAvailable()
|
||||
def test_routing_policy_rule_l3mdev(self):
|
||||
copy_network_unit('25-fibrule-l3mdev.network', '11-dummy.netdev')
|
||||
start_networkd()
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output('ip rule')
|
||||
print(output)
|
||||
self.assertIn('1500: from all lookup [l3mdev-table]', output)
|
||||
self.assertIn('2000: from all lookup [l3mdev-table] unreachable', output)
|
||||
|
||||
@expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
|
||||
def test_routing_policy_rule_uidrange(self):
|
||||
copy_network_unit('25-fibrule-uidrange.network', '11-dummy.netdev')
|
||||
|
Loading…
Reference in New Issue
Block a user