mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
Merge pull request #18711 from yuwata/network-nexthop-onlink
network: nexthop: add OnLink= setting
This commit is contained in:
@@ -1340,6 +1340,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
to <literal>ipv4</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>OnLink=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If set to true, the kernel does not have to check if the gateway is
|
||||
reachable directly by the current machine (i.e., attached to the local network), so that we
|
||||
can insert the nexthop in the kernel table without it being complained about. Defaults to
|
||||
<literal>no</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
@@ -1361,9 +1370,9 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
<term><varname>GatewayOnLink=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If set to true, the kernel does not have to check if the gateway is
|
||||
reachable directly by the current machine (i.e., the kernel does not need to check if the
|
||||
gateway is attached to the local network), so that we can insert the route in the kernel
|
||||
table without it being complained about. Defaults to <literal>no</literal>.</para>
|
||||
reachable directly by the current machine (i.e., attached to the local network), so that we
|
||||
can insert the route in the kernel table without it being complained about. Defaults to
|
||||
<literal>no</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
@@ -189,6 +189,7 @@ Route.NextHop, config_parse_route_nexthop,
|
||||
NextHop.Id, config_parse_nexthop_id, 0, 0
|
||||
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
|
||||
NextHop.Family, config_parse_nexthop_family, 0, 0
|
||||
NextHop.OnLink, config_parse_nexthop_onlink, 0, 0
|
||||
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||
DHCPv4.UseDNS, config_parse_dhcp_use_dns, 0, 0
|
||||
DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns)
|
||||
|
||||
@@ -47,6 +47,7 @@ static int nexthop_new(NextHop **ret) {
|
||||
|
||||
*nexthop = (NextHop) {
|
||||
.family = AF_UNSPEC,
|
||||
.onlink = -1,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(nexthop);
|
||||
@@ -360,6 +361,12 @@ static int nexthop_configure(const NextHop *nexthop, Link *link) {
|
||||
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
|
||||
|
||||
if (nexthop->onlink > 0) {
|
||||
r = sd_rtnl_message_nexthop_set_flags(req, RTNH_F_ONLINK);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to set RTNH_F_ONLINK flag: %m");
|
||||
}
|
||||
}
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,
|
||||
@@ -549,6 +556,16 @@ static int nexthop_section_verify(NextHop *nh) {
|
||||
/* When no Gateway= is specified, assume IPv4. */
|
||||
nh->family = AF_INET;
|
||||
|
||||
if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw) &&
|
||||
ordered_hashmap_isempty(nh->network->addresses_by_section)) {
|
||||
/* If no address is configured, in most cases the gateway cannot be reachable.
|
||||
* TODO: we may need to improve the condition above. */
|
||||
log_warning("%s: Gateway= without static address configured. "
|
||||
"Enabling OnLink= option.",
|
||||
nh->section->filename);
|
||||
nh->onlink = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -722,3 +739,48 @@ int config_parse_nexthop_family(
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_nexthop_onlink(
|
||||
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_(nexthop_free_or_set_invalidp) NextHop *n = NULL;
|
||||
Network *network = userdata;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = nexthop_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
n->onlink = -1;
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->onlink = r;
|
||||
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct NextHop {
|
||||
uint32_t id;
|
||||
int family;
|
||||
union in_addr_union gw;
|
||||
int onlink;
|
||||
} NextHop;
|
||||
|
||||
NextHop *nexthop_free(NextHop *nexthop);
|
||||
@@ -41,3 +42,4 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_family);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_onlink);
|
||||
|
||||
@@ -2743,9 +2743,10 @@ static int route_section_verify(Route *route, Network *network) {
|
||||
if (route->family == AF_INET6 && route->priority == 0)
|
||||
route->priority = IP6_RT_PRIO_USER;
|
||||
|
||||
if (ordered_hashmap_isempty(network->addresses_by_section) &&
|
||||
in_addr_is_set(route->gw_family, &route->gw) &&
|
||||
route->gateway_onlink < 0) {
|
||||
if (route->gateway_onlink < 0 && in_addr_is_set(route->gw_family, &route->gw) &&
|
||||
ordered_hashmap_isempty(network->addresses_by_section)) {
|
||||
/* If no address is configured, in most cases the gateway cannot be reachable.
|
||||
* TODO: we may need to improve the condition above. */
|
||||
log_warning("%s: Gateway= without static address configured. "
|
||||
"Enabling GatewayOnLink= option.",
|
||||
network->filename);
|
||||
|
||||
@@ -352,6 +352,7 @@ SendVendorOption=
|
||||
Id=
|
||||
Gateway=
|
||||
Family=
|
||||
OnLink=
|
||||
[QDisc]
|
||||
Parent=
|
||||
Handle=
|
||||
|
||||
@@ -23,6 +23,11 @@ Family=ipv6
|
||||
Id=4
|
||||
Family=ipv4
|
||||
|
||||
[NextHop]
|
||||
Id=5
|
||||
Gateway=192.168.10.1
|
||||
OnLink=yes
|
||||
|
||||
[NextHop]
|
||||
Gateway=192.168.5.2
|
||||
|
||||
@@ -37,3 +42,7 @@ Destination=10.10.10.11
|
||||
[Route]
|
||||
NextHop=2
|
||||
Destination=2001:1234:5:8f62::1
|
||||
|
||||
[Route]
|
||||
NextHop=5
|
||||
Destination=10.10.10.12
|
||||
|
||||
@@ -2812,6 +2812,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output)
|
||||
self.assertIn('id 3 dev veth99', output)
|
||||
self.assertIn('id 4 dev veth99', output)
|
||||
self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink')
|
||||
self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
|
||||
|
||||
output = check_output('ip route show dev veth99 10.10.10.10')
|
||||
@@ -2822,6 +2823,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output)
|
||||
|
||||
output = check_output('ip route show dev veth99 10.10.10.12')
|
||||
print(output)
|
||||
self.assertEqual('10.10.10.12 nhid 5 via 192.168.10.1 proto static onlink', output)
|
||||
|
||||
output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1')
|
||||
print(output)
|
||||
self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output)
|
||||
|
||||
Reference in New Issue
Block a user