summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-02-05 02:09:12 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-02-19 08:41:52 +0100
commitbfe6043454da12ef4e48856974b44fafc0b7028f (patch)
tree289d653b4e4fbda086e37f1f41c921c1d333ecd8 /src
parentnetwork: configure nexthop before routes that requires gateway (diff)
downloadsystemd-bfe6043454da12ef4e48856974b44fafc0b7028f.tar.xz
systemd-bfe6043454da12ef4e48856974b44fafc0b7028f.zip
network: nexthop: update ID of nexthop created without specifiying ID
Otherwise, nexthop_configure() -> nexthop_add() creates NextHop object without ID in link->nexthop, and then, manager_rtnl_process_nexthop() -> nexthop_add_foreign() also creates another NextHop object with ID in link->nexthop_foreign.
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-nexthop.c75
1 files changed, 67 insertions, 8 deletions
diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c
index 2aaddccf17..028aaad313 100644
--- a/src/network/networkd-nexthop.c
+++ b/src/network/networkd-nexthop.c
@@ -217,7 +217,44 @@ static int nexthop_add(Link *link, const NextHop *in, NextHop **ret) {
return is_new;
}
-static void log_nexthop_debug(const NextHop *nexthop, const char *str, const Link *link) {
+static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
+ int r;
+
+ assert(link);
+ assert(nexthop);
+ assert(in);
+ assert(in->id > 0);
+
+ /* Currently, this only updates ID. */
+
+ if (nexthop->id > 0)
+ return nexthop->id == in->id ? 0 : -EINVAL;
+
+ nexthop = set_remove(link->nexthops, nexthop);
+ if (!nexthop)
+ return -ENOENT;
+
+ nexthop->id = in->id;
+
+ r = set_put(link->nexthops, nexthop);
+ if (r <= 0) {
+ int k;
+
+ /* On failure, revert the change. */
+ nexthop->id = 0;
+ k = set_put(link->nexthops, nexthop);
+ if (k <= 0) {
+ nexthop_free(nexthop);
+ return k < 0 ? k : -EEXIST;
+ }
+
+ return r < 0 ? r : -EEXIST;
+ }
+
+ return 0;
+}
+
+static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *str, const Link *link) {
assert(nexthop);
assert(str);
assert(link);
@@ -227,8 +264,12 @@ static void log_nexthop_debug(const NextHop *nexthop, const char *str, const Lin
(void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw);
- log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s",
- str, nexthop->id, strna(gw));
+ if (nexthop->id == id)
+ log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s",
+ str, nexthop->id, strna(gw));
+ else
+ log_link_debug(link, "%s nexthop: id: %"PRIu32"→%"PRIu32", gw: %s",
+ str, nexthop->id, id, strna(gw));
}
}
@@ -272,7 +313,7 @@ static int nexthop_configure(const NextHop *nexthop, Link *link) {
assert(link->ifindex > 0);
assert(IN_SET(nexthop->family, AF_INET, AF_INET6));
- log_nexthop_debug(nexthop, "Configuring", link);
+ log_nexthop_debug(nexthop, nexthop->id, "Configuring", link);
r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req,
RTM_NEWNEXTHOP, nexthop->family,
@@ -430,23 +471,41 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
return 0;
}
- (void) nexthop_get(link, tmp, &nexthop);
+ r = nexthop_get(link, tmp, &nexthop);
+ if (r < 0) {
+ uint32_t id;
+
+ /* The nexthop may be created without setting NHA_ID. */
+
+ id = tmp->id;
+ tmp->id = 0;
+
+ (void) nexthop_get(link, tmp, &nexthop);
+
+ tmp->id = id;
+ }
switch (type) {
case RTM_NEWNEXTHOP:
if (nexthop)
- log_nexthop_debug(tmp, "Received remembered", link);
+ log_nexthop_debug(nexthop, tmp->id, "Received remembered", link);
else {
- log_nexthop_debug(tmp, "Remembering foreign", link);
+ log_nexthop_debug(tmp, tmp->id, "Remembering foreign", link);
r = nexthop_add_foreign(link, tmp, &nexthop);
if (r < 0) {
log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
return 0;
}
}
+
+ r = nexthop_update(link, nexthop, tmp);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not update nexthop, ignoring: %m");
+ return 0;
+ }
break;
case RTM_DELNEXTHOP:
- log_nexthop_debug(tmp, nexthop ? "Forgetting" : "Kernel removed unknown", link);
+ log_nexthop_debug(tmp, tmp->id, nexthop ? "Forgetting" : "Kernel removed unknown", link);
nexthop_free(nexthop);
break;