summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-07-12 07:31:50 +0200
committerGitHub <noreply@github.com>2019-07-12 07:31:50 +0200
commita04285c6b1a53e7b3cf1bd0df341f324592ef1b1 (patch)
tree8935ceeb28d22c7eb5f5b4e50633911caa626e87
parenttree-wide: get rid of strappend() (diff)
parenttest-network: add tests for route with type local, multicast, anycast, or bro... (diff)
downloadsystemd-a04285c6b1a53e7b3cf1bd0df341f324592ef1b1.tar.xz
systemd-a04285c6b1a53e7b3cf1bd0df341f324592ef1b1.zip
Merge pull request #13031 from yuwata/network-route-type-local-12975-2
network: make Route.Type= support local or friends
-rw-r--r--man/systemd.network.xml11
-rw-r--r--src/network/networkd-manager.c28
-rw-r--r--src/network/networkd-route.c185
-rw-r--r--src/network/networkd-route.h15
-rw-r--r--test/test-network/conf/25-route-static.network16
-rw-r--r--test/test-network/conf/26-bridge-slave-interface-1.network3
-rw-r--r--test/test-network/conf/26-bridge-slave-interface-2.network3
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py33
8 files changed, 242 insertions, 52 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 612450dbd8..c9d6fd4d72 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1086,8 +1086,9 @@
<varlistentry>
<term><varname>Table=</varname></term>
<listitem>
- <para>Specifies the routing table identifier to lookup if the rule
- selector matches. The table identifier for a route (a number between 1 and 4294967295).</para>
+ <para>Specifies the routing table identifier to lookup if the rule selector matches. Takes
+ one of <literal>default</literal>, <literal>main</literal>, and <literal>local</literal>,
+ or a number between 1 and 4294967295. Defaults to <literal>main</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -1232,7 +1233,11 @@
<varlistentry>
<term><varname>Type=</varname></term>
<listitem>
- <para>Specifies the type for the route. If <literal>unicast</literal>, a regular route is defined, i.e. a
+ <para>Specifies the type for the route. Takes one of <literal>unicast</literal>,
+ <literal>local</literal>, <literal>broadcast</literal>, <literal>anycast</literal>,
+ <literal>multicast</literal>, <literal>blackhole</literal>, <literal>unreachable</literal>,
+ <literal>prohibit</literal>, <literal>throw</literal>, <literal>nat</literal>, and
+ <literal>xresolve</literal>. If <literal>unicast</literal>, a regular route is defined, i.e. a
route indicating the path to take to a destination network address. If <literal>blackhole</literal>, packets
to the defined route are discarded silently. If <literal>unreachable</literal>, packets to the defined route
are discarded and the ICMP message "Host Unreachable" is generated. If <literal>prohibit</literal>, packets
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 33b7ec1d6c..ec3bb47ea6 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -298,7 +298,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex);
if (r == -ENODATA) {
- log_debug("rtnl: received route without ifindex, ignoring");
+ log_debug("rtnl: received route message without ifindex, ignoring");
return 0;
} else if (r < 0) {
log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m");
@@ -313,7 +313,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
/* when enumerating we might be out of sync, but we will
* get the route again, so just ignore it */
if (!m->enumerating)
- log_warning("rtnl: received route for link (%d) we do not know about, ignoring", ifindex);
+ log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex);
return 0;
}
@@ -391,43 +391,43 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
r = sd_rtnl_message_route_get_dst_prefixlen(message, &dst_prefixlen);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid destination prefixlen, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_src_prefixlen(message, &src_prefixlen);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid source prefixlen, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_scope(message, &scope);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid scope, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_tos(message, &tos);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid tos, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_type(message, &rt_type);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid type, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_table(message, &table);
if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid table, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m");
return 0;
}
r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &priority);
if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route with invalid priority, ignoring: %m");
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m");
return 0;
}
@@ -436,6 +436,8 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL,
*buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL;
+ char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX],
+ buf_protocol[ROUTE_PROTOCOL_STR_MAX];
if (!in_addr_is_null(family, &dst)) {
(void) in_addr_to_string(family, &dst, &buf_dst);
@@ -449,10 +451,14 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
(void) in_addr_to_string(family, &prefsrc, &buf_prefsrc);
log_link_debug(link,
- "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s",
+ "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
type == RTM_DELROUTE ? "Forgetting" : route ? "Updating remembered" : "Remembering",
strna(buf_dst), strempty(buf_dst_prefixlen),
- strna(buf_src), strna(buf_gw), strna(buf_prefsrc));
+ strna(buf_src), strna(buf_gw), strna(buf_prefsrc),
+ format_route_scope(scope, buf_scope, sizeof buf_scope),
+ format_route_table(table, buf_table, sizeof buf_table),
+ format_route_protocol(protocol, buf_protocol, sizeof buf_protocol),
+ strna(route_type_to_string(rt_type)));
}
switch (type) {
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index f79d5b2057..ddc0fe279f 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -12,7 +12,9 @@
#include "networkd-route.h"
#include "parse-util.h"
#include "set.h"
+#include "string-table.h"
#include "string-util.h"
+#include "strxcpyx.h"
#include "sysctl-util.h"
#include "util.h"
@@ -412,6 +414,29 @@ int route_remove(Route *route, Link *link,
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
+ char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
+
+ if (!in_addr_is_null(route->family, &route->dst)) {
+ (void) in_addr_to_string(route->family, &route->dst, &dst);
+ (void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen);
+ }
+ if (!in_addr_is_null(route->family, &route->src))
+ (void) in_addr_to_string(route->family, &route->src, &src);
+ if (!in_addr_is_null(route->family, &route->gw))
+ (void) in_addr_to_string(route->family, &route->gw, &gw);
+ if (!in_addr_is_null(route->family, &route->prefsrc))
+ (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
+
+ log_link_debug(link, "Removing route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
+ strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
+ format_route_scope(route->scope, scope, sizeof(scope)),
+ format_route_table(route->table, table, sizeof(table)),
+ format_route_protocol(route->protocol, protocol, sizeof(protocol)),
+ strna(route_type_to_string(route->type)));
+ }
+
if (in_addr_is_null(route->family, &route->gw) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
if (r < 0)
@@ -513,6 +538,7 @@ int route_configure(
if (DEBUG_LOGGING) {
_cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
+ char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
if (!in_addr_is_null(route->family, &route->dst)) {
(void) in_addr_to_string(route->family, &route->dst, &dst);
@@ -525,8 +551,12 @@ int route_configure(
if (!in_addr_is_null(route->family, &route->prefsrc))
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
- log_link_debug(link, "Configuring route: dst: %s%s, src: %s, gw: %s, prefsrc: %s",
- strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc));
+ log_link_debug(link, "Configuring route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
+ strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
+ format_route_scope(route->scope, scope, sizeof(scope)),
+ format_route_table(route->table, table, sizeof(table)),
+ format_route_protocol(route->protocol, protocol, sizeof(protocol)),
+ strna(route_type_to_string(route->type)));
}
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
@@ -718,6 +748,8 @@ int network_add_ipv4ll_route(Network *network) {
n->family = AF_INET;
n->dst_prefixlen = 16;
n->scope = RT_SCOPE_LINK;
+ n->scope_set = true;
+ n->table_set = true;
n->priority = IPV4LL_ROUTE_METRIC;
n->protocol = RTPROT_STATIC;
@@ -749,6 +781,88 @@ int network_add_default_route_on_device(Network *network) {
return 0;
}
+static const char * const route_type_table[__RTN_MAX] = {
+ [RTN_UNICAST] = "unicast",
+ [RTN_LOCAL] = "local",
+ [RTN_BROADCAST] = "broadcast",
+ [RTN_ANYCAST] = "anycast",
+ [RTN_MULTICAST] = "multicast",
+ [RTN_BLACKHOLE] = "blackhole",
+ [RTN_UNREACHABLE] = "unreachable",
+ [RTN_PROHIBIT] = "prohibit",
+ [RTN_THROW] = "throw",
+ [RTN_NAT] = "nat",
+ [RTN_XRESOLVE] = "xresolve",
+};
+
+assert_cc(__RTN_MAX <= UCHAR_MAX);
+DEFINE_STRING_TABLE_LOOKUP(route_type, int);
+
+static const char * const route_scope_table[] = {
+ [RT_SCOPE_UNIVERSE] = "global",
+ [RT_SCOPE_SITE] = "site",
+ [RT_SCOPE_LINK] = "link",
+ [RT_SCOPE_HOST] = "host",
+ [RT_SCOPE_NOWHERE] = "nowhere",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int);
+
+const char *format_route_scope(int scope, char *buf, size_t size) {
+ const char *s;
+ char *p = buf;
+
+ s = route_scope_to_string(scope);
+ if (s)
+ strpcpy(&p, size, s);
+ else
+ strpcpyf(&p, size, "%d", scope);
+
+ return buf;
+}
+
+static const char * const route_table_table[] = {
+ [RT_TABLE_DEFAULT] = "default",
+ [RT_TABLE_MAIN] = "main",
+ [RT_TABLE_LOCAL] = "local",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int);
+
+const char *format_route_table(int table, char *buf, size_t size) {
+ const char *s;
+ char *p = buf;
+
+ s = route_table_to_string(table);
+ if (s)
+ strpcpy(&p, size, s);
+ else
+ strpcpyf(&p, size, "%d", table);
+
+ return buf;
+}
+
+static const char * const route_protocol_table[] = {
+ [RTPROT_KERNEL] = "kernel",
+ [RTPROT_BOOT] = "boot",
+ [RTPROT_STATIC] = "static",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_protocol, int);
+
+const char *format_route_protocol(int protocol, char *buf, size_t size) {
+ const char *s;
+ char *p = buf;
+
+ s = route_protocol_to_string(protocol);
+ if (s)
+ strpcpy(&p, size, s);
+ else
+ strpcpyf(&p, size, "%d", protocol);
+
+ return buf;
+}
+
int config_parse_gateway(
const char *unit,
const char *filename,
@@ -948,17 +1062,14 @@ int config_parse_route_scope(
if (r < 0)
return r;
- if (streq(rvalue, "host"))
- n->scope = RT_SCOPE_HOST;
- else if (streq(rvalue, "link"))
- n->scope = RT_SCOPE_LINK;
- else if (streq(rvalue, "global"))
- n->scope = RT_SCOPE_UNIVERSE;
- else {
+ r = route_scope_from_string(rvalue);
+ if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue);
return 0;
}
+ n->scope = r;
+ n->scope_set = true;
TAKE_PTR(n);
return 0;
}
@@ -989,13 +1100,19 @@ int config_parse_route_table(
if (r < 0)
return r;
- r = safe_atou32(rvalue, &n->table);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
- return 0;
+ r = route_table_from_string(rvalue);
+ if (r >= 0)
+ n->table = r;
+ else {
+ r = safe_atou32(rvalue, &n->table);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
+ }
}
+ n->table_set = true;
TAKE_PTR(n);
return 0;
}
@@ -1094,12 +1211,9 @@ int config_parse_route_protocol(
if (r < 0)
return r;
- if (streq(rvalue, "kernel"))
- n->protocol = RTPROT_KERNEL;
- else if (streq(rvalue, "boot"))
- n->protocol = RTPROT_BOOT;
- else if (streq(rvalue, "static"))
- n->protocol = RTPROT_STATIC;
+ r = route_protocol_from_string(rvalue);
+ if (r >= 0)
+ n->protocol = r;
else {
r = safe_atou8(rvalue , &n->protocol);
if (r < 0) {
@@ -1127,28 +1241,21 @@ int config_parse_route_type(
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
- int r;
+ int t, r;
r = route_new_static(network, filename, section_line, &n);
if (r < 0)
return r;
- if (streq(rvalue, "unicast"))
- n->type = RTN_UNICAST;
- else if (streq(rvalue, "blackhole"))
- n->type = RTN_BLACKHOLE;
- else if (streq(rvalue, "unreachable"))
- n->type = RTN_UNREACHABLE;
- else if (streq(rvalue, "prohibit"))
- n->type = RTN_PROHIBIT;
- else if (streq(rvalue, "throw"))
- n->type = RTN_THROW;
- else {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ t = route_type_from_string(rvalue);
+ if (t < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
"Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
+ n->type = (unsigned char) t;
+
TAKE_PTR(n);
return 0;
}
@@ -1366,6 +1473,18 @@ int route_section_verify(Route *route, Network *network) {
route->section->filename, route->section->line);
}
+ if (route->family != AF_INET6) {
+ if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
+ route->table = RT_TABLE_LOCAL;
+
+ if (!route->scope_set) {
+ if (IN_SET(route->type, RTN_LOCAL, RTN_NAT))
+ route->scope = RT_SCOPE_HOST;
+ else if (IN_SET(route->type, RTN_BROADCAST, RTN_ANYCAST))
+ route->scope = RT_SCOPE_LINK;
+ }
+ }
+
if (network->n_static_addresses == 0 &&
in_addr_is_null(route->family, &route->gw) == 0 &&
route->gateway_onlink < 0) {
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 3c0ac896ae..86a7a82617 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -2,6 +2,7 @@
#pragma once
#include "conf-parser.h"
+#include "macro.h"
typedef struct Route Route;
typedef struct NetworkConfigSection NetworkConfigSection;
@@ -23,11 +24,13 @@ struct Route {
unsigned char dst_prefixlen;
unsigned char src_prefixlen;
unsigned char scope;
+ bool scope_set;
unsigned char protocol; /* RTPROT_* */
unsigned char type; /* RTN_* */
unsigned char tos;
uint32_t priority; /* note that ip(8) calls this 'metric' */
uint32_t table;
+ bool table_set;
uint32_t mtu;
uint32_t initcwnd;
uint32_t initrwnd;
@@ -65,6 +68,18 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
int network_add_ipv4ll_route(Network *network);
int network_add_default_route_on_device(Network *network);
+const char* route_type_to_string(int t) _const_;
+int route_type_from_string(const char *s) _pure_;
+
+#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1)
+const char *format_route_scope(int scope, char *buf, size_t size);
+
+#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
+const char *format_route_table(int table, char *buf, size_t size);
+
+#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("kernel") + 1)
+const char *format_route_protocol(int protocol, char *buf, size_t size);
+
CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
CONFIG_PARSER_PROTOTYPE(config_parse_destination);
diff --git a/test/test-network/conf/25-route-static.network b/test/test-network/conf/25-route-static.network
index 9e12480a65..9c8269e3b8 100644
--- a/test/test-network/conf/25-route-static.network
+++ b/test/test-network/conf/25-route-static.network
@@ -46,3 +46,19 @@ Destination=202.54.1.3
[Route]
Type=prohibit
Destination=202.54.1.4
+
+[Route]
+Type=local
+Destination=149.10.123.1
+
+[Route]
+Type=anycast
+Destination=149.10.123.2
+
+[Route]
+Type=broadcast
+Destination=149.10.123.3
+
+[Route]
+Type=multicast
+Destination=149.10.123.4
diff --git a/test/test-network/conf/26-bridge-slave-interface-1.network b/test/test-network/conf/26-bridge-slave-interface-1.network
index 1f8c5b5648..6aed178525 100644
--- a/test/test-network/conf/26-bridge-slave-interface-1.network
+++ b/test/test-network/conf/26-bridge-slave-interface-1.network
@@ -13,3 +13,6 @@ MulticastFlood = false
MulticastToUnicast = true
NeighborSuppression = true
Learning = false
+Priority = 23
+UseBPDU = true
+AllowPortToBeRoot=true
diff --git a/test/test-network/conf/26-bridge-slave-interface-2.network b/test/test-network/conf/26-bridge-slave-interface-2.network
index 45ec2de999..5fccfec5d1 100644
--- a/test/test-network/conf/26-bridge-slave-interface-2.network
+++ b/test/test-network/conf/26-bridge-slave-interface-2.network
@@ -3,3 +3,6 @@ Name=test1
[Network]
Bridge=bridge99
+
+[Bridge]
+Priority=0
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 399824af5c..e396af05da 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -1552,14 +1552,18 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
start_networkd()
wait_online(['dummy98:routable'])
+ print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98')
print(output)
self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
+ print('### ip -6 route show dev dummy98 default')
output = check_output('ip -6 route show dev dummy98 default')
+ print(output)
self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
+ print('### ip -4 route show dev dummy98')
output = check_output('ip -4 route show dev dummy98')
print(output)
self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
@@ -1567,20 +1571,33 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
+ self.assertRegex(output, 'multicast 149.10.123.4 proto static')
+ print('### ip -4 route show dev dummy98 default')
output = check_output('ip -4 route show dev dummy98 default')
+ print(output)
self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
self.assertRegex(output, 'default via 149.10.124.64 proto static')
self.assertRegex(output, 'default proto static')
+ print('### ip -4 route show table local dev dummy98')
+ output = check_output('ip -4 route show table local dev dummy98')
+ print(output)
+ self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
+ self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
+ self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
+
+ print('### ip route show type blackhole')
output = check_output('ip route show type blackhole')
print(output)
self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
+ print('### ip route show type unreachable')
output = check_output('ip route show type unreachable')
print(output)
self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
+ print('### ip route show type prohibit')
output = check_output('ip route show type prohibit')
print(output)
self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
@@ -2007,18 +2024,24 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
output = check_output('bridge -d link show dummy98')
print(output)
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
+ self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
+ self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
- self.assertEqual(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(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
+ self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
+ self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
+ self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
- # CONFIG_BRIDGE_IGMP_SNOOPING=y
- if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
+ output = check_output('bridge -d link show test1')
+ print(output)
+ self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
check_output('ip address add 192.168.0.16/24 dev bridge99')
time.sleep(1)