From 0ac147d632ed6a150bf0216964888a21b1c8d43c Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Tue, 24 Jan 2023 01:46:29 +0100 Subject: feat: libhicnctrl: new API to allow sending MAP-Me command on specific face MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iac39a1d145a5c1b4f19e1fa35d713ca720393760 Ticket: HICN-832 Signed-off-by: Jordan Augé (cherry picked from commit 49776ceac54eecadabca6c0e2fdc0b9ee2e8e663) --- hicn-light/src/hicn/config/CMakeLists.txt | 3 +- hicn-light/src/hicn/config/commands.c | 97 ++++++++-- hicn-light/src/hicn/core/connection.h | 4 +- hicn-light/src/hicn/core/fib.c | 23 +-- hicn-light/src/hicn/core/fib.h | 4 +- hicn-light/src/hicn/core/fib_entry.c | 15 +- hicn-light/src/hicn/core/fib_entry.h | 6 +- hicn-light/src/hicn/core/forwarder.c | 39 ++-- hicn-light/src/hicn/core/mapme.c | 238 ++++++++++++++++-------- hicn-light/src/hicn/core/mapme.h | 29 ++- hicn-light/src/hicn/core/msgbuf.h | 8 +- hicn-light/src/hicn/strategies/local_prefixes.c | 4 +- 12 files changed, 329 insertions(+), 141 deletions(-) (limited to 'hicn-light') diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt index 36abe96ce..8e9415f7d 100644 --- a/hicn-light/src/hicn/config/CMakeLists.txt +++ b/hicn-light/src/hicn/config/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Cisco and/or its affiliates. +# Copyright (c) 2021-2023 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -22,6 +22,7 @@ list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/connection.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/listener.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/mapme.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/route.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/stats.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/strategy.c diff --git a/hicn-light/src/hicn/config/commands.c b/hicn-light/src/hicn/config/commands.c index c6212aaf4..47ea23a8a 100644 --- a/hicn-light/src/hicn/config/commands.c +++ b/hicn-light/src/hicn/config/commands.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -351,6 +351,7 @@ uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet, size_t n = listener_table_len(table); msg_listener_list_t *msg_received = (msg_listener_list_t *)packet; uint8_t command_id = msg_received->header.command_id; + INFO("listener list seq num %d", msg_received->header.seq_num); uint32_t seq_num = msg_received->header.seq_num; msg_listener_list_reply_t *msg = NULL; @@ -733,7 +734,11 @@ uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet, unsigned conn_id = symbolic_to_conn_id_self( forwarder, control->symbolic_or_connid, ingress_id); + + /* We accept routes without conn_id */ +#if 0 if (!connection_id_is_valid(conn_id)) goto NACK; +#endif hicn_ip_prefix_t prefix = {.family = control->family, .address = control->address, @@ -1165,7 +1170,7 @@ uint8_t *configuration_on_punting_add(forwarder_t *forwarder, uint8_t *packet, #if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING) cmd_punting_add_t *control = &msg->payload; - if (ip_address_empty(&control->address)) goto NACK; + if (hicn_ip_address_empty(&control->address)) goto NACK; /* This is for hICN listeners only */ // XXX add check ! @@ -1316,15 +1321,18 @@ NACK: return (uint8_t *)msg; } -uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder, - uint8_t *packet, - unsigned ingress_id, - size_t *reply_size) { +uint8_t *configuration_on_mapme_add(forwarder_t *forwarder, uint8_t *packet, + unsigned ingress_id, size_t *reply_size) { assert(forwarder); assert(packet); - INFO("CMD: mapme send update (ingress=%d)", ingress_id); - msg_mapme_send_update_t *msg = (msg_mapme_send_update_t *)packet; + /* Check ingress is local (for now this is only used locally) */ + connection_table_t *table = forwarder_get_connection_table(forwarder); + const connection_t *connection = connection_table_at(table, ingress_id); + + msg_mapme_add_t *msg = (msg_mapme_add_t *)packet; + + if (!connection_is_local(connection)) goto NACK; *reply_size = sizeof(msg_header_t); @@ -1333,20 +1341,69 @@ uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder, mapme_t *mapme = forwarder_get_mapme(forwarder); - /* - * The command triggers a mapme update for all prefixes produced on this - * face - * */ - fib_foreach_entry(fib, entry, { - const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - nexthops_foreach(nexthops, nexthop, { - if (nexthop != ingress_id) continue; - /* This entry points to the producer face */ - mapme_set_all_adjacencies(mapme, entry); - break; + cmd_mapme_add_t *control = &msg->payload; + /* If the message comes from the producer, address, family, len and + * face_id will be NULL + */ + if (hicn_ip_address_empty(&control->address) && (control->len == 0) && + (control->family == 0) && (control->face_id == 0)) { + /* + * The command triggers a mapme update for all prefixes produced on this + * face + * + * XXX This should in fact be an UPDATE command + */ + + fib_foreach_entry(fib, entry, { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + nexthops_foreach(nexthops, nexthop, { + if (nexthop != ingress_id) continue; + /* This entry points to the producer face */ + mapme_set_all_adjacencies(mapme, entry); + break; + }); }); - }); + goto END; + } + + /* Control plane triggered + * + * We might not only receive MAP-Me update requests for prefixes we own, + * but also for more specific ones (for instance, we have a /64 and + * want to send an update on a /128). This requires a FIB lookup. + * + * NOTE: we need to avoid modifying the FIB because of this. + * + * TODO: + * - assert face_id is valid and exists + * - assert family is correct + */ + + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &name_prefix); + +#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY + fib_entry_t *entry = fib_contains(fib, &name_prefix); + if (!entry) { + entry = mapme_create_fib_entry(mapme, &name_prefix, INVALID_FACE_ID); + if (!entry) goto NACK; // we could also perform as in the other branch + } + mapme_set_adjacency(mapme, entry, control->face_id, NULL); + +#else + fib_entry_t *entry = fib_match_prefix(fib, &name_prefix); + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + if (hicn_prefix_get_len(prefix) == control->len) { + mapme_set_adjacency(mapme, entry, control->face_id, NULL); + } else { + mapme_set_adjacency(mapme, NULL, control->face_id, prefix); + } +#endif + +END: make_ack(msg); return (uint8_t *)msg; diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h index b459a6d81..e177e2039 100644 --- a/hicn-light/src/hicn/core/connection.h +++ b/hicn-light/src/hicn/core/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -31,7 +31,7 @@ #include #endif /* WITH_POLICY */ -#define CONNECTION_ID_UNDEFINED ~0 +#define CONNECTION_ID_UNDEFINED INVALID_FACE_ID #define foreach_connection_event \ _(UNDEFINED) \ diff --git a/hicn-light/src/hicn/core/fib.c b/hicn-light/src/hicn/core/fib.c index 5f8788155..c44d2daf0 100644 --- a/hicn-light/src/hicn/core/fib.c +++ b/hicn-light/src/hicn/core/fib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -291,7 +291,7 @@ void _fib_remove(fib_t *fib, fib_node_t *curr, fib_node_t *parent) { * / \ * l L */ -void fib_add(fib_t *fib, fib_entry_t *entry) { +fib_entry_t *fib_add(fib_t *fib, fib_entry_t *entry) { assert(fib); assert(entry); @@ -329,17 +329,12 @@ void fib_add(fib_t *fib, fib_entry_t *entry) { /* Case 2 */ if (search.prefix_len == search.match_len && prefix_len == search.match_len) { - if (!curr->is_used) { - curr->is_used = true; - if (curr->entry) fib_entry_free(curr->entry); - curr->entry = entry; - fib->size++; - } else { - const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - nexthops_foreach(nexthops, nexthop, - { fib_entry_nexthops_add(curr->entry, nexthop); }); - fib_entry_free(entry); - } + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + nexthops_foreach(nexthops, nexthop, + { fib_entry_nexthops_add(curr->entry, nexthop); }); + fib_entry_free(entry); + entry = curr->entry; + curr->is_used = true; goto END; } @@ -366,7 +361,7 @@ END: #if 0 fib_dump(fib); #endif - ; /* required by clang */ + return entry; } /* diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h index 501935b0b..4fb5009f5 100644 --- a/hicn-light/src/hicn/core/fib.h +++ b/hicn-light/src/hicn/core/fib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -30,7 +30,7 @@ void fib_free(fib_t *fib); size_t fib_get_size(const fib_t *fib); -void fib_add(fib_t *fib, fib_entry_t *node); +fib_entry_t *fib_add(fib_t *fib, fib_entry_t *node); fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix); diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c index b588e3638..b510b68b4 100644 --- a/hicn-light/src/hicn/core/fib_entry.c +++ b/hicn-light/src/hicn/core/fib_entry.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -633,6 +633,19 @@ bool fib_entry_has_local_nexthop(const fib_entry_t *entry) { return false; } +bool fib_entry_has_all_local_nexthops(const fib_entry_t *entry) { + connection_table_t *table = forwarder_get_connection_table(entry->forwarder); + + int count = 0; + nexthops_foreach(fib_entry_get_nexthops(entry), nexthop, { + const connection_t *conn = connection_table_at(table, nexthop); + /* Ignore non-local connections */ + if (!connection_is_local(conn)) return false; + count++; + }); + return (count > 0); +} + #ifdef WITH_MAPME void *fib_entry_get_user_data(const fib_entry_t *entry) { diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h index b625a33ef..e1e48c871 100644 --- a/hicn-light/src/hicn/core/fib_entry.h +++ b/hicn-light/src/hicn/core/fib_entry.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -175,12 +175,12 @@ nexthops_t *fib_entry_get_nexthops_from_strategy( /** * @function fib_entry_get_prefix - * @abstract Returns a copy of the prefix. - * @return A reference counted copy that you must destroy + * @return The FIB entry prefix */ const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *fib_entry); bool fib_entry_has_local_nexthop(const fib_entry_t *entry); +bool fib_entry_has_all_local_nexthops(const fib_entry_t *entry); #ifdef WITH_MAPME diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c index d0472b520..8c276bfef 100644 --- a/hicn-light/src/hicn/core/forwarder.c +++ b/hicn-light/src/hicn/core/forwarder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,6 +32,11 @@ /* Batch sending: only if the previous option is undefined */ #define USE_QUEUE true +/* Shall we send mapme updates to advertise all local prefixes on newly created + * faces + */ +//#define ADVERTISE_PREFIXES_ON_NEW_FACES + #ifndef _WIN32 #include #include @@ -250,9 +255,11 @@ void forwarder_on_route_event(const forwarder_t *forwarder, fib_entry_t *entry) { commands_notify_route(forwarder, entry); +#ifdef ADVERTISE_PREFIXES_ON_NEW_FACES nexthops_t new_nexthops = NEXTHOPS_EMPTY; - nexthops_t *nexthops; +#endif /* ADVERTISE_PREFIXES_ON_NEW_FACES */ + nexthops_t *nexthops = NULL; char *prefix_type_s; const connection_table_t *table = @@ -272,6 +279,7 @@ void forwarder_on_route_event(const forwarder_t *forwarder, nexthops = fib_entry_get_nexthops(entry); nexthops_reset(nexthops); fib_entry_filter_nexthops(entry, nexthops, ~0, false); +#ifdef ADVERTISE_PREFIXES_ON_NEW_FACES } else { /* Check available non-local connections (on which we would send MAP-Me * updates */ @@ -281,10 +289,14 @@ void forwarder_on_route_event(const forwarder_t *forwarder, fib_entry_filter_nexthops(entry, nexthops, ~0, true); #ifdef WITH_MAPME - mapme_set_adjacencies(forwarder->mapme, entry, nexthops); + mapme_set_adjacencies(forwarder->mapme, entry, nexthops, NULL); #endif /* WITH_MAPME */ +#endif /* ADVERTISE_PREFIXES_ON_NEW_FACES */ } + if (!nexthops) + return; + if (!fib_entry_nexthops_changed(entry, nexthops)) return; /* Send notification */ @@ -785,12 +797,15 @@ static int _forwarder_get_interest_manifest( hicn_payload_type_t payload_type; HICN_UNUSED(int rc) = hicn_packet_get_payload_type(pkbuf, &payload_type); - assert(rc == HICN_LIB_ERROR_NONE); + // XXX ASSERT HERE !!! + if (rc != HICN_LIB_ERROR_NONE) return -1; + // assert(rc == HICN_LIB_ERROR_NONE); if (payload_type != HPT_MANIFEST) return -1; rc = hicn_packet_get_payload(pkbuf, &payload, payload_size, false); - assert(rc == HICN_LIB_ERROR_NONE); + // assert(rc == HICN_LIB_ERROR_NONE); + if (rc != HICN_LIB_ERROR_NONE) return -1; *int_manifest_header = (interest_manifest_header_t *)payload; @@ -1252,9 +1267,8 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) return false; - DEBUG("Adding prefix=%s for conn_id=%d", prefix_s, ingress_id); + INFO("Adding prefix=%s for conn_id=%d", prefix_s, ingress_id); - // XXX TODO this should store options too strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s); hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; @@ -1263,11 +1277,13 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); if (!entry) { entry = fib_entry_create(&name_prefix, strategy_type, NULL, forwarder); - fib_entry_nexthops_add(entry, ingress_id); - fib_add(forwarder->fib, entry); + if (ingress_id != INVALID_FACE_ID) + fib_entry_nexthops_add(entry, ingress_id); + entry = fib_add(forwarder->fib, entry); } else { - fib_entry_nexthops_add(entry, ingress_id); + if (ingress_id != INVALID_FACE_ID) + fib_entry_nexthops_add(entry, ingress_id); } forwarder_on_route_event(forwarder, entry); @@ -1553,7 +1569,7 @@ RETRY: #endif case HICN_PACKET_TYPE_MAPME: - // XXX what about acks ? + INFO("Received MAP-Me packet"); if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); @@ -1568,6 +1584,7 @@ RETRY: ERROR("Could not create new connection"); goto DROP; } + INFO("Created connection upon MAP-Me packet"); msgbuf->connection_id = connection_id; } mapme_process(forwarder->mapme, msgbuf); diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c index 53c7ec9da..acda2b8cd 100644 --- a/hicn-light/src/hicn/core/mapme.c +++ b/hicn-light/src/hicn/core/mapme.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -129,7 +129,6 @@ #define MS2NS(x) x * 1000000 #define T2NS(x) forwarder_TicksToNanos(x) -//#define MAPME_ALLOW_NONEXISTING_FIB_ENTRY #define MAPME_DEFAULT_TU 5000 /* ms */ #define MAPME_DEFAULT_RETX 500 /* ms */ #define MAPME_DEFAULT_DISCOVERY false @@ -303,6 +302,7 @@ static void mapme_create_tfib(const mapme_t *mapme, fib_entry_t *entry) { static hicn_mapme_type_t mapme_get_type_from_heuristic(const mapme_t *mapme, fib_entry_t *entry) { #if 0 + if (!entry) return UPDATE; if (fib_entry_has_local_nexthop(entry)) /* We are a producer for this entry, send update */ return UPDATE; @@ -315,43 +315,67 @@ static hicn_mapme_type_t mapme_get_type_from_heuristic(const mapme_t *mapme, * * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB * entries on various other connections. + * + * prefix can be specified to send an update for a More Specific Prefix (MSP), + * or left NULL for the default behaviour. Note there will be no support for + * retransmission for MSP. + * + * NOTES: + * - if the face is pending an we receive an IN, maybe we should not cancel the + * timer + * - this function should never be called for Notifications. */ -/* NOTE: if the face is pending an we receive an IN, maybe we should not cancel - * the timer - */ -// XXX Make sure this function is never called for Notifications -// XXX overall review notification code and integrate it in VPP int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, - const nexthops_t *nexthops) { + const nexthops_t *nexthops, + const hicn_prefix_t *prefix) { + INFO("mapme send to nexthops"); + const hicn_prefix_t *mapme_prefix; + uint32_t mapme_seq; + + assert(!!prefix ^ !!entry); + if (mapme->enabled == false) { WARN("MAP-Me is NOT enabled"); return -1; } - mapme_tfib_t *tfib = TFIB(entry); - if (tfib == NULL) { - mapme_create_tfib(mapme, entry); - tfib = TFIB(entry); + if (prefix) { + INFO("mapme with given prefix"); + mapme_prefix = prefix; + mapme_seq = 1; + } else { + INFO("mapme wih fib entry prefix"); + mapme_tfib_t *tfib = TFIB(entry); + if (tfib == NULL) { + mapme_create_tfib(mapme, entry); + tfib = TFIB(entry); + } + + mapme_prefix = fib_entry_get_prefix(entry); + mapme_seq = tfib->seq; } - const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + char prefix_s[MAXSZ_IP_PREFIX]; + int rc = hicn_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, mapme_prefix); + assert(rc < MAXSZ_IP_PREFIX); + if (rc < 0) NULL; - WITH_DEBUG({ + INFO("mapme send to nexthops prefix= %s", prefix_s); + + WITH_INFO({ char buf[MAXSZ_HICN_PREFIX]; - int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, mapme_prefix); if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); - DEBUG("sending IU/IN for name %s on all nexthops", buf); + INFO("sending IU/IN for name %s on nexthops", buf); }) - mapme_params_t params = { - .protocol = mapme->protocol, - .type = mapme_get_type_from_heuristic(mapme, entry), - .seq = tfib->seq, - }; + mapme_params_t params = {.protocol = mapme->protocol, + .type = mapme_get_type_from_heuristic(mapme, entry), + .seq = mapme_seq}; uint8_t packet[MTU]; - size_t size = hicn_mapme_create_packet(packet, prefix, ¶ms); + size_t size = hicn_mapme_create_packet(packet, mapme_prefix, ¶ms); if (size <= 0) { ERROR("Could not create MAP-Me packet"); return -1; @@ -360,8 +384,8 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, connection_table_t *table = forwarder_get_connection_table(mapme->forwarder); nexthops_foreach(nexthops, nexthop, { - INFO("sending mapme packet on connection %d", nexthop); const connection_t *conn = connection_table_get_by_id(table, nexthop); + assert(!connection_is_local(conn)); connection_send_packet(conn, packet, size); }); @@ -407,34 +431,62 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry) { nexthops_t *nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops); /* We set force to true to avoid overriding the FIB cache */ - return mapme_set_adjacencies(mapme, entry, nexthops); + return mapme_set_adjacencies(mapme, entry, nexthops, NULL); } // XXX this will change with the FIB cache // XXX we are sometimes incrementing tfib seq for nothing int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops) { + nexthops_t *nexthops, const hicn_prefix_t *prefix) { + INFO("mapme set adjacenies"); + /* + * - entry is provided in case of a producer reannouncement + * - prefix is provided for control plane triggered updates + */ + assert(!!prefix ^ !!entry); + if (mapme->enabled == false) { WARN("MAP-Me is NOT enabled"); return -1; } - if (!fib_entry_has_local_nexthop(entry)) return -1; + if (entry) { + /* Check disabled, we need to be able to send an update for a larger prefix + * that the one being served. + */ + // if (!fib_entry_has_local_nexthop(entry)) return -1; - /* Advertise prefix on all available next hops (if needed) */ - mapme_tfib_t *tfib = TFIB(entry); - if (tfib == NULL) { - mapme_create_tfib(mapme, entry); - tfib = TFIB(entry); - } + mapme_tfib_t *tfib = TFIB(entry); + if (tfib == NULL) { + mapme_create_tfib(mapme, entry); + tfib = TFIB(entry); + } + + /* + * We need to prevent pending updates to recreate a link which does not make + * since anymore since we edit the graph here. + */ + nexthops_clear(&tfib->nexthops); - nexthops_clear(&tfib->nexthops); - tfib->seq++; + /* We update the sequence number in all cases otherwise this won't allow + * repetition + */ + tfib->seq++; + } - mapme_send_to_nexthops(mapme, entry, nexthops); + INFO("calling send to nh"); + mapme_send_to_nexthops(mapme, entry, nexthops, prefix); return 0; } +int mapme_set_adjacency(const mapme_t *mapme, fib_entry_t *entry, + nexthop_t nexthop, const hicn_prefix_t *prefix) { + nexthops_t nexthops = NEXTHOPS_EMPTY; + nexthops_add(&nexthops, nexthop); + + return mapme_set_adjacencies(mapme, entry, &nexthops, prefix); +} + int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry, bool inc_iu_seq) { if (mapme->enabled == false) { @@ -450,7 +502,7 @@ int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry, if (inc_iu_seq) tfib->seq++; - mapme_send_to_nexthops(mapme, entry, &tfib->nexthops); + mapme_send_to_nexthops(mapme, entry, &tfib->nexthops, NULL); return 0; } @@ -464,7 +516,7 @@ int mapme_send_to_nexthop(const mapme_t *mapme, fib_entry_t *entry, nexthops_t nexthops = NEXTHOPS_EMPTY; nexthops_add(&nexthops, nexthop); - return mapme_send_to_nexthops(mapme, entry, &nexthops); + return mapme_send_to_nexthops(mapme, entry, &nexthops, NULL); } #if 0 @@ -525,34 +577,47 @@ void mapme_on_connection_event(const mapme_t *mapme, * Special Interest handling *----------------------------------------------------------------------------*/ -// XXX this code has not been updated -#ifdef MAPME_ALLOW_NONEXISTING_FIB_ENTRY -int mapme_create_fib_entry(const mapme_t *mapme, const Name *name, - unsigned ingress_id) { - INFO(" - Re-creating FIB entry with next hop on connection %d", ingress_id); +#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY +fib_entry_t *mapme_create_fib_entry(const mapme_t *mapme, + const hicn_prefix_t *prefix, + unsigned ingress_id) { + INFO(" - creating FIB entry with next hop on connection %d", ingress_id); + /* * This might happen for a node hosting a producer which has moved. * Destroying the face has led to removing all corresponding FIB * entries. In that case, we need to correctly restore the FIB entries. + * Also in case we have an intermediate node with just a less specific prefix + * (eg. a default route), and thus an announcement with a more specific + * prefix. In that case we need to perform a FIB lookup to find the next hops + * to which the message should be propagated (before adding). */ - strategy_type fwdStrategy = LAST_STRATEGY_VALUE; + forwarder_t *forwarder = mapme->forwarder; + + fib_t *fib = forwarder_get_fib(forwarder); + configuration_t *config = forwarder_get_configuration(forwarder); + + char prefix_s[MAXSZ_IP_PREFIX]; + int rc = hicn_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix); + assert(rc < MAXSZ_IP_PREFIX); + if (rc < 0) NULL; + + INFO("creating FIB entry for prefix %s", prefix_s); + + strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s); + fib_entry_t *entry = fib_entry_create(prefix, strategy_type, NULL, forwarder); + mapme_create_tfib(mapme, entry); + + fib_entry_t *lpm = fib_match_prefix(fib, prefix); + + // Keep this after the LPM lookup + fib_add(fib, entry); - /* - * It might also be due to the announcement of a more specific prefix. In - * that case we need to perform a FIB lookup to find the next hops to which - * the message should be propagated. - */ -#ifdef WITH_POLICY - entry = fib_entry_Create(name, fwdStrategy, mapme->forwarder); -#else - entry = fib_entry_Create(name, fwdStrategy); -#endif /* WITH_POLICY */ - fib_entry_t *lpm = fib_MatchName(fib, name); - fib_Add(fib, entry); if (!lpm) { - TFIB(entry)->seq = seq; - fib_entry_AddNexthop(entry, ingress_id); - return true; + TFIB(entry)->seq = 0; + if (ingress_id != INVALID_FACE_ID) + fib_entry_nexthops_add(entry, ingress_id); + return entry; } /* @@ -560,11 +625,9 @@ int mapme_create_fib_entry(const mapme_t *mapme, const Name *name, * the more specific name, and proceed as usual. Worst case we clone the * default route... */ - const NumberSet *lpm_nexthops = fib_entry_nexthops_get(lpm); - for (size_t i = 0; i < numberSet_Length(lpm_nexthops); i++) { - fib_entry_AddNexthop(entry, numberSet_GetItem(lpm_nexthops, i)); - } - return 0; + const nexthops_t *lpm_nexthops = fib_entry_get_nexthops(lpm); + nexthops_foreach(lpm_nexthops, nh, { fib_entry_nexthops_add(entry, nh); }); + return entry; } #endif @@ -797,13 +860,13 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, msgbuf_pool_put(msgbuf_pool, ack); - WITH_DEBUG({ + WITH_INFO({ char buf[MAXSZ_HICN_PREFIX]; int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); - DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, buf, - params->seq); + INFO("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, buf, + params->seq); }); /* EPM on FIB */ @@ -811,7 +874,8 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) { #ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY - if (mapme_create_fib_entry(mapme, &name, ingress_id) < 0) { + entry = mapme_create_fib_entry(mapme, prefix, ingress_id); + if (!entry) { ERROR("Failed to create FIB entry"); return; } @@ -836,7 +900,13 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, * for which the prefix has a local next hop in the FIB. */ // XXX NOT IN VPP ? - if (fib_entry_has_local_nexthop(entry)) { + + /* Initially we were detecting that the update completed when it returned to + * the producer, Because there might be proxies (using local/remote strategy), + * we need instead to verify if there is no non-local faces. + */ + + if (fib_entry_has_all_local_nexthops(entry)) { INFO("Received original interest... Update complete"); return; } @@ -856,12 +926,24 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, * * This could might optimized for situations where nothing changes, but * this is very unlikely if not impossible... - * */ - nexthops_foreach(&entry->nexthops, prevhop, - { nexthops_add(&tfib->nexthops, prevhop); }); + */ + nexthops_t nexthops_keep = NEXTHOPS_EMPTY; + nexthops_foreach(&entry->nexthops, prevhop, { + const connection_t *conn = connection_table_get_by_id(table, prevhop); + /* Preserve local connections, migrate others to TFIB */ + if (connection_is_local(conn)) { + nexthops_add(&nexthops_keep, prevhop); + } else { + nexthops_add(&tfib->nexthops, prevhop); + } + }); + nexthops_remove(&tfib->nexthops, ingress_id); + nexthops_clear(&entry->nexthops); nexthops_add(&entry->nexthops, ingress_id); + nexthops_foreach(&nexthops_keep, nh, + { nexthops_add(&entry->nexthops, nh); }); event = MAPME_EVENT_NH_SET; @@ -899,8 +981,8 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, params->seq, tfib->seq, ingress_id); return; } else { - DEBUG("Received seq %d < fib_seq %d, sending backwards on face %d", - params->seq, tfib->seq, ingress_id); + INFO("Received seq %d < fib_seq %d, sending backwards on face %d", + params->seq, tfib->seq, ingress_id); nexthops_add(&tfib->nexthops, ingress_id); } @@ -916,13 +998,13 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, static void mapme_on_data(mapme_t *mapme, msgbuf_t *msgbuf, unsigned ingress_id, hicn_prefix_t *prefix, mapme_params_t *params) { - WITH_DEBUG({ + WITH_INFO({ char buf[MAXSZ_HICN_PREFIX]; int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); - DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", buf, - params->seq, ingress_id); + INFO("Received ack for name prefix=%s seq=%d on conn id=%d", buf, + params->seq, ingress_id); }) const fib_t *fib = forwarder_get_fib(mapme->forwarder); @@ -979,8 +1061,8 @@ void mapme_process(mapme_t *mapme, msgbuf_t *msgbuf) { if (rc < 0) return; // XXX TYPE STR - DEBUG("Received interest type: %d seq: %d len:%d", params.type, params.seq, - prefix.len); + INFO("Received interest type: %d seq: %d len:%d", params.type, params.seq, + prefix.len); // XXX RENAME TYPES switch (params.type) { diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h index 188607421..9ece8a090 100644 --- a/hicn-light/src/hicn/core/mapme.h +++ b/hicn-light/src/hicn/core/mapme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -33,6 +33,10 @@ #include "fib_entry.h" #include "msgbuf.h" +// Allow processing of MAP-Me requests when no FIB entry is present. +// An alternative would be to perform a LPM +#define HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY + typedef struct mapme_s mapme_t; /** @@ -85,9 +89,24 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry); * @param [in] mapme - Pointer to the MAP-Me data structure. * @param [in] fib_entry - The FIB entry to consider * @param [in] nexthops - next hops on which to send the update. + * @param [in] prefix - A more specific prefix (special use with no retx), or + * NULL */ int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops); + nexthops_t *nexthops, const hicn_prefix_t *prefix); + +/** + * @function mapme_set_adjacencies + * @abstract sends an update to the specified adjacency. Used by control plane + * commands. + * @param [in] mapme - Pointer to the MAP-Me data structure. + * @param [in] fib_entry - The FIB entry to consider + * @param [in] nexthop - nexthop on which to send the update. + * @param [in] prefix - A more specific prefix (special use with no retx), or + * NULL + */ +int mapme_set_adjacency(const mapme_t *mapme, fib_entry_t *entry, + nexthop_t nexthop, const hicn_prefix_t *prefix); /** * @function mapme_update_adjacencies @@ -122,6 +141,12 @@ void mapme_on_connection_event(const mapme_t *mapme, const connection_t *conn, // nexthops_t * mapme_get_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry, // const msgbuf_t *interest); +#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY +fib_entry_t *mapme_create_fib_entry(const mapme_t *mapme, + const hicn_prefix_t *prefix, + unsigned ingress_id); +#endif /* HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY */ + void mapme_set_enable(mapme_t *mapme, bool enable); void mapme_set_discovery(mapme_t *mapme, bool enable); void mapme_set_timescale(mapme_t *mapme, uint32_t time); diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h index ef2b38c51..7a35929f4 100644 --- a/hicn-light/src/hicn/core/msgbuf.h +++ b/hicn-light/src/hicn/core/msgbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -111,8 +111,7 @@ static inline u32 msgbuf_get_name_hash(const msgbuf_t *msgbuf) { static inline u32 msgbuf_get_interest_lifetime(const msgbuf_t *msgbuf) { u32 lifetime; int rc = hicn_interest_get_lifetime(msgbuf_get_pkbuf(msgbuf), &lifetime); - assert(rc == HICN_LIB_ERROR_NONE); // XXX - _unused(rc); + if (rc != HICN_LIB_ERROR_NONE) return 0; return lifetime; } @@ -130,8 +129,7 @@ static inline bool msgbuf_set_interest_lifetime(msgbuf_t *msgbuf, static inline u32 msgbuf_get_data_expiry_time(const msgbuf_t *msgbuf) { u32 lifetime; int rc = hicn_data_get_expiry_time(msgbuf_get_pkbuf(msgbuf), &lifetime); - assert(rc == HICN_LIB_ERROR_NONE); // XXX - _unused(rc); + if (rc != HICN_LIB_ERROR_NONE) return 0; return lifetime; } diff --git a/hicn-light/src/hicn/strategies/local_prefixes.c b/hicn-light/src/hicn/strategies/local_prefixes.c index 25927ac69..fb161ab2a 100644 --- a/hicn-light/src/hicn/strategies/local_prefixes.c +++ b/hicn-light/src/hicn/strategies/local_prefixes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -77,6 +77,6 @@ void update_remote_node_paths(const void *nexthops, const void *forwarder, fib_entry_t *entry = fib_match_prefix(fib, &prefixes->local_prefixes[i]); if (!entry) continue; // XXX we don't want to force - mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops); + mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops, NULL); } } -- cgit 1.2.3-korg