diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-11-11 17:52:07 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-11-14 03:59:59 +0100 |
commit | ae2ffddcfc00aa961fb2567cc804983ea2174a25 (patch) | |
tree | eaeb75ae49aaae63fceb135a2d82f6e2aa54993d /src/network | |
parent | network/nexthop: preparation for dynamically configuring nexthops (diff) | |
download | systemd-ae2ffddcfc00aa961fb2567cc804983ea2174a25.tar.xz systemd-ae2ffddcfc00aa961fb2567cc804983ea2174a25.zip |
network/nexthop: serialize/deserialize nexthops
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/networkd-json.c | 82 | ||||
-rw-r--r-- | src/network/networkd-json.h | 1 | ||||
-rw-r--r-- | src/network/networkd-serialize.c | 65 |
3 files changed, 119 insertions, 29 deletions
diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index 460fbe5968..160bcbdcca 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -164,45 +164,58 @@ static int nexthop_group_build_json(NextHop *nexthop, sd_json_variant **ret) { return 0; } -static int nexthop_append_json(NextHop *n, sd_json_variant **array) { - _cleanup_(sd_json_variant_unrefp) sd_json_variant *group = NULL; - _cleanup_free_ char *flags = NULL, *protocol = NULL, *state = NULL; +static int nexthop_append_json(NextHop *n, bool serializing, sd_json_variant **array) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; int r; assert(n); assert(array); - r = route_flags_to_string_alloc(n->flags, &flags); + r = sd_json_buildo( + &v, + SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id), + SD_JSON_BUILD_PAIR_INTEGER("Family", n->family), + SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)), + JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &n->provider, n->family)); if (r < 0) return r; - r = route_protocol_to_string_alloc(n->protocol, &protocol); - if (r < 0) - return r; + if (!serializing) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *group = NULL; + _cleanup_free_ char *flags = NULL, *protocol = NULL, *state = NULL; - r = network_config_state_to_string_alloc(n->state, &state); - if (r < 0) - return r; + r = route_flags_to_string_alloc(n->flags, &flags); + if (r < 0) + return r; - r = nexthop_group_build_json(n, &group); - if (r < 0) - return r; + r = route_protocol_to_string_alloc(n->protocol, &protocol); + if (r < 0) + return r; - return sd_json_variant_append_arraybo( - array, - SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family), - SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags), - SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)), - SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol), - SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol), - SD_JSON_BUILD_PAIR_BOOLEAN("Blackhole", n->blackhole), - JSON_BUILD_PAIR_VARIANT_NON_NULL("Group", group), - SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)), - SD_JSON_BUILD_PAIR_STRING("ConfigState", state)); + r = network_config_state_to_string_alloc(n->state, &state); + if (r < 0) + return r; + + r = nexthop_group_build_json(n, &group); + if (r < 0) + return r; + + r = sd_json_variant_merge_objectbo( + &v, + JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family), + SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags), + SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)), + SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol), + SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol), + SD_JSON_BUILD_PAIR_BOOLEAN("Blackhole", n->blackhole), + JSON_BUILD_PAIR_VARIANT_NON_NULL("Group", group), + SD_JSON_BUILD_PAIR_STRING("ConfigState", state)); + } + + return sd_json_variant_append_array(array, v); } -static int nexthops_append_json(Manager *manager, int ifindex, sd_json_variant **v) { +int nexthops_append_json(Manager *manager, int ifindex, sd_json_variant **v) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL; NextHop *nexthop; int r; @@ -211,10 +224,21 @@ static int nexthops_append_json(Manager *manager, int ifindex, sd_json_variant * assert(v); HASHMAP_FOREACH(nexthop, manager->nexthops_by_id) { - if (nexthop->ifindex != ifindex) - continue; + if (ifindex >= 0) { + if (nexthop->ifindex != ifindex) + continue; + } else { + /* negative ifindex means we are serializing now. */ + + if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN) + continue; + if (!nexthop_exists(nexthop)) + continue; + + log_nexthop_debug(nexthop, "Serializing", manager); + } - r = nexthop_append_json(nexthop, &array); + r = nexthop_append_json(nexthop, /* serializing = */ ifindex < 0, &array); if (r < 0) return r; } diff --git a/src/network/networkd-json.h b/src/network/networkd-json.h index e8be60458f..ada2500e39 100644 --- a/src/network/networkd-json.h +++ b/src/network/networkd-json.h @@ -9,6 +9,7 @@ typedef struct Link Link; typedef struct Manager Manager; int addresses_append_json(Link *link, bool serializing, sd_json_variant **v); +int nexthops_append_json(Manager *manager, int ifindex, sd_json_variant **v); int routes_append_json(Manager *manager, int ifindex, sd_json_variant **v); int link_build_json(Link *link, sd_json_variant **ret); int manager_build_json(Manager *manager, sd_json_variant **ret); diff --git a/src/network/networkd-serialize.c b/src/network/networkd-serialize.c index 8cc74baae9..26a38bd4dd 100644 --- a/src/network/networkd-serialize.c +++ b/src/network/networkd-serialize.c @@ -11,6 +11,7 @@ #include "networkd-json.h" #include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-nexthop.h" #include "networkd-route.h" #include "networkd-serialize.h" @@ -49,6 +50,10 @@ int manager_serialize(Manager *manager) { if (r < 0) return r; + r = nexthops_append_json(manager, /* ifindex = */ -1, &v); + if (r < 0) + return r; + r = routes_append_json(manager, /* ifindex = */ -1, &v); if (r < 0) return r; @@ -230,6 +235,63 @@ static int manager_deserialize_link(Manager *manager, sd_json_variant *v) { return ret; } +typedef struct NextHopParam { + uint32_t id; + int family; + NetworkConfigSource source; + struct iovec provider; +} NextHopParam; + +static void nexthop_param_done(NextHopParam *p) { + assert(p); + + iovec_done(&p->provider); +} + +static int manager_deserialize_nexthop(Manager *manager, sd_json_variant *v) { + static const sd_json_dispatch_field dispatch_table[] = { + { "ID", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32, offsetof(NextHopParam, id), SD_JSON_MANDATORY }, + { "Family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(NextHopParam, family), SD_JSON_MANDATORY }, + { "ConfigSource", SD_JSON_VARIANT_STRING, json_dispatch_network_config_source, offsetof(NextHopParam, source), SD_JSON_MANDATORY }, + { "ConfigProvider", SD_JSON_VARIANT_ARRAY, json_dispatch_byte_array_iovec, offsetof(NextHopParam, provider), 0 }, + {}, + }; + + int r; + + assert(manager); + assert(v); + + _cleanup_(nexthop_param_done) NextHopParam p = {}; + r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p); + if (r < 0) + return log_debug_errno(r, "Failed to dispatch nexthop from json variant: %m"); + + if (p.id == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Dispatched nexthop ID is zero."); + + if (p.provider.iov_len != 0 && p.provider.iov_len != FAMILY_ADDRESS_SIZE(p.family)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Dispatched provider address size (%zu) is incompatible with the family (%s).", + p.provider.iov_len, af_to_ipv4_ipv6(p.family)); + + NextHop *nexthop; + r = nexthop_get_by_id(manager, p.id, &nexthop); + if (r < 0) { + log_debug_errno(r, "Cannot find deserialized nexthop (ID=%"PRIu32"): %m", p.id); + return 0; /* Already removed? */ + } + + if (nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN) + return 0; /* Huh?? Already deserialized?? */ + + nexthop->source = p.source; + memcpy_safe(&nexthop->provider, p.provider.iov_base, p.provider.iov_len); + + log_nexthop_debug(nexthop, "Deserialized", manager); + return 0; +} + typedef struct RouteParam { Route route; @@ -395,6 +457,9 @@ int manager_deserialize(Manager *manager) { JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "Interfaces")) RET_GATHER(ret, manager_deserialize_link(manager, i)); + JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "NextHops")) + RET_GATHER(ret, manager_deserialize_nexthop(manager, i)); + JSON_VARIANT_ARRAY_FOREACH(i, sd_json_variant_by_key(v, "Routes")) RET_GATHER(ret, manager_deserialize_route(manager, i)); |