diff options
50 files changed, 988 insertions, 575 deletions
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c index f630792c4..88595a9bc 100644 --- a/ctrl/facemgr/src/api.c +++ b/ctrl/facemgr/src/api.c @@ -1279,7 +1279,6 @@ facemgr_bootstrap(facemgr_t * facemgr) #ifdef __APPLE__ network_framework_cfg_t nf_cfg = { - .rules = &facemgr->rules, }; rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg, &facemgr->nf); if (rc < 0) { diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c index 4a9d24f61..ed2f88e9e 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c @@ -529,11 +529,6 @@ int nf_initialize(interface_t * interface, void * cfg) if (!data) goto ERR_MALLOC; - if (cfg) - data->cfg = * (network_framework_cfg_t *)cfg; - else - data->cfg.rules = NULL; - data->pm = nw_path_monitor_create(); if (!data->pm) goto ERR_PM; diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h index 4209c6eb6..75f05988f 100755 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h @@ -58,6 +58,7 @@ typedef enum { ADD_ROUTE, LIST_ROUTES, REMOVE_CONNECTION, + REMOVE_LISTENER, REMOVE_ROUTE, CACHE_STORE, CACHE_SERVE, @@ -77,7 +78,6 @@ typedef enum { REMOVE_POLICY, UPDATE_CONNECTION, #endif /* WITH_POLICY */ - REMOVE_LISTENER, LAST_COMMAND_VALUE } command_id; diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c index f704d237e..ab0e0e6d8 100644 --- a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c +++ b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c @@ -63,6 +63,7 @@ static int payloadLengthController[LAST_COMMAND_VALUE] = { sizeof(add_route_command), sizeof(list_routes_command), // needed when get response from FWD sizeof(remove_connection_command), + sizeof(remove_listener_command), sizeof(remove_route_command), sizeof(cache_store_command), sizeof(cache_serve_command), diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt index b1e475aee..45f36e8ff 100644 --- a/hicn-light/src/hicn/config/CMakeLists.txt +++ b/hicn-light/src/hicn/config/CMakeLists.txt @@ -35,6 +35,7 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.h ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.h ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.h ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.h ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.h @@ -78,6 +79,7 @@ list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.c ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.c ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.c ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.c ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.c diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c index b14ea551a..83fce748c 100644 --- a/hicn-light/src/hicn/config/configuration.c +++ b/hicn-light/src/hicn/config/configuration.c @@ -346,7 +346,6 @@ static void configuration_SendResponse(Configuration *config, struct iovec *msg, if (conn == NULL) { return; } - connection_SendIOVBuffer(conn, msg, 2); } @@ -450,6 +449,10 @@ struct iovec *configuration_ProcessCreateTunnel(Configuration *config, /* Hook: new connection created through the control protocol */ forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_UPDATE); #endif /* WITH_MAPME */ + if (source) + addressDestroy(&source); + if (destination) + addressDestroy(&destination); success = true; #else @@ -472,6 +475,70 @@ ERR: return utils_CreateNack(header, control, sizeof(add_connection_command)); } +struct iovec *configuration_ProcessRemoveListener(Configuration *config, + struct iovec *request, + unsigned ingressId) { + header_control_message *header = request[0].iov_base; + remove_listener_command *control = request[1].iov_base; + + bool success = false; + + const char *symbolicOrListenerid = control->symbolicOrListenerid; + unsigned listenerId = -1; + ListenerSet *listenerSet = forwarder_GetListenerSet(config->forwarder); + if (utils_IsNumber(symbolicOrListenerid)) { + // case for connid as input + listenerId = (unsigned)strtold(symbolicOrListenerid, NULL); + } else { + listenerId = listenerSet_FindIdByListenerName(listenerSet, symbolicOrListenerid); + } + + if (listenerId >= 0) { + + ConnectionTable *connTable = forwarder_GetConnectionTable(config->forwarder); + ListenerOps *listenerOps = listenerSet_FindById(listenerSet, listenerId); + if (listenerOps) { + ConnectionList *connectionList =connectionTable_GetEntries(connTable); + for (size_t i =0; i < connectionList_Length(connectionList); i++) { + Connection *connection = connectionList_Get(connectionList, i); + const AddressPair *addressPair = connection_GetAddressPair(connection); + const Address *address = addressPair_GetLocal(addressPair); + if (addressEquals(listenerOps->getListenAddress(listenerOps),address)) { + // case for connid as input + unsigned connid = connection_GetConnectionId(connection); + // remove connection from the FIB + forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid); + // remove connection + connectionTable_RemoveById(connTable, connid); + const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid); + symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection); + } + } + // remove listener + listenerSet_RemoveById(listenerSet, listenerId); + success = true; + } else { + logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, + PARCLogLevel_Error, __func__, + "Listener Id not found, check list listeners"); + } + } + + // generate ACK/NACK + struct iovec *response; + + if (success) { // ACK + response = + utils_CreateAck(header, control, sizeof(remove_listener_command)); + } else { // NACK + response = + utils_CreateNack(header, control, sizeof(remove_connection_command)); + } + + return response; +} + + /** * Add an IP-based tunnel. * @@ -493,7 +560,6 @@ struct iovec *configuration_ProcessRemoveTunnel(Configuration *config, const char *symbolicOrConnid = control->symbolicOrConnid; ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); - if (strcmp(symbolicOrConnid, "SELF") == 0) { forwarder_RemoveConnectionIdFromRoutes(config->forwarder, ingressId); connectionTable_RemoveById(table, ingressId); @@ -515,6 +581,9 @@ struct iovec *configuration_ProcessRemoveTunnel(Configuration *config, forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid); // remove connection connectionTable_RemoveById(table, connid); + // remove connection from symbolicNameTable + const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid); + symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection); #ifdef WITH_MAPME /* Hook: new connection created through the control protocol */ @@ -568,6 +637,8 @@ struct iovec *configuration_ProcessRemoveTunnel(Configuration *config, } } + + // generate ACK/NACK struct iovec *response; @@ -612,8 +683,8 @@ struct iovec *configuration_ProcessConnectionList(Configuration *config, list_connections_command *listConnectionsCommand = (list_connections_command *)(payloadResponse + (i * sizeof(list_connections_command))); - // set structure fields + listConnectionsCommand->connid = connection_GetConnectionId(original); const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original)); @@ -1202,7 +1273,6 @@ struct iovec *configuration_DispatchCommand(Configuration *config, struct iovec *control, unsigned ingressId) { struct iovec *response = NULL; - switch (command) { case ADD_LISTENER: response = configurationListeners_Add(config, control, ingressId); @@ -1229,6 +1299,10 @@ struct iovec *configuration_DispatchCommand(Configuration *config, response = configuration_ProcessRemoveTunnel(config, control, ingressId); break; + case REMOVE_LISTENER: + response = configuration_ProcessRemoveListener(config, control, ingressId); + break; + case REMOVE_ROUTE: response = configuration_ProcessUnregisterHicnPrefix(config, control); break; diff --git a/hicn-light/src/hicn/config/configurationListeners.c b/hicn-light/src/hicn/config/configurationListeners.c index 86d8a215a..c321007e2 100644 --- a/hicn-light/src/hicn/config/configurationListeners.c +++ b/hicn-light/src/hicn/config/configurationListeners.c @@ -317,6 +317,7 @@ static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, char *listenerNa * Create a new IPV6/UDP listener. * * @param [in,out] forwarder The hicn-light forwarder instance + * @param [in] listenerName The name of the listener * @param [in] addr6 The ipv6 address in network byte order * @param [in] port The port number in network byte order * @param [in] interfaceName The name of the interface to bind the socket @@ -615,7 +616,8 @@ void configurationListeners_SetutpLocalIPv4(const Configuration *config, Forwarder *forwarder = configuration_GetForwarder(config); in_addr_t addr = inet_addr("127.0.0.1"); uint16_t network_byte_order_port = htons(port); - char listenerNameUdp[16] = "lo_udp"; + + char listenerNameUdp[16] = "lo_udp"; char listenerNameTcp[16] = "lo_tcp"; char *loopback_interface = "lo"; _setupUdpListenerOnInet(forwarder, listenerNameUdp,(ipv4_addr_t *)&(addr), diff --git a/hicn-light/src/hicn/config/controlAddConnection.c b/hicn-light/src/hicn/config/controlAddConnection.c index e09b61b37..eaa680bde 100644 --- a/hicn-light/src/hicn/config/controlAddConnection.c +++ b/hicn-light/src/hicn/config/controlAddConnection.c @@ -42,11 +42,13 @@ static CommandReturn _controlAddConnection_Execute(CommandParser *parser, // =================================================== +#ifdef __linux__ static CommandReturn _controlAddConnection_HicnHelpExecute( CommandParser *parser, CommandOps *ops, PARCList *args); static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, CommandOps *ops, PARCList *args); +#endif static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, CommandOps *ops, @@ -65,11 +67,15 @@ static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser, // =================================================== static const char *_commandAddConnection = "add connection"; +#ifdef __linux__ static const char *_commandAddConnectionHicn = "add connection hicn"; +#endif static const char *_commandAddConnectionUdp = "add connection udp"; static const char *_commandAddConnectionTcp = "add connection tcp"; static const char *_commandAddConnectionHelp = "help add connection"; +#ifdef __linux__ static const char *_commandAddConnectionHicnHelp = "help add connection hicn"; +#endif static const char *_commandAddConnectionUdpHelp = "help add connection udp"; static const char *_commandAddConnectionTcpHelp = "help add connection tcp"; @@ -89,11 +95,13 @@ CommandOps *controlAddConnection_HelpCreate(ControlState *state) { // =================================================== +#ifdef __linux__ static CommandOps *_controlAddConnection_HicnCreate(ControlState *state) { return commandOps_Create(state, _commandAddConnectionHicn, NULL, _controlAddConnection_HicnExecute, commandOps_Destroy); } +#endif static CommandOps *_controlAddConnection_UdpCreate(ControlState *state) { return commandOps_Create(state, _commandAddConnectionUdp, NULL, @@ -108,12 +116,13 @@ static CommandOps *_controlAddConnection_TcpCreate(ControlState *state) { } // =================================================== - +#ifdef __linux__ static CommandOps *_controlAddConnection_HicnHelpCreate(ControlState *state) { return commandOps_Create(state, _commandAddConnectionHicnHelp, NULL, _controlAddConnection_HicnHelpExecute, commandOps_Destroy); } +#endif static CommandOps *_controlAddConnection_UdpHelpCreate(ControlState *state) { return commandOps_Create(state, _commandAddConnectionUdpHelp, NULL, @@ -133,7 +142,9 @@ static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser, CommandOps *ops, PARCList *args) { printf("Available commands:\n"); +#ifdef __linux__ printf(" %s\n", _commandAddConnectionHicn); +#endif printf(" %s\n", _commandAddConnectionUdp); printf(" %s\n", _commandAddConnectionTcp); printf("\n"); @@ -142,14 +153,17 @@ static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser, static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops) { ControlState *state = ops->closure; +#ifdef __linux__ controlState_RegisterCommand(state, _controlAddConnection_HicnHelpCreate(state)); +#endif controlState_RegisterCommand(state, _controlAddConnection_UdpHelpCreate(state)); controlState_RegisterCommand(state, _controlAddConnection_TcpHelpCreate(state)); - +#ifdef __linux__ controlState_RegisterCommand(state, _controlAddConnection_HicnCreate(state)); +#endif controlState_RegisterCommand(state, _controlAddConnection_UdpCreate(state)); controlState_RegisterCommand(state, _controlAddConnection_TcpCreate(state)); } @@ -255,7 +269,9 @@ static CommandReturn _controlAddConnection_IpHelp(CommandParser *parser, CommandOps *ops, PARCList *args, const char *protocol) { +#ifdef __linux__ printf("add connection hicn <symbolic> <remote_ip> <local_ip>\n"); +#endif printf( "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port>\n"); printf( @@ -268,6 +284,7 @@ static CommandReturn _controlAddConnection_IpHelp(CommandParser *parser, return CommandReturn_Success; } +#ifdef __linux__ static CommandReturn _controlAddConnection_HicnHelpExecute( CommandParser *parser, CommandOps *ops, PARCList *args) { _controlAddConnection_IpHelp(parser, ops, args, "hicn"); @@ -303,6 +320,7 @@ static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, return _controlAddConnection_CreateTunnel( parser, ops, local_ip, port, remote_ip, port, HICN_CONN, symbolic); } +#endif static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, CommandOps *ops, diff --git a/hicn-light/src/hicn/config/controlAddListener.c b/hicn-light/src/hicn/config/controlAddListener.c index c9253425a..cfd061131 100644 --- a/hicn-light/src/hicn/config/controlAddListener.c +++ b/hicn-light/src/hicn/config/controlAddListener.c @@ -58,27 +58,26 @@ static const int _indexProtocol = 2; static const int _indexSymbolic = 3; static const int _indexAddress = 4; static const int _indexPort = 5; -#ifdef __linux__ static const int _indexInterfaceName = 6; -#endif static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, CommandOps *ops, PARCList *args) { printf("commands:\n"); - printf(" add listener hicn <symbolic> <localAddress> \n"); #ifdef __linux__ + printf(" add listener hicn <symbolic> <localAddress> \n"); +#endif printf(" add listener udp <symbolic> <localAddress> <port> <interface>\n"); printf(" add listener tcp <symbolic> <localAddress> <port> <interface>\n"); -#else - printf(" add listener udp <symbolic> <localAddress> <port>\n"); - printf(" add listener tcp <symbolic> <localAddress> <port>\n"); -#endif printf("\n"); printf( " symbolic: User defined name for listener, must start with " "alpha and be alphanum\n"); +#ifdef __linux__ printf(" protocol: hicn | udp\n"); +#else + printf(" protocol: udp\n"); +#endif printf( " localAddress: IPv4 or IPv6 address (or prefix protocol = hicn) " "assigend to the local interface\n"); @@ -88,23 +87,18 @@ static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, printf("\n"); printf("Notes:\n"); printf(" The symblic name must be unique or the source will reject it.\n"); +#ifdef __linux__ printf( - " If protocol = hinc: the address 0::0 indicates the main listern, " + " If protocol = hicn: the address 0::0 indicates the main listern, " "for which we can set punting rules.\n"); +#endif return CommandReturn_Success; } -#ifdef __linux__ -static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, - const char *symbolic, const char *addr, - const char *port, const char *interfaceName, listener_mode mode, - connection_type type) { -#else static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, const char *symbolic, const char *addr, - const char *port, listener_mode mode, + const char *port, char *interfaceName, listener_mode mode, connection_type type) { -#endif ControlState *state = ops->closure; // allocate command payload @@ -126,9 +120,7 @@ static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, } // Fill remaining payload fields -#ifdef __linux__ memcpy(addListenerCommand->interfaceName, interfaceName, 16); -#endif addListenerCommand->listenerMode = mode; addListenerCommand->connectionType = type; addListenerCommand->port = htons((uint16_t)atoi(port)); @@ -149,11 +141,7 @@ static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, static CommandReturn _controlAddListener_Execute(CommandParser *parser, CommandOps *ops, PARCList *args) { -#ifdef __linux__ if (parcList_Size(args) != 5 && parcList_Size(args) != 7) { -#else - if (parcList_Size(args) != 5 && parcList_Size(args) != 6) { -#endif _controlAddListener_HelpExecute(parser, ops, args); return CommandReturn_Failure; } @@ -169,45 +157,26 @@ static CommandReturn _controlAddListener_Execute(CommandParser *parser, return result; } - const char *host = parcList_GetAtIndex(args, _indexAddress); -#ifdef __linux__ - const char *interfaceName = parcList_GetAtIndex(args, _indexInterfaceName); -#endif const char *protocol = parcList_GetAtIndex(args, _indexProtocol); - + const char *host = parcList_GetAtIndex(args, _indexAddress); + char *interfaceName = parcList_GetAtIndex(args, _indexInterfaceName); if ((strcasecmp("hicn", protocol) == 0)) { const char *port = "1234"; // this is a random port number that will be ignored // here we discard the prefix len if it exists, since we don't use it in // code but we let libhicn to find the right ip address. -#ifdef __linux__ return _CreateListener(parser, ops, symbolic, host, port, "hicn", HICN_MODE, HICN_CONN); -#else - return _CreateListener(parser, ops, symbolic, host, port, HICN_MODE, - HICN_CONN); -#endif } - const char *port = parcList_GetAtIndex(args, _indexPort); if ((strcasecmp("udp", protocol) == 0)) { -#ifdef __linux__ return _CreateListener(parser, ops, symbolic, host, port, interfaceName, IP_MODE, UDP_CONN); -#else - return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, - UDP_CONN); -#endif } else if ((strcasecmp("tcp", protocol) == 0)) { -#ifdef __linux__ return _CreateListener(parser, ops, symbolic, host, port, interfaceName, IP_MODE, TCP_CONN); -#else - return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, - TCP_CONN); -#endif } else { _controlAddListener_HelpExecute(parser, ops, args); return CommandReturn_Failure; diff --git a/hicn-light/src/hicn/config/controlListConnections.c b/hicn-light/src/hicn/config/controlListConnections.c index dbd9707ca..c8a4c1b4b 100644 --- a/hicn-light/src/hicn/config/controlListConnections.c +++ b/hicn-light/src/hicn/config/controlListConnections.c @@ -120,6 +120,8 @@ static CommandReturn _controlListConnections_Execute(CommandParser *parser, #endif /* WITH_POLICY */ // Process/Print payload + + printf("%5s %10s %6s %40s %40s %5s\n", "id", "name", "state", "source", "destination", "type"); for (int i = 0; i < receivedHeader->length; i++) { list_connections_command *listConnectionsCommand = (list_connections_command *)(receivedPayload + diff --git a/hicn-light/src/hicn/config/controlRemove.c b/hicn-light/src/hicn/config/controlRemove.c index af833dc8b..ef0c15934 100644 --- a/hicn-light/src/hicn/config/controlRemove.c +++ b/hicn-light/src/hicn/config/controlRemove.c @@ -27,6 +27,7 @@ #include <parc/algol/parc_Memory.h> #include <hicn/config/controlRemove.h> +#include <hicn/config/controlRemoveListener.h> #include <hicn/config/controlRemoveConnection.h> #include <hicn/config/controlRemovePunting.h> #include <hicn/config/controlRemoveRoute.h> @@ -62,6 +63,7 @@ static CommandReturn _controlRemove_HelpExecute(CommandParser *parser, CommandOps *ops, PARCList *args) { CommandOps *ops_remove_connection = controlRemoveConnection_Create(NULL); + CommandOps *ops_remove_listener = controlRemoveListener_Create(NULL); CommandOps *ops_remove_route = controlRemoveRoute_Create(NULL); CommandOps *ops_remove_punting = controlRemovePunting_Create(NULL); #ifdef WITH_POLICY @@ -70,6 +72,7 @@ static CommandReturn _controlRemove_HelpExecute(CommandParser *parser, printf("Available commands:\n"); printf(" %s\n", ops_remove_connection->command); + printf(" %s\n", ops_remove_listener->command); printf(" %s\n", ops_remove_route->command); printf(" %s\n", ops_remove_punting->command); #ifdef WITH_POLICY @@ -78,6 +81,7 @@ static CommandReturn _controlRemove_HelpExecute(CommandParser *parser, printf("\n"); commandOps_Destroy(&ops_remove_connection); + commandOps_Destroy(&ops_remove_listener); commandOps_Destroy(&ops_remove_route); commandOps_Destroy(&ops_remove_punting); #ifdef WITH_POLICY @@ -90,8 +94,11 @@ static void _controlRemove_Init(CommandParser *parser, CommandOps *ops) { ControlState *state = ops->closure; controlState_RegisterCommand(state, controlRemoveConnection_HelpCreate(state)); + controlState_RegisterCommand(state, + controlRemoveListener_HelpCreate(state)); controlState_RegisterCommand(state, controlRemoveRoute_HelpCreate(state)); controlState_RegisterCommand(state, controlRemoveConnection_Create(state)); + controlState_RegisterCommand(state, controlRemoveListener_Create(state)); controlState_RegisterCommand(state, controlRemoveRoute_Create(state)); controlState_RegisterCommand(state, controlRemovePunting_Create(state)); controlState_RegisterCommand(state, controlRemovePunting_HelpCreate(state)); diff --git a/hicn-light/src/hicn/config/controlRemoveListener.c b/hicn-light/src/hicn/config/controlRemoveListener.c new file mode 100644 index 000000000..50581a8d9 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveListener.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017-2019 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <hicn/hicn-light/config.h> + +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include <parc/assert/parc_Assert.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Network.h> +#include <hicn/utils/address.h> + +#include <hicn/config/controlRemoveListener.h> + +#include <hicn/utils/commands.h> +#include <hicn/utils/utils.h> + +static CommandReturn _controlRemoveListener_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlRemoveListener_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +static const char *_commandRemoveListener = "remove listener"; +static const char *_commandRemoveListenerHelp = "help remove listener"; + +// ==================================================== + +CommandOps *controlRemoveListener_Create(ControlState *state) { + return commandOps_Create(state, _commandRemoveListener, NULL, + _controlRemoveListener_Execute, + commandOps_Destroy); +} + +CommandOps *controlRemoveListener_HelpCreate(ControlState *state) { + return commandOps_Create(state, _commandRemoveListenerHelp, NULL, + _controlRemoveListener_HelpExecute, + commandOps_Destroy); +} + +// ==================================================== + +static CommandReturn _controlRemoveListener_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + printf("command:\n"); + printf(" remove listener <symbolic|id>\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlRemoveListener_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 3) { + _controlRemoveListener_HelpExecute(parser, ops, args); + return false; + } + + if ((strcmp(parcList_GetAtIndex(args, 0), "remove") != 0) || + (strcmp(parcList_GetAtIndex(args, 1), "listener") != 0)) { + _controlRemoveListener_HelpExecute(parser, ops, args); + return false; + } + + const char *listenerId = parcList_GetAtIndex(args, 2); + +if (!utils_ValidateSymbolicName(listenerId) && + !utils_IsNumber(listenerId)) { + printf( + "ERROR: Invalid symbolic or listenerId:\nsymbolic name must begin with an " + "alpha followed by alphanum;\nlistenerId must be an integer\n"); + return CommandReturn_Failure; + } + + // allocate command payload + remove_listener_command *removeListenerCommand = + parcMemory_AllocateAndClear(sizeof(remove_listener_command)); + // fill payload + //removeListenerCommand->listenerId = atoi(listenerId); + strncpy(removeListenerCommand->symbolicOrListenerid, listenerId, strlen(listenerId)); + + // send message and receive response + struct iovec *response = + utils_SendRequest(state, REMOVE_LISTENER, removeListenerCommand, + sizeof(remove_listener_command)); + + if (!response) { // get NULL pointer + return CommandReturn_Failure; + } + + parcMemory_Deallocate(&response); // free iovec pointer + return CommandReturn_Success; +} diff --git a/hicn-light/src/hicn/config/controlRemoveListener.h b/hicn-light/src/hicn/config/controlRemoveListener.h new file mode 100644 index 000000000..794d1e1a9 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveListener.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file control_RemoveConnection.h + * @brief Remove a connection from the connection table + * + * Implements the "remove connection" and "help remove connection" nodes of the + * CLI tree + * + */ + +#ifndef Control_RemoveListener_h +#define Control_RemoveListener_h + +#include <hicn/config/controlState.h> +CommandOps *controlRemoveListener_Create(ControlState *state); +CommandOps *controlRemoveListener_HelpCreate(ControlState *state); +#endif // Control_RemoveListener_h diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c index 821da884d..fb43d4a1e 100644 --- a/hicn-light/src/hicn/core/connection.c +++ b/hicn-light/src/hicn/core/connection.c @@ -32,6 +32,7 @@ #endif /* WITH_POLICY */ struct connection { + const AddressPair *addressPair; IoOperations *ops; diff --git a/hicn-light/src/hicn/io/hicnListener.c b/hicn-light/src/hicn/io/hicnListener.c index 995347d6a..8409db027 100644 --- a/hicn-light/src/hicn/io/hicnListener.c +++ b/hicn-light/src/hicn/io/hicnListener.c @@ -82,6 +82,12 @@ static EncapType _getEncapType(const ListenerOps *ops); static int _getSocket(const ListenerOps *ops); static unsigned _createNewConnection(ListenerOps *listener, int fd, const AddressPair *pair); static const Connection * _lookupConnection(ListenerOps * listener, const AddressPair *pair); +static Message *_readMessage(ListenerOps * listener, int fd, uint8_t *msgBuffer); +static void _hicnListener_readcb(int fd, PARCEventType what, void *listener_void); +static Address *_createAddressFromPacket(uint8_t *msgBuffer); +static void _handleProbeMessage(ListenerOps * listener, uint8_t *msgBuffer); +static void _handleWldrNotification(ListenerOps *listener, uint8_t *msgBuffer); +static void _readFrameToDiscard(HicnListener *hicn, int fd); static ListenerOps _hicnTemplate = { .context = NULL, @@ -96,8 +102,6 @@ static ListenerOps _hicnTemplate = { .lookupConnection = &_lookupConnection, }; -static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid); - static bool _isEmptyAddressIPv6(Address *address) { struct sockaddr_in6 *addr6 = parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); @@ -118,6 +122,100 @@ static bool _isEmptyAddressIPv6(Address *address) { return res; } +static Message *_readMessage(ListenerOps * listener, int fd, uint8_t *msgBuffer) { + HicnListener * hicn = (HicnListener*)listener->context; + Message *message = NULL; + + ssize_t readLength = read(fd, msgBuffer, MTU_SIZE); + + if (readLength < 0) { + printf("read failed %d: (%d) %s\n", fd, errno, strerror(errno)); + return message; + } + + size_t packetLength = messageHandler_GetTotalPacketLength(msgBuffer); + + if (readLength != packetLength) { + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } + + if (messageHandler_IsTCP(msgBuffer)) { + MessagePacketType pktType; + unsigned connid = 0; + if (messageHandler_IsData(msgBuffer)) { + pktType = MessagePacketType_ContentObject; + if (hicn->connection_id == -1) { + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } else { + connid = hicn->connection_id; + } + } else if (messageHandler_IsInterest(msgBuffer)) { + // notice that the connections for the interest (the one that we create at + // run time) uses as a local address 0::0, so the main tun + pktType = MessagePacketType_Interest; + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + AddressPair *pair_find = addressPair_Create(packetAddr, /* dummy */ hicn->localAddress); + const Connection *conn = _lookupConnection(listener, pair_find); + addressPair_Release(&pair_find); + if (conn == NULL) { + AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr); + connid = _createNewConnection(listener, fd, pair); + addressPair_Release(&pair); + } else { + connid = connection_GetConnectionId(conn); + } + addressDestroy(&packetAddr); + } else { + printf("Got a packet that is not a data nor an interest, drop it!\n"); + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } + + message = message_CreateFromByteArray(connid, msgBuffer, pktType, + forwarder_GetTicks(hicn->forwarder), + forwarder_GetLogger(hicn->forwarder)); + if (message == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + } + } else if (messageHandler_IsWldrNotification(msgBuffer)) { + _handleWldrNotification(listener, msgBuffer); + } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) { + _handleProbeMessage(listener, msgBuffer); + } else { + messageHandler_handleHooks(hicn->forwarder, msgBuffer, listener, fd, NULL); + parcMemory_Deallocate((void **)&msgBuffer); + } + + return message; +} + +static void _receivePacket(ListenerOps * listener, int fd) { + HicnListener * hicn = (HicnListener*)listener->context; + Message *msg = NULL; + uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE); + msg = _readMessage(listener, fd, msgBuffer); + + if (msg) { + forwarder_Receive(hicn->forwarder, msg); + } +} + +static void _hicnListener_readcb(int fd, PARCEventType what, void *listener_void) { + ListenerOps * listener = (ListenerOps *)listener_void; + HicnListener *hicn = (HicnListener *)listener->context; + + if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) { + if (what & PARCEventType_Read) { + _receivePacket(listener, fd); + } + } else { + _readFrameToDiscard(hicn, fd); + } +} + static bool _isEmptyAddressIPv4(Address *address) { bool res = false; @@ -133,13 +231,8 @@ ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic, hicn->forwarder = forwarder; hicn->listenerName = parcMemory_StringDuplicate(symbolic, strlen(symbolic)); - hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - - hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder)); hicn->conn_id = forwarder_GetNextConnectionId(forwarder); - hicn->localAddress = addressCopy(address); - hicn->inetFamily = IPv4; hicn->connection_id = -1; @@ -438,6 +531,7 @@ static const char *_getListenerName(const ListenerOps *ops) { HicnListener *hicn = (HicnListener *)ops->context; return hicn->listenerName; } + static const char *_getInterfaceName(const ListenerOps *ops) { const char *interfaceName = ""; return interfaceName; @@ -601,96 +695,6 @@ static void _handleWldrNotification(ListenerOps *listener, uint8_t *msgBuffer) { } -static Message *_readMessage(ListenerOps * listener, int fd, uint8_t *msgBuffer) { - HicnListener * hicn = (HicnListener*)listener->context; - Message *message = NULL; - - ssize_t readLength = read(fd, msgBuffer, MTU_SIZE); - - if (readLength < 0) { - printf("read failed %d: (%d) %s\n", fd, errno, strerror(errno)); - return message; - } - - size_t packetLength = messageHandler_GetTotalPacketLength(msgBuffer); - if (readLength != packetLength) { - parcMemory_Deallocate((void **)&msgBuffer); - return message; - } - if (messageHandler_IsTCP(msgBuffer)) { - MessagePacketType pktType; - unsigned connid = 0; - if (messageHandler_IsData(msgBuffer)) { - pktType = MessagePacketType_ContentObject; - if (hicn->connection_id == -1) { - parcMemory_Deallocate((void **)&msgBuffer); - return message; - } else { - connid = hicn->connection_id; - } - } else if (messageHandler_IsInterest(msgBuffer)) { - // notice that the connections for the interest (the one that we create at - // run time) uses as a local address 0::0, so the main tun - pktType = MessagePacketType_Interest; - Address *packetAddr = _createAddressFromPacket(msgBuffer); - AddressPair *pair_find = addressPair_Create(packetAddr, /* dummy */ hicn->localAddress); - const Connection *conn = _lookupConnection(listener, pair_find); - addressPair_Release(&pair_find); - if (conn == NULL) { - AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr); - connid = _createNewConnection(listener, fd, pair); - addressPair_Release(&pair); - } else { - connid = connection_GetConnectionId(conn); - } - addressDestroy(&packetAddr); - } else { - printf("Got a packet that is not a data nor an interest, drop it!\n"); - parcMemory_Deallocate((void **)&msgBuffer); - return message; - } - - message = message_CreateFromByteArray(connid, msgBuffer, pktType, - forwarder_GetTicks(hicn->forwarder), - forwarder_GetLogger(hicn->forwarder)); - if (message == NULL) { - parcMemory_Deallocate((void **)&msgBuffer); - } - } else if (messageHandler_IsWldrNotification(msgBuffer)) { - _handleWldrNotification(listener, msgBuffer); - } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) { - _handleProbeMessage(listener, msgBuffer); - } else { - messageHandler_handleHooks(hicn->forwarder, msgBuffer, listener, fd, NULL); - parcMemory_Deallocate((void **)&msgBuffer); - } - - return message; -} - -static void _receivePacket(ListenerOps * listener, int fd) { - HicnListener * hicn = (HicnListener*)listener->context; - Message *msg = NULL; - uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE); - msg = _readMessage(listener, fd, msgBuffer); - - if (msg) { - forwarder_Receive(hicn->forwarder, msg); - } -} - -static void _hicnListener_readcb(int fd, PARCEventType what, void *listener_void) { - ListenerOps * listener = (ListenerOps *)listener_void; - HicnListener *hicn = (HicnListener *)listener->context; - - if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) { - if (what & PARCEventType_Read) { - _receivePacket(listener, fd); - } - } else { - _readFrameToDiscard(hicn, fd); - } -} diff --git a/hicn-light/src/hicn/io/ioOperations.c b/hicn-light/src/hicn/io/ioOperations.c index 31e37a461..b2d346ed8 100644 --- a/hicn-light/src/hicn/io/ioOperations.c +++ b/hicn-light/src/hicn/io/ioOperations.c @@ -41,6 +41,8 @@ const AddressPair *ioOperations_GetAddressPair(const IoOperations *ops) { return ops->getAddressPair(ops); } + + bool ioOperations_IsUp(const IoOperations *ops) { return ops->isUp(ops); } bool ioOperations_IsLocal(const IoOperations *ops) { return ops->isLocal(ops); } diff --git a/hicn-light/src/hicn/io/listenerSet.c b/hicn-light/src/hicn/io/listenerSet.c index 3e44973d7..45dbe887a 100644 --- a/hicn-light/src/hicn/io/listenerSet.c +++ b/hicn-light/src/hicn/io/listenerSet.c @@ -166,3 +166,17 @@ int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listene return index; } + +void listenerSet_RemoveById(const ListenerSet *set, unsigned id) { + parcAssertNotNull(set, "Parameter set must be non-null"); + + for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners); + i++) { + ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i); + parcAssertNotNull(ops, "Got null listener ops at index %zu", i); + if (ops->getInterfaceIndex(ops) == id) { + parcArrayList_RemoveAtIndex(set->listOfListeners, i); + break; + } + } +} diff --git a/hicn-light/src/hicn/io/listenerSet.h b/hicn-light/src/hicn/io/listenerSet.h index c8937fa02..5779d2af4 100644 --- a/hicn-light/src/hicn/io/listenerSet.h +++ b/hicn-light/src/hicn/io/listenerSet.h @@ -135,7 +135,6 @@ ListenerOps *listenerSet_Get(const ListenerSet *set, size_t index); ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType, const Address *localAddress); - /** * Looks up a listener by its id * @@ -153,6 +152,7 @@ ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType, * @endcode */ ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id); + /** * Looks up a listener by its id * @@ -171,4 +171,18 @@ ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id); */ int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listenerName); +/** + * Remove up a listener by its id + * + * <#Paragraphs Of Explanation#> + * + * @param [in] set An allocated listener set + * @param [in] id of the listener + * + * Example: + * @code + * + * @endcode + */ +void listenerSet_RemoveById(const ListenerSet *set, unsigned id); #endif diff --git a/hicn-light/src/hicn/io/streamConnection.c b/hicn-light/src/hicn/io/streamConnection.c index 224f129f7..08ff728d6 100644 --- a/hicn-light/src/hicn/io/streamConnection.c +++ b/hicn-light/src/hicn/io/streamConnection.c @@ -589,6 +589,7 @@ static void _conn_readcb(PARCEventQueue *event, PARCEventType type, // kind of packets while (parcEventBuffer_GetLength(input) >= sizeof(header_control_message) && parcEventBuffer_GetLength(input) >= stream->nextMessageLength) { + if ((command = _isACommand(input)) != LAST_COMMAND_VALUE) { struct iovec *rx; // Get message from the stream and set the stream->nextMessageLength diff --git a/hicn-light/src/hicn/io/tcpListener.c b/hicn-light/src/hicn/io/tcpListener.c index 4464edf28..e2b80c215 100644 --- a/hicn-light/src/hicn/io/tcpListener.c +++ b/hicn-light/src/hicn/io/tcpListener.c @@ -31,7 +31,6 @@ typedef struct tcp_listener { char *listenerName; - Forwarder *forwarder; Logger *logger; @@ -49,10 +48,15 @@ typedef struct tcp_listener { static void _tcpListener_Destroy(_TcpListener **listenerPtr); static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr); + static const char *_tcpListener_ListenerName(const ListenerOps *ops); + static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops); + static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops); + static const char *_tcpListener_InterfaceName(const ListenerOps *ops); + static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops); static ListenerOps _tcpTemplate = { @@ -71,6 +75,7 @@ static void _tcpListener_Listen(int, struct sockaddr *, int socklen, ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, char *listenerName, struct sockaddr_in6 sin6, char *interfaceName) { + _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(_TcpListener)); @@ -123,7 +128,10 @@ ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, char *listenerName, sizeof(_TcpListener)); tcp->forwarder = forwarder; + tcp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName)); tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + tcp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName)); + tcp->listener = dispatcher_CreateListener( forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1, (struct sockaddr *)&sin, sizeof(sin)); @@ -175,7 +183,6 @@ static void _tcpListener_Destroy(_TcpListener **listenerPtr) { parcMemory_Deallocate((void **)&tcp->listenerName); parcMemory_Deallocate((void **)&tcp->interfaceName); - logger_Release(&tcp->logger); dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder), &tcp->listener); diff --git a/hicn-light/src/hicn/io/udpListener.c b/hicn-light/src/hicn/io/udpListener.c index 050ca104c..f43756a11 100644 --- a/hicn-light/src/hicn/io/udpListener.c +++ b/hicn-light/src/hicn/io/udpListener.c @@ -40,8 +40,8 @@ #define IPv6 6 struct udp_listener { - Forwarder *forwarder; char *listenerName; + Forwarder *forwarder; Logger *logger; PARCEvent *udp_event; @@ -76,6 +76,7 @@ static ListenerOps udpTemplate = { .getInterfaceName = &_getInterfaceName, }; + static void _readcb(int fd, PARCEventType what, void * listener_void); #ifdef __ANDROID__ diff --git a/hicn-light/src/hicn/processor/fib.c b/hicn-light/src/hicn/processor/fib.c index 6489e59e2..6bb29c404 100644 --- a/hicn-light/src/hicn/processor/fib.c +++ b/hicn-light/src/hicn/processor/fib.c @@ -452,6 +452,8 @@ void fib_RemoveConnectionId(FIB *fib, unsigned connectionId) { for (int i = 0; i < fibEntryList_Length(list); i++) { _removeNode(fib, fibEntry_GetPrefix(fibEntryList_Get(list, i))); } + + fibEntryList_Destroy(&list); } size_t fib_Length(const FIB *fib) { diff --git a/hicn-light/src/hicn/processor/fibEntry.c b/hicn-light/src/hicn/processor/fibEntry.c index 04e453ab9..f12dd506b 100644 --- a/hicn-light/src/hicn/processor/fibEntry.c +++ b/hicn-light/src/hicn/processor/fibEntry.c @@ -201,6 +201,7 @@ NumberSet * fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) { ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder); NumberSet * nexthops; + bool dealloc_nexthops = false; policy_t policy = fibEntry_GetPolicy(fibEntry); /* Reset available next hops and start filtering */ @@ -214,6 +215,7 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) if (in_connection == ~0) { /* We might advertise among all available up connections */ nexthops = numberSet_Create(); + dealloc_nexthops = true; ConnectionList * list = connectionTable_GetEntries(table); for (size_t i = 0; i < connectionList_Length(list); i++) { @@ -226,7 +228,7 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) continue; numberSet_Add(nexthops, connection_GetConnectionId(conn)); } - + connectionList_Destroy(&list); } else { nexthops = (NumberSet*)fibEntry_GetNexthops(fibEntry); for (size_t k = 0; k < numberSet_Length(nexthops); k++) { @@ -247,8 +249,12 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) numberSet_Add(available_nexthops, conn_id); } - if (numberSet_Length(available_nexthops) > 0) + if (numberSet_Length(available_nexthops) > 0){ + if(dealloc_nexthops){ + numberSet_Release(&nexthops); + } return available_nexthops; + } } for (size_t k = 0; k < numberSet_Length(nexthops); k++) { @@ -297,6 +303,9 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) numberSet_Add(available_nexthops, conn_id); } + if(dealloc_nexthops) + numberSet_Release(&nexthops); + if (numberSet_Length(available_nexthops) == 0) return available_nexthops; diff --git a/hicn-light/src/hicn/processor/messageProcessor.c b/hicn-light/src/hicn/processor/messageProcessor.c index 456618269..3ca9264b8 100644 --- a/hicn-light/src/hicn/processor/messageProcessor.c +++ b/hicn-light/src/hicn/processor/messageProcessor.c @@ -298,7 +298,7 @@ bool messageProcessor_AddOrUpdateRoute(MessageProcessor *processor, unsigned ifidx) { Configuration *config = forwarder_GetConfiguration(processor->forwarder); - const char *prefixStr = utils_PrefixLenToString( + char *prefixStr = (char *) utils_PrefixLenToString( control->addressType, &control->address, &control->len); strategy_type fwdStrategy = configuration_GetForwardingStrategy(config, prefixStr); @@ -323,6 +323,7 @@ bool messageProcessor_AddOrUpdateRoute(MessageProcessor *processor, fib_Add(processor->fib, entry); } + free(prefixStr); name_Release(&prefix); /* For policy implementation, we need access to the ConnectionTable in all diff --git a/hicn-light/src/hicn/strategies/loadBalancer.c b/hicn-light/src/hicn/strategies/loadBalancer.c index b66de217e..ca9d34289 100644 --- a/hicn-light/src/hicn/strategies/loadBalancer.c +++ b/hicn-light/src/hicn/strategies/loadBalancer.c @@ -201,6 +201,7 @@ static NumberSet *_strategyLoadBalancer_LookupNexthop( PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i)); const StrategyNexthopState *elem = parcHashMap_Get(lb->strategy_state, cid); + parcUnsigned_Release(&cid); if (!elem) continue; sum += strategyNexthopState_GetWeight(elem); @@ -213,12 +214,15 @@ static NumberSet *_strategyLoadBalancer_LookupNexthop( PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i)); const StrategyNexthopState *state = parcHashMap_Get(lb->strategy_state, cid); - if (!state) - continue; + if (!state){ + parcUnsigned_Release(&cid); + continue; + } distance -= strategyNexthopState_GetWeight(state); if (distance < 0) { numberSet_Add(outList, parcUnsigned_GetUnsigned(cid)); _update_Stats(lb, (StrategyNexthopState *)state, true); + parcUnsigned_Release(&cid); break; } } @@ -296,19 +300,20 @@ static void _strategyLoadBalancer_resetState(StrategyImpl *strategy) { static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy, unsigned connectionId) { - StrategyNexthopState *state = strategyNexthopState_Create(); PARCUnsigned *cid = parcUnsigned_Create(connectionId); StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; if (!parcHashMap_Contains(lb->strategy_state, cid)) { + StrategyNexthopState *state = strategyNexthopState_Create(); parcHashMap_Put(lb->strategy_state, cid, state); #ifndef WITH_POLICY numberSet_Add(lb->nexthops, connectionId); #endif /* WITH_POLICY */ _strategyLoadBalancer_resetState(strategy); } + parcUnsigned_Release(&cid); } static void _strategyLoadBalancer_RemoveNexthop(StrategyImpl *strategy, diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h index 834da6259..a48dacf48 100644 --- a/hicn-light/src/hicn/utils/commands.h +++ b/hicn-light/src/hicn/utils/commands.h @@ -58,6 +58,7 @@ typedef enum { ADD_ROUTE, LIST_ROUTES, REMOVE_CONNECTION, + REMOVE_LISTENER, REMOVE_ROUTE, CACHE_STORE, CACHE_SERVE, @@ -124,7 +125,7 @@ typedef struct { uint8_t connectionType; } add_listener_command; -// SIZE=40 +// SIZE=56 //========== [01] ADD CONNECTION ========== @@ -167,11 +168,11 @@ typedef struct { uint32_t connid; uint8_t state; uint8_t admin_state; - char connectionName[16]; char interfaceName[16]; + char connectionName[16]; } list_connections_command; -// SIZE=64 +// SIZE=80 //========== [03] ADD ROUTE ========== @@ -198,14 +199,18 @@ typedef struct { // SIZE=24 //========== [05] REMOVE CONNECTION ========== - typedef struct { char symbolicOrConnid[16]; } remove_connection_command; +//========== [06] REMOVE LISTENER ========== +typedef struct { + char symbolicOrListenerid[16]; +} remove_listener_command; + // SIZE=16 -//========== [06] REMOVE ROUTE ========== +//========== [07] REMOVE ROUTE ========== typedef struct { char symbolicOrConnid[16]; @@ -216,7 +221,7 @@ typedef struct { // SIZE=36 -//========== [07] CACHE STORE ========== +//========== [08] CACHE STORE ========== typedef struct { uint8_t activate; @@ -224,7 +229,7 @@ typedef struct { // SIZE=1 -//========== [08] CACHE SERVE ========== +//========== [09] CACHE SERVE ========== typedef struct { uint8_t activate; @@ -232,7 +237,7 @@ typedef struct { // SIZE=1 -//========== [09] SET STRATEGY ========== +//========== [10] SET STRATEGY ========== typedef enum { SET_STRATEGY_LOADBALANCER, @@ -285,7 +290,7 @@ typedef struct { uint8_t encapType; } list_listeners_command; -// SIZE=24 +// SIZE=56 //========== [14] MAPME ========== @@ -353,9 +358,11 @@ static inline int payloadLengthDaemon(command_id id) { case ADD_ROUTE: return sizeof(add_route_command); case LIST_ROUTES: - return 0; // list routes: payload always 0 + return 0; // list rout`es: payload always 0 case REMOVE_CONNECTION: return sizeof(remove_connection_command); + case REMOVE_LISTENER: + return sizeof(remove_listener_command); case REMOVE_ROUTE: return sizeof(remove_route_command); case CACHE_STORE: diff --git a/hicn-light/src/hicn/utils/utils.c b/hicn-light/src/hicn/utils/utils.c index 61ff9a904..93a3efd81 100644 --- a/hicn-light/src/hicn/utils/utils.c +++ b/hicn-light/src/hicn/utils/utils.c @@ -90,7 +90,6 @@ struct iovec *utils_CreateNack(header_control_message *header, void *payload, parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); header->messageType = NACK_LIGHT; - response[0].iov_base = header; response[0].iov_len = sizeof(header_control_message); response[1].iov_base = payload; diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt index 97279e540..8425a5cf3 100644 --- a/hicn-plugin/CMakeLists.txt +++ b/hicn-plugin/CMakeLists.txt @@ -307,6 +307,10 @@ install(FILES ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn COMPONENT ${HICN_PLUGIN}-dev) +install(FILES ${HICN_API_GENERATED_FILES} + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn + COMPONENT ${HICN_PLUGIN_DEV}) + install(FILES ${HICN_VAPI_GENERATED_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vapi COMPONENT ${HICN_PLUGIN}-dev) diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c index 53308a49d..ca3baaa0d 100644 --- a/hicn-plugin/src/data_fwd_node.c +++ b/hicn-plugin/src/data_fwd_node.c @@ -176,6 +176,7 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, dpo_vft0, &hicn_dpo_id0); +#if HICN_FEATURE_CS if (hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP) { push_in_cache (vm, bi0, &n_left_to_next, &next0, &to_next, @@ -186,6 +187,10 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, &next_index, node); } +#else + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); +#endif stats.pit_expired_count++; if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c index aeb8c2276..fdf855e57 100644 --- a/hicn-plugin/src/data_pcslookup_node.c +++ b/hicn-plugin/src/data_pcslookup_node.c @@ -102,27 +102,17 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, b0 = vlib_get_buffer (vm, bi0); hb0 = hicn_get_buffer (b0); + next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP; /* Incr packet counter */ stats.pkts_processed += 1; ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - - if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE)) - { - next0 = - isv6 ? HICN_DATA_PCSLOOKUP_NEXT_V6_LOOKUP : - HICN_DATA_PCSLOOKUP_NEXT_V4_LOOKUP; - } nameptr = (u8 *) (&name); - if (PREDICT_FALSE - (ret0 != HICN_ERROR_NONE - || hicn_hashtb_fullhash (nameptr, namelen, - &name_hash) != HICN_ERROR_NONE)) - { - next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP; - } - else + + if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE && + hicn_hashtb_fullhash (nameptr, namelen, + &name_hash) == HICN_ERROR_NONE)) { int res = hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr, @@ -137,9 +127,10 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, stats.pkts_data_count += 1; +#if HICN_FEATURE_CS if ((res == HICN_ERROR_HASHTB_HASH_NOT_FOUND || (res == HICN_ERROR_NONE && is_cs0)) - && (hb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP)) + && ((hb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP))) { next0 = HICN_DATA_PCSLOOKUP_NEXT_STORE_DATA; } @@ -153,6 +144,18 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0; } } +#else + if (res == HICN_ERROR_NONE) + { + /* + * In case the result of the lookup + * is a CS entry, the packet is + * dropped + */ + next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0; + } + } +#endif hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0, vft_id0, hash_entry_id, bucket_id, diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c index 7e6117b84..bbcc7fa6e 100644 --- a/hicn-plugin/src/faces/app/face_prod.c +++ b/hicn-plugin/src/faces/app/face_prod.c @@ -218,7 +218,7 @@ hicn_face_prod_add (hicn_prefix_t * prefix, u32 sw_if, u32 * cs_reserved, remote_app_ip = to_ip46 ( /* isv6 */ 0, remote_app_ip4.as_u8); ret = - hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid); + hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid, HICN_FACE_FLAGS_APPFACE_PROD); } else { @@ -238,7 +238,7 @@ hicn_face_prod_add (hicn_prefix_t * prefix, u32 sw_if, u32 * cs_reserved, remote_app_ip = to_ip46 ( /* isv6 */ 1, remote_app_ip6.as_u8); ret = - hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid); + hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid, HICN_FACE_FLAGS_APPFACE_PROD); } face = hicn_dpoi_get_from_idx (*faceid); diff --git a/hicn-plugin/src/faces/ip/dpo_ip.c b/hicn-plugin/src/faces/ip/dpo_ip.c index de71f1b01..d05fec1a0 100644 --- a/hicn-plugin/src/faces/ip/dpo_ip.c +++ b/hicn-plugin/src/faces/ip/dpo_ip.c @@ -19,6 +19,8 @@ mhash_t hicn_face_ip_local_hashtb; mhash_t hicn_face_ip_remote_hashtb; dpo_type_t hicn_face_ip_type; +hicn_face_ip_vec_t * hicn_vec_pool; + const static char *const hicn_face_ip4dpoi_nodes[] = { "hicn-face-ip4-input", "hicn-face-ip4-output", @@ -51,12 +53,14 @@ void hicn_dpo_ip_module_init (void) { mhash_init (&hicn_face_ip_local_hashtb, - sizeof (hicn_face_id_t) /* value */ , + sizeof (hicn_face_ip_input_faces_t) /* value */ , sizeof (hicn_face_ip_key_t) /* key */ ); mhash_init (&hicn_face_ip_remote_hashtb, sizeof (hicn_face_id_t) /* value */ , sizeof (hicn_face_ip_key_t) /* key */ ); + pool_alloc(hicn_vec_pool, 100); + /* * How much useful is the following registration? * So far it seems that we need it only for setting the dpo_type. @@ -65,106 +69,6 @@ hicn_dpo_ip_module_init (void) dpo_register_new_type (&hicn_face_ip_vft, hicn_ip_nodes); } - -int -hicn_dpo_ip4_create (dpo_id_t * dpo, - const ip4_address_t * local_addr, - const ip4_address_t * remote_addr, - u32 sw_if, - adj_index_t adj, - u32 node_index, - hicn_face_flags_t flags, hicn_face_id_t * face_id) -{ - /* If local matches the dpoi is a face */ - hicn_face_t *face = - hicn_face_ip4_get (local_addr, sw_if, &hicn_face_ip_local_hashtb); - u8 hicnb_flags; - - if (face != NULL) - return HICN_ERROR_FACE_ALREADY_CREATED; - - face = hicn_face_ip4_get (remote_addr, sw_if, &hicn_face_ip_remote_hashtb); - - if (face == NULL) - { - hicn_dpo_ip4_add_and_lock_from_remote (dpo, &hicnb_flags, local_addr, - remote_addr, sw_if, node_index); - *face_id = (hicn_face_id_t) dpo->dpoi_index; - face = hicn_dpoi_get_from_idx (*face_id); - } - else - { - *face_id = hicn_dpoi_get_index (face); - dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, *face_id); - dpo->dpoi_next_node = node_index; - } - - - hicn_face_ip_key_t key; - hicn_face_ip4_get_key (local_addr, sw_if, &key); - - mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) face_id, 0); - - hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - ip46_address_set_ip4 (&ip_face->local_addr, local_addr); - ip46_address_set_ip4 (&ip_face->remote_addr, remote_addr); - face->shared.flags = flags; - face->shared.adj = adj; - - return HICN_ERROR_NONE; -} - -int -hicn_dpo_ip6_create (dpo_id_t * dpo, - const ip6_address_t * local_addr, - const ip6_address_t * remote_addr, - u32 sw_if, - adj_index_t adj, - u32 node_index, - hicn_face_flags_t flags, hicn_face_id_t * face_id) -{ - /* If local matches the dpoi is a face */ - hicn_face_t *face = - hicn_face_ip6_get (local_addr, sw_if, &hicn_face_ip_local_hashtb); - - u8 hicnb_flags; - - if (face != NULL) - return HICN_ERROR_FACE_ALREADY_CREATED; - - face = hicn_face_ip6_get (remote_addr, sw_if, &hicn_face_ip_remote_hashtb); - - /* If remote matches the dpoi is a iface */ - if (face == NULL) - { - hicn_dpo_ip6_add_and_lock_from_remote (dpo, &hicnb_flags, local_addr, - remote_addr, sw_if, node_index); - *face_id = (hicn_face_id_t) dpo->dpoi_index; - face = hicn_dpoi_get_from_idx (*face_id); - } - else - { - *face_id = hicn_dpoi_get_index (face); - dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP6, *face_id); - dpo->dpoi_next_node = node_index; - } - - hicn_face_ip_key_t key; - hicn_face_ip6_get_key (local_addr, sw_if, &key); - - mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) face_id, 0); - - hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip6_address_t)); - clib_memcpy (&ip_face->remote_addr, remote_addr, sizeof (ip6_address_t)); - face->shared.sw_if = sw_if; - face->shared.flags = flags; - face->shared.adj = adj; - - - return HICN_ERROR_NONE; -} - void hicn_dpo_ip_create_from_face (hicn_face_t * face, dpo_id_t * dpo, u16 dpoi_next_node) diff --git a/hicn-plugin/src/faces/ip/dpo_ip.h b/hicn-plugin/src/faces/ip/dpo_ip.h index 164931a06..d6b4f5f7e 100644 --- a/hicn-plugin/src/faces/ip/dpo_ip.h +++ b/hicn-plugin/src/faces/ip/dpo_ip.h @@ -29,10 +29,9 @@ void hicn_dpo_ip_module_init (void); /** - * @brief Retrieve a face from the ip4 local address and returns its dpo. This - * method adds a lock on the face state. + * @brief Retrieve a vector of faces from the ip4 local address and returns its index. * - * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL + * @param vec: Result of the lookup. If no face exists for the local address vec = NULL * @param hicnb_flags: Flags that indicate whether the face is an application * face or not * @param local_addr: Ip v4 local address of the face @@ -42,22 +41,25 @@ void hicn_dpo_ip_module_init (void); */ always_inline int hicn_dpo_ip4_lock_from_local (dpo_id_t * dpo, + u32 * in_faces_vec_id, u8 * hicnb_flags, const ip4_address_t * local_addr, u32 sw_if) { - hicn_face_t *face = - hicn_face_ip4_get (local_addr, sw_if, &hicn_face_ip_local_hashtb); + hicn_face_ip_input_faces_t * in_faces_vec = + hicn_face_ip4_get_vec (local_addr, sw_if, &hicn_face_ip_local_hashtb); - if (PREDICT_FALSE (face == NULL)) + if (PREDICT_FALSE (in_faces_vec == NULL)) return HICN_ERROR_FACE_NOT_FOUND; + *in_faces_vec_id = in_faces_vec->vec_id; + hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; *hicnb_flags |= (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >> HICN_FACE_FLAGS_APPFACE_PROD_BIT; - hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face); - dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, dpoi_index); + dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, in_faces_vec->face_id); dpo->dpoi_next_node = ~0; dpo_lock (dpo); @@ -78,22 +80,25 @@ hicn_dpo_ip4_lock_from_local (dpo_id_t * dpo, */ always_inline int hicn_dpo_ip6_lock_from_local (dpo_id_t * dpo, + u32 * in_faces_vec_id, u8 * hicnb_flags, const ip6_address_t * local_addr, u32 sw_if) { - hicn_face_t *face = - hicn_face_ip6_get (local_addr, sw_if, &hicn_face_ip_local_hashtb); + hicn_face_ip_input_faces_t * in_faces_vec = + hicn_face_ip6_get_vec (local_addr, sw_if, &hicn_face_ip_local_hashtb); - if (PREDICT_FALSE (face == NULL)) + if (PREDICT_FALSE (in_faces_vec == NULL)) return HICN_ERROR_FACE_NOT_FOUND; + *in_faces_vec_id = in_faces_vec->vec_id; + hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; *hicnb_flags |= (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >> HICN_FACE_FLAGS_APPFACE_PROD_BIT; - hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face); - dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP6, dpoi_index); + dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP6, in_faces_vec->face_id); dpo->dpoi_next_node = ~0; dpo_lock (dpo); @@ -210,49 +215,49 @@ hicn_dpo_ip6_add_and_lock_from_remote (dpo_id_t * dpo, } -/** - * @brief Create an ip face and its corresponding dpo. Meant to be used for the - * control plane. - * - * @param dpo: Data plane object that point to the face created. - * @param local_addr: Ip v4 local address of the face - * @param remote_addr: Ip v4 remote address of the face - * @param sw_if: software interface id of the face - * @param adj: Ip adjacency corresponding to the remote address in the face - * @param node_index: vlib edge index to use in the packet processing - * @param flags: Flags of the face - * @param face_id: Identifier for the face (dpoi_index) - * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE - */ -int hicn_dpo_ip4_create (dpo_id_t * dpo, - const ip4_address_t * local_addr, - const ip4_address_t * remote_addr, - u32 sw_if, - adj_index_t adj, - u32 node_index, - hicn_face_flags_t flags, hicn_face_id_t * face_id); - -/** - * @brief Create an ip face and its corresponding dpo. Meant to be used for the - * control plane. - * - * @param dpo: Data plane object that point to the face created. - * @param local_addr: Ip v6 local address of the face - * @param remote_addr: Ip v6 remote address of the face - * @param sw_if: software interface id of the face - * @param adj: Ip adjacency corresponding to the remote address in the face - * @param node_index: vlib edge index to use in the packet processing - * @param flags: Flags of the face - * @param face_id: Identifier for the face (dpoi_index) - * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE - */ -int hicn_dpo_ip6_create (dpo_id_t * dpo, - const ip6_address_t * local_addr, - const ip6_address_t * remote_addr, - u32 sw_if, - adj_index_t adj, - u32 node_index, - hicn_face_flags_t flags, hicn_face_id_t * face_id); +/* /\** */ +/* * @brief Create an ip face and its corresponding dpo. Meant to be used for the */ +/* * control plane. */ +/* * */ +/* * @param dpo: Data plane object that point to the face created. */ +/* * @param local_addr: Ip v4 local address of the face */ +/* * @param remote_addr: Ip v4 remote address of the face */ +/* * @param sw_if: software interface id of the face */ +/* * @param adj: Ip adjacency corresponding to the remote address in the face */ +/* * @param node_index: vlib edge index to use in the packet processing */ +/* * @param flags: Flags of the face */ +/* * @param face_id: Identifier for the face (dpoi_index) */ +/* * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE */ +/* *\/ */ +/* int hicn_dpo_ip4_create (dpo_id_t * dpo, */ +/* const ip4_address_t * local_addr, */ +/* const ip4_address_t * remote_addr, */ +/* u32 sw_if, */ +/* adj_index_t adj, */ +/* u32 node_index, */ +/* hicn_face_flags_t flags, hicn_face_id_t * face_id); */ + +/* /\** */ +/* * @brief Create an ip face and its corresponding dpo. Meant to be used for the */ +/* * control plane. */ +/* * */ +/* * @param dpo: Data plane object that point to the face created. */ +/* * @param local_addr: Ip v6 local address of the face */ +/* * @param remote_addr: Ip v6 remote address of the face */ +/* * @param sw_if: software interface id of the face */ +/* * @param adj: Ip adjacency corresponding to the remote address in the face */ +/* * @param node_index: vlib edge index to use in the packet processing */ +/* * @param flags: Flags of the face */ +/* * @param face_id: Identifier for the face (dpoi_index) */ +/* * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE */ +/* *\/ */ +/* int hicn_dpo_ip6_create (dpo_id_t * dpo, */ +/* const ip6_address_t * local_addr, */ +/* const ip6_address_t * remote_addr, */ +/* u32 sw_if, */ +/* adj_index_t adj, */ +/* u32 node_index, */ +/* hicn_face_flags_t flags, hicn_face_id_t * face_id); */ /** * @brief Create a dpo from an ip face diff --git a/hicn-plugin/src/faces/ip/face_ip.c b/hicn-plugin/src/faces/ip/face_ip.c index 6e279583c..23d3900ec 100644 --- a/hicn-plugin/src/faces/ip/face_ip.c +++ b/hicn-plugin/src/faces/ip/face_ip.c @@ -12,6 +12,8 @@ * License for the specific language governing permissions and limitations * under the License. */ +#include <vnet/adj/adj_midchain.h> +#include <vnet/adj/adj.h> #include "face_ip.h" #include "face_ip_node.h" @@ -96,62 +98,165 @@ hicn_face_ip_del (hicn_face_id_t face_id) hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data; hicn_face_ip_key_t key; hicn_face_ip_key_t old_key; + hicn_face_ip_key_t old_key2; if (ip46_address_is_ip4 (&face_ip->local_addr)) { hicn_face_ip4_get_key (&(face_ip->local_addr.ip4), face->shared.sw_if, &key); - mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key); - hicn_face_ip4_get_key (&(face_ip->remote_addr.ip4), face->shared.sw_if, - &key); - mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key); + hicn_face_ip_input_faces_t * in_faces_vec = hicn_face_ip4_get_vec(&(face_ip->local_addr.ip4), face->shared.sw_if, + &hicn_face_ip_local_hashtb); + if (in_faces_vec != NULL) + { + hicn_face_ip_vec_t * vec = pool_elt_at_index (hicn_vec_pool, in_faces_vec->vec_id); + u32 index_face = vec_search(*vec, face_id); + vec_del1(*vec, index_face); + + if (vec_len(*vec) == 0) + { + pool_put_index(hicn_vec_pool, in_faces_vec->vec_id); + mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key); + vec_free(*vec); + } + else + { + /* Check if the face we are deleting is the preferred one. */ + /* If so, repleace with another. */ + if (in_faces_vec->face_id == face_id) + { + in_faces_vec->face_id = (*vec)[0]; + } + } + hicn_face_ip4_get_key (&(face_ip->remote_addr.ip4), face->shared.sw_if, + &key); + mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key2); + } } else { hicn_face_ip6_get_key (&(face_ip->local_addr.ip6), face->shared.sw_if, &key); - mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key); - hicn_face_ip6_get_key (&(face_ip->remote_addr.ip6), face->shared.sw_if, - &key); - mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key); + + hicn_face_ip_input_faces_t * in_faces_vec = hicn_face_ip6_get_vec(&(face_ip->local_addr.ip6), face->shared.sw_if, + &hicn_face_ip_local_hashtb); + if (in_faces_vec != NULL) + { + hicn_face_ip_vec_t * vec = pool_elt_at_index (hicn_vec_pool, in_faces_vec->vec_id); + u32 index_face = vec_search(*vec, face_id); + vec_del1(*vec, index_face); + + if (vec_len(*vec) == 0) + { + pool_put(hicn_vec_pool, vec); + mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key); + vec_free(*vec); + } + else + { + /* Check if the face we are deleting is the preferred one. */ + /* If so, repleace with another. */ + if (in_faces_vec->face_id == face_id) + { + in_faces_vec->face_id = (*vec)[0]; + } + } + hicn_face_ip6_get_key (&(face_ip->remote_addr.ip6), face->shared.sw_if, + &key); + mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key); + } } return hicn_face_del (face_id); } +/** + * @brief Helper for handling midchain adjacencies + */ +void face_midchain_fixup_t (vlib_main_t * vm, + struct ip_adjacency_t_ * adj, + vlib_buffer_t * b0, + const void *data) { + vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; +}; -/* - * Utility that adds a new face cache entry. For the moment we assume that - * the ip_adjacency has already been set up. +/** + * @brief Build a rewrite string for the face. */ -int -hicn_face_ip_add (const ip46_address_t * local_addr, - const ip46_address_t * remote_addr, - int sw_if, hicn_face_id_t * pfaceid) +static u8* +face_build_rewrite_i (void) { - /* fib_protocol_t fib_type; */ - /* vnet_link_t link_type; */ - adj_index_t adj; - dpo_proto_t dpo_proto; + /* + * passing the adj code a NULL rewrite means 'i don't have one cos + * t'other end is unresolved'. That's not the case here. For the mpls + * tunnel there are just no bytes of encap to apply in the adj. We'll impose + * the label stack once we choose a path. So return a zero length rewrite. + */ + u8 *rewrite = NULL; - /* Check if we found at least one ip address */ - if (ip46_address_is_zero (local_addr) || ip46_address_is_zero (remote_addr)) - return HICN_ERROR_FACE_NO_GLOBAL_IP; + vec_validate(rewrite, 0); + vec_reset_length(rewrite); + return (rewrite); +} + +always_inline int +hicn_face_ip_find_adj (const ip46_address_t * remote_addr, + int sw_if, adj_index_t * adj) +{ fib_prefix_t fib_pfx; fib_node_index_t fib_entry_index; fib_prefix_from_ip46_addr (remote_addr, &fib_pfx); fib_pfx.fp_len = ip46_address_is_ip4(remote_addr)? 32 : 128; + vnet_link_t link_type = ip46_address_is_ip4(&fib_pfx.fp_addr)? VNET_LINK_IP4 : VNET_LINK_IP6; + *adj = adj_nbr_find(fib_pfx.fp_proto, link_type, &fib_pfx.fp_addr, sw_if); - u32 fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, - HICN_FIB_TABLE, - FIB_SOURCE_PLUGIN_HI); + if (*adj == ADJ_INDEX_INVALID) + { + u32 fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, + HICN_FIB_TABLE, + FIB_SOURCE_PLUGIN_HI); + + fib_entry_index = fib_table_lookup (fib_index, &fib_pfx); + + if (fib_entry_index == (FIB_NODE_INDEX_INVALID)) + return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND; + + *adj = fib_entry_get_adj (fib_entry_index); + ip_adjacency_t * temp = NULL; + if (*adj != ~0) + temp = adj_get(*adj); + + if (temp == NULL || temp->lookup_next_index <= IP_LOOKUP_NEXT_REWRITE) + { + if(sw_if != ~0) + *adj = adj_nbr_add_or_lock(fib_pfx.fp_proto, link_type, remote_addr, sw_if); + else + return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND; + } + else + { + adj_nbr_midchain_update_rewrite(*adj, &face_midchain_fixup_t, NULL, ADJ_FLAG_NONE, face_build_rewrite_i()); + adj_midchain_delegate_stack(*adj, fib_index, &fib_pfx); + } + } - fib_entry_index = fib_table_lookup (fib_index, &fib_pfx); + return HICN_ERROR_NONE; +} - adj = fib_entry_get_adj (fib_entry_index); +/* + * Utility that adds a new face cache entry. For the moment we assume that + * the ip_adjacency has already been set up. + */ +int +hicn_face_ip_add (const ip46_address_t * local_addr, + const ip46_address_t * remote_addr, + int sw_if, hicn_face_id_t * pfaceid, + u8 is_app_prod) +{ + dpo_proto_t dpo_proto; - if (adj == ~0) - return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND; + /* Check if we found at least one ip address */ + if (ip46_address_is_zero (remote_addr)) + return HICN_ERROR_FACE_NO_GLOBAL_IP; hicn_face_flags_t flags = (hicn_face_flags_t) 0; flags |= HICN_FACE_FLAGS_FACE; @@ -160,17 +265,10 @@ hicn_face_ip_add (const ip46_address_t * local_addr, if (ip46_address_is_ip4 (local_addr)) { face = - hicn_face_ip4_get (&(local_addr->ip4), sw_if, - &hicn_face_ip_local_hashtb); - - if (face != NULL) - return HICN_ERROR_FACE_ALREADY_CREATED; - - face = hicn_face_ip4_get (&(remote_addr->ip4), sw_if, &hicn_face_ip_remote_hashtb); - /* If remote matches the face is a iface */ + /* If remote matches the face we need to check if it is an incomplete face */ if (face == NULL) { hicn_iface_ip_add (local_addr, remote_addr, sw_if, pfaceid); @@ -181,31 +279,83 @@ hicn_face_ip_add (const ip46_address_t * local_addr, *pfaceid = hicn_dpoi_get_index (face); } + if (!(face->shared.flags & HICN_FACE_FLAGS_IFACE)) + return HICN_ERROR_FACE_ALREADY_CREATED; + hicn_face_ip_key_t key; hicn_face_ip4_get_key (&(local_addr->ip4), sw_if, &key); - mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) pfaceid, 0); - - hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip4_address_t)); - clib_memcpy (&ip_face->remote_addr, remote_addr, - sizeof (ip4_address_t)); - face->shared.sw_if = sw_if; - face->shared.flags = flags; - face->shared.adj = adj; - - dpo_proto = DPO_PROTO_IP4; + hicn_face_ip_input_faces_t * in_faces = + hicn_face_ip4_get_vec (&(local_addr->ip4), sw_if, + &hicn_face_ip_local_hashtb); + + if (in_faces == NULL) + { + adj_index_t adj; + int ret = hicn_face_ip_find_adj(remote_addr, sw_if, &adj); + if (ret != HICN_ERROR_NONE) + return ret; + + hicn_face_ip_input_faces_t in_faces_temp; + hicn_face_ip_vec_t *vec; + pool_get(hicn_vec_pool, vec); + *vec = vec_new(hicn_face_ip_vec_t, 0); + u32 index = vec - hicn_vec_pool; + in_faces_temp.vec_id = index; + vec_add1(*vec, *pfaceid); + + hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; + clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip4_address_t)); + clib_memcpy (&ip_face->remote_addr, remote_addr, + sizeof (ip4_address_t)); + face->shared.sw_if = sw_if; + face->shared.flags = flags; + face->shared.adj = adj; + + dpo_proto = DPO_PROTO_IP4; + + in_faces_temp.face_id = *pfaceid; + + mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) &in_faces_temp, 0); + } + else + { + hicn_face_ip_vec_t * vec = pool_elt_at_index(hicn_vec_pool, in_faces->vec_id); + + /* */ + if (vec_search(*vec, *pfaceid) != ~0) + return HICN_ERROR_FACE_ALREADY_CREATED; + + adj_index_t adj; + int ret = hicn_face_ip_find_adj(remote_addr, sw_if, &adj); + if (ret != HICN_ERROR_NONE) + return ret; + + vec_add1(*vec, *pfaceid); + + hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; + clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip4_address_t)); + clib_memcpy (&ip_face->remote_addr, remote_addr, + sizeof (ip4_address_t)); + face->shared.sw_if = sw_if; + face->shared.flags = flags; + face->shared.adj = adj; + + dpo_proto = DPO_PROTO_IP4; + + mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) in_faces, 0); + + /* If the face is an application producer face, we set it as the preferred incoming face. */ + /* This is required to handle the CS separation, and the push api in a lightway*/ + if (is_app_prod) + { + in_faces->face_id = *pfaceid; + } + } } else { face = - hicn_face_ip6_get (&(local_addr->ip6), sw_if, - &hicn_face_ip_local_hashtb); - - if (face != NULL) - return HICN_ERROR_FACE_ALREADY_CREATED; - - face = hicn_face_ip6_get (&(remote_addr->ip6), sw_if, &hicn_face_ip_remote_hashtb); @@ -220,20 +370,79 @@ hicn_face_ip_add (const ip46_address_t * local_addr, *pfaceid = hicn_dpoi_get_index (face); } + if (!(face->shared.flags & HICN_FACE_FLAGS_IFACE)) + return HICN_ERROR_FACE_ALREADY_CREATED; + hicn_face_ip_key_t key; hicn_face_ip6_get_key (&(local_addr->ip6), sw_if, &key); - mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) pfaceid, 0); - - hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip6_address_t)); - clib_memcpy (&ip_face->remote_addr, remote_addr, - sizeof (ip6_address_t)); - face->shared.sw_if = sw_if; - face->shared.flags = flags; - face->shared.adj = adj; - - dpo_proto = DPO_PROTO_IP6; + hicn_face_ip_input_faces_t * in_faces = + hicn_face_ip6_get_vec (&(local_addr->ip6), sw_if, + &hicn_face_ip_local_hashtb); + + if (in_faces == NULL) + { + adj_index_t adj; + int ret = hicn_face_ip_find_adj(remote_addr, sw_if, &adj); + if (ret != HICN_ERROR_NONE) + return ret; + + hicn_face_ip_input_faces_t in_faces_temp; + hicn_face_ip_vec_t *vec; + pool_get(hicn_vec_pool, vec); + vec_alloc(*vec, 1); + u32 index = vec - hicn_vec_pool; + in_faces_temp.vec_id = index; + vec_add1(*vec, *pfaceid); + + hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; + clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip6_address_t)); + clib_memcpy (&ip_face->remote_addr, remote_addr, + sizeof (ip6_address_t)); + face->shared.sw_if = sw_if; + face->shared.flags = flags; + face->shared.adj = adj; + + dpo_proto = DPO_PROTO_IP6; + + in_faces_temp.face_id = *pfaceid; + + mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) &in_faces_temp, 0); + } + else + { + hicn_face_ip_vec_t *vec = pool_elt_at_index(hicn_vec_pool, in_faces->vec_id); + + /* */ + if (vec_search(*vec, *pfaceid) != ~0) + return HICN_ERROR_FACE_ALREADY_CREATED; + + adj_index_t adj; + int ret = hicn_face_ip_find_adj(remote_addr, sw_if, &adj); + if (ret != HICN_ERROR_NONE) + return ret; + + vec_add1(*vec, *pfaceid); + + hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; + clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip6_address_t)); + clib_memcpy (&ip_face->remote_addr, remote_addr, + sizeof (ip6_address_t)); + face->shared.sw_if = sw_if; + face->shared.flags = flags; + face->shared.adj = adj; + + dpo_proto = DPO_PROTO_IP6; + + mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) in_faces, 0); + + /* If the face is an application producer face, we set it as the preferred incoming face. */ + /* This is required to handle the CS separation, and the push api in a lightway*/ + if (is_app_prod) + { + in_faces->face_id = *pfaceid; + } + } } retx_t *retx = vlib_process_signal_event_data (vlib_get_main (), diff --git a/hicn-plugin/src/faces/ip/face_ip.h b/hicn-plugin/src/faces/ip/face_ip.h index 852106b70..0491af506 100644 --- a/hicn-plugin/src/faces/ip/face_ip.h +++ b/hicn-plugin/src/faces/ip/face_ip.h @@ -43,6 +43,24 @@ typedef struct hicn_ip_face_t_ } hicn_face_ip_t; +/** + * @bried vector of faces used to collect faces having the same local address + * + */ +typedef hicn_face_id_t * hicn_face_ip_vec_t; + +typedef struct hicn_ip_input_faces_s_ +{ + /* Vector of all possible input faces */ + u32 vec_id; + + /* Preferred face. If an prod_app face is in the vector it will be the preferred one. */ + /* It's not possible to have multiple prod_app face in the same vector, they would have */ + /* the same local address. Every prod_app face is a point-to-point face between the forwarder */ + /* and the application. */ + hicn_face_id_t face_id; + +} hicn_face_ip_input_faces_t; /** * Hash tables that indexes a face by local address. For fast lookup when an @@ -57,6 +75,11 @@ extern mhash_t hicn_face_ip_local_hashtb; extern mhash_t hicn_face_ip_remote_hashtb; /** + * Pool containing the vector of possible incoming faces. + */ +extern hicn_face_ip_vec_t * hicn_vec_pool; + +/** * Key definition for the mhash table. An ip face is uniquely identified by ip * address and the interface id. The ip address can correspond to the remote ip * address of the next hicn hop, or to the local address of the receiving @@ -129,6 +152,42 @@ hicn_face_ip4_get (const ip4_address_t * addr, u32 sw_if, mhash_t * hashtb) } /** + * @brief Get the vector of faces from the ip v4 address. Does not add any lock. + * + * @param addr Ip v4 address used to create the key for the hash table. + * @param sw_if Software interface id used to create the key for the hash table. + * @param hashtb Hash table (remote or local) where to perform the lookup. + * + * @result Pointer to the face. + */ +always_inline hicn_face_ip_input_faces_t * +hicn_face_ip4_get_vec (const ip4_address_t * addr, u32 sw_if, mhash_t * hashtb) +{ + hicn_face_ip_key_t key; + + hicn_face_ip4_get_key (addr, sw_if, &key); + return (hicn_face_ip_input_faces_t *) mhash_get (hashtb,&key); +} + +/** + * @brief Get the vector of faces from the ip v6 address. Does not add any lock. + * + * @param addr Ip v6 address used to create the key for the hash table. + * @param sw_if Software interface id used to create the key for the hash table. + * @param hashtb Hash table (remote or local) where to perform the lookup. + * + * @result Pointer to the face. + */ +always_inline hicn_face_ip_input_faces_t * +hicn_face_ip6_get_vec (const ip6_address_t * addr, u32 sw_if, mhash_t * hashtb) +{ + hicn_face_ip_key_t key; + + hicn_face_ip6_get_key (addr, sw_if, &key); + return (hicn_face_ip_input_faces_t *) mhash_get (hashtb,&key); +} + +/** * @brief Get the dpoi from the ip v6 address. Does not add any lock. * * @param addr Ip v6 address used to create the key for the hash table. @@ -158,12 +217,13 @@ hicn_face_ip6_get (const ip6_address_t * addr, u32 sw_if, mhash_t * hashtb) * @param sw_if interface associated to the face * @param is_app_face Boolean to set the face as an application face * @param pfaceid Pointer to return the face id + * @param is_app_prod if HICN_FACE_FLAGS_APPFACE_PROD the face is a local application face, all other values are ignored * @return HICN_ERROR_FACE_NO_GLOBAL_IP if the face does not have a globally * reachable ip address, otherwise HICN_ERROR_NONE */ int hicn_face_ip_add (const ip46_address_t * local_addr, const ip46_address_t * remote_addr, - int swif, hicn_face_id_t * pfaceid); + int swif, hicn_face_id_t * pfaceid, u8 is_app_prod); /** * @brief Create a new incomplete face ip. (Meant to be used by the data plane) diff --git a/hicn-plugin/src/faces/ip/face_ip_cli.c b/hicn-plugin/src/faces/ip/face_ip_cli.c index 760768be1..4c4986f97 100644 --- a/hicn-plugin/src/faces/ip/face_ip_cli.c +++ b/hicn-plugin/src/faces/ip/face_ip_cli.c @@ -158,7 +158,7 @@ hicn_face_ip_cli_set_command_fn (vlib_main_t * vm, } } - rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &face_id); + rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &face_id, 0); if (rv == HICN_ERROR_NONE) { @@ -194,7 +194,7 @@ hicn_face_ip_cli_set_command_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (hicn_face_ip_cli_set_command, static) = { .path = "hicn face ip", - .short_help = "hicn face ip {add local <src_address> remote <dst_address> intfc <sw_if>} | {del id <face_id>}", + .short_help = "hicn face ip {add [local <src_address>] remote <dst_address> intfc <sw_if>} | {del id <face_id>}", .function = hicn_face_ip_cli_set_command_fn, }; /* *INDENT-ON* */ diff --git a/hicn-plugin/src/faces/ip/face_ip_node.c b/hicn-plugin/src/faces/ip/face_ip_node.c index 6592dc065..3f1f6a0d0 100644 --- a/hicn-plugin/src/faces/ip/face_ip_node.c +++ b/hicn-plugin/src/faces/ip/face_ip_node.c @@ -144,6 +144,7 @@ typedef enum \ ret = LOCK_FROM_LOCAL_IP##ipv \ (&(hicnb0->face_dpo_id), \ + &(hicnb0->in_faces_vec_id), \ &hicnb0->flags, \ &(ip_hdr->dst_address), \ vnet_buffer (b0)->sw_if_index[VLIB_RX]); \ @@ -232,12 +233,14 @@ typedef enum \ ret0 = LOCK_FROM_LOCAL_IP##ipv \ (&(hicnb0->face_dpo_id), \ + &(hicnb0->in_faces_vec_id), \ &hicnb0->flags, \ &(ip_hdr0->dst_address), \ vnet_buffer (b0)->sw_if_index[VLIB_RX]); \ \ ret1 = LOCK_FROM_LOCAL_IP##ipv \ (&(hicnb1->face_dpo_id), \ + &(hicnb1->in_faces_vec_id), \ &hicnb1->flags, \ &(ip_hdr1->dst_address), \ vnet_buffer (b1)->sw_if_index[VLIB_RX]); \ diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h index 87628ba53..1b57ce9e2 100644 --- a/hicn-plugin/src/hicn.h +++ b/hicn-plugin/src/hicn.h @@ -64,8 +64,9 @@ typedef struct u8 dpo_ctx_id; /* used for data path */ u8 vft_id; /* " */ - dpo_id_t face_dpo_id; /* ingress face ,sizeof(iface_dpo_id) - * <= sizeof(u64) */ + dpo_id_t face_dpo_id; /* ingress iface, sizeof(dpo_id_t) + * <= sizeof(u64) */ + u32 in_faces_vec_id; /* vector of possible input face for a data packet */ hicn_type_t type; } hicn_buffer_t; diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c index 9bca748e6..f8933206d 100644 --- a/hicn-plugin/src/hicn_api.c +++ b/hicn-plugin/src/hicn_api.c @@ -249,7 +249,7 @@ vl_api_hicn_api_face_ip_add_t_handler (vl_api_hicn_api_face_ip_add_t * mp) } if (rv == HICN_ERROR_NONE) - rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &faceid); + rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &faceid, 0); else faceid = HICN_FACE_NULL; diff --git a/hicn-plugin/src/mgmt.c b/hicn-plugin/src/mgmt.c index b992ba15c..cfeef6cb6 100644 --- a/hicn-plugin/src/mgmt.c +++ b/hicn-plugin/src/mgmt.c @@ -66,10 +66,6 @@ hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp) rmp->pkts_processed += clib_host_to_net_u64 (em->counters[node_cntr_base_idx + HICNFWD_ERROR_PROCESSED]); - n = - vlib_get_node (this_vlib_main, - hicn_data_pcslookup_node.index); - node_cntr_base_idx = n->error_heap_index; rmp->pkts_data_count += clib_host_to_net_u64 (em->counters[node_cntr_base_idx + HICNFWD_ERROR_DATAS]); diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h index 28f9c3c37..c7e8a4b59 100644 --- a/hicn-plugin/src/pcs.h +++ b/hicn-plugin/src/pcs.h @@ -685,9 +685,9 @@ hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) { hash_entry->locks--; - pitcs->pcs_pit_count--; if (hash_entry->locks == 0) { + pitcs->pcs_pit_count--; hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id); } diff --git a/lib/src/compat.c b/lib/src/compat.c index d76e17a6d..68f761ac0 100644 --- a/lib/src/compat.c +++ b/lib/src/compat.c @@ -344,7 +344,7 @@ hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h, return HICN_LIB_ERROR_NOT_IMPLEMENTED; } - memcpy (prefix->address.buffer, locator, ip_prefix_len(prefix)); + memcpy (prefix->address.buffer, locator, ip_address_len(&prefix->address, prefix->family)); return HICN_LIB_ERROR_NONE; } @@ -370,7 +370,7 @@ hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h, return HICN_LIB_ERROR_INVALID_PARAMETER; } - memcpy (locator, prefix->address.buffer, ip_prefix_len(prefix)); + memcpy (locator, prefix->address.buffer, ip_address_len(&prefix->address, prefix->family)); return HICN_LIB_ERROR_NONE; } diff --git a/lib/src/name.c b/lib/src/name.c index 1f1051522..a19971d49 100644 --- a/lib/src/name.c +++ b/lib/src/name.c @@ -95,7 +95,8 @@ hicn_name_create_from_prefix (const ip_prefix_t * prefix, u32 id, return HICN_LIB_ERROR_NOT_IMPLEMENTED; } - memcpy (name->buffer, prefix->address.buffer, ip_prefix_len (prefix)); + memcpy (name->buffer, prefix->address.buffer, + ip_address_len(&prefix->address, prefix->family)); *(u32 *) (name->buffer + name->len) = id; return HICN_LIB_ERROR_NONE; diff --git a/libtransport/src/hicn/transport/core/forwarder_interface.h b/libtransport/src/hicn/transport/core/forwarder_interface.h index 6bcdaafc1..a89ed8a3c 100644 --- a/libtransport/src/hicn/transport/core/forwarder_interface.h +++ b/libtransport/src/hicn/transport/core/forwarder_interface.h @@ -50,7 +50,9 @@ class ForwarderInterface { output_interface_(""), content_store_reserved_(standard_cs_reserved) { inet_address_.family = AF_INET; + inet_address_.len = IPV4_ADDR_LEN; inet6_address_.family = AF_INET6; + inet6_address_.len = IPV6_ADDR_LEN; } public: diff --git a/libtransport/src/hicn/transport/core/portal.h b/libtransport/src/hicn/transport/core/portal.h index 3ea37c938..17f35d819 100644 --- a/libtransport/src/hicn/transport/core/portal.h +++ b/libtransport/src/hicn/transport/core/portal.h @@ -417,8 +417,14 @@ class Portal { pending_interest->startCountdown(portal_details::makeCustomAllocatorHandler( async_callback_memory_, std::bind(&Portal<ForwarderInt>::timerHandler, this, std::placeholders::_1, hash))); - pending_interest_hash_table_.emplace( - std::make_pair(hash, std::move(pending_interest))); + + auto it = pending_interest_hash_table_.find(hash); + if(it != pending_interest_hash_table_.end()){ + it->second->cancelTimer(); + it->second = std::move(pending_interest); + }else{ + pending_interest_hash_table_[hash] = std::move(pending_interest); + } } /** diff --git a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc index 5667b0640..740f9f77c 100644 --- a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc +++ b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc @@ -32,8 +32,8 @@ #define HICN_MAX_DATA_SEQ 0xefffffff //slow production rate param -#define MIN_PRODUCTION_RATE 8000 // in bytes per sec. this value is computed - // through experiments +#define MIN_PRODUCTION_RATE 10 // in pacekts per sec. this value is computed + // through experiments #define LIFETIME_FRACTION 0.5 // NACK HEADER @@ -63,15 +63,14 @@ RTCProducerSocket::RTCProducerSocket(asio::io_service &io_service) bytesProductionRate_(INIT_PACKET_PRODUCTION_RATE * 1400), packetsProductionRate_(INIT_PACKET_PRODUCTION_RATE), perSecondFactor_(MILLI_IN_A_SEC / STATS_INTERVAL_DURATION), - timer_on_(false), - active_(false) { - lastStats_ = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); + timer_on_(false){ srand((unsigned int)time(NULL)); prodLabel_ = ((rand() % 255) << 24UL); interests_cache_timer_ = std::make_unique<asio::steady_timer>( this->getIoService()); + round_timer_ = std::make_unique<asio::steady_timer>( + this->getIoService()); + scheduleRoundTimer(); } RTCProducerSocket::RTCProducerSocket() @@ -82,15 +81,14 @@ RTCProducerSocket::RTCProducerSocket() bytesProductionRate_(INIT_PACKET_PRODUCTION_RATE * 1400), packetsProductionRate_(INIT_PACKET_PRODUCTION_RATE), perSecondFactor_(MILLI_IN_A_SEC / STATS_INTERVAL_DURATION), - timer_on_(false), - active_(false) { - lastStats_ = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); + timer_on_(false){ srand((unsigned int)time(NULL)); prodLabel_ = ((rand() % 255) << 24UL); interests_cache_timer_ = std::make_unique<asio::steady_timer>( this->getIoService()); + round_timer_ = std::make_unique<asio::steady_timer>( + this->getIoService()); + scheduleRoundTimer(); } RTCProducerSocket::~RTCProducerSocket() {} @@ -113,18 +111,22 @@ void RTCProducerSocket::registerPrefix(const Prefix &producer_namespace) { } } -void RTCProducerSocket::updateStats(uint32_t packet_size, uint64_t now) { - producedBytes_ += packet_size; - producedPackets_++; - uint64_t duration = now - lastStats_; - if (duration >= STATS_INTERVAL_DURATION) { - lastStats_ = now; - bytesProductionRate_ = producedBytes_ * perSecondFactor_; - packetsProductionRate_ = producedPackets_ * perSecondFactor_; - if (packetsProductionRate_.load() == 0) packetsProductionRate_ = 1; - producedBytes_ = 0; - producedPackets_ = 0; - } +void RTCProducerSocket::scheduleRoundTimer(){ + round_timer_->expires_from_now( + std::chrono::milliseconds(STATS_INTERVAL_DURATION)); + round_timer_->async_wait([this](std::error_code ec) { + if (ec) return; + updateStats(); + }); +} + +void RTCProducerSocket::updateStats() { + bytesProductionRate_ = producedBytes_.load() * perSecondFactor_; + packetsProductionRate_ = producedPackets_.load() * perSecondFactor_; + if (packetsProductionRate_.load() == 0) packetsProductionRate_ = 1; + producedBytes_ = 0; + producedPackets_ = 0; + scheduleRoundTimer(); } void RTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) { @@ -143,13 +145,8 @@ void RTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) { std::chrono::steady_clock::now().time_since_epoch()) .count(); - { - utils::SpinLock::Acquire locked(lock_); - active_ = true; - lastProduced_ = now; - } - - updateStats((uint32_t)(buffer_size + headerSize_ + TIMESTAMP_LEN), now); + producedBytes_ += (uint32_t)(buffer_size + headerSize_ + TIMESTAMP_LEN); + producedPackets_++; ContentObject content_object(flowName_.setSuffix(currentSeg_)); @@ -203,27 +200,14 @@ void RTCProducerSocket::onInterest(Interest::Ptr &&interest) { std::chrono::steady_clock::now().time_since_epoch()) .count(); - bool isActive; - { - utils::SpinLock::Acquire locked(lock_); - isActive = active_; - if (isActive) { - if ((now - lastProduced_) > INACTIVE_TIME) { - // socket is inactive - active_ = false; - isActive = false; - } - } - } - if(interestSeg > HICN_MAX_DATA_SEQ){ - sendNack(interestSeg, isActive); + sendNack(interestSeg); return; } // if the production rate is less than MIN_PRODUCTION_RATE we put the // interest in a queue, otherwise we handle it in the usual way - if(bytesProductionRate_ < MIN_PRODUCTION_RATE && interestSeg > currentSeg_){ + if(packetsProductionRate_.load() < MIN_PRODUCTION_RATE && interestSeg >= currentSeg_){ utils::SpinLock::Acquire locked(interests_cache_lock_); @@ -265,34 +249,29 @@ void RTCProducerSocket::onInterest(Interest::Ptr &&interest) { if(!timer_on_){ //set timeout timer_on_ = true; - scheduleTimer(timers_map_.begin()->first - now); + scheduleCacheTimer(timers_map_.begin()->first - now); } else { //re-schedule the timer because a new interest will expires sooner if(next_timer > timers_map_.begin()->first){ interests_cache_timer_->cancel(); - scheduleTimer(timers_map_.begin()->first - now); + scheduleCacheTimer(timers_map_.begin()->first - now); } } return; } - if (TRANSPORT_EXPECT_FALSE(!isActive)) { - sendNack(interestSeg, false); - return; - } - uint32_t max_gap = (uint32_t)floor( (double)((double)((double)lifetime * INTEREST_LIFETIME_REDUCTION_FACTOR / 1000.0) * (double)packetsProductionRate_.load())); if (interestSeg < currentSeg_ || interestSeg > (max_gap + currentSeg_)) { - sendNack(interestSeg, true); + sendNack(interestSeg); } // else drop packet } -void RTCProducerSocket::scheduleTimer(uint64_t wait){ +void RTCProducerSocket::scheduleCacheTimer(uint64_t wait){ interests_cache_timer_->expires_from_now( std::chrono::milliseconds(wait)); interests_cache_timer_->async_wait([this](std::error_code ec) { @@ -312,7 +291,7 @@ void RTCProducerSocket::interestCacheTimer(){ uint64_t expire = it_timers->first; if(expire <= now){ uint32_t seq = it_timers->second; - sendNack(seq, active_); + sendNack(seq); //remove the interest from the other map seqs_map_.erase(seq); it_timers = timers_map_.erase(it_timers); @@ -325,11 +304,11 @@ void RTCProducerSocket::interestCacheTimer(){ timer_on_ = false; }else{ timer_on_ = true; - scheduleTimer(timers_map_.begin()->first - now); + scheduleCacheTimer(timers_map_.begin()->first - now); } } -void RTCProducerSocket::sendNack(uint32_t sequence, bool isActive) { +void RTCProducerSocket::sendNack(uint32_t sequence) { auto nack_payload = utils::MemBuf::create(NACK_HEADER_SIZE); nack_payload->append(NACK_HEADER_SIZE); ContentObject nack; @@ -340,11 +319,7 @@ void RTCProducerSocket::sendNack(uint32_t sequence, bool isActive) { uint32_t *payload_ptr = (uint32_t *)nack.getPayload()->data(); *payload_ptr = currentSeg_; - if (isActive) { - *(++payload_ptr) = bytesProductionRate_; - } else { - *(++payload_ptr) = 0; - } + *(++payload_ptr) = bytesProductionRate_.load(); nack.setLifetime(0); nack.setPathLabel(prodLabel_); diff --git a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h index aa67f1a29..a2540ceef 100644 --- a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h +++ b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h @@ -41,21 +41,23 @@ class RTCProducerSocket : public ProducerSocket { void onInterest(Interest::Ptr &&interest) override; private: - void sendNack(uint32_t sequence, bool isActive); - void updateStats(uint32_t packet_size, uint64_t now); - void scheduleTimer(uint64_t wait); + void sendNack(uint32_t sequence); + void updateStats(); + void scheduleCacheTimer(uint64_t wait); + void scheduleRoundTimer(); void interestCacheTimer(); uint32_t currentSeg_; uint32_t prodLabel_; uint16_t headerSize_; Name flowName_; - uint32_t producedBytes_; - uint32_t producedPackets_; - uint32_t bytesProductionRate_; + std::atomic<uint32_t> producedBytes_; + std::atomic<uint32_t> producedPackets_; + std::atomic<uint32_t> bytesProductionRate_; std::atomic<uint32_t> packetsProductionRate_; uint32_t perSecondFactor_; - uint64_t lastStats_; + + std::unique_ptr<asio::steady_timer> round_timer_; // cache for the received interests // this map maps the expiration time of an interest to @@ -70,10 +72,6 @@ class RTCProducerSocket : public ProducerSocket { bool timer_on_; std::unique_ptr<asio::steady_timer> interests_cache_timer_; utils::SpinLock interests_cache_lock_; - - uint64_t lastProduced_; - bool active_; - utils::SpinLock lock_; }; } // namespace interface diff --git a/libtransport/src/hicn/transport/protocols/rtc.cc b/libtransport/src/hicn/transport/protocols/rtc.cc index 4104d8883..accd98495 100644 --- a/libtransport/src/hicn/transport/protocols/rtc.cc +++ b/libtransport/src/hicn/transport/protocols/rtc.cc @@ -31,10 +31,8 @@ RTCTransportProtocol::RTCTransportProtocol( inflightInterests_(1 << default_values::log_2_default_buffer_size), modMask_((1 << default_values::log_2_default_buffer_size) - 1) { icnet_socket->getSocketOption(PORTAL, portal_); - nack_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService()); rtx_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService()); probe_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService()); - nack_timer_used_ = false; reset(); } @@ -92,7 +90,6 @@ void RTCTransportProtocol::reset() { highestReceived_ = 0; firstSequenceInRound_ = 0; - nack_timer_used_ = false; rtx_timer_used_ = false; for(int i = 0; i < (1 << default_values::log_2_default_buffer_size); i++){ inflightInterests_[i] = {0}; @@ -673,36 +670,6 @@ void RTCTransportProtocol::onTimeout(Interest::Ptr &&interest) { scheduleNextInterests(); } -bool RTCTransportProtocol::checkIfProducerIsActive( - const ContentObject &content_object) { - uint32_t *payload = (uint32_t *)content_object.getPayload()->data(); - uint32_t productionSeg = *payload; - uint32_t productionRate = *(++payload); - - if (productionRate == 0) { - // the producer socket is not active - // in this case we consider only the first nack - if (nack_timer_used_) { - return false; - } - - nack_timer_used_ = true; - // actualSegment_ should be the one in the nack, which will be the next in - // production - actualSegment_ = productionSeg; - // all the rest (win size should not change) - // we wait a bit before pull the socket again - nack_timer_->expires_from_now(std::chrono::milliseconds(500)); - nack_timer_->async_wait([this](std::error_code ec) { - if (ec) return; - nack_timer_used_ = false; - scheduleNextInterests(); - }); - return false; - } - return true; -} - bool RTCTransportProtocol::onNack(const ContentObject &content_object, bool rtx) { uint32_t *payload = (uint32_t *)content_object.getPayload()->data(); uint32_t productionSeg = *payload; @@ -719,7 +686,7 @@ bool RTCTransportProtocol::onNack(const ContentObject &content_object, bool rtx) if (productionSeg > nackSegment) { // we are asking for stuff produced in the past - actualSegment_ = max(productionSeg + 1, actualSegment_) % HICN_MIN_PROBE_SEQ; + actualSegment_ = max(productionSeg, actualSegment_) % HICN_MIN_PROBE_SEQ; if(!rtx) { if (currentState_ == HICN_RTC_NORMAL_STATE) { @@ -756,7 +723,11 @@ bool RTCTransportProtocol::onNack(const ContentObject &content_object, bool rtx) currentState_ = HICN_RTC_NORMAL_STATE; } } - } // equal should not happen + } else { + //we are asking the right thing, but the producer is slow + //keep doing the same until the packet is produced + actualSegment_ = productionSeg % HICN_MIN_PROBE_SEQ; + } return old_nack; } @@ -771,7 +742,6 @@ void RTCTransportProtocol::onContentObject( uint32_t payload_size = (uint32_t)payload->length(); uint32_t segmentNumber = content_object->getName().getSuffix(); uint32_t pkt = segmentNumber & modMask_; - bool schedule_next_interest = true; ConsumerContentObjectCallback *callback_content_object = nullptr; socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT, @@ -802,25 +772,19 @@ void RTCTransportProtocol::onContentObject( } if (payload_size == HICN_NACK_HEADER_SIZE) { - schedule_next_interest = checkIfProducerIsActive(*content_object); - if (inflightInterests_[pkt].state == sent_) { inflightInterestsCount_--; } - // if checkIfProducerIsActive returns false, we did all we need to do - // inside that function, no need to call onNack bool old_nack = false; - if (schedule_next_interest){ - if (interestRetransmissions_.find(segmentNumber) == + if (interestRetransmissions_.find(segmentNumber) == interestRetransmissions_.end()){ - //this is not a retransmitted packet - old_nack = onNack(*content_object, false); - updateDelayStats(*content_object); - } else { - old_nack = onNack(*content_object, true); - } + //this is not a retransmitted packet + old_nack = onNack(*content_object, false); + updateDelayStats(*content_object); + } else { + old_nack = onNack(*content_object, true); } //the nacked_ state is used only to avoid to decrease inflightInterestsCount_ @@ -870,9 +834,7 @@ void RTCTransportProtocol::onContentObject( interestRetransmissions_.erase(segmentNumber); - if (schedule_next_interest) { - scheduleNextInterests(); - } + scheduleNextInterests(); } void RTCTransportProtocol::returnContentToApplication( diff --git a/libtransport/src/hicn/transport/protocols/rtc.h b/libtransport/src/hicn/transport/protocols/rtc.h index 4ebae2b90..509f11361 100644 --- a/libtransport/src/hicn/transport/protocols/rtc.h +++ b/libtransport/src/hicn/transport/protocols/rtc.h @@ -128,10 +128,6 @@ class RTCTransportProtocol : public TransportProtocol, public Reassembly { void checkRtx(); void probeRtt(); void onTimeout(Interest::Ptr &&interest) override; - // checkIfProducerIsActive: return true if we need to schedule an interest - // immediatly after, false otherwise (this happens when the producer socket - // is not active) - bool checkIfProducerIsActive(const ContentObject &content_object); bool onNack(const ContentObject &content_object, bool rtx); void onContentObject(Interest::Ptr &&interest, ContentObject::Ptr &&content_object) override; @@ -155,6 +151,7 @@ class RTCTransportProtocol : public TransportProtocol, public Reassembly { uint32_t inflightInterestsCount_; //map seq to rtx std::map<uint32_t, uint8_t> interestRetransmissions_; + bool rtx_timer_used_; std::unique_ptr<asio::steady_timer> rtx_timer_; std::vector<sentInterest> inflightInterests_; uint32_t lastSegNacked_; //indicates the segment id in the last received @@ -163,12 +160,6 @@ class RTCTransportProtocol : public TransportProtocol, public Reassembly { uint32_t lastReceived_; //segment of the last content object received //indicates the base of the window on the client - bool nack_timer_used_; - bool rtx_timer_used_; - std::unique_ptr<asio::steady_timer> nack_timer_; // timer used to schedule - // a nack retransmission in case - // of inactive prod socket - //rtt probes //the RTC transport tends to overestimate the RTT //du to the production time on the server side diff --git a/utils/src/hiperf.cc b/utils/src/hiperf.cc index 3e39990a4..ccb22779b 100644 --- a/utils/src/hiperf.cc +++ b/utils/src/hiperf.cc @@ -67,7 +67,8 @@ struct ClientConfiguration { download_size(0), report_interval_milliseconds_(1000), rtc_(false), - test_mode_(false) {} + test_mode_(false), + interest_lifetime_(1000) {} Name name; bool verify; @@ -82,6 +83,7 @@ struct ClientConfiguration { TransportProtocolAlgorithms transport_protocol_; bool rtc_; bool test_mode_; + uint32_t interest_lifetime_; }; /** @@ -325,6 +327,7 @@ class HIperfClient { } consumer_socket_ = std::make_unique<ConsumerSocket>(transport_protocol); + consumer_socket_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME, configuration_.interest_lifetime_); #if defined(DEBUG) && defined(__linux__) std::shared_ptr<transport::BasePortal> portal; @@ -509,11 +512,7 @@ class HIperfClient { void readBufferAvailable( std::unique_ptr<utils::MemBuf> &&buffer) noexcept override { - if (client_.configuration_.receive_buffer) { - client_.configuration_.receive_buffer->prependChain(std::move(buffer)); - } else { - client_.configuration_.receive_buffer = std::move(buffer); - } + return; } size_t maxBufferSize() const override { return read_size; } @@ -898,6 +897,8 @@ void usage() { << std::endl; std::cerr << "-d <drop_factor_parameter> = RAAQM drop factor parameter" << std::endl; + std::cerr << "-L\t<interest lifetime>\t\t" + << "Set interest lifetime." << std::endl; std::cerr << "-M = store the content downloaded" "(default false)" << std::endl; @@ -943,7 +944,7 @@ int main(int argc, char *argv[]) { int opt; #ifndef _WIN32 - while ((opt = getopt(argc, argv, "DSCf:b:d:W:RMc:vA:s:rmlk:y:p:hi:xB:It")) != + while ((opt = getopt(argc, argv, "DSCf:b:d:W:RMc:vA:s:rmlk:y:p:hi:xB:ItL:")) != -1) { switch (opt) { // Common @@ -956,7 +957,7 @@ int main(int argc, char *argv[]) { break; } #else - while ((opt = getopt(argc, argv, "SCf:b:d:W:RMc:vA:s:rmlk:y:p:hi:xB:t")) != + while ((opt = getopt(argc, argv, "SCf:b:d:W:RMc:vA:s:rmlk:y:p:hi:xB:tL:")) != -1) { switch (opt) { #endif @@ -1021,6 +1022,11 @@ int main(int argc, char *argv[]) { options = 1; break; } + case 'L': { + client_configuration.interest_lifetime_ = std::stoul(optarg); + options = 1; + break; + } // Server specific case 'A': { server_configuration.download_size = std::stoul(optarg); |