network/nexthop: serialize/deserialize nexthops

This commit is contained in:
Yu Watanabe
2024-11-12 01:52:07 +09:00
parent b5b42b516e
commit ae2ffddcfc
3 changed files with 123 additions and 33 deletions

View File

@@ -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);
if (r < 0)
return r;
r = route_protocol_to_string_alloc(n->protocol, &protocol);
if (r < 0)
return r;
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;
return sd_json_variant_append_arraybo(
array,
r = sd_json_buildo(
&v,
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_INTEGER("Family", n->family),
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &n->provider, n->family));
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 = route_flags_to_string_alloc(n->flags, &flags);
if (r < 0)
return r;
r = route_protocol_to_string_alloc(n->protocol, &protocol);
if (r < 0)
return r;
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. */
r = nexthop_append_json(nexthop, &array);
if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
if (!nexthop_exists(nexthop))
continue;
log_nexthop_debug(nexthop, "Serializing", manager);
}
r = nexthop_append_json(nexthop, /* serializing = */ ifindex < 0, &array);
if (r < 0)
return r;
}

View File

@@ -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);

View File

@@ -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));