diff options
Diffstat (limited to 'ctrl')
237 files changed, 22696 insertions, 27357 deletions
diff --git a/ctrl/.clang-format b/ctrl/.clang-format new file mode 100644 index 000000000..2f629734d --- /dev/null +++ b/ctrl/.clang-format @@ -0,0 +1,15 @@ +# Copyright (c) 2021 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. + +BasedOnStyle: Google +SortIncludes: false diff --git a/ctrl/CMakeLists.txt b/ctrl/CMakeLists.txt index 331ae9078..e601d9509 100644 --- a/ctrl/CMakeLists.txt +++ b/ctrl/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -10,13 +10,17 @@ # 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. - +############################################################## +# Project and cmake version +############################################################## cmake_minimum_required(VERSION 3.10 FATAL_ERROR) - project(ctrl) -add_subdirectory(libhicnctrl) -if (NOT (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")) - add_subdirectory(facemgr) -endif ()
\ No newline at end of file +############################################################## +# Subdirectories +############################################################## +add_subdirectory(libhicnctrl) +if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Android" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") + add_subdirectory(facemgr) +endif () diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt index 2fad5d839..9d549bddf 100644 --- a/ctrl/facemgr/CMakeLists.txt +++ b/ctrl/facemgr/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,62 +11,98 @@ # See the License for the specific language governing permissions and # limitations under the License. +############################################################## +# Project and cmake version +############################################################## +project(facemgr) + if (APPLE) - # >= 3.13 - CMP0079 (only needed on Apple platform for conditionally linking Network.framwork to libfacemgr) - cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + # >= 3.13 - CMP0079 (only needed on Apple platform for conditionally linking Network.framwork to libfacemgr) + cmake_minimum_required(VERSION 3.13 FATAL_ERROR) else() - cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + cmake_minimum_required(VERSION 3.10 FATAL_ERROR) endif() -project(facemgr) +############################################################## +# C Standard +############################################################## +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +############################################################## +# CMAKE Options +############################################################## option(WITH_THREAD "Run library as thread" OFF) option(WITH_EXAMPLE_DUMMY "Compile dummy example interface" OFF) option(WITH_EXAMPLE_UPDOWN "Compile updown example interface" OFF) if(WITH_THREAD) - message("Building with thread support") + message(STATUS "Building with thread support") endif() if(WITH_EXAMPLE_DUMMY) - message("Building with 'dummy' example interface") + message(STATUS "Building with 'dummy' example interface") endif() if(WITH_EXAMPLE_UPDOWN) - message("Building with 'updown' example interface") -endif() - -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Building with 'updown' example interface") endif() if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3") endif() + +############################################################## +# Cmake modules +############################################################## set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" ) -include(BuildMacros) -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) +############################################################## +# Libs and Bins names +############################################################## +set(FACEMGR facemgr CACHE INTERNAL "" FORCE) +set(LIBFACEMGR facemgr CACHE INTERNAL "" FORCE) + + +############################################################## +# Packaging and versioning +############################################################## +include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) -find_package_wrapper(Libconfig REQUIRED) -find_package_wrapper(LibEvent REQUIRED) -set(FACEMGR facemgr CACHE INTERNAL "" FORCE) -set(LIBFACEMGR facemgr CACHE INTERNAL "" FORCE) +############################################################## +# Dependencies and third party libs +############################################################## +find_package(Libconfig ${LIBCONFIG_DEFAULT_VERSION} REQUIRED) +find_package(LibEvent ${LIBEVENT_DEFAULT_VERSION} REQUIRED) + +############################################################## +# Check if building as subproject or as root project +############################################################## if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_package_wrapper(Libhicn REQUIRED) - find_package_wrapper(Libhicnctrl REQUIRED) + include(CommonSetup) + + find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE) + + if (DISABLE_SHARED_LIBRARIES) + set(LIBTYPE static) + else() + set(LIBTYPE shared) + endif() + + list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE}) + list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE}) else() if (DISABLE_SHARED_LIBRARIES) if (WIN32) @@ -89,11 +125,18 @@ else() endif () endif() + +############################################################## +# Subdirectories +############################################################## add_subdirectory(includes) add_subdirectory(src) -include(Packaging) + +############################################################## +# Service file +############################################################## # Install service file in linux systems include(ServiceScript) install_service_script( @@ -101,14 +144,23 @@ install_service_script( COMPONENT ${FACEMGR} ) + +############################################################## # Configuration file +############################################################## set(FACEMGR_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.conf) -set(FACEMGR_CONF_FOLDER "/etc/facemgr") -if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - install (FILES ${FACEMGR_CONF_FILE} DESTINATION ${FACEMGR_CONF_FOLDER} COMPONENT ${FACEMGR}) +if (${CMAKE_SYSTEM_NAME} MATCHES Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Linux) + set(FACEMGR_CONF_FOLDER "${CMAKE_INSTALL_FULL_SYSCONFDIR}/facemgr") +else () + set(FACEMGR_CONF_FOLDER "${CMAKE_INSTALL_PREFIX}/etc/hicn") endif() +install (FILES + ${FACEMGR_CONF_FILE} + DESTINATION ${FACEMGR_CONF_FOLDER} + COMPONENT ${FACEMGR} +) + if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - include(Packager) - make_packages() + make_packages() endif() diff --git a/ctrl/facemgr/cmake/Modules/Packaging.cmake b/ctrl/facemgr/cmake/packaging.cmake index bb4fa42fa..62b14b202 100644 --- a/ctrl/facemgr/cmake/Modules/Packaging.cmake +++ b/ctrl/facemgr/cmake/packaging.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -20,27 +20,37 @@ set(${FACEMGR}_DESCRIPTION CACHE STRING "Description for deb/rpm package." ) +set(${FACEMGR}-dev_DEB_DEPENDENCIES + "libconfig9, libevent-dev, lib${LIBHICNCTRL}-dev (= stable_version)" + CACHE STRING "Dependencies for deb/rpm package." +) + set(${FACEMGR}_DEB_DEPENDENCIES - "libconfig9, libevent-dev, lib${LIBHICNCTRL} (>= stable_version)" + "libconfig9, libevent-2.1-7, lib${LIBHICNCTRL} (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) -set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA +set(${FACEMGR}_DEB_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/config/postinst;${CMAKE_CURRENT_SOURCE_DIR}/config/prerm" CACHE STRING "Control scripts conffiles, postinst, postrm, prerm." ) set(${FACEMGR}_RPM_DEPENDENCIES - "libconfig, libevent-devel, lib${LIBHICNCTRL} >= stable_version" + "libconfig, libevent, lib${LIBHICNCTRL} = stable_version" + CACHE STRING "Dependencies for deb/rpm package." +) + +set(${FACEMGR}-dev_RPM_DEPENDENCIES + "libconfig, libevent-devel, lib${LIBHICNCTRL}-dev = stable_version" CACHE STRING "Dependencies for deb/rpm package." ) -set(${HICN_LIGHT}_RPM_POST_INSTALL_SCRIPT_FILE +set(${FACEMGR}_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config/post" CACHE STRING "Install script that will be copied in the %post section" ) -set(${HICN_LIGHT}_RPM_PRE_UNINSTALL_SCRIPT_FILE +set(${FACEMGR}_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config/preun" CACHE STRING "Install script that will be copied in the %post section" ) diff --git a/ctrl/facemgr/config/facemgr.service b/ctrl/facemgr/config/facemgr.service index 0f9e818ea..89d4f9283 100644 --- a/ctrl/facemgr/config/facemgr.service +++ b/ctrl/facemgr/config/facemgr.service @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/config/postinst b/ctrl/facemgr/config/postinst index 4113b0eca..7b2fd57fe 100755 --- a/ctrl/facemgr/config/postinst +++ b/ctrl/facemgr/config/postinst @@ -1,3 +1,5 @@ #!/bin/bash -systemctl enable facemgr +if pidof systemd; then + systemctl enable facemgr +fi diff --git a/ctrl/facemgr/config/prerm b/ctrl/facemgr/config/prerm index b5c486ea5..8c0eadf0d 100755 --- a/ctrl/facemgr/config/prerm +++ b/ctrl/facemgr/config/prerm @@ -1,3 +1,5 @@ #!/bin/bash -systemctl disable facemgr +if pidof systemd; then + systemctl disable facemgr +fi diff --git a/ctrl/facemgr/config/preun b/ctrl/facemgr/config/preun index b5c486ea5..8c0eadf0d 100755 --- a/ctrl/facemgr/config/preun +++ b/ctrl/facemgr/config/preun @@ -1,3 +1,5 @@ #!/bin/bash -systemctl disable facemgr +if pidof systemd; then + systemctl disable facemgr +fi diff --git a/ctrl/facemgr/examples/mobility/mobility.c b/ctrl/facemgr/examples/mobility/mobility.c index 528951446..ae1d6dee3 100644 --- a/ctrl/facemgr/examples/mobility/mobility.c +++ b/ctrl/facemgr/examples/mobility/mobility.c @@ -7,82 +7,81 @@ * Test server using nc: nc -4kvul localhost 9533 */ -#include <arpa/inet.h> // inet_ntop -#include <errno.h> // EINTR,. .. -#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN +#include <arpa/inet.h> // inet_ntop +#include <errno.h> // EINTR,. .. +#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN #include <stdio.h> #include <inttypes.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/timerfd.h> -#include <sys/un.h> // sockaddr_un -#include <unistd.h> // fcntl -#include <fcntl.h> // fcntl +#include <sys/un.h> // sockaddr_un +#include <unistd.h> // fcntl +#include <fcntl.h> // fcntl #define MS2US(x) (x * 1000) /** * \brief Main function */ -int main(int argc, char **argv) -{ - int rc; +int main(int argc, char **argv) { + int rc; - if (argc != 4) { - fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, " IP Target hostname\n"); - fprintf(stderr, " PORT Target port\n"); - fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n"); - fprintf(stderr, "\n"); - exit(EXIT_FAILURE); - } + if (argc != 4) { + fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, " IP Target hostname\n"); + fprintf(stderr, " PORT Target port\n"); + fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n"); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); + } - int interval = atoi(argv[3]); + int interval = atoi(argv[3]); - int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - perror("socket"); - goto ERR_SOCKET; - } + int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + perror("socket"); + goto ERR_SOCKET; + } - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(argv[1]); - addr.sin_port = htons(atoi(argv[2])); + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(argv[1]); + addr.sin_port = htons(atoi(argv[2])); - if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - perror("connect"); - goto ERR_CONNECT; - } + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("connect"); + goto ERR_CONNECT; + } - unsigned state = 0; - char buf[1]; - for(;;) { - usleep(MS2US(interval)); + unsigned state = 0; + char buf[1]; + for (;;) { + usleep(MS2US(interval)); - buf[0] = state; - rc = send(fd, buf, 1, 0); - if (rc < 0) { - if (errno == ECONNREFUSED) { - continue; - } - perror("send"); - goto ERR_SEND; - } - - state = 1 - state; + buf[0] = state; + rc = send(fd, buf, 1, 0); + if (rc < 0) { + if (errno == ECONNREFUSED) { + continue; + } + perror("send"); + goto ERR_SEND; } - close(fd); + state = 1 - state; + } + + close(fd); - exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); ERR_SEND: ERR_CONNECT: - close(fd); + close(fd); ERR_SOCKET: - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } diff --git a/ctrl/facemgr/examples/updowncli/updowncli.c b/ctrl/facemgr/examples/updowncli/updowncli.c index 4f5a14165..34ec3fb97 100644 --- a/ctrl/facemgr/examples/updowncli/updowncli.c +++ b/ctrl/facemgr/examples/updowncli/updowncli.c @@ -5,6 +5,8 @@ #include <stdlib.h> #include <unistd.h> +#include <hicn/util/sstrncpy.h> + /** * \brief Default unix socket path (the leading \0 means using the abstract * namespace instead of the filesystem). @@ -12,46 +14,46 @@ #define UNIX_PATH "\0updownsrv" int main() { - struct sockaddr_un addr; - char buf[100]; - int fd,rc; - - char * socket_path = UNIX_PATH; - - if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - perror("socket error"); - exit(-1); - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (*socket_path == '\0') { - *addr.sun_path = '\0'; - strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2); - } else { - strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); - } - - if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { - perror("connect error"); - exit(-1); - } - - printf("Waiting for server data...\n"); - while( (rc=read(fd, buf, sizeof(buf))) > 0) { - assert(rc == 1); - switch(buf[0]) { - case '\0': - printf("WiFi\n"); - break; - case '\1': - printf("LTE\n"); - break; - default: - printf("Unknown\n"); - break; - } + struct sockaddr_un addr; + char buf[100]; + int fd, rc; + + char* socket_path = UNIX_PATH; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + perror("socket error"); + exit(-1); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (*socket_path == '\0') { + *addr.sun_path = '\0'; + strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, socket_path + 1); + } else { + strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, socket_path); + } + + if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + perror("connect error"); + exit(-1); + } + + printf("Waiting for server data...\n"); + while ((rc = read(fd, buf, sizeof(buf))) > 0) { + assert(rc == 1); + switch (buf[0]) { + case '\0': + printf("WiFi\n"); + break; + case '\1': + printf("LTE\n"); + break; + default: + printf("Unknown\n"); + break; } + } - return 0; + return 0; } diff --git a/ctrl/facemgr/examples/updownsrv/updownsrv.c b/ctrl/facemgr/examples/updownsrv/updownsrv.c index 3aba3cfd0..57661d427 100644 --- a/ctrl/facemgr/examples/updownsrv/updownsrv.c +++ b/ctrl/facemgr/examples/updownsrv/updownsrv.c @@ -5,19 +5,20 @@ * using unix domains that sets a face up and down. */ -#include <arpa/inet.h> // inet_ntop -#include <errno.h> // EINTR,. .. -#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN +#include <arpa/inet.h> // inet_ntop +#include <errno.h> // EINTR,. .. +#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN #include <stdio.h> #include <inttypes.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/timerfd.h> -#include <sys/un.h> // sockaddr_un -#include <unistd.h> // fcntl -#include <fcntl.h> // fcntl +#include <sys/un.h> // sockaddr_un +#include <unistd.h> // fcntl +#include <fcntl.h> // fcntl +#include <hicn/util/sstrncpy.h> /** * \brief Default unix socket path (the leading \0 means using the abstract @@ -40,199 +41,190 @@ */ #define LISTEN_BACKLOG MAX_CLIENTS - /** * \brief Creates a unix server socket * \param [in] path - string representing the path on which to listen for * connections * \return int - fd associated to the socket */ -int -create_unix_server(char * path) -{ - struct sockaddr_un addr; - int fd; - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - perror("socket error"); - return -1; - } - - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (*path == '\0') { - *addr.sun_path = '\0'; - strncpy(addr.sun_path+1, path+1, sizeof(addr.sun_path)-2); - } else { - strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1); - unlink(path); - } - - if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { - perror("bind error"); - return -1; - } - - if (listen(fd, LISTEN_BACKLOG) == -1) { - perror("listen error"); - return -1; - } - - return fd; +int create_unix_server(char* path) { + struct sockaddr_un addr; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + perror("socket error"); + return -1; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + perror("fcntl"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (*path == '\0') { + *addr.sun_path = '\0'; + strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, path + 1); + } else { + strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, path); + unlink(path); + } + + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + perror("bind error"); + return -1; + } + + if (listen(fd, LISTEN_BACKLOG) == -1) { + perror("listen error"); + return -1; + } + + return fd; } - /** * \brief Main function */ int main() { - int fd, tfd; - int rc; - - /* Alternating state of the server : 0 / 1 */ - unsigned state = 0; - - /* - * This server has to send a signal to all connected clients at periodic - * intervals. Since we don't expect a large number of connected clients for - * such a simple program, we simply use a statically allocated array. - */ - int clients[MAX_CLIENTS]; - size_t num_clients = 0; - - fd_set active_fd_set, read_fd_set; - FD_ZERO (&active_fd_set); - - /* Create listening unix socket */ - fd = create_unix_server(UNIX_PATH); - if (fd < 0) - exit(EXIT_FAILURE); - - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl"); - exit(EXIT_FAILURE); - } - - FD_SET (fd, &active_fd_set); - - /* Create timer */ - tfd = timerfd_create(CLOCK_MONOTONIC, 0); - if (tfd == -1) { - perror("timer error"); - exit(EXIT_FAILURE); + int fd, tfd; + int rc; + + /* Alternating state of the server : 0 / 1 */ + unsigned state = 0; + + /* + * This server has to send a signal to all connected clients at periodic + * intervals. Since we don't expect a large number of connected clients for + * such a simple program, we simply use a statically allocated array. + */ + int clients[MAX_CLIENTS]; + size_t num_clients = 0; + + fd_set active_fd_set, read_fd_set; + FD_ZERO(&active_fd_set); + + /* Create listening unix socket */ + fd = create_unix_server(UNIX_PATH); + if (fd < 0) exit(EXIT_FAILURE); + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + perror("fcntl"); + exit(EXIT_FAILURE); + } + + FD_SET(fd, &active_fd_set); + + /* Create timer */ + tfd = timerfd_create(CLOCK_MONOTONIC, 0); + if (tfd == -1) { + perror("timer error"); + exit(EXIT_FAILURE); + } + + if (fcntl(tfd, F_SETFL, O_NONBLOCK) < 0) { + perror("fcntl"); + exit(EXIT_FAILURE); + } + + FD_SET(tfd, &active_fd_set); + + struct itimerspec ts = {.it_interval = + { + .tv_sec = DEFAULT_INTERVAL_SEC, + .tv_nsec = DEFAULT_INTERVAL_NSEC, + }, + .it_value = { + .tv_sec = DEFAULT_INTERVAL_SEC, + .tv_nsec = DEFAULT_INTERVAL_NSEC, + }}; + rc = timerfd_settime(tfd, 0, &ts, NULL); + if (rc == -1) { + perror("timerfd_settime"); + exit(EXIT_FAILURE); + } + + printf("Waiting for clients...\n"); + + for (;;) { + /* Block until input arrives on one or more active sockets. */ + read_fd_set = active_fd_set; + rc = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL); + if (rc < 0) { + if (rc == EINTR) break; + perror("select"); + exit(EXIT_FAILURE); } - if (fcntl(tfd, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl"); - exit(EXIT_FAILURE); - } - - FD_SET (tfd, &active_fd_set); - - struct itimerspec ts = { - .it_interval = { - .tv_sec = DEFAULT_INTERVAL_SEC, - .tv_nsec = DEFAULT_INTERVAL_NSEC, - }, - .it_value = { - .tv_sec = DEFAULT_INTERVAL_SEC, - .tv_nsec = DEFAULT_INTERVAL_NSEC, - } - }; - rc = timerfd_settime(tfd, 0, &ts, NULL); - if (rc == -1) { - perror("timerfd_settime"); - exit(EXIT_FAILURE); - } - - printf("Waiting for clients...\n"); - - for(;;) { - /* Block until input arrives on one or more active sockets. */ - read_fd_set = active_fd_set; - rc = select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL); - if (rc < 0) { - if (rc == EINTR) - break; - perror("select"); - exit (EXIT_FAILURE); + /* Service all the sockets with input pending. */ + for (int i = 0; i < FD_SETSIZE; ++i) { + if (!FD_ISSET(i, &read_fd_set)) continue; + if (i == fd) { + /* Connection request on original socket. */ + int client_fd = accept(fd, NULL, NULL); + if (client_fd < 0) { + perror("accept"); + continue; } - /* Service all the sockets with input pending. */ - for (int i = 0; i < FD_SETSIZE; ++i) { - if (!FD_ISSET (i, &read_fd_set)) - continue; - if (i == fd) { - /* Connection request on original socket. */ - int client_fd = accept(fd, NULL, NULL); - if (client_fd < 0) { - perror("accept"); - continue; - } - - fprintf(stderr, "Server: connect from new client\n"); - clients[num_clients++] = client_fd; - FD_SET(client_fd, &active_fd_set); - } else if (i == tfd) { - /* Timer event */ - uint64_t res; - - read(tfd, &res, sizeof(res)); -// while (read(fd, &missed, sizeof(missed)) > 0) -// ; - for (unsigned j = 0; j < num_clients; j++) { - write(clients[j], state ? "\1" : "\0", 1); - } - printf("STATE=%d\n", state); - state = 1 - state; - } else { - char buf[1024]; - rc = read(i, buf, sizeof(buf)); - /* Client event : we close the connection on any event... */ - for (unsigned j = 0; j < num_clients; j++) { - if (i == clients[j]) { - clients[j] = clients[num_clients--]; - break; - } - } - close(i); - FD_CLR(i, &active_fd_set); - } + fprintf(stderr, "Server: connect from new client\n"); + clients[num_clients++] = client_fd; + FD_SET(client_fd, &active_fd_set); + } else if (i == tfd) { + /* Timer event */ + uint64_t res; + + read(tfd, &res, sizeof(res)); + // while (read(fd, &missed, sizeof(missed)) > 0) + // ; + for (unsigned j = 0; j < num_clients; j++) { + write(clients[j], state ? "\1" : "\0", 1); } - - } - - int ret = EXIT_SUCCESS; - - /* Close all active client connections */ - for (unsigned i = 0; i < num_clients; i++) { - rc = close(clients[i]); - if (rc == -1) { - perror("close"); - ret = EXIT_FAILURE; + printf("STATE=%d\n", state); + state = 1 - state; + } else { + char buf[1024]; + rc = read(i, buf, sizeof(buf)); + /* Client event : we close the connection on any event... */ + for (unsigned j = 0; j < num_clients; j++) { + if (i == clients[j]) { + clients[j] = clients[num_clients--]; + break; + } } + close(i); + FD_CLR(i, &active_fd_set); + } } + } - /* Close server */ - rc = close(fd); - if (rc == -1) { - perror("close"); - ret = EXIT_FAILURE; - } + int ret = EXIT_SUCCESS; - /* Terminate timer */ - ts.it_value.tv_sec = 0; - rc = timerfd_settime(tfd, 0, &ts, NULL); + /* Close all active client connections */ + for (unsigned i = 0; i < num_clients; i++) { + rc = close(clients[i]); if (rc == -1) { - perror("timerfd_settime"); - exit(EXIT_FAILURE); + perror("close"); + ret = EXIT_FAILURE; } - - exit(ret); + } + + /* Close server */ + rc = close(fd); + if (rc == -1) { + perror("close"); + ret = EXIT_FAILURE; + } + + /* Terminate timer */ + ts.it_value.tv_sec = 0; + rc = timerfd_settime(tfd, 0, &ts, NULL); + if (rc == -1) { + perror("timerfd_settime"); + exit(EXIT_FAILURE); + } + + exit(ret); } diff --git a/ctrl/facemgr/includes/CMakeLists.txt b/ctrl/facemgr/includes/CMakeLists.txt index 065a9022f..bfbf65717 100644 --- a/ctrl/facemgr/includes/CMakeLists.txt +++ b/ctrl/facemgr/includes/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,15 +11,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -# XXX - +############################################################## +# Public headers directory +############################################################## set(LIBFACEMGR_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR} "" + ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" FORCE ) -if (${CMAKE_SYSTEM_NAME} STREQUAL "Android") + +############################################################## +# To install header files +############################################################## +if (${CMAKE_SYSTEM_NAME} STREQUAL "Android") set(TO_INSTALL_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h @@ -28,9 +33,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android") ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h PARENT_SCOPE ) - else () - set(TO_INSTALL_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h @@ -39,7 +42,4 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h PARENT_SCOPE ) - endif () - - diff --git a/ctrl/facemgr/includes/facemgr.h b/ctrl/facemgr/includes/facemgr.h index b3b482ccc..b62bb88ce 100644 --- a/ctrl/facemgr/includes/facemgr.h +++ b/ctrl/facemgr/includes/facemgr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -26,4 +26,3 @@ #include <hicn/facemgr/loop.h> #endif /* HICN_FACEMGR_H */ - diff --git a/ctrl/facemgr/includes/hicn/facemgr.h b/ctrl/facemgr/includes/hicn/facemgr.h index 4165a8fc4..83a76cc08 100644 --- a/ctrl/facemgr/includes/hicn/facemgr.h +++ b/ctrl/facemgr/includes/hicn/facemgr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -24,4 +24,3 @@ #include <hicn/facemgr/api.h> #endif /* HICN_FACEMGR_H */ - diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h index e9d25f132..582be0e78 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/api.h +++ b/ctrl/facemgr/includes/hicn/facemgr/api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -30,40 +30,38 @@ /* facemgr callbacks */ typedef enum { - FACEMGR_CB_TYPE_REGISTER_FD, - FACEMGR_CB_TYPE_UNREGISTER_FD, - FACEMGR_CB_TYPE_REGISTER_TIMER, - FACEMGR_CB_TYPE_UNREGISTER_TIMER, + FACEMGR_CB_TYPE_REGISTER_FD, + FACEMGR_CB_TYPE_UNREGISTER_FD, + FACEMGR_CB_TYPE_REGISTER_TIMER, + FACEMGR_CB_TYPE_UNREGISTER_TIMER, } facemgr_cb_type_t; -typedef int (*facemgr_cb_t)(void * loop, facemgr_cb_type_t type, void * data); - +typedef int (*facemgr_cb_t)(void *loop, facemgr_cb_type_t type, void *data); /* * \brief Manual overlay settings (alternative to service discovery) */ typedef struct { - uint16_t local_port; - ip_address_t remote_addr; - uint16_t remote_port; + uint16_t local_port; + hicn_ip_address_t remote_addr; + uint16_t remote_port; } facemgr_overlay_setting_t; -#define FACEMGR_OVERLAY_SETTING_EMPTY (facemgr_overlay_setting_t) { \ - .local_port = 0, \ - .remote_addr = IP_ADDRESS_EMPTY, \ - .remote_port = 0, \ -} +#define FACEMGR_OVERLAY_SETTING_EMPTY \ + (facemgr_overlay_setting_t) { \ + .local_port = 0, .remote_addr = IP_ADDRESS_EMPTY, .remote_port = 0, \ + } typedef struct { - facemgr_overlay_setting_t v4; - facemgr_overlay_setting_t v6; + facemgr_overlay_setting_t v4; + facemgr_overlay_setting_t v6; } facemgr_overlay_t; -#define FACEMGR_OVERLAY_EMPTY (facemgr_overlay_t) { \ - .v4 = FACEMGR_OVERLAY_SETTING_EMPTY, \ - .v6 = FACEMGR_OVERLAY_SETTING_EMPTY, \ -} +#define FACEMGR_OVERLAY_EMPTY \ + (facemgr_overlay_t) { \ + .v4 = FACEMGR_OVERLAY_SETTING_EMPTY, .v6 = FACEMGR_OVERLAY_SETTING_EMPTY, \ + } /* * \brief Face manager context @@ -72,24 +70,30 @@ typedef struct facemgr_s facemgr_t; int facemgr_initialize(facemgr_t *); int facemgr_finalize(facemgr_t *); -facemgr_t * facemgr_create(); -facemgr_t * facemgr_create_with_config(facemgr_cfg_t * cfg); +facemgr_t *facemgr_create(); +facemgr_t *facemgr_create_with_config(facemgr_cfg_t *cfg); void facemgr_stop(facemgr_t *); void facemgr_free(facemgr_t *); +void facemgr_set_callback(facemgr_t *facemgr, void *callback_owner, + facemgr_cb_t callback); -void facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback); - -int facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg); -int facemgr_reset_config(facemgr_t * facemgr); -int facemgr_bootstrap(facemgr_t * facemgr); +int facemgr_set_config(facemgr_t *facemgr, facemgr_cfg_t *cfg); +int facemgr_reset_config(facemgr_t *facemgr); +int facemgr_bootstrap(facemgr_t *facemgr); #ifdef __ANDROID__ -void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm); +void facemgr_set_jvm(facemgr_t *facemgr, JavaVM *jvm); +void facemgr_on_android_callback(facemgr_t *facemgr, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address); #endif /* __ANDROID__ */ -typedef int (*facemgr_list_facelets_cb_t)(const facemgr_t * facemgr, const facelet_t * facelet, void * user_data); +typedef int (*facemgr_list_facelets_cb_t)(const facemgr_t *facemgr, + const facelet_t *facelet, + void *user_data); -void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data); -int facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer); +void facemgr_list_facelets(const facemgr_t *facemgr, + facemgr_list_facelets_cb_t cb, void *user_data); +int facemgr_list_facelets_json(const facemgr_t *facemgr, char **buffer); #endif /* FACEMGR_H */ diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h index 84d63fe73..57d8f35bc 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h +++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -20,7 +20,7 @@ #ifndef FACEMGR_CFG_H #define FACEMGR_CFG_H -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include <hicn/facemgr/facelet.h> #include <hicn/util/log.h> @@ -38,68 +38,72 @@ #define FACEMGR_CFG_DEFAULT_IPV4 true #define FACEMGR_CFG_DEFAULT_IPV6 false - - typedef struct facemgr_cfg_s facemgr_cfg_t; -facemgr_cfg_t * facemgr_cfg_create(); -void facemgr_cfg_free(facemgr_cfg_t * cfg); -int facemgr_cfg_initialize(facemgr_cfg_t * cfg); -int facemgr_cfg_finalize(facemgr_cfg_t * cfg); -void facemgr_cfg_dump(facemgr_cfg_t * cfg); +facemgr_cfg_t* facemgr_cfg_create(); +void facemgr_cfg_free(facemgr_cfg_t* cfg); +int facemgr_cfg_initialize(facemgr_cfg_t* cfg); +int facemgr_cfg_finalize(facemgr_cfg_t* cfg); +void facemgr_cfg_dump(facemgr_cfg_t* cfg); /* Rules */ typedef struct facemgr_cfg_rule_s facemgr_cfg_rule_t; -facemgr_cfg_rule_t * facemgr_cfg_rule_create(); -void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule); -int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule); -int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule); +facemgr_cfg_rule_t* facemgr_cfg_rule_create(); +void facemgr_cfg_rule_free(facemgr_cfg_rule_t* rule); +int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t* rule); +int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t* rule); -int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule, - const char * interface_name, netdevice_type_t interface_type); +int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t* rule, + const char* interface_name, + netdevice_type_t interface_type); -int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * cfg_rule, facemgr_face_type_t * face_type); -int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * cfg_rule); +int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t* cfg_rule, + facemgr_face_type_t* face_type); +int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t* cfg_rule); -int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * cfg_rule, bool status); -int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * cfg_rule); +int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t* cfg_rule, bool status); +int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t* cfg_rule); -int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * cfg_rule, bool status); -int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * cfg_rule); +int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t* cfg_rule, bool status); +int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t* cfg_rule); -int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * cfg_rule, bool status); -int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * cfg_rule); +int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t* cfg_rule, bool status); +int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t* cfg_rule); -int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * cfg_rule, bool status); -int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * cfg_rule); +int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t* cfg_rule, bool status); +int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t* cfg_rule); -int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family, - ip_address_t * local_addr, uint16_t local_port, - ip_address_t * remote_addr, uint16_t remote_port); -int facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family); +int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t* rule, int family, + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port); +int facemgr_rule_unset_overlay(facemgr_cfg_rule_t* rule, int family); /* General */ -int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type); -int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg); -int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status); -int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg); -int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status); -int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg); -int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status); -int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg); - -int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family, - ip_address_t * local_addr, uint16_t local_port, - ip_address_t * remote_addr, uint16_t remote_port); -int facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family); - - -int facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule); -int facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule); -int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name, - netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule); +int facemgr_cfg_set_face_type(facemgr_cfg_t* cfg, + facemgr_face_type_t* face_type); +int facemgr_cfg_unset_face_type(facemgr_cfg_t* cfg); +int facemgr_cfg_set_discovery(facemgr_cfg_t* cfg, bool status); +int facemgr_cfg_unset_discovery(facemgr_cfg_t* cfg); +int facemgr_cfg_set_ipv4(facemgr_cfg_t* cfg, bool status); +int facemgr_cfg_unset_ipv4(facemgr_cfg_t* cfg); +int facemgr_cfg_set_ipv6(facemgr_cfg_t* cfg, bool status); +int facemgr_cfg_unset_ipv6(facemgr_cfg_t* cfg); + +int facemgr_cfg_set_overlay(facemgr_cfg_t* cfg, int family, + hicn_ip_address_t* local_addr, uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port); +int facemgr_cfg_unset_overlay(facemgr_cfg_t* cfg, int family); + +int facemgr_cfg_add_rule(facemgr_cfg_t* cfg, facemgr_cfg_rule_t* rule); +int facemgr_cfg_del_rule(facemgr_cfg_t* cfg, facemgr_cfg_rule_t* rule); +int facemgr_cfg_get_rule(const facemgr_cfg_t* cfg, const char* interface_name, + netdevice_type_t interface_type, + facemgr_cfg_rule_t** rule); /* Log */ @@ -107,57 +111,63 @@ int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name, * Query API * * Takes the overrides into account - * - * TODO : interface_types are currently not taken into account by this API */ -int facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - facemgr_face_type_t * face_type); -int facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * discovery); -int facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ignore); -int facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ipv4); -int facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ipv6); -int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t * addr); -int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, u16 * port); -int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t * addr); -int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, u16 * port); - -int facemgr_cfg_rule_get(const facemgr_cfg_t * cfg, const netdevice_t netdevice, - netdevice_type_t netdevice_type, facemgr_cfg_rule_t ** rule); -int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t * cfg_rule, facemgr_face_type_t * face_type); -int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t * cfg_rule, bool * status); -int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t * cfg_rule, bool * status); -int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t * cfg_rule, bool * status); -int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t * cfg_rule, bool * status); -int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t * rule, int family, - ip_address_t * addr); -int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t * rule, int family, - uint16_t * port); -int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t * rule, int family, - ip_address_t * addr); -int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t * rule, int family, - uint16_t * port); - -int facemgr_cfg_add_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet); -int facemgr_cfg_remove_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet, - facelet_t ** removed_facelet); -int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t * cfg, facelet_t *** array); +int facemgr_cfg_get_face_type(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, + facemgr_face_type_t* face_type); +int facemgr_cfg_get_discovery(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, bool* discovery); +int facemgr_cfg_get_ignore(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, bool* ignore); +int facemgr_cfg_get_ipv4(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, + netdevice_type_t netdevice_type, bool* ipv4); +int facemgr_cfg_get_ipv6(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, + netdevice_type_t netdevice_type, bool* ipv6); +int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, + int family, hicn_ip_address_t* addr); +int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, + int family, u16* port); +int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, + int family, hicn_ip_address_t* addr); +int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t* cfg, + const netdevice_t* netdevice, + netdevice_type_t netdevice_type, + int family, u16* port); + +int facemgr_cfg_rule_get(const facemgr_cfg_t* cfg, const netdevice_t netdevice, + netdevice_type_t netdevice_type, + facemgr_cfg_rule_t** rule); +int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t* cfg_rule, + facemgr_face_type_t* face_type); +int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t* cfg_rule, + bool* status); +int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t* cfg_rule, + bool* status); +int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t* cfg_rule, bool* status); +int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t* cfg_rule, bool* status); +int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t* rule, + int family, + hicn_ip_address_t* addr); +int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t* rule, + int family, uint16_t* port); +int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t* rule, + int family, + hicn_ip_address_t* addr); +int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t* rule, + int family, uint16_t* port); + +int facemgr_cfg_add_static_facelet(facemgr_cfg_t* cfg, facelet_t* facelet); +int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t* cfg, + facelet_t*** array); #endif /* FACEMGR_CFG_H */ diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h index cfdc5540e..9b04832b3 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h +++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -28,7 +28,7 @@ #include <stdbool.h> -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include <hicn/ctrl/route.h> #define MAXSZ_FACELET 1024 @@ -36,111 +36,111 @@ #define FACELET_MAX_ERRORS 10 /* NOTE: Any test should be sufficient */ -#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0')) +#define IS_VALID_NETDEVICE(netdevice) \ + ((netdevice.index != 0) && (netdevice.name[0] != '\0')) typedef struct facelet_s facelet_t; /* Face type */ #define foreach_face_type_layer \ - _(UNDEFINED) \ - _(3) \ - _(4) \ - _(N) + _(UNDEFINED) \ + _(3) \ + _(4) \ + _(N) typedef enum { -#define _(x) FACE_TYPE_LAYER_ ## x, - foreach_face_type_layer +#define _(x) FACE_TYPE_LAYER_##x, + foreach_face_type_layer #undef _ } face_type_layer_t; #define foreach_face_type_encap \ - _(UNDEFINED) \ - _(TCP) \ - _(UDP) \ - _(N) + _(UNDEFINED) \ + _(TCP) \ + _(UDP) \ + _(N) typedef enum { -#define _(x) FACE_TYPE_ENCAP_ ## x, - foreach_face_type_encap +#define _(x) FACE_TYPE_ENCAP_##x, + foreach_face_type_encap #undef _ } face_type_encap_t; typedef struct { - face_type_layer_t layer; - face_type_encap_t encap; + face_type_layer_t layer; + face_type_encap_t encap; } facemgr_face_type_t; +extern const char* face_type_layer_str[]; +extern const char* face_type_encap_str[]; -extern const char * face_type_layer_str[]; -extern const char * face_type_encap_str[]; +#define FACEMGR_FACE_TYPE_STR(x) \ + face_type_layer_str[x.layer], face_type_encap_str[x.encap] -#define FACEMGR_FACE_TYPE_STR(x) \ - face_type_layer_str[x.layer], face_type_encap_str[x.encap] +#define FACEMGR_FACE_TYPE_UNDEFINED \ + (facemgr_face_type_t) { \ + .layer = FACE_TYPE_LAYER_UNDEFINED, .encap = FACE_TYPE_ENCAP_UNDEFINED, \ + } -#define FACEMGR_FACE_TYPE_UNDEFINED (facemgr_face_type_t) { \ - .layer = FACE_TYPE_LAYER_UNDEFINED, \ - .encap = FACE_TYPE_ENCAP_UNDEFINED, \ -} +#define FACEMGR_FACE_TYPE_NATIVE_UDP \ + (facemgr_face_type_t) { \ + .layer = FACE_TYPE_LAYER_3, .encap = FACE_TYPE_ENCAP_UDP, \ + } -#define FACEMGR_FACE_TYPE_NATIVE_UDP (facemgr_face_type_t) { \ - .layer = FACE_TYPE_LAYER_3, \ - .encap = FACE_TYPE_ENCAP_UDP, \ -} +#define FACEMGR_FACE_TYPE_NATIVE_TCP \ + (facemgr_face_type_t) { \ + .layer = FACE_TYPE_LAYER_3, .encap = FACE_TYPE_ENCAP_TCP, \ + } -#define FACEMGR_FACE_TYPE_NATIVE_TCP (facemgr_face_type_t) { \ - .layer = FACE_TYPE_LAYER_3, \ - .encap = FACE_TYPE_ENCAP_TCP, \ -} +#define FACEMGR_FACE_TYPE_OVERLAY_UDP \ + (facemgr_face_type_t) { \ + .layer = FACE_TYPE_LAYER_4, .encap = FACE_TYPE_ENCAP_UDP, \ + } -#define FACEMGR_FACE_TYPE_OVERLAY_UDP (facemgr_face_type_t) { \ - .layer = FACE_TYPE_LAYER_4, \ - .encap = FACE_TYPE_ENCAP_UDP, \ -} - -#define FACEMGR_FACE_TYPE_OVERLAY_TCP (facemgr_face_type_t) { \ - .layer = FACE_TYPE_LAYER_4, \ - .encap = FACE_TYPE_ENCAP_TCP, \ -} +#define FACEMGR_FACE_TYPE_OVERLAY_TCP \ + (facemgr_face_type_t) { \ + .layer = FACE_TYPE_LAYER_4, .encap = FACE_TYPE_ENCAP_TCP, \ + } /* Facelet status */ -#define foreach_facelet_status \ - _(UNDEFINED) \ - _(DOWN) \ - _(UNCERTAIN) \ - _(INCOMPLETE) \ - _(CREATE) \ - _(CLEAN) \ - _(IGNORED) \ - _(UPDATE) \ - _(DELETE) \ - _(DELETED) \ - _(N) +#define foreach_facelet_status \ + _(UNDEFINED) \ + _(DOWN) \ + _(UNCERTAIN) \ + _(INCOMPLETE) \ + _(CREATE) \ + _(CLEAN) \ + _(IGNORED) \ + _(UPDATE) \ + _(DELETE) \ + _(DELETED) \ + _(N) typedef enum { -#define _(x) FACELET_STATUS_ ## x, - foreach_facelet_status +#define _(x) FACELET_STATUS_##x, + foreach_facelet_status #undef _ } facelet_status_t; -extern const char * facelet_status_str[]; +extern const char* facelet_status_str[]; /* Facelet error reason */ -#define foreach_facelet_error_reason \ - _(UNDEFINED) \ - _(UNSPECIFIED_ERROR) \ - _(FORWARDER_OFFLINE) \ - _(PERMISSION_DENIED) \ - _(INTERNAL_ERROR) \ - _(N) +#define foreach_facelet_error_reason \ + _(UNDEFINED) \ + _(UNSPECIFIED_ERROR) \ + _(FORWARDER_OFFLINE) \ + _(PERMISSION_DENIED) \ + _(INTERNAL_ERROR) \ + _(N) typedef enum { -#define _(x) FACELET_ERROR_REASON_ ## x, - foreach_facelet_error_reason +#define _(x) FACELET_ERROR_REASON_##x, + foreach_facelet_error_reason #undef _ } facelet_error_reason_t; -extern const char * facelet_error_reason_str[]; +extern const char* facelet_error_reason_str[]; /* Facelet attribute status */ @@ -148,62 +148,48 @@ extern const char * facelet_error_reason_str[]; * We expect an attribute in the cache to be able to take any value but * UNDEFINED and N, which facelet events should either be UNSET or CLEAN */ -#define foreach_facelet_attr_status \ - _(UNDEFINED, '?') \ - _(UNSET, 'X') \ - _(CLEAN, ' ') \ - _(DIRTY, '*') \ - _(PENDING, 'P') \ - _(CONFLICT, '!') \ - _(N, '-') +#define foreach_facelet_attr_status \ + _(UNDEFINED, '?') \ + _(UNSET, 'X') \ + _(CLEAN, ' ') \ + _(DIRTY, '*') \ + _(PENDING, 'P') \ + _(CONFLICT, '!') \ + _(N, '-') typedef enum { -#define _(x, y) FACELET_ATTR_STATUS_ ## x, - foreach_facelet_attr_status +#define _(x, y) FACELET_ATTR_STATUS_##x, + foreach_facelet_attr_status #undef _ } facelet_attr_status_t; -extern const char * facelet_attr_status_str[]; -extern const char * facelet_attr_status_str_short[]; +extern const char* facelet_attr_status_str[]; +extern const char* facelet_attr_status_str_short[]; /* Facelet attribute */ -#ifdef WITH_POLICY -#define foreach_facelet_attr \ - _(netdevice_type_t, netdevice_type) \ - _(netdevice_t, netdevice) \ - _(int, family) \ - _(ip_address_t, local_addr) \ - _(u16, local_port) \ - _(ip_address_t, remote_addr) \ - _(u16, remote_port) \ - _(face_state_t, admin_state) \ - _(face_state_t, state) \ - _(u32, priority) \ - _(facemgr_face_type_t, face_type) -#else -#define foreach_facelet_attr \ - _(netdevice_type_t, netdevice_type) \ - _(netdevice_t, netdevice) \ - _(int, family) \ - _(ip_address_t, local_addr) \ - _(u16, local_port) \ - _(ip_address_t, remote_addr) \ - _(u16, remote_port) \ - _(face_state_t, admin_state) \ - _(face_state_t, state) \ - _(facemgr_face_type_t, face_type) -#endif /* WITH_POLICY */ - -#define foreach_facelet_event \ - _(UNDEFINED) \ - _(GET) \ - _(CREATE) \ - _(UPDATE) \ - _(DELETE) \ - _(SET_UP) \ - _(SET_DOWN) \ - _(N) +#define foreach_facelet_attr \ + _(netdevice_type_t, netdevice_type) \ + _(netdevice_t, netdevice) \ + _(int, family) \ + _(hicn_ip_address_t, local_addr) \ + _(u16, local_port) \ + _(hicn_ip_address_t, remote_addr) \ + _(u16, remote_port) \ + _(face_state_t, admin_state) \ + _(face_state_t, state) \ + _(u32, priority) \ + _(facemgr_face_type_t, face_type) + +#define foreach_facelet_event \ + _(UNDEFINED) \ + _(GET) \ + _(CREATE) \ + _(UPDATE) \ + _(DELETE) \ + _(SET_UP) \ + _(SET_DOWN) \ + _(N) #define MAXSZ_EVENT__ 10 #define MAXSZ_EVENT_ MAXSZ_EVENT_ + 1 @@ -212,37 +198,37 @@ extern const char * facelet_attr_status_str_short[]; * \brief Enumeration of the possible types of event */ typedef enum { -#define _(x) FACELET_EVENT_ ## x, -foreach_facelet_event +#define _(x) FACELET_EVENT_##x, + foreach_facelet_event #undef _ } facelet_event_t; -extern const char * facelet_event_str[]; +extern const char* facelet_event_str[]; /** * \brief Create a facelet. */ -facelet_t * facelet_create(); +facelet_t* facelet_create(); -facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice); +facelet_t* facelet_create_from_netdevice(netdevice_t* netdevice); -unsigned facelet_get_id(facelet_t * facelet); -void facelet_set_id(facelet_t * facelet, unsigned id); +unsigned facelet_get_id(facelet_t* facelet); +void facelet_set_id(facelet_t* facelet, unsigned id); -int facelet_validate_face(const facelet_t * facelet); +int facelet_validate_face(const facelet_t* facelet); -facelet_t * facelet_create_from_face(face_t * face); +facelet_t* facelet_create_from_face(face_t* face); -void facelet_free(facelet_t * facelet); +void facelet_free(facelet_t* facelet); -facelet_t * facelet_dup(const facelet_t * current_facelet); +facelet_t* facelet_dup(const facelet_t* current_facelet); -int facelet_cmp(const facelet_t * f1, const facelet_t * f2); +int facelet_cmp(const facelet_t* f1, const facelet_t* f2); -bool facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2); +bool facelet_equals(const facelet_t* facelet1, const facelet_t* facelet2); /* NOTE: only clean attributes are matched */ -bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match); +bool facelet_match(const facelet_t* facelet, const facelet_t* facelet_match); /** * \brief Returns whether the specified facelet has all key attributes defined. @@ -251,55 +237,58 @@ bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match); * uniquely identify a facelet, otherwise it is a 'wildcard' facelet * specification and might match several facelets. */ -bool facelet_has_key(const facelet_t * facelet); +bool facelet_has_key(const facelet_t* facelet); -#define FACELET_ACCESSORS_H(TYPE, NAME) \ -bool facelet_has_ ## NAME(const facelet_t * facelet); \ -facelet_attr_status_t facelet_get_ ## NAME ## _status(const facelet_t * facelet);\ -void facelet_set_ ## NAME ## _status(facelet_t * facelet, \ - facelet_attr_status_t status); \ -int facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME); \ -int facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME); \ -int facelet_unset_ ## NAME(facelet_t * facelet); +#define FACELET_ACCESSORS_H(TYPE, NAME) \ + bool facelet_has_##NAME(const facelet_t* facelet); \ + facelet_attr_status_t facelet_get_##NAME##_status(const facelet_t* facelet); \ + void facelet_set_##NAME##_status(facelet_t* facelet, \ + facelet_attr_status_t status); \ + int facelet_get_##NAME(const facelet_t* facelet, TYPE* NAME); \ + int facelet_set_##NAME(facelet_t* facelet, TYPE NAME); \ + int facelet_unset_##NAME(facelet_t* facelet); #define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME) foreach_facelet_attr #undef _ -int facelet_get_face(const facelet_t * facelet, face_t ** pface); + int + facelet_get_face(const facelet_t* facelet, face_t** pface); -int facelet_merge(facelet_t * facelet, facelet_t * facelet_to_merge); +int facelet_merge(facelet_t* facelet, facelet_t* facelet_to_merge); -facelet_status_t facelet_get_status(const facelet_t * facelet); -void facelet_set_status(facelet_t * facelet, facelet_status_t status); -void facelet_set_attr_clean(facelet_t * facelet); +facelet_status_t facelet_get_status(const facelet_t* facelet); +void facelet_set_status(facelet_t* facelet, facelet_status_t status); +void facelet_set_attr_clean(facelet_t* facelet); -void facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason); -void facelet_unset_error(facelet_t * facelet); -bool facelet_get_error(const facelet_t * facelet); +void facelet_set_error(facelet_t* facelet, facelet_error_reason_t reason); +void facelet_unset_error(facelet_t* facelet); +bool facelet_get_error(const facelet_t* facelet); -void facelet_set_bj_done(facelet_t * facelet); -void facelet_unset_bj_done(facelet_t * facelet); -bool facelet_is_bj_done(const facelet_t * facelet); -void facelet_set_au_done(facelet_t * facelet); -bool facelet_is_au_done(const facelet_t * facelet); +void facelet_set_bj_done(facelet_t* facelet); +void facelet_unset_bj_done(facelet_t* facelet); +bool facelet_is_bj_done(const facelet_t* facelet); -facelet_event_t facelet_get_event(const facelet_t * facelet); -void facelet_set_event(facelet_t * facelet, facelet_event_t event); +facelet_event_t facelet_get_event(const facelet_t* facelet); +void facelet_set_event(facelet_t* facelet, facelet_event_t event); -int facelet_add_route(facelet_t * facelet, hicn_route_t * route); -int facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed); -int facelet_clear_routes(facelet_t * facelet); -int facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array); +int facelet_add_route(facelet_t* facelet, hicn_route_t* route); +int facelet_remove_route(facelet_t* facelet, hicn_route_t* route, + hicn_route_t** route_removed); +int facelet_clear_routes(facelet_t* facelet); +int facelet_get_route_array(const facelet_t* facelet, + hicn_route_t*** route_array); -int facelet_snprintf(char * buf, size_t size, const facelet_t * facelet); +int facelet_snprintf(char* buf, size_t size, const facelet_t* facelet); -#define DUMP_FACELET(msg, facelet) do { \ - char buf[MAXSZ_FACELET]; \ - facelet_snprintf(buf, MAXSZ_FACELET, facelet); \ - DEBUG("%s : %s", msg, buf); \ -} while(0) +#define DUMP_FACELET(msg, facelet) \ + do { \ + char buf[MAXSZ_FACELET]; \ + facelet_snprintf(buf, MAXSZ_FACELET, facelet); \ + DEBUG("%s : %s", msg, buf); \ + } while (0) -int facelet_snprintf_json(char * buf, size_t size, const facelet_t * facelet, int indent); +int facelet_snprintf_json(char* buf, size_t size, const facelet_t* facelet, + int indent); #endif /* FACEMGR_FACELET_H */ diff --git a/ctrl/facemgr/includes/hicn/facemgr/loop.h b/ctrl/facemgr/includes/hicn/facemgr/loop.h index 752a3b365..3965a1f27 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/loop.h +++ b/ctrl/facemgr/includes/hicn/facemgr/loop.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,23 +25,21 @@ /* fd & timer callbacks */ -typedef int (*fd_callback_t)(void * owner, int fd, void * data); +typedef int (*fd_callback_t)(void *owner, int fd, void *data); typedef struct { - int fd; - void *owner; - fd_callback_t callback; - //int (*callback)(void * owner, int fd, void * data); - void *data; + int fd; + void *owner; + fd_callback_t callback; + void *data; } fd_callback_data_t; /* timer callbacks */ typedef struct { - unsigned delay_ms; - void *owner; - fd_callback_t callback; - //int (*callback)(void * owner, int fd, void * data); - void *data; + unsigned delay_ms; + void *owner; + fd_callback_t callback; + void *data; } timer_callback_data_t; /* loop */ @@ -52,33 +50,32 @@ typedef struct loop_s loop_t; * \brief Creates a main loop * \return Pointer to the newly created loop, or NULL in case of error */ -loop_t * loop_create(); +loop_t *loop_create(); /** * \brief Releases a loop instance and frees all associated memory * \param [in] loop - Pointer to the loop instance to free */ -void loop_free(loop_t * loop); +void loop_free(loop_t *loop); /** * \brief Runs the loop instance to process events * \param [in] loop - Pointer to the loop instance * \return 0 if successful, -1 otherwise */ -int loop_dispatch(loop_t * loop); +int loop_dispatch(loop_t *loop); /** * \brief Terminates the dispatching of events * \param [in] loop - Pointer to the loop instance */ -int loop_undispatch(loop_t * loop); +int loop_undispatch(loop_t *loop); /** * \brief Breaks out of the loop * \param [in] loop - Pointer to the loop instance */ -void loop_break(loop_t * loop); - +void loop_break(loop_t *loop); /** * \brief Callback for loop helpers @@ -86,6 +83,6 @@ void loop_break(loop_t * loop); * \param [in] type - Type of service to be requested * \param [in] data - Service specific data */ -int loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data); +int loop_callback(loop_t *loop, facemgr_cb_type_t type, void *data); #endif /* FACEMGR_LOOP_H */ diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt index cf5606e04..87938fb57 100644 --- a/ctrl/facemgr/src/CMakeLists.txt +++ b/ctrl/facemgr/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -12,130 +12,157 @@ # limitations under the License. if(UNIX AND NOT APPLE) - set(LINUX TRUE) + set(LINUX TRUE) endif() -set(COMPILER_DEFINITIONS - "-DWITH_POLICY" -) +############################################################## +# Sources +############################################################## set(HEADER_FILES - common.h - error.h - facelet_array.h - interface.h - loop.h + common.h + error.h + facelet_array.h + interface.h + loop.h ) set(SOURCE_FILES - api.c - cfg.c - cfg_file.c - error.c - facelet.c - facelet_array.c - interface.c + api.c + cfg.c + cfg_file.c + error.c + facelet.c + facelet_array.c + interface.c ) if(APPLE) -set(SOURCE_FILES + set(SOURCE_FILES ${SOURCE_FILES} loop_dispatcher.c -) + ) endif() if (LINUX) -set(SOURCE_FILES + set(SOURCE_FILES ${SOURCE_FILES} loop_libevent.c -) + ) endif() +add_subdirectory(interfaces) + + +############################################################## +# Include directories +############################################################## set(INCLUDE_DIRS - ./ - ../includes/ - ${HICN_INCLUDE_DIRS} - ${LIBHICNCTRL_INCLUDE_DIRS} - ${CONFIG_INCLUDE_DIR} - ${LIBEVENT_INCLUDE_DIR} + PRIVATE ./ + PRIVATE ${CONFIG_INCLUDE_DIR} + PRIVATE ${LIBEVENT_INCLUDE_DIR} + PUBLIC + $<BUILD_INTERFACE:${LIBFACEMGR_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) + +############################################################## +# Libraries to link +############################################################## set(LIBRARIES - m - ${HICN_LIBRARIES} - ${LIBHICNCTRL_LIBRARIES} - ${LIBCONFIG_LIBRARIES} - ${LIBEVENT_LIBRARY} + PUBLIC ${HICN_LIBRARIES} + PUBLIC ${LIBHICNCTRL_LIBRARIES} + PRIVATE m + PRIVATE ${LIBCONFIG_LIBRARIES} + PRIVATE ${LIBEVENT_LIBRARY} ) -set(FACEMGR_LIBRARY_LIST "${LIBCONFIG_LIBRARIES};${LIBEVENT_LIBRARY}" CACHE INTERNAL "FACEMGR_LIBRARY_LIST") +if(WITH_THREAD) + set(LIBRARIES + ${LIBRARIES} + "pthread" + "event_pthreads" + ) + set(COMPILER_DEFINITIONS + ${COMPILER_DEFINITIONS} + "-DWITH_THREAD" + ) +endif() -add_subdirectory(interfaces) +############################################################## +# Compiler definitions +############################################################## if(WITH_THREAD) - set(LIBRARIES - ${LIBRARIES} - "pthread" - "event_pthreads" - ) - set(COMPILER_DEFINITIONS - ${COMPILER_DEFINITIONS} - "-DWITH_THREAD" - ) + list(APPEND COMPILER_DEFINITIONS + "-DWITH_THREAD" + ) endif() if(WITH_EXAMPLE_DUMMY) - set(COMPILER_DEFINITIONS - ${COMPILER_DEFINITIONS} - "-DWITH_EXAMPLE_DUMMY" - ) + list(APPEND COMPILER_DEFINITIONS + "-DWITH_EXAMPLE_DUMMY" + ) endif() if(WITH_EXAMPLE_UPDOWN) - set(COMPILER_DEFINITIONS - ${COMPILER_DEFINITIONS} - "-DWITH_EXAMPLE_UPDOWN" - ) + list(APPEND COMPILER_DEFINITIONS + "-DWITH_EXAMPLE_UPDOWN" + ) endif() + +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + + +############################################################## +# Build type +############################################################## if (DISABLE_SHARED_LIBRARIES) - build_library(${LIBFACEMGR} - STATIC - SOURCES ${SOURCE_FILES} - INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} - DEPENDS ${DEPENDENCIES} - LINK_LIBRARIES ${LIBRARIES} - COMPONENT ${FACEMGR} - INCLUDE_DIRS ${INCLUDE_DIRS} - HEADER_ROOT_DIR hicn - DEFINITIONS ${COMPILER_DEFINITIONS} - ) + set(LINK_TYPE STATIC) else () - build_library(${LIBFACEMGR} - SHARED STATIC NO_DEV - SOURCES ${SOURCE_FILES} - INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} - DEPENDS ${DEPENDENCIES} - LINK_LIBRARIES ${LIBRARIES} - COMPONENT ${FACEMGR} - INCLUDE_DIRS ${INCLUDE_DIRS} - HEADER_ROOT_DIR hicn - DEFINITIONS ${COMPILER_DEFINITIONS} - ) + set(LINK_TYPE SHARED STATIC) endif () + +############################################################## +# Build libfacemgr +############################################################## +build_library(${LIBFACEMGR} + ${LINK_TYPE} + SOURCES ${SOURCE_FILES} + INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} + DEPENDS ${DEPENDENCIES} + LINK_LIBRARIES ${LIBRARIES} + COMPONENT ${FACEMGR} + INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS} + DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} +) + + +############################################################## +# Build executable +############################################################## if(NOT DISABLE_EXECUTABLES) - list(APPEND DAEMON_SRC - main.c - ) - - build_executable(${FACEMGR} - SOURCES ${DAEMON_SRC} - LINK_LIBRARIES ${LIBFACEMGR}.static ${LIBRARIES} - DEPENDS ${LIBFACEMGR}.static - COMPONENT ${FACEMGR} - INCLUDE_DIRS ${INCLUDE_DIRS} - DEFINITIONS ${COMPILER_DEFINITIONS} - ) + list(APPEND DAEMON_SRC + main.c + ) + + build_executable(${FACEMGR} + SOURCES ${DAEMON_SRC} + LINK_LIBRARIES PRIVATE ${LIBFACEMGR}.static + DEPENDS ${LIBFACEMGR}.static + COMPONENT ${FACEMGR} + INCLUDE_DIRS ${INCLUDE_DIRS} + DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} + ) endif () diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c index dfbd24bcb..f271b24c7 100644 --- a/ctrl/facemgr/src/api.c +++ b/ctrl/facemgr/src/api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,22 +21,14 @@ #ifdef __ANDROID__ /* - * Use FacemgrUtility to determine interface types - * - * NOTE: this is currently disabled as SDK APIs do not allow to determine the - * type of interfaces that are DOWN - */ -//#define WITH_FACEMGR_UTILITY - -/* * Use priority controller interface */ -#define WITH_PRIORITY_CONTROLLER +//#define WITH_PRIORITY_CONTROLLER /* * Dump facelets (debug) */ -//#define WITH_DUMP +#define WITH_DUMP 1 /* * Allow priority setting before interface is actually created @@ -62,15 +54,14 @@ #ifdef __linux__ #include "interfaces/bonjour/bonjour.h" +#ifdef __ANDROID__ +#include "interfaces/android/android.h" +#endif /* __ANDROID__ */ #endif /* __linux__ */ -#ifdef WITH_FACEMGR_UTILITY -#include "interfaces/android_utility/android_utility.h" -#endif /* WITH_FACEMGR_UTILITY */ - #include "interfaces/priority_controller/priority_controller.h" -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include <hicn/facemgr/facelet.h> #include "common.h" #include "facelet_array.h" @@ -84,19 +75,21 @@ #define MAX_FDS 10 typedef struct { - interface_t * interface; - int fds[MAX_FDS]; - size_t num_fds; + interface_t *interface; + int fds[MAX_FDS]; + size_t num_fds; } interface_map_data_t; TYPEDEF_SET_H(facelet_set, facelet_t *); TYPEDEF_SET(facelet_set, facelet_t *, facelet_cmp, facelet_snprintf); TYPEDEF_MAP_H(interface_map, const char *, interface_map_data_t *); -TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, string_snprintf, generic_snprintf); +TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, + string_snprintf, generic_snprintf); TYPEDEF_MAP_H(bonjour_map, netdevice_t *, interface_t *); -TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_snprintf, generic_snprintf); +TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, + generic_snprintf, generic_snprintf); /* TODO automatically register interfaces */ @@ -104,12 +97,13 @@ TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_sn extern interface_ops_t network_framework_ops; #endif #ifdef __linux__ +#ifdef __ANDROID__ +extern interface_ops_t android_ops; +#else extern interface_ops_t netlink_ops; +#endif /* __ANDROID__ */ extern interface_ops_t bonjour_ops; #endif -#ifdef WITH_FACEMGR_UTILITY -extern interface_ops_t android_utility_ops; -#endif /* WITH_FACEMGR_UTILITY */ #ifdef WITH_PRIORITY_CONTROLLER extern interface_ops_t priority_controller_ops; #endif @@ -121,458 +115,424 @@ extern interface_ops_t updown_ops; #endif extern interface_ops_t hicn_light_ops; -int facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet); +int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet); -int -facemgr_overlay_snprintf(char * s, size_t size, const facemgr_overlay_t * overlay) -{ - return -1; +int facemgr_overlay_snprintf(char *s, size_t size, + const facemgr_overlay_t *overlay) { + return -1; } struct facemgr_s { - /**************************************************/ - /* Configuration parameters (exposed through API) */ + /**************************************************/ + /* Configuration parameters (exposed through API) */ - facemgr_cfg_t * cfg; + facemgr_cfg_t *cfg; #ifdef __ANDROID__ - /* - * Those two pointers are needed to call java functions from the face - * manager. - */ - JavaVM *jvm; + /* + * Those two pointers are needed to call java functions from the face + * manager. + */ + JavaVM *jvm; #endif /* __ANDROID__ */ - /* Callback */ - facemgr_cb_t callback; - void * callback_owner; + /* Callback */ + facemgr_cb_t callback; + void *callback_owner; - /****************************/ - /* Internal data structures */ + /****************************/ + /* Internal data structures */ - /* Map of interfaces index by name */ - interface_map_t * interface_map; + /* Map of interfaces index by name */ + interface_map_t *interface_map; - /* Faces under construction */ - facelet_set_t * facelet_cache; + /* Faces under construction */ + facelet_set_t *facelet_cache; - /* Static facelets */ - facelet_array_t * static_facelets; + /* Static facelets */ + facelet_array_t *static_facelets; #ifdef WITH_DEFAULT_PRIORITIES - /* Default priorities */ - u32 default_priority[NETDEVICE_TYPE_N+1]; + /* Default priorities */ + u32 default_priority[NETDEVICE_TYPE_N + 1]; #endif /* WITH_DEFAULT_PRIORITIES */ - /********************************************************/ - /* Interfaces - Those should be fully replaced by a map */ - - interface_t * hl; + /********************************************************/ + /* Interfaces - Those should be fully replaced by a map */ -#ifdef WITH_FACEMGR_UTILITY - interface_t * au; /* android_utility */ -#endif /* WITH_FACEMGR_UTILITY */ + interface_t *hl; #ifdef WITH_PRIORITY_CONTROLLER - interface_t * pc; + interface_t *pc; #endif #ifdef __APPLE__ - interface_t * nf; /* network_framework */ -#endif /* __APPLE__ */ + interface_t *nf; /* network_framework */ +#endif /* __APPLE__ */ #ifdef __linux__ - interface_t * nl; /* netlink */ - /* - * We maintain a map of dynamically created bonjour interfaces, one for each - * found netdevice - */ - bonjour_map_t * bonjour_map; +#ifdef __ANDROID__ + interface_t *android; +#else + interface_t *nl; /* netlink */ +#endif /* __ANDROID__ */ + /* + * We maintain a map of dynamically created bonjour interfaces, one for each + * found netdevice + */ + bonjour_map_t *bonjour_map; #endif /* __linux__ */ #ifdef WITH_EXAMPLE_DUMMY - interface_t * dummy; + interface_t *dummy; #endif #ifdef WITH_EXAMPLE_UPDOWN - interface_t * updown; + interface_t *updown; #endif - int timer_fd; /* Timer used for reattempts */ + int timer_fd; /* Timer used for reattempts */ - int cur_static_id; /* Used to distinguish static faces (pre-incremented) */ + int cur_static_id; /* Used to distinguish static faces (pre-incremented) */ }; -int -facemgr_initialize(facemgr_t * facemgr) -{ - facemgr->interface_map = interface_map_create(); - if (!facemgr->interface_map) { - ERROR("[facemgr_initialize] Error creating interface map"); - goto ERR_INTERFACE_MAP; - } - - facemgr->facelet_cache = facelet_set_create(); - if (!facemgr->facelet_cache) { - ERROR("[facemgr_initialize] Error creating interface map"); - goto ERR_FACE_CACHE_PENDING; - } - - facemgr->static_facelets = facelet_array_create(); - if (!facemgr->static_facelets) { - ERROR("[facemgr_initialize] Error creating interface map"); - goto ERR_STATIC; - } +int facemgr_initialize(facemgr_t *facemgr) { + facemgr->interface_map = interface_map_create(); + if (!facemgr->interface_map) { + ERROR("[facemgr_initialize] Error creating interface map"); + goto ERR_INTERFACE_MAP; + } + + facemgr->facelet_cache = facelet_set_create(); + if (!facemgr->facelet_cache) { + ERROR("[facemgr_initialize] Error creating interface map"); + goto ERR_FACE_CACHE_PENDING; + } + + facemgr->static_facelets = facelet_array_create(); + if (!facemgr->static_facelets) { + ERROR("[facemgr_initialize] Error creating interface map"); + goto ERR_STATIC; + } #ifdef __linux__ - facemgr->bonjour_map = bonjour_map_create(); - if (!facemgr->bonjour_map) { - ERROR("[facemgr_initialize] Error creating bonjour map"); - goto ERR_BJ; - } + facemgr->bonjour_map = bonjour_map_create(); + if (!facemgr->bonjour_map) { + ERROR("[facemgr_initialize] Error creating bonjour map"); + goto ERR_BJ; + } #endif /* __linux */ - facemgr->cfg = facemgr_cfg_create(); - if (!facemgr->cfg) { - ERROR("[facemgr_initialize] Error creating face manager configuration"); - goto ERR_CFG; - } + facemgr->cfg = facemgr_cfg_create(); + if (!facemgr->cfg) { + ERROR("[facemgr_initialize] Error creating face manager configuration"); + goto ERR_CFG; + } - facemgr->timer_fd = 0; - facemgr->cur_static_id = 0; + facemgr->timer_fd = 0; + facemgr->cur_static_id = 0; #ifdef WITH_DEFAULT_PRIORITIES -#define _(x) facemgr->default_priority[NETDEVICE_TYPE_ ## x] = 0; -foreach_netdevice_type +#define _(x) facemgr->default_priority[NETDEVICE_TYPE_##x] = 0; + foreach_netdevice_type #undef _ #endif /* WITH_DEFAULT_PRIORITIES */ - return 0; + return 0; ERR_CFG: #ifdef __linux__ - bonjour_map_free(facemgr->bonjour_map); + bonjour_map_free(facemgr->bonjour_map); ERR_BJ: #endif /* __linux__ */ - facelet_array_free(facemgr->static_facelets); + facelet_array_free(facemgr->static_facelets); ERR_STATIC: - facelet_set_free(facemgr->facelet_cache); + facelet_set_free(facemgr->facelet_cache); ERR_FACE_CACHE_PENDING: - interface_map_free(facemgr->interface_map); + interface_map_free(facemgr->interface_map); ERR_INTERFACE_MAP: - return -1; + return -1; } -int -facemgr_finalize(facemgr_t * facemgr) -{ - int ret = 0; - int rc; +int facemgr_finalize(facemgr_t *facemgr) { + int ret = 0; + int rc; - if (facemgr->timer_fd) { - rc = facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd); - if (rc < 0) { - ERROR("[facemgr_finalize] Error unregistering timer"); - ret = -1; - } - facemgr->timer_fd = 0; + if (facemgr->timer_fd) { + rc = + facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd); + if (rc < 0) { + ERROR("[facemgr_finalize] Error unregistering timer"); + ret = -1; } + facemgr->timer_fd = 0; + } - interface_map_free(facemgr->interface_map); + interface_map_free(facemgr->interface_map); - /* Free all facelets from cache */ - facelet_t ** facelet_array; - int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); - if (n < 0) { - ERROR("[facemgr_finalize] Could not retrieve facelets in cache"); - } else { - for (unsigned i = 0; i < n; i++) { - facelet_t * facelet = facelet_array[i]; - if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL)) { - ERROR("[facemgr_finalize] Could not purge facelet from cache"); - } - facelet_free(facelet); - } - free(facelet_array); + /* Free all facelets from cache */ + facelet_t **facelet_array; + int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); + if (n < 0) { + ERROR("[facemgr_finalize] Could not retrieve facelets in cache"); + } else { + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet = facelet_array[i]; + if (!facelet) continue; /* Should not occur */ + if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL)) { + ERROR("[facemgr_finalize] Could not purge facelet from cache"); + } + facelet_free(facelet); } + free(facelet_array); + } - facelet_set_free(facemgr->facelet_cache); + facelet_set_free(facemgr->facelet_cache); - /* Free all facelets from static array */ - for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) { - facelet_t * facelet; - if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) { - ERROR("[facemgr_cfg_finalize] Error getting facelet in array"); - continue; - } - if (facelet_array_remove_index(facemgr->static_facelets, i, NULL) < 0) { - ERROR("[facemgr_finalize] Could not purge facelet from static array"); - } - facelet_free(facelet); + /* Free all facelets from static array */ + n = (int)facelet_array_len(facemgr->static_facelets); + + INFO("Removing %d facelets from static array", n); + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet; + if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) { + ERROR("[facemgr_cfg_finalize] Error getting facelet in array"); + continue; + } + if (facelet_array_remove_index(facemgr->static_facelets, i, NULL) < 0) { + ERROR("[facemgr_finalize] Could not purge facelet from static array"); } + facelet_free(facelet); + } - facelet_array_free(facemgr->static_facelets); + facelet_array_free(facemgr->static_facelets); #ifdef __linux__ - bonjour_map_free(facemgr->bonjour_map); + bonjour_map_free(facemgr->bonjour_map); #endif /* __linux__ */ - interface_unregister_all(); + interface_unregister_all(); - return ret; + return ret; } AUTOGENERATE_CREATE_FREE(facemgr); -int -facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg) -{ - if (facemgr->cfg) { - facemgr_cfg_free(facemgr->cfg); - } - facemgr->cfg = cfg; - - /* Populate the initial list of static facelets */ - facelet_t ** facelet_array; - int n = facemgr_cfg_get_static_facelet_array(cfg, &facelet_array); - if (n < 0) { - ERROR("[facemgr_finalize] Could not retrieve static facelets from cfg"); - } else { - for (unsigned i = 0; i < n; i++) { - facelet_t * facelet = facelet_dup(facelet_array[i]); - facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); - facelet_set_attr_clean(facelet); - if (facelet_array_add(facemgr->static_facelets, facelet)) { - ERROR("[facemgr_finalize] Could not add static facelet to face manager"); - } - } +int facemgr_set_config(facemgr_t *facemgr, facemgr_cfg_t *cfg) { + if (facemgr->cfg) { + facemgr_cfg_free(facemgr->cfg); + } + facemgr->cfg = cfg; + + /* Populate the initial list of static facelets */ + facelet_t **facelet_array; + int n = facemgr_cfg_get_static_facelet_array(cfg, &facelet_array); + if (n < 0) { + ERROR("[facemgr_finalize] Could not retrieve static facelets from cfg"); + } else { + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet = facelet_dup(facelet_array[i]); + facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); + facelet_set_attr_clean(facelet); + if (facelet_array_add(facemgr->static_facelets, facelet)) { + ERROR( + "[facemgr_finalize] Could not add static facelet to face manager"); + } } + } - return 0; + return 0; } -int facemgr_reset_config(facemgr_t * facemgr) -{ - assert(facemgr->cfg); - facemgr_cfg_free(facemgr->cfg); - facemgr->cfg = facemgr_cfg_create(); - if (!facemgr->cfg) - return -1; - return 0; +int facemgr_reset_config(facemgr_t *facemgr) { + assert(facemgr->cfg); + facemgr_cfg_free(facemgr->cfg); + facemgr->cfg = facemgr_cfg_create(); + if (!facemgr->cfg) return -1; + return 0; } -facemgr_t * -facemgr_create_with_config(facemgr_cfg_t * cfg) -{ - facemgr_t * facemgr = facemgr_create(); - if (!facemgr) - return NULL; - int rc = facemgr_set_config(facemgr, cfg); - if (rc < 0) { - free(facemgr); - return NULL; - } - return facemgr; +facemgr_t *facemgr_create_with_config(facemgr_cfg_t *cfg) { + facemgr_t *facemgr = facemgr_create(); + if (!facemgr) return NULL; + int rc = facemgr_set_config(facemgr, cfg); + if (rc < 0) { + free(facemgr); + return NULL; + } + return facemgr; } /* * \brief Heuristics to determine face type based on name, until a better * solution is found */ -netdevice_type_t -facemgr_get_netdevice_type(const facemgr_t * facemgr, const char * interface_name) -{ - if (strncmp(interface_name, "lo", 2) == 0) { - return NETDEVICE_TYPE_LOOPBACK; - } - if ((strncmp(interface_name, "eth", 3) == 0) || - (strncmp(interface_name, "en", 2) == 0)) { - /* eth* en* enx* */ - return NETDEVICE_TYPE_WIRED; - } - if (strncmp(interface_name, "wl", 2) == 0) { - /* wlan* wlp* wlx* */ - return NETDEVICE_TYPE_WIFI; - } - if (strncmp(interface_name, "rmnet_ipa", 9) == 0) { - /* Qualcomm IPA driver */ - return NETDEVICE_TYPE_UNDEFINED; - } - if ((strncmp(interface_name, "rmnet", 5) == 0) || - (strncmp(interface_name, "rev_rmnet", 9) == 0) || - (strncmp(interface_name, "ccmni", 5) == 0)) { - /* - * rmnet* (Qualcomm) ccmni* (MediaTek) - */ - return NETDEVICE_TYPE_CELLULAR; - } - /* usb0 might be cellular (eg Zenfone2) */ - /* what about tethering */ - /* tun* dummy* ... */ - /* bnet* pan* hci* for bluetooth */ +netdevice_type_t facemgr_get_netdevice_type(const facemgr_t *facemgr, + const char *interface_name) { + if (strncmp(interface_name, "lo", 2) == 0) { + return NETDEVICE_TYPE_LOOPBACK; + } + if ((strncmp(interface_name, "eth", 3) == 0) || + (strncmp(interface_name, "en", 2) == 0)) { + /* eth* en* enx* */ + return NETDEVICE_TYPE_WIRED; + } + if (strncmp(interface_name, "wl", 2) == 0) { + /* wlan* wlp* wlx* */ + return NETDEVICE_TYPE_WIFI; + } + if (strncmp(interface_name, "rmnet_ipa", 9) == 0) { + /* Qualcomm IPA driver */ return NETDEVICE_TYPE_UNDEFINED; + } + if ((strncmp(interface_name, "rmnet", 5) == 0) || + (strncmp(interface_name, "rev_rmnet", 9) == 0) || + (strncmp(interface_name, "ccmni", 5) == 0)) { + /* + * rmnet* (Qualcomm) ccmni* (MediaTek) + */ + return NETDEVICE_TYPE_CELLULAR; + } + /* usb0 might be cellular (eg Zenfone2) */ + /* what about tethering */ + /* tun* dummy* ... */ + /* bnet* pan* hci* for bluetooth */ + return NETDEVICE_TYPE_UNDEFINED; } -int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data); - -int -facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * type, void * cfg, interface_t ** pinterface) -{ - char rand_name[RAND_NAME_LEN+1]; - interface_t * interface; - - if (!name) { - /* - * We can manipulate the name on the stack as it will be strdup'ed by - * interface_create - */ - rand_str(rand_name, RAND_NAME_LEN); - name = rand_name; - } - - INFO("Creating interface %s [%s]...", name, type); - interface = interface_create(name, type); - if (!interface) { - ERROR("Error creating interface %s [%s]", name, type); - goto ERR_CREATE; - } - interface_set_callback(interface, facemgr, facemgr_callback); +int facemgr_callback(facemgr_t *facemgr, interface_cb_type_t type, void *data); - interface_map_data_t * interface_map_data = malloc(sizeof(interface_map_data_t)); - if (!interface_map_data) - goto ERR_MAP_DATA; - - *interface_map_data = (interface_map_data_t) { - .interface = interface, - .fds = {0}, - .num_fds = 0, - }; - - if (interface_map_add(facemgr->interface_map, interface->name, interface_map_data) < 0) - goto ERR_MAP_ADD; +int facemgr_create_interface(facemgr_t *facemgr, const char *name, + const char *type, void *cfg, + interface_t **pinterface) { + char rand_name[RAND_NAME_LEN + 1]; + interface_t *interface; + if (!name) { /* - * This should be called _after_ the interface_map is initialized otherwise - * it will be impossible to register fds from *_initialize + * We can manipulate the name on the stack as it will be strdup'ed by + * interface_create */ - if (interface_initialize(interface, cfg) < 0) { - ERROR("[facemgr_create_interface] Error initializing interface"); - goto ERR_INIT; - } - - DEBUG("Interface %s created successfully.", name); - if (pinterface) - *pinterface = interface; - return 0; - - - //interface_finalize(interface); + rand_str(rand_name, RAND_NAME_LEN); + name = rand_name; + } + + INFO("Creating interface %s [%s]...", name, type); + interface = interface_create(name, type); + if (!interface) { + ERROR("Error creating interface %s [%s]", name, type); + goto ERR_CREATE; + } + interface_set_callback(interface, facemgr, facemgr_callback); + + interface_map_data_t *interface_map_data = + malloc(sizeof(interface_map_data_t)); + if (!interface_map_data) goto ERR_MAP_DATA; + + *interface_map_data = (interface_map_data_t){ + .interface = interface, + .fds = {0}, + .num_fds = 0, + }; + + if (interface_map_add(facemgr->interface_map, interface->name, + interface_map_data) < 0) + goto ERR_MAP_ADD; + + /* + * This should be called _after_ the interface_map is initialized otherwise + * it will be impossible to register fds from *_initialize + */ + if (interface_initialize(interface, cfg) < 0) { + ERROR("[facemgr_create_interface] Error initializing interface"); + goto ERR_INIT; + } + + DEBUG("Interface %s created successfully.", name); + if (pinterface) *pinterface = interface; + return 0; + + // interface_finalize(interface); ERR_INIT: - interface_map_remove(facemgr->interface_map, interface->name, NULL); + interface_map_remove(facemgr->interface_map, interface->name, NULL); ERR_MAP_ADD: - free(interface_map_data); + free(interface_map_data); ERR_MAP_DATA: - interface_free(interface); + interface_free(interface); ERR_CREATE: - if (pinterface) - *pinterface = NULL; - return -1; + if (pinterface) *pinterface = NULL; + return -1; } -int -facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface) -{ - int rc; +int facemgr_delete_interface(facemgr_t *facemgr, interface_t *interface) { + int rc; - interface_map_data_t * interface_map_data = NULL; + /* + * It is possible that one interface was never initialized, and thus the + * facemgr never started, and we still call stop(). This is for instance the + * case on Android (sdk 30) when netlink is blocked. + */ + if (!interface) return 0; - DEBUG("Removing interface %s", interface->name); - rc = interface_map_remove(facemgr->interface_map, interface->name, &interface_map_data); - if (rc < 0) - return -1; + interface_map_data_t *interface_map_data = NULL; - if (!interface_map_data) - return -1; - - for (unsigned i = 0; i < interface_map_data->num_fds; i++) { - int fd = interface_map_data->fds[i]; - fd_callback_data_t fd_callback_data = { - .fd = fd, - .owner = facemgr, - .callback = NULL, - .data = NULL, - }; - facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD, &fd_callback_data); - if (rc < 0) - WARN("[facemgr_delete_interface] Error unregistering fd %d for interface", fd); - } + DEBUG("Removing interface %s", interface->name); + rc = interface_map_remove(facemgr->interface_map, interface->name, + &interface_map_data); + if (rc < 0) return -1; - free(interface_map_data); + if (!interface_map_data) return -1; - interface_finalize(interface); - interface_free(interface); - - return 0; -} - -#ifdef __linux__ -int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice) -{ - interface_t * bj = NULL; - - int rc = bonjour_map_get(facemgr->bonjour_map, netdevice, &bj); + for (unsigned i = 0; i < interface_map_data->num_fds; i++) { + int fd = interface_map_data->fds[i]; + fd_callback_data_t fd_callback_data = { + .fd = fd, + .owner = facemgr, + .callback = NULL, + .data = NULL, + }; + facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD, + &fd_callback_data); if (rc < 0) - return rc; - - if (!bj) { - /* Create a new bonjour interface */ - bonjour_cfg_t bj_cfg = { - .netdevice = *netdevice, - }; - rc = facemgr_create_interface(facemgr, NULL, "bonjour", &bj_cfg, &bj); - if (rc < 0) { - ERROR("Error creating 'Bonjour' interface for '%s'\n", netdevice->name); - return -1; - } - } + WARN("[facemgr_delete_interface] Error unregistering fd %d for interface", + fd); + } + + free(interface_map_data); - DEBUG("sending event to bonjour interface"); + interface_finalize(interface); + interface_free(interface); - /* Send an event to the interface (GET ?) */ - // XXX error handling - return interface_on_event(bj, NULL); + return 0; } -#endif /* __linux__ */ -#ifdef WITH_FACEMGR_UTILITY -int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice) -{ - /* Send an event to the interface */ - facelet_t * facelet = facelet_create(); - if (!facelet) - goto ERR_MALLOC; +#ifdef __linux__ +int facemgr_query_bonjour(facemgr_t *facemgr, netdevice_t *netdevice) { + interface_t *bj = NULL; - int rc = facelet_set_netdevice(facelet, netdevice); - if (rc < 0) - goto ERR_ND; + int rc = bonjour_map_get(facemgr->bonjour_map, netdevice, &bj); + if (rc < 0) return rc; - rc = interface_on_event(facemgr->au, facelet); + if (!bj) { + /* Create a new bonjour interface */ + bonjour_cfg_t bj_cfg = { + .netdevice = *netdevice, + }; + rc = facemgr_create_interface(facemgr, NULL, "bonjour", &bj_cfg, &bj); if (rc < 0) { - // XXX error handling - goto ERR_EVENT; + ERROR("Error creating 'Bonjour' interface for '%s'\n", netdevice->name); + return -1; } + } - return 0; + DEBUG("sending event to bonjour interface"); -ERR_EVENT: -ERR_ND: - facelet_free(facelet); -ERR_MALLOC: - return -1; + /* Send an event to the interface (GET ?) */ + // XXX error handling + return interface_on_event(bj, NULL); } -#endif /* WITH_FACEMGR_UTILITY */ - +#endif /* __linux__ */ /** * \brief Performs a cache lookup to find matching facelets @@ -583,43 +543,38 @@ ERR_MALLOC: * \return The number of entries in the array in case of success (positive * value), or -1 in case of error. */ -int -facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet, - facelet_t ***cached_facelets) -{ - assert(facelet); - - /* ...otherwise, we iterate over the facelet - * cache to find matching elements. - */ - facelet_t ** facelet_array; - int n = facelet_set_get_array(facelet_cache, &facelet_array); - if (n < 0) { - ERROR("[facelet_cache_lookup] Error during cache match"); - return -1; - } - if (cached_facelets) - *cached_facelets = malloc(n * sizeof(facelet_t*)); +int facelet_cache_lookup(const facelet_set_t *facelet_cache, facelet_t *facelet, + facelet_t ***cached_facelets) { + assert(facelet); + + /* ...otherwise, we iterate over the facelet + * cache to find matching elements. + */ + facelet_t **facelet_array; + int n = facelet_set_get_array(facelet_cache, &facelet_array); + if (n < 0) { + ERROR("[facelet_cache_lookup] Error during cache match"); + return -1; + } + if (cached_facelets) *cached_facelets = malloc(n * sizeof(facelet_t *)); - int num_match = 0; - for (unsigned i = 0; i < n; i++) { + int num_match = 0; + for (unsigned i = 0; i < n; i++) { #if 0 - char facelet_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]); - DEBUG("cache entry #%d/%di = %s", i+1, n, facelet_s); + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]); + DEBUG("cache entry #%d/%di = %s", i + 1, n, facelet_s); #endif - if (!facelet_match(facelet_array[i], facelet)) { - continue; - } - if (cached_facelets) - (*cached_facelets)[num_match] = facelet_array[i]; - num_match++; - } - free(facelet_array); - return num_match; + facelet_t *f = facelet_array[i]; + if (!f) continue; /* Should not occur */ + if (!facelet_match(f, facelet)) continue; + if (cached_facelets) (*cached_facelets)[num_match] = f; + num_match++; + } + free(facelet_array); + return num_match; } - /** * \brief Checks whether the facelet satisfies face creation rules * \param [in] facemgr - Pointer to the face manager instance @@ -627,129 +582,92 @@ facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet, * \return 0 in case of success, -2 if we don't have enough information to * decide, -3 if the face does not satisfy rules, and -1 in case of error */ -int -facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet) -{ - /* As key, netdevice and family should always be present */ - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) { - ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet"); +int facemgr_facelet_satisfy_rules(facemgr_t *facemgr, facelet_t *facelet) { + /* As key, netdevice and family should always be present */ + netdevice_t netdevice = NETDEVICE_EMPTY; + int rc = facelet_get_netdevice(facelet, &netdevice); + if (rc < 0) { + ERROR( + "[facemgr_facelet_satisfy_rules] Error retrieving netdevice from " + "facelet"); + return -1; + } + + int family = AF_UNSPEC; + if (facelet_has_family(facelet)) { + if (facelet_get_family(facelet, &family) < 0) { + ERROR( + "[facemgr_facelet_satisfy_rules] Error retrieving family from " + "facelet"); + return -1; + } + } + + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + /* + * In addition to netdevice, netdevice_type should be present to correctly + * apply rules + */ + rc = facelet_get_netdevice_type(facelet, &netdevice_type); + if (rc < 0) { + ERROR( + "[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from " + "facelet"); + return -2; + } + + /* Default ignore list */ + if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || + (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) { + DEBUG("Ignored interface '%s/%s'...", netdevice.name, + netdevice_type_str(netdevice_type)); + return -3; + } + + /* Ignore */ + bool ignore; + if (facemgr_cfg_get_ignore(facemgr->cfg, &netdevice, netdevice_type, + &ignore) < 0) + return -1; + if (ignore) { + DEBUG("Ignored interface '%s/%s'...", netdevice.name, + netdevice_type_str(netdevice_type)); + return -3; + } + + switch (family) { + case AF_INET: { + bool ipv4; + if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type, + &ipv4) < 0) return -1; - } - - int family = AF_UNSPEC; - if (facelet_has_family(facelet)) { - if (facelet_get_family(facelet, &family) < 0) { - ERROR("[facemgr_facelet_satisfy_rules] Error retrieving family from facelet"); - return -1; - } - } - - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; -#ifndef WITH_FACEMGR_UTILITY - /* - * In addition to netdevice, netdevice_type should be present to correctly - * apply rules - */ - rc = facelet_get_netdevice_type(facelet, &netdevice_type); - if (rc < 0) { - ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet"); - return -2; - } -#endif /* WITH_FACEMGR_UTILITY */ - - /* Default ignore list */ - if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) { - DEBUG("Ignored interface '%s/%s'...", netdevice.name, - netdevice_type_str[netdevice_type]); + if (!ipv4) { + DEBUG("Ignored IPv4 facelet..."); return -3; + } + break; } - /* Ignore */ - bool ignore; - if (facemgr_cfg_get_ignore(facemgr->cfg, &netdevice, netdevice_type, - &ignore) < 0) + case AF_INET6: { + bool ipv6; + if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type, + &ipv6) < 0) return -1; - if (ignore) { - DEBUG("Ignored interface '%s/%s'...", netdevice.name, - netdevice_type_str[netdevice_type]); + if (!ipv6) { + DEBUG("Ignored IPv6 facelet..."); return -3; + } + break; } - switch(family) { - case AF_INET: - { - bool ipv4; - if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type, - &ipv4) < 0) - return -1; - if (!ipv4) { - DEBUG("Ignored IPv4 facelet..."); - return -3; - } - break; - } - - case AF_INET6: - { - bool ipv6; - if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type, - &ipv6) < 0) - return -1; - if (!ipv6) { - DEBUG("Ignored IPv6 facelet..."); - return -3; - } - break; - } - - default: - DEBUG("Ignored facelet with unknown family"); - return -2; - } + default: + DEBUG("Ignored facelet with unknown family"); + return -2; + } - return 0; + return 0; } -#ifdef WITH_FACEMGR_UTILITY -/** - * \brief Complements facelet information through Android Utility interface - * \return 0 if request was successful, -1 in case of error, and -2 if the - * interface is not applicable - * - * This function returnds _after_ completion. - */ -int -facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet) -{ - - if (facelet_has_netdevice_type(facelet)) - return -2; - - if (facelet_is_au_done(facelet)) - return -2; - - netdevice_t netdevice = NETDEVICE_EMPTY; - - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet"); - return -1; - } - - DEBUG("Querying android utility..."); - - /* /!\ Synchronous code here /!\ */ - if (facemgr_query_android_utility(facemgr, netdevice) < 0) { - return -1; - } - - facelet_set_au_done(facelet); - return 0; -} -#endif /* WITH_FACEMGR_UTILITY */ - #ifdef __linux__ /** * \brief Complements facelet information through Bonjour interface. @@ -759,66 +677,68 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet) * This function returnds _before_ completion as bonjour querying is * asynchronous. */ -int -facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet) -{ - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet"); - return -1; - } - - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; -#ifndef WITH_FACEMGR_UTILITY - /* - * In addition to netdevice, netdevice_type should be present to correctly - * apply rules - */ - rc = facelet_get_netdevice_type(facelet, &netdevice_type); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet"); - return -2; - } -#endif /* WITH_FACEMGR_UTILITY */ - - bool discovery; - if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type, - &discovery) < 0) - return -2; - - DEBUG("Discovery: %s", discovery ? "ON" : "OFF"); - - if (!discovery) - return -2; - - facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; - if (facelet_get_face_type(facelet, &face_type) < 0) { - ERROR("[facemgr_complement_facelet_bj] Error retrieving face type from facelet"); - return -1; - } +int facemgr_complement_facelet_bj(facemgr_t *facemgr, facelet_t *facelet) { + netdevice_t netdevice = NETDEVICE_EMPTY; + int rc = facelet_get_netdevice(facelet, &netdevice); + if (rc < 0) { + ERROR( + "[facemgr_complement_facelet_bj] Error retrieving netdevice from " + "facelet"); + return -1; + } + + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + /* + * In addition to netdevice, netdevice_type should be present to correctly + * apply rules + */ + rc = facelet_get_netdevice_type(facelet, &netdevice_type); + if (rc < 0) { + ERROR( + "[facemgr_complement_facelet_bj] Error retrieving netdevice_type from " + "facelet"); + return -2; + } + + bool discovery; + if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type, + &discovery) < 0) + return -2; + + DEBUG("Discovery: %s", discovery ? "ON" : "OFF"); + + if (!discovery) return -2; + + facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; + if (facelet_get_face_type(facelet, &face_type) < 0) { + ERROR( + "[facemgr_complement_facelet_bj] Error retrieving face type from " + "facelet"); + return -1; + } - bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) && - ((!facelet_has_remote_addr(facelet)) || (!facelet_has_remote_port(facelet))); + bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) && + ((!facelet_has_remote_addr(facelet)) || + (!facelet_has_remote_port(facelet))); - DEBUG("Discovery needed: %s", discovery ? "ON" : "OFF"); + DEBUG("Discovery needed: %s", discovery ? "ON" : "OFF"); - if (!discovery_needed) { - return -2; - } + if (!discovery_needed) { + return -2; + } - if (!facelet_has_local_addr(facelet)) { - DEBUG("No discovery possible without local address"); - return -2; - } + if (!facelet_has_local_addr(facelet)) { + DEBUG("No discovery possible without local address"); + return -2; + } - if (facelet_is_bj_done(facelet)) { - DEBUG("Bonjour already queried"); - return -2; - } + if (facelet_is_bj_done(facelet)) { + DEBUG("Bonjour already queried"); + return -2; + } - facelet_set_bj_done(facelet); - return facemgr_query_bonjour(facemgr, &netdevice); + facelet_set_bj_done(facelet); + return facemgr_query_bonjour(facemgr, &netdevice); } #endif /* __linux__ */ @@ -830,49 +750,52 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet) * This function returnds _before_ completion as bonjour querying is * asynchronous. */ -int -facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet) -{ - - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice from facelet"); - return -1; - } - - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; -#ifndef WITH_FACEMGR_UTILITY - /* - * In addition to netdevice, netdevice_type should be present to correctly - * apply rules - */ - rc = facelet_get_netdevice_type(facelet, &netdevice_type); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet"); - return -2; - } -#endif /* WITH_FACEMGR_UTILITY */ - - int family = AF_UNSPEC; - if (facelet_has_family(facelet)) { - if (facelet_get_family(facelet, &family) < 0) { - ERROR("[facemgr_complement_facelet_manual] Error retrieving family from facelet"); - return -1; - } - } - - /* Do not query manual is there is a change to go through bonjour */ - bool discovery; - if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type, - &discovery) < 0) - return -2; - - facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; - if (facelet_get_face_type(facelet, &face_type) < 0) { - ERROR("[facemgr_complement_facelet_manual] Error retrieving face type from facelet"); - return -1; - } +int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) { + netdevice_t netdevice = NETDEVICE_EMPTY; + int rc = facelet_get_netdevice(facelet, &netdevice); + if (rc < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error retrieving netdevice from " + "facelet"); + return -1; + } + + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + /* + * In addition to netdevice, netdevice_type should be present to correctly + * apply rules + */ + rc = facelet_get_netdevice_type(facelet, &netdevice_type); + if (rc < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error retrieving netdevice_type " + "from facelet"); + return -2; + } + + int family = AF_UNSPEC; + if (facelet_has_family(facelet)) { + if (facelet_get_family(facelet, &family) < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error retrieving family from " + "facelet"); + return -1; + } + } + + /* Do not query manual is there is a change to go through bonjour */ + bool discovery; + if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type, + &discovery) < 0) + return -2; + + facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; + if (facelet_get_face_type(facelet, &face_type) < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error retrieving face type from " + "facelet"); + return -1; + } #if 0 /* Wrong if we need to complement local addr / port */ bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) && @@ -884,91 +807,97 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet) } #endif - if (discovery && !facelet_is_bj_done(facelet)) { - DEBUG("manual settings not considered as discovery is enabled and Bonjour has not yet been done"); - return -2; - } - - DEBUG("Applying manual settings..."); - /* - * Manual overlay specification (remote addr/port) - * We never override a result we have obtained through bonjour - */ - if (!facelet_has_remote_addr(facelet)) { - ip_address_t remote_addr; - if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg, - &netdevice, netdevice_type, family, &remote_addr) < 0) { - ERROR("[facemgr_complement_facelet_manual] Error getting remote addr information from cfg"); - return -1; - } - if (ip_address_empty(&remote_addr)) { - ERROR("[facemgr_complement_facelet_manual] Got empty remote addr information from cfg"); - } else { - DEBUG(" - remote address"); - facelet_set_remote_addr(facelet, remote_addr); - } - } - - if (!facelet_has_remote_port(facelet)) { - uint16_t remote_port; - int rc = facemgr_cfg_get_overlay_remote_port(facemgr->cfg, - &netdevice, netdevice_type, family, &remote_port); - if (rc < 0) { - ERROR("[facemgr_complement_facelet_manual] Error getting remote port information from cfg"); - return -1; - } - DEBUG(" - remote port"); - facelet_set_remote_port(facelet, remote_port); - } - - /* - * Complementing local addr/port XXX this should be done somewhere - * else : manual settings have the lowest priority - * - * Local IP address is specific as it allows to override the source - * address just before creating the face... we would need to check - * whether this is an address that belong to us... it might be used - * to arbitrate amongst several IP addresses instead... - */ - ip_address_t local_addr; - if (facemgr_cfg_get_overlay_local_addr(facemgr->cfg, &netdevice, - netdevice_type, family, &local_addr) < 0) { - ERROR("[facemgr_complement_facelet_manual] Error getting local addr information from cfg"); - return -1; - } - if (ip_address_empty(&local_addr)) { - ERROR("[facemgr_complement_facelet_manual] Got empty local addr information from cfg"); + if (discovery && !facelet_is_bj_done(facelet)) { + DEBUG( + "manual settings not considered as discovery is enabled and Bonjour " + "has not yet been done"); + return -2; + } + + DEBUG("Applying manual settings..."); + /* + * Manual overlay specification (remote addr/port) + * We never override a result we have obtained through bonjour + */ + if (!facelet_has_remote_addr(facelet)) { + hicn_ip_address_t remote_addr; + if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg, &netdevice, + netdevice_type, family, + &remote_addr) < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error getting remote addr " + "information from cfg"); + return -1; + } + if (hicn_ip_address_empty(&remote_addr)) { + ERROR( + "[facemgr_complement_facelet_manual] Got empty remote addr " + "information from cfg"); } else { - DEBUG(" - local addres"); - facelet_set_local_addr(facelet, local_addr); + DEBUG(" - remote address"); + facelet_set_remote_addr(facelet, remote_addr); } + } - /* Sets a default local port, so far nobody sets it */ - uint16_t local_port; - if (facemgr_cfg_get_overlay_local_port(facemgr->cfg, - &netdevice, netdevice_type, family, &local_port) < 0) { - ERROR("[facemgr_complement_facelet_manual] Error getting local port information from cfg"); - return -1; - } - DEBUG(" - local port"); - facelet_set_local_port(facelet, local_port); - return 0; + if (!facelet_has_remote_port(facelet)) { + uint16_t remote_port; + int rc = facemgr_cfg_get_overlay_remote_port( + facemgr->cfg, &netdevice, netdevice_type, family, &remote_port); + if (rc < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error getting remote port " + "information from cfg"); + return -1; + } + DEBUG(" - remote port"); + facelet_set_remote_port(facelet, remote_port); + } + + /* + * Complementing local addr/port XXX this should be done somewhere + * else : manual settings have the lowest priority + * + * Local IP address is specific as it allows to override the source + * address just before creating the face... we would need to check + * whether this is an address that belong to us... it might be used + * to arbitrate amongst several IP addresses instead... + */ + hicn_ip_address_t local_addr; + if (facemgr_cfg_get_overlay_local_addr( + facemgr->cfg, &netdevice, netdevice_type, family, &local_addr) < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error getting local addr " + "information from cfg"); + return -1; + } + if (hicn_ip_address_empty(&local_addr)) { + ERROR( + "[facemgr_complement_facelet_manual] Got empty local addr information " + "from cfg"); + } else { + DEBUG(" - local addres"); + facelet_set_local_addr(facelet, local_addr); + } + + /* Sets a default local port, so far nobody sets it */ + uint16_t local_port; + if (facemgr_cfg_get_overlay_local_port( + facemgr->cfg, &netdevice, netdevice_type, family, &local_port) < 0) { + ERROR( + "[facemgr_complement_facelet_manual] Error getting local port " + "information from cfg"); + return -1; + } + DEBUG(" - local port"); + facelet_set_local_port(facelet, local_port); + return 0; } -int -facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet) -{ - int rc; - - DEBUG("[facemgr_complement_facelet]"); - if (!facelet_has_key(facelet)) - return -2; +int facemgr_complement_facelet(facemgr_t *facemgr, facelet_t *facelet) { + int rc; -#ifdef WITH_FACEMGR_UTILITY - rc = facemgr_complement_facelet_au(facemgr, facelet); - if (rc != -2) - return rc; -#endif /* WITH_FACEMGR_UTILITY */ + DEBUG("[facemgr_complement_facelet]"); + if (!facelet_has_key(facelet)) return -2; #if 0 if (!facelet_has_netdevice_type(facelet)) { @@ -988,51 +917,51 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet) */ #ifdef __linux__ - rc = facemgr_complement_facelet_bj(facemgr, facelet); - if (rc != -2) - return rc; + rc = facemgr_complement_facelet_bj(facemgr, facelet); + if (rc != -2) return rc; #endif /* __linux__ */ - DEBUG("[facemgr_complement_facelet] Complement manual"); + DEBUG("[facemgr_complement_facelet] Complement manual"); - rc = facemgr_complement_facelet_manual(facemgr, facelet); - if (rc != -2) - return rc; + rc = facemgr_complement_facelet_manual(facemgr, facelet); + if (rc != -2) return rc; - INFO("[facemgr_complement_facelet] No more interfaces to query... incomplete face"); - return 0; + INFO( + "[facemgr_complement_facelet] No more interfaces to query... incomplete " + "face"); + return 0; } -int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet) -{ - DEBUG("[facemgr_assign_face_type]"); - /* As key, netdevice and family should always be present */ - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) { - ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet"); - return -1; - } - - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; -#ifndef WITH_FACEMGR_UTILITY - /* - * In addition to netdevice, netdevice_type should be present to correctly - * apply rules - */ - rc = facelet_get_netdevice_type(facelet, &netdevice_type); - if (rc < 0) { - ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet"); - return -2; - } -#endif /* WITH_FACEMGR_UTILITY */ - - facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; - if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0) - return rc; - facelet_set_face_type(facelet, face_type); - DEBUG("[facemgr_assign_face_type] %s", FACEMGR_FACE_TYPE_STR(face_type)); - return 0; +int facemgr_assign_face_type(facemgr_t *facemgr, facelet_t *facelet) { + DEBUG("[facemgr_assign_face_type]"); + /* As key, netdevice and family should always be present */ + netdevice_t netdevice = NETDEVICE_EMPTY; + int rc = facelet_get_netdevice(facelet, &netdevice); + if (rc < 0) { + ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet"); + return -1; + } + + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + /* + * In addition to netdevice, netdevice_type should be present to correctly + * apply rules + */ + rc = facelet_get_netdevice_type(facelet, &netdevice_type); + if (rc < 0) { + ERROR( + "[facemgr_assign_face_type] Error retrieving netdevice_type from " + "facelet"); + return -2; + } + + facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED; + if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, + &face_type) < 0) + return rc; + facelet_set_face_type(facelet, face_type); + DEBUG("[facemgr_assign_face_type] %s", FACEMGR_FACE_TYPE_STR(face_type)); + return 0; } /* @@ -1041,102 +970,102 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet) * * We assume the facelet is already present in the cache */ -int -facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) -{ - int rc; - facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR; - - switch(facelet_get_status(facelet)) { - case FACELET_STATUS_UNCERTAIN: - /* - * All new faces are marked UNCERTAIN. We need to check whether we - * have sufficient information to check rules, if not proceed, - * otherwise possibly mark the face as IGNORED. Otherwise, we verify - * the completeness of the information we have, and continue towards - * being able to mark the face as CREATE. - */ - rc = facemgr_facelet_satisfy_rules(facemgr, facelet); - switch(rc) { - case -3: - /* Does not satisfy rules */ - DEBUG("[facemgr_process_facelet] Does not satisfy rules"); - facelet_set_status(facelet, FACELET_STATUS_IGNORED); - return 0; - - case -2: - DEBUG("[facemgr_process_facelet] Complementing facelet is required"); - if (facemgr_complement_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation"); - goto ERR; - } - return 0; - - case 0: - /* Ok pass rules */ - break; - - default: - /* -1 - Error */ - goto ERR; - } - - if (facemgr_assign_face_type(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet] Could not assign face type"); - goto ERR; - } - facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE); - /* Continue in case facelet satisfies rules */ - - case FACELET_STATUS_INCOMPLETE: - if (!facelet_validate_face(facelet)) { - /* We need additional information */ - if (facemgr_complement_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation"); - goto ERR; - } - } - if (!facelet_validate_face(facelet)) - return 0; - - facelet_set_status(facelet, FACELET_STATUS_CREATE); - /* Continue in case we need to proceed to creation */ - - case FACELET_STATUS_CREATE: - facelet_set_event(facelet, FACELET_EVENT_CREATE); - rc = interface_on_event(facemgr->hl, facelet); - if (rc < 0) { - ERROR("[facemgr_process_facelet] Failed to create face"); - reason = -rc; - goto ERR; - } - - /* This works assuming the call to hicn-light is blocking */ - facelet_set_status(facelet, FACELET_STATUS_CLEAN); - break; +int facemgr_process_facelet(facemgr_t *facemgr, facelet_t *facelet) { + int rc; + facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR; + + switch (facelet_get_status(facelet)) { + case FACELET_STATUS_UNCERTAIN: + /* + * All new faces are marked UNCERTAIN. We need to check whether we + * have sufficient information to check rules, if not proceed, + * otherwise possibly mark the face as IGNORED. Otherwise, we verify + * the completeness of the information we have, and continue towards + * being able to mark the face as CREATE. + */ + rc = facemgr_facelet_satisfy_rules(facemgr, facelet); + switch (rc) { + case -3: + /* Does not satisfy rules */ + DEBUG("[facemgr_process_facelet] Does not satisfy rules"); + facelet_set_status(facelet, FACELET_STATUS_IGNORED); + return 0; + + case -2: + DEBUG("[facemgr_process_facelet] Complementing facelet is required"); + if (facemgr_complement_facelet(facemgr, facelet) < 0) { + ERROR( + "[facemgr_process_facelet] Error while attempting to " + "complement face for fields required by face creation"); + goto ERR; + } + return 0; + case 0: + /* Ok pass rules */ + break; - case FACELET_STATUS_UPDATE: - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - rc = interface_on_event(facemgr->hl, facelet); - if (rc < 0) { - ERROR("[facemgr_process_facelet] Failed to update face"); - reason = -rc; - goto ERR; - } + default: + /* -1 - Error */ + goto ERR; + } - /* This works assuming the call to hicn-light is blocking */ - facelet_set_status(facelet, FACELET_STATUS_CLEAN); - break; - - case FACELET_STATUS_DELETE: - facelet_set_event(facelet, FACELET_EVENT_DELETE); - rc = interface_on_event(facemgr->hl, facelet); - if (rc < 0) { - ERROR("[facemgr_process_facelet] Failed to delete face"); - reason = -rc; - goto ERR; - } + if (facemgr_assign_face_type(facemgr, facelet) < 0) { + ERROR("[facemgr_process_facelet] Could not assign face type"); + goto ERR; + } + facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE); + /* Continue in case facelet satisfies rules */ + + case FACELET_STATUS_INCOMPLETE: + if (!facelet_validate_face(facelet)) { + /* We need additional information */ + if (facemgr_complement_facelet(facemgr, facelet) < 0) { + ERROR( + "[facemgr_process_facelet] Error while attempting to complement " + "face for fields required by face creation"); + goto ERR; + } + } + if (!facelet_validate_face(facelet)) return 0; + + facelet_set_status(facelet, FACELET_STATUS_CREATE); + /* Continue in case we need to proceed to creation */ + + case FACELET_STATUS_CREATE: + facelet_set_event(facelet, FACELET_EVENT_CREATE); + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { + ERROR("[facemgr_process_facelet] Failed to create face"); + reason = -rc; + goto ERR; + } + + /* This works assuming the call to hicn-light is blocking */ + facelet_set_status(facelet, FACELET_STATUS_CLEAN); + break; + + case FACELET_STATUS_UPDATE: + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { + ERROR("[facemgr_process_facelet] Failed to update face"); + reason = -rc; + goto ERR; + } + + /* This works assuming the call to hicn-light is blocking */ + facelet_set_status(facelet, FACELET_STATUS_CLEAN); + break; + + case FACELET_STATUS_DELETE: + facelet_set_event(facelet, FACELET_EVENT_DELETE); + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { + ERROR("[facemgr_process_facelet] Failed to delete face"); + reason = -rc; + goto ERR; + } #if 0 if (facelet_get_id(facelet) > 0) { @@ -1147,111 +1076,102 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) facelet_free(facelet); } else { #endif - /* This works assuming the call to hicn-light is blocking */ - DEBUG("[facemgr_process_facelet] Cleaning cached data"); - facelet_unset_local_addr(facelet); - facelet_unset_local_port(facelet); - if (facelet_get_id(facelet) == 0) { - facelet_unset_remote_addr(facelet); - facelet_unset_remote_port(facelet); - facelet_clear_routes(facelet); - } - - facelet_unset_admin_state(facelet); - facelet_unset_state(facelet); - facelet_unset_bj_done(facelet); -#ifdef WITH_FACEMGR_UTILITY - facelet_unset_au_done(facelet); -#endif /* WITH_FACEMGR_UTILITY */ - - facelet_set_status(facelet, FACELET_STATUS_DELETED); + /* This works assuming the call to hicn-light is blocking */ + DEBUG("[facemgr_process_facelet] Cleaning cached data"); + facelet_unset_local_addr(facelet); + facelet_unset_local_port(facelet); + if (facelet_get_id(facelet) == 0) { + facelet_unset_remote_addr(facelet); + facelet_unset_remote_port(facelet); + facelet_clear_routes(facelet); + } + + facelet_unset_admin_state(facelet); + facelet_unset_state(facelet); + facelet_unset_bj_done(facelet); + + facelet_set_status(facelet, FACELET_STATUS_DELETED); #if 0 } #endif - break; - - case FACELET_STATUS_CLEAN: - case FACELET_STATUS_IGNORED: - case FACELET_STATUS_DOWN: - case FACELET_STATUS_DELETED: - /* Nothing to do */ - break; - - case FACELET_STATUS_UNDEFINED: - case FACELET_STATUS_N: - ERROR("[facemgr_process_facelet] Unexpected facelet status"); - goto ERR; - } + break; - facelet_unset_error(facelet); - return 0; + case FACELET_STATUS_CLEAN: + case FACELET_STATUS_IGNORED: + case FACELET_STATUS_DOWN: + case FACELET_STATUS_DELETED: + /* Nothing to do */ + break; + + case FACELET_STATUS_UNDEFINED: + case FACELET_STATUS_N: + ERROR("[facemgr_process_facelet] Unexpected facelet status"); + goto ERR; + } + + facelet_unset_error(facelet); + return 0; ERR: - facelet_set_error(facelet, reason); - return -1; + facelet_set_error(facelet, reason); + return -1; } -int -facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data) -{ - bool has_error = false; +int facemgr_reattempt_timeout(facemgr_t *facemgr, int fd, void *data) { + bool has_error = false; - assert(data == NULL); + assert(data == NULL); - /* Free all facelets from cache */ - facelet_t ** facelet_array; - int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); - if (n < 0) { - ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache"); + /* Free all facelets from cache */ + facelet_t **facelet_array; + int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); + if (n < 0) { + ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache"); + has_error = true; + } else { + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet = facelet_array[i]; + if (!facelet) continue; /* Should not occur */ + if (!facelet_get_error(facelet)) continue; + + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + DEBUG("Reattempt to process failed facelet %s", buf); + if (facemgr_process_facelet(facemgr, facelet) < 0) { + ERROR("[facemgr_reattempt_timeout] Error processing facelet"); has_error = true; - } else { - for (unsigned i = 0; i < n; i++) { - facelet_t * facelet = facelet_array[i]; - - if (!facelet_get_error(facelet)) - continue; - - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - DEBUG("Reattempt to process failed facelet %s", buf); - if (facemgr_process_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_reattempt_timeout] Error processing facelet"); - has_error = true; - continue; - } - facelet_unset_error(facelet); - } - free(facelet_array); + continue; + } + facelet_unset_error(facelet); } + free(facelet_array); + } - if (has_error) - return 0; + if (has_error) return 0; - DEBUG("Cancelling timer"); - if (facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd) < 0) { - ERROR("[facemgr_reattempt_timeout] Error unregistering reattempt timer"); - return -1; - } - facemgr->timer_fd = 0; - return 0; + DEBUG("Cancelling timer"); + if (facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_UNREGISTER_TIMER, + &facemgr->timer_fd) < 0) { + ERROR("[facemgr_reattempt_timeout] Error unregistering reattempt timer"); + return -1; + } + facemgr->timer_fd = 0; + return 0; } -int -facemgr_start_reattempts(facemgr_t * facemgr) -{ - if (facemgr->timer_fd > 0) - return 0; - - timer_callback_data_t timer_callback = { - .delay_ms = DEFAULT_REATTEMPT_DELAY_MS, - .owner = facemgr, - .callback = (fd_callback_t)facemgr_reattempt_timeout, - .data = NULL, - }; - facemgr->timer_fd = facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_REGISTER_TIMER, &timer_callback); - return (facemgr->timer_fd > 0); +int facemgr_start_reattempts(facemgr_t *facemgr) { + if (facemgr->timer_fd > 0) return 0; + + timer_callback_data_t timer_callback = { + .delay_ms = DEFAULT_REATTEMPT_DELAY_MS, + .owner = facemgr, + .callback = (fd_callback_t)facemgr_reattempt_timeout, + .data = NULL, + }; + facemgr->timer_fd = facemgr->callback( + facemgr->callback_owner, FACEMGR_CB_TYPE_REGISTER_TIMER, &timer_callback); + return (facemgr->timer_fd > 0); } /** @@ -1261,218 +1181,226 @@ facemgr_start_reattempts(facemgr_t * facemgr) * \return 0 if everything went correctly, or -1 in case of error. * -2 means we ignored the face purposedly */ -int -facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet) -{ - char facelet_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); - DEBUG("[facemgr_process_facelet_create] %s", facelet_s); - switch(facelet_get_status(facelet)) { - case FACELET_STATUS_UNCERTAIN: - case FACELET_STATUS_INCOMPLETE: - case FACELET_STATUS_CREATE: - /* No change */ - DEBUG("[facemgr_process_facelet_create] UNCHANGED STATUS"); - break; - case FACELET_STATUS_UPDATE: - case FACELET_STATUS_DELETE: - /* - * Unlikely. The face had been created and is planned to - * be deleted. Schedule for creation (we should have all - * needed information), but make sure to handle errors - * correctly if the face is still present. - * TODO What if some fields have been updated ? - */ - DEBUG("[facemgr_process_facelet_create] SET STATUS TO CREATE"); - facelet_set_status(facelet, FACELET_STATUS_CREATE); - break; - case FACELET_STATUS_CLEAN: - case FACELET_STATUS_IGNORED: - /* - * We should have nothing to do unless some fields have - * been updated. - */ - DEBUG("[facemgr_process_facelet_create] NOTHING TO DO"); - break; - - case FACELET_STATUS_DOWN: - case FACELET_STATUS_DELETED: - /* - * Unless rules have changed, we only need to recover - * missing information, and proceed to face creation. - * Rule changes should be handled separately. - */ - DEBUG("[facemgr_process_facelet_create] SET STATUS TO INCOMPLETE"); - facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE); - break; - case FACELET_STATUS_UNDEFINED: - case FACELET_STATUS_N: - ERROR("[facemgr_process_facelet_create] Unexpected facelet status"); - return -1; - } - - - DEBUG("[facemgr_process_facelet_create] Processing facelet"); - if (facemgr_process_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet_create] Error processing facelet"); - return -1; - } +int facemgr_process_facelet_create(facemgr_t *facemgr, facelet_t *facelet) { + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + DEBUG("[facemgr_process_facelet_create] %s", facelet_s); + switch (facelet_get_status(facelet)) { + case FACELET_STATUS_UNCERTAIN: + case FACELET_STATUS_INCOMPLETE: + case FACELET_STATUS_CREATE: + /* No change */ + DEBUG("[facemgr_process_facelet_create] UNCHANGED STATUS"); + break; + case FACELET_STATUS_UPDATE: + case FACELET_STATUS_DELETE: + /* + * Unlikely. The face had been created and is planned to + * be deleted. Schedule for creation (we should have all + * needed information), but make sure to handle errors + * correctly if the face is still present. + * TODO What if some fields have been updated ? + */ + DEBUG("[facemgr_process_facelet_create] SET STATUS TO CREATE"); + facelet_set_status(facelet, FACELET_STATUS_CREATE); + break; + case FACELET_STATUS_CLEAN: + case FACELET_STATUS_IGNORED: + /* + * We should have nothing to do unless some fields have + * been updated. + */ + DEBUG("[facemgr_process_facelet_create] NOTHING TO DO"); + break; + + case FACELET_STATUS_DOWN: + case FACELET_STATUS_DELETED: + /* + * Unless rules have changed, we only need to recover + * missing information, and proceed to face creation. + * Rule changes should be handled separately. + */ + DEBUG("[facemgr_process_facelet_create] SET STATUS TO INCOMPLETE"); + facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE); + break; + case FACELET_STATUS_UNDEFINED: + case FACELET_STATUS_N: + ERROR("[facemgr_process_facelet_create] Unexpected facelet status"); + return -1; + } + + DEBUG("[facemgr_process_facelet_create] Processing facelet"); + if (facemgr_process_facelet(facemgr, facelet) < 0) { + ERROR("[facemgr_process_facelet_create] Error processing facelet"); + return -1; + } - return 0; + return 0; } /* * \return 0 in case of success and no static facelet was added, 1 if a static * facelet was added, and -1 in case of error. */ -int -facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet) -{ - /* - * We need to analyze the facelet and eventually: - * - add it in our static list - * - replicate it on multipath interfaces - */ - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) - return -1; - - if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || - (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) - return 0; - - if ((facelet_get_route_array(facelet, NULL) == 0)) - return 0; - - /* - * How to differenciate facelet created by face manager from user - * created ones ? This cannot be a flag in the facelet as it needs - * to work across restarts of the face manager... - * Also we might have two default routes. - * - * TODO: - * - The static one should not be a duplicate of the one we would - * create by default.... - * - This should anyways be detected... - * - * One solution would be to install the default ones as static but - * this requires to implement a priority scheme between some of the - * static routes so that the override mechanism continues to work as - * usual. - * - * Current, we recognize the routes created by default by the face - * maanger thanks to the routing prefixes (a single default route). - */ - - facelet_t * static_facelet = facelet_dup(facelet); - facelet_set_event(static_facelet, FACELET_EVENT_CREATE); - facelet_unset_netdevice(static_facelet); - facelet_unset_netdevice_type(static_facelet); - facelet_unset_local_addr(static_facelet); - facelet_unset_local_port(static_facelet); - - facelet_t * facelet_found = NULL; - if (facelet_array_get(facemgr->static_facelets, static_facelet, &facelet_found) < 0) { - ERROR("[facemgr_consider_static_facelet] Error checking whether static facelet already exists or not"); - return -1; - } +int facemgr_consider_static_facelet(facemgr_t *facemgr, facelet_t *facelet) { + /* + * We need to analyze the facelet and eventually: + * - add it in our static list + * - replicate it on multipath interfaces + */ + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) return -1; + + if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || + (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) + return 0; - /* Skip addition if facelet exists */ - if (facelet_found) - return 0; + if ((facelet_get_route_array(facelet, NULL) == 0)) return 0; + + /* + * How to differenciate facelet created by face manager from user + * created ones ? This cannot be a flag in the facelet as it needs + * to work across restarts of the face manager... + * Also we might have two default routes. + * + * TODO: + * - The static one should not be a duplicate of the one we would + * create by default.... + * - This should anyways be detected... + * + * One solution would be to install the default ones as static but + * this requires to implement a priority scheme between some of the + * static routes so that the override mechanism continues to work as + * usual. + * + * Current, we recognize the routes created by default by the face + * maanger thanks to the routing prefixes (a single default route). + */ + + facelet_t *static_facelet = facelet_dup(facelet); + facelet_set_event(static_facelet, FACELET_EVENT_CREATE); + facelet_unset_netdevice(static_facelet); + facelet_unset_netdevice_type(static_facelet); + facelet_unset_local_addr(static_facelet); + facelet_unset_local_port(static_facelet); + + facelet_t *facelet_found = NULL; + if (facelet_array_get(facemgr->static_facelets, static_facelet, + &facelet_found) < 0) { + ERROR( + "[facemgr_consider_static_facelet] Error checking whether static " + "facelet already exists or not"); + return -1; + } - facemgr->cur_static_id++; + /* Skip addition if facelet exists */ + if (facelet_found) return 0; - facelet_set_id(static_facelet, facemgr->cur_static_id); - facelet_set_id(facelet, facemgr->cur_static_id); + facemgr->cur_static_id++; - if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) { - ERROR("[facemgr_consider_static_facelet] Could not add facelet to static array"); - facelet_free(static_facelet); - return -1; - } + facelet_set_id(static_facelet, facemgr->cur_static_id); + facelet_set_id(facelet, facemgr->cur_static_id); - char facelet_s[MAXSZ_FACELET]; - int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet); - if (rc >= MAXSZ_FACELET) - ERROR("[facemgr_consider_static_facelet] Unexpected truncation of facelet string"); - if (rc < 0) - ERROR("[facemgr_consider_static_facelet] Error during facelet string output"); - DEBUG("[facemgr_consider_static_facelet] Successfully added facelet to static array %s", facelet_s); + if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) { + ERROR( + "[facemgr_consider_static_facelet] Could not add facelet to static " + "array"); + facelet_free(static_facelet); + return -1; + } + + char facelet_s[MAXSZ_FACELET]; + int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet); + if (rc >= MAXSZ_FACELET) + ERROR( + "[facemgr_consider_static_facelet] Unexpected truncation of facelet " + "string"); + if (rc < 0) + ERROR( + "[facemgr_consider_static_facelet] Error during facelet string output"); + DEBUG( + "[facemgr_consider_static_facelet] Successfully added facelet to static " + "array %s", + facelet_s); #if 1 - /* Force application of the static face on all existing interfaces */ - facelet_t ** facelet_array; - int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); - if (n >= 0) { - for (unsigned i = 0; i < n; i++) { - facelet_t * cached_facelet = facelet_array[i]; - - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("[facemgr_consider_static_facelet] Error retrieving netdevice type from cached facelet"); - continue; - } - if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) - continue; - - facelet_t * new_facelet = facelet_dup(cached_facelet); - facelet_unset_remote_addr(new_facelet); - facelet_unset_remote_port(new_facelet); - facelet_unset_admin_state(new_facelet); - facelet_unset_state(new_facelet); - facelet_unset_bj_done(new_facelet); - facelet_clear_routes(new_facelet); -#ifdef WITH_FACEMGR_UTILITY - facelet_unset_au_done(new_facelet); -#endif /* WITH_FACEMGR_UTILITY */ - - /* We try to apply static_facelet over facelet */ - if (!facelet_match(new_facelet, static_facelet)) { - facelet_free(new_facelet); - continue; - } - - if (facelet_merge(new_facelet, static_facelet) < 0) { - ERROR("[facemgr_consider_static_facelet] Error merging facelets"); - facelet_free(new_facelet); - continue; - } - - /* - * We need to set the id before checking for existence as tuple used - * is (id, netdevice, family) - */ - facelet_set_id(new_facelet, facemgr->cur_static_id); - - facelet_found = NULL; - if (facelet_set_get(facemgr->facelet_cache, new_facelet, &facelet_found) < 0) { - ERROR("[facemgr_consider_static_facelet] Error checking whether new static facelet already exists or not"); - continue; - } - - - /* Skip addition if facelet exists */ - if (facelet_found) { - facelet_free(new_facelet); - continue; - } - - facelet_set_attr_clean(new_facelet); - facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); - - if (facemgr_on_event(facemgr, new_facelet) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error creating static facelet for existing face"); - continue; - } - - INFO("Successfully created static facelet for existing face"); - } - free(facelet_array); + /* Force application of the static face on all existing interfaces */ + facelet_t **facelet_array; + int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); + if (n >= 0) { + for (unsigned i = 0; i < n; i++) { + facelet_t *cached_facelet = facelet_array[i]; + if (!cached_facelet) continue; /* Should not occur */ + + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR( + "[facemgr_consider_static_facelet] Error retrieving netdevice type " + "from cached facelet"); + continue; + } + if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || + (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) + continue; + + facelet_t *new_facelet = facelet_dup(cached_facelet); + facelet_unset_remote_addr(new_facelet); + facelet_unset_remote_port(new_facelet); + facelet_unset_admin_state(new_facelet); + facelet_unset_state(new_facelet); + facelet_unset_bj_done(new_facelet); + facelet_clear_routes(new_facelet); + + /* We try to apply static_facelet over facelet */ + if (!facelet_match(new_facelet, static_facelet)) { + facelet_free(new_facelet); + continue; + } + + if (facelet_merge(new_facelet, static_facelet) < 0) { + ERROR("[facemgr_consider_static_facelet] Error merging facelets"); + facelet_free(new_facelet); + continue; + } + + /* + * We need to set the id before checking for existence as tuple used + * is (id, netdevice, family) + */ + facelet_set_id(new_facelet, facemgr->cur_static_id); + + facelet_found = NULL; + if (facelet_set_get(facemgr->facelet_cache, new_facelet, &facelet_found) < + 0) { + ERROR( + "[facemgr_consider_static_facelet] Error checking whether new " + "static facelet already exists or not"); + continue; + } + + /* Skip addition if facelet exists */ + if (facelet_found) { + facelet_free(new_facelet); + continue; + } + + facelet_set_attr_clean(new_facelet); + facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); + + if (facemgr_on_event(facemgr, new_facelet) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error creating static " + "facelet for existing face"); + continue; + } + + INFO("Successfully created static facelet for existing face"); } + free(facelet_array); + } #endif - return 1; + return 1; } /** @@ -1482,93 +1410,96 @@ facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet) * \return 0 if everything went correctly, or -1 in case of error. * -2 means we ignored the face purposedly */ -int -facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet) -{ - assert(facelet); +int facemgr_process_facelet_get(facemgr_t *facemgr, facelet_t *facelet) { + assert(facelet); - if (!facelet_has_netdevice(facelet)) - return -2; + if (!facelet_has_netdevice(facelet)) return -2; - netdevice_t netdevice; - if (facelet_get_netdevice(facelet, &netdevice) < 0) - return -1; - if (!IS_VALID_NETDEVICE(netdevice)) - return -2; + netdevice_t netdevice; + if (facelet_get_netdevice(facelet, &netdevice) < 0) return -1; + if (!IS_VALID_NETDEVICE(netdevice)) return -2; - facelet_set_status(facelet, FACELET_STATUS_CLEAN); + facelet_set_status(facelet, FACELET_STATUS_CLEAN); - /* Skip if face exists */ - int n = facelet_cache_lookup(facemgr->facelet_cache, facelet, NULL); - if (n < 0) { - ERROR("[facemgr_process_facelet_get] Error during cache lookup"); - return -1; - } - assert (n <= 1); - if (n > 0) - return 0; - - /* Process untagged faces */ - netdevice_type_t netdevice_type; + /* Skip if face exists */ + int n = facelet_cache_lookup(facemgr->facelet_cache, facelet, NULL); + if (n < 0) { + ERROR("[facemgr_process_facelet_get] Error during cache lookup"); + return -1; + } + assert(n <= 1); + if (n > 0) return 0; + + /* Process untagged faces */ + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + facelet_set_netdevice_type( + facelet, facemgr_get_netdevice_type(facemgr, netdevice.name)); if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - facelet_set_netdevice_type(facelet, facemgr_get_netdevice_type(facemgr, netdevice.name)); - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - /* Inspect local address */ - int family; - ip_address_t local; - if (facelet_get_family(facelet, &family) < 0) { - ERROR("[facemgr_process_facelet_get] Error getting facelet family"); - return -1; - } - if (facelet_get_local_addr(facelet, &local) < 0) { - ERROR("[facemgr_process_facelet_get] Error getting facelet local address"); - return -1; - } - switch(family) { - case AF_INET: - if (ip_address_cmp(&local, &IPV4_LOOPBACK, family) == 0) { - facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); - } else { - return -2; - } - break; - case AF_INET6: - if (ip_address_cmp(&local, &IPV6_LOOPBACK, family) == 0) { - facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); - } else { - return -2; - } - break; - default: - return -2; - } - } - - if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) - return 0; - - if (facemgr_process_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet_get] Error processing facelet"); - return -1; - } - } - - if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) - return 0; - - if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) { - ERROR("[facemgr_process_facelet_get] Error adding received facelet to cache"); + /* Inspect local address */ + int family; + hicn_ip_address_t local; + if (facelet_get_family(facelet, &family) < 0) { + ERROR("[facemgr_process_facelet_get] Error getting facelet family"); return -1; + } + if (facelet_get_local_addr(facelet, &local) < 0) { + ERROR( + "[facemgr_process_facelet_get] Error getting facelet local " + "address"); + return -1; + } + switch (family) { + case AF_INET: + if (hicn_ip_address_cmp(&local, &IPV4_LOOPBACK) == 0) { + facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); + } else { + return -2; + } + break; + case AF_INET6: + if (hicn_ip_address_cmp(&local, &IPV6_LOOPBACK) == 0) { + facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); + } else { + return -2; + } + break; + default: + return -2; + } } - n = facemgr_consider_static_facelet(facemgr, facelet); - if (n < 0) { - ERROR("[facemgr_process_facelet_get] Could not add facelet to static array"); - return -1; + if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || + (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) + return -2; + + if (facemgr_process_facelet(facemgr, facelet) < 0) { + ERROR("[facemgr_process_facelet_get] Error processing facelet"); + return -1; } + } + if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || + (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) + return -2; - return 0; + if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) { + ERROR( + "[facemgr_process_facelet_get] Error adding received facelet to cache"); + return -1; + } + + /* + * From there, don't raise errors otherwise the facelet just added to cache + * will be freed + */ + n = facemgr_consider_static_facelet(facemgr, facelet); + if (n < 0) { + ERROR( + "[facemgr_process_facelet_get] Could not add facelet to static array"); + } + + return 0; } /** @@ -1578,45 +1509,43 @@ facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet) * \return 0 if everything went correctly, or -1 in case of error. * -2 means we ignored the face purposedly */ -int -facemgr_process_facelet_update(facemgr_t * facemgr, facelet_t * facelet) -{ - char facelet_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); - DEBUG("[facemgr_process_facelet_update] %s", facelet_s); - switch(facelet_get_status(facelet)) { - case FACELET_STATUS_UNCERTAIN: - case FACELET_STATUS_INCOMPLETE: - case FACELET_STATUS_CREATE: - case FACELET_STATUS_UPDATE: - /* No change */ - DEBUG("[facemgr_process_facelet_update] UNCHANGED STATUS"); - break; - case FACELET_STATUS_CLEAN: - DEBUG("[facemgr_process_facelet_update] SET STATUS TO UPDATE"); - facelet_set_status(facelet, FACELET_STATUS_UPDATE); - break; - case FACELET_STATUS_DOWN: - case FACELET_STATUS_DELETE: - case FACELET_STATUS_DELETED: - case FACELET_STATUS_IGNORED: - /* Reconsider face creation in light of new information */ - DEBUG("[facemgr_process_facelet_update] SET STATUS TO UNCERTAIN"); - facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN); - break; - case FACELET_STATUS_UNDEFINED: - case FACELET_STATUS_N: - ERROR("[facemgr_process_facelet_update] Unexpected facelet status"); - return -1; - } - - DEBUG("[facemgr_process_facelet_update] Processing facelet"); - if (facemgr_process_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet_update] Error processing facelet"); - return -1; - } +int facemgr_process_facelet_update(facemgr_t *facemgr, facelet_t *facelet) { + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + DEBUG("[facemgr_process_facelet_update] %s", facelet_s); + switch (facelet_get_status(facelet)) { + case FACELET_STATUS_UNCERTAIN: + case FACELET_STATUS_INCOMPLETE: + case FACELET_STATUS_CREATE: + case FACELET_STATUS_UPDATE: + /* No change */ + DEBUG("[facemgr_process_facelet_update] UNCHANGED STATUS"); + break; + case FACELET_STATUS_CLEAN: + DEBUG("[facemgr_process_facelet_update] SET STATUS TO UPDATE"); + facelet_set_status(facelet, FACELET_STATUS_UPDATE); + break; + case FACELET_STATUS_DOWN: + case FACELET_STATUS_DELETE: + case FACELET_STATUS_DELETED: + case FACELET_STATUS_IGNORED: + /* Reconsider face creation in light of new information */ + DEBUG("[facemgr_process_facelet_update] SET STATUS TO UNCERTAIN"); + facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN); + break; + case FACELET_STATUS_UNDEFINED: + case FACELET_STATUS_N: + ERROR("[facemgr_process_facelet_update] Unexpected facelet status"); + return -1; + } + + DEBUG("[facemgr_process_facelet_update] Processing facelet"); + if (facemgr_process_facelet(facemgr, facelet) < 0) { + ERROR("[facemgr_process_facelet_update] Error processing facelet"); + return -1; + } - return 0; + return 0; } /** @@ -1626,15 +1555,13 @@ facemgr_process_facelet_update(facemgr_t * facemgr, facelet_t * facelet) * \return 0 if everything went correctly, or -1 in case of error. * -2 means we ignored the face purposedly */ -int -facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet) -{ - switch(facelet_get_status(facelet)) { - case FACELET_STATUS_UNCERTAIN: - case FACELET_STATUS_INCOMPLETE: - case FACELET_STATUS_IGNORED: - case FACELET_STATUS_DOWN: - case FACELET_STATUS_CREATE: +int facemgr_process_facelet_delete(facemgr_t *facemgr, facelet_t *facelet) { + switch (facelet_get_status(facelet)) { + case FACELET_STATUS_UNCERTAIN: + case FACELET_STATUS_INCOMPLETE: + case FACELET_STATUS_IGNORED: + case FACELET_STATUS_DOWN: + case FACELET_STATUS_CREATE: #if 0 /* Facelets created from static get deleted */ if (facelet_get_id(facelet) > 0) { @@ -1645,142 +1572,160 @@ facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet) facelet_free(facelet); } else { #endif - /* Face has not been created */ - DEBUG("[facemgr_process_facelet] Cleaning cached data"); - facelet_unset_local_addr(facelet); - facelet_unset_local_port(facelet); - if (facelet_get_id(facelet) == 0) { - facelet_unset_remote_addr(facelet); - facelet_unset_remote_port(facelet); - facelet_clear_routes(facelet); - } - facelet_unset_admin_state(facelet); - facelet_unset_state(facelet); - facelet_unset_bj_done(facelet); -#ifdef WITH_FACEMGR_UTILITY - facelet_unset_au_done(facelet); -#endif /* WITH_FACEMGR_UTILITY */ - facelet_unset_error(facelet); - facelet_set_status(facelet, FACELET_STATUS_DELETED); + /* Face has not been created */ + DEBUG("[facemgr_process_facelet] Cleaning cached data"); + facelet_unset_local_addr(facelet); + facelet_unset_local_port(facelet); + if (facelet_get_id(facelet) == 0) { + facelet_unset_remote_addr(facelet); + facelet_unset_remote_port(facelet); + facelet_clear_routes(facelet); + } + facelet_unset_admin_state(facelet); + facelet_unset_state(facelet); + facelet_unset_bj_done(facelet); + facelet_unset_error(facelet); + facelet_set_status(facelet, FACELET_STATUS_DELETED); #if 0 } #endif - break; - - case FACELET_STATUS_UPDATE: - case FACELET_STATUS_CLEAN: - facelet_set_status(facelet, FACELET_STATUS_DELETE); - if (facemgr_process_facelet(facemgr, facelet) < 0) { - ERROR("[facemgr_process_facelet_delete] Error processing facelet"); - return -1; - } - break; + break; - case FACELET_STATUS_DELETE: - case FACELET_STATUS_DELETED: - /* Nothing to do */ - break; + case FACELET_STATUS_UPDATE: + case FACELET_STATUS_CLEAN: + facelet_set_status(facelet, FACELET_STATUS_DELETE); + if (facemgr_process_facelet(facemgr, facelet) < 0) { + ERROR("[facemgr_process_facelet_delete] Error processing facelet"); + return -1; + } + break; - case FACELET_STATUS_UNDEFINED: - case FACELET_STATUS_N: - ERROR("[facemgr_process_facelet_delete] Unexpected facelet status"); - return -1; - } + case FACELET_STATUS_DELETE: + case FACELET_STATUS_DELETED: + /* Nothing to do */ + break; - return 0; -} + case FACELET_STATUS_UNDEFINED: + case FACELET_STATUS_N: + ERROR("[facemgr_process_facelet_delete] Unexpected facelet status"); + return -1; + } -int -facemgr_process_facelet_create_no_family(facemgr_t * facemgr, facelet_t * facelet) -{ + return 0; +} +int facemgr_process_facelet_create_no_family(facemgr_t *facemgr, + facelet_t *facelet) { #ifdef WITH_DEFAULT_PRIORITIES - /* Assign default priority based on face type */ - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error getting netdevice_type: no default priority set."); - goto ERR_PRIORITY; - } - if (facelet_set_priority(facelet, facemgr->default_priority[netdevice_type]) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error setting default priority"); - } + /* Assign default priority based on face type */ + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error getting " + "netdevice_type: no default priority set."); + goto ERR_PRIORITY; + } + if (facelet_set_priority(facelet, facemgr->default_priority[netdevice_type]) < + 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error setting default " + "priority"); + } ERR_PRIORITY: #endif /* WITH_DEFAULT_PRIORITIES */ - DEBUG("[facemgr_process_facelet_create_no_family] Default v4"); - /* Create default v4 and v6 facelets */ - facelet_t * facelet_v4 = facelet_dup(facelet); - if (!facelet_v4) { - ERROR("[facemgr_process_facelet_create_no_family] Error allocating default IPv4 face"); - } else { - facelet_set_family(facelet_v4, AF_INET); - facelet_set_attr_clean(facelet_v4); - if (facemgr_on_event(facemgr, facelet_v4) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv4 face"); - //facelet_free(facelet_v4); - } - } - - DEBUG("[facemgr_process_facelet_create_no_family] Default v6"); - facelet_t * facelet_v6 = facelet_dup(facelet); - if (!facelet_v6) { - ERROR("[facemgr_process_facelet_create_no_family] Error allocating default IPv6 face"); - } else { - facelet_set_family(facelet_v6, AF_INET6); - facelet_set_attr_clean(facelet_v6); - if (facemgr_on_event(facemgr, facelet_v6) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv6 face"); - //facelet_free(facelet_v6); - } + DEBUG("[facemgr_process_facelet_create_no_family] Default v4"); + /* Create default v4 and v6 facelets */ + facelet_t *facelet_v4 = facelet_dup(facelet); + if (!facelet_v4) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error allocating default " + "IPv4 face"); + } else { + facelet_set_family(facelet_v4, AF_INET); + facelet_set_attr_clean(facelet_v4); + if (facemgr_on_event(facemgr, facelet_v4) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error creating default " + "IPv4 face"); + // facelet_free(facelet_v4); + } + } + + DEBUG("[facemgr_process_facelet_create_no_family] Default v6"); + facelet_t *facelet_v6 = facelet_dup(facelet); + if (!facelet_v6) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error allocating default " + "IPv6 face"); + } else { + facelet_set_family(facelet_v6, AF_INET6); + facelet_set_attr_clean(facelet_v6); + if (facemgr_on_event(facemgr, facelet_v6) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error creating default " + "IPv6 face"); + // facelet_free(facelet_v6); + } + } + + /* Create additional connections + * + * This is where we spawn multiple facelets based on the + * configured "static routes" in addition to the default + * routes managed by the face manager. + */ + DEBUG("[facemgr_process_facelet_create_no_family] Loop static"); + int n = (int)facelet_array_len(facemgr->static_facelets); + for (unsigned i = 0; i < n; i++) { + facelet_t *static_facelet; + if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) < + 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error getting static " + "facelet"); + continue; } - /* Create additional connections - * - * This is where we spawn multiple facelets based on the - * configured "static routes" in addition to the default - * routes managed by the face manager. + /* + * We don't enforce any present or absent fields. A match + * operation will be performed deciding whether to create + * the facelet (if it bring additional information to the + * ingress one) or not. */ - DEBUG("[facemgr_process_facelet_create_no_family] Loop static"); - for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) { - facelet_t * static_facelet; - if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error getting static facelet"); - continue; - } - - /* - * We don't enforce any present or absent fields. A match - * operation will be performed deciding whether to create - * the facelet (if it bring additional information to the - * ingress one) or not. - */ - /* We try to apply static_facelet over facelet */ - if (!facelet_match(facelet, static_facelet)) { - continue; - } - - facelet_t * facelet_new = facelet_dup(facelet); - if (!facelet_new) { - ERROR("[facemgr_process_facelet_create_no_family] Error allocating static facelet"); - continue; - } else { - if (facelet_merge(facelet_new, static_facelet) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error merging facelets"); - facelet_free(facelet_new); - continue; - } - facelet_set_id(facelet_new, facelet_get_id(static_facelet)); - facelet_set_attr_clean(facelet_new); - facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); - - if (facemgr_on_event(facemgr, facelet_new) < 0) { - ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv6 face"); - //facelet_free(facelet_new); - } - } + /* We try to apply static_facelet over facelet */ + if (!facelet_match(facelet, static_facelet)) { + continue; } - return 0; + facelet_t *facelet_new = facelet_dup(facelet); + if (!facelet_new) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error allocating static " + "facelet"); + continue; + } else { + if (facelet_merge(facelet_new, static_facelet) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error merging " + "facelets"); + facelet_free(facelet_new); + continue; + } + facelet_set_id(facelet_new, facelet_get_id(static_facelet)); + facelet_set_attr_clean(facelet_new); + facelet_set_status(facelet, FACELET_STATUS_UNDEFINED); + + if (facemgr_on_event(facemgr, facelet_new) < 0) { + ERROR( + "[facemgr_process_facelet_create_no_family] Error creating default " + "IPv6 face"); + // facelet_free(facelet_new); + } + } + } + + return 0; } /** @@ -1790,30 +1735,29 @@ ERR_PRIORITY: * - Any event or timeout due to an interface triggers either a local cache * update, as well a face operations needed to resync the state. */ -int -facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) -{ - bool remove_facelet = true; -#if WITH_DUMP - bool dump = true; +int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet_in) { + bool remove_facelet = true; +#ifdef WITH_DUMP + bool dump = true; #endif /* WITH_DUMP */ - int ret = 0; - int rc; - assert(facelet_in); - - /* Update Netdevice type */ - if ((facelet_get_event(facelet_in) != FACELET_EVENT_GET) && - facelet_has_netdevice(facelet_in) && - (!facelet_has_netdevice_type(facelet_in))) { - netdevice_t netdevice = NETDEVICE_EMPTY; + int ret = 0; + int rc; + assert(facelet_in); + + /* Update Netdevice type */ + if ((facelet_get_event(facelet_in) != FACELET_EVENT_GET) && + facelet_has_netdevice(facelet_in) && + (!facelet_has_netdevice_type(facelet_in))) { + netdevice_t netdevice = NETDEVICE_EMPTY; - rc = facelet_get_netdevice(facelet_in, &netdevice); - if (rc < 0) { - ERROR("[facemgr_on_event] Error retrieving netdevice from facelet"); - return -1; - } - facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name)); + rc = facelet_get_netdevice(facelet_in, &netdevice); + if (rc < 0) { + ERROR("[facemgr_on_event] Error retrieving netdevice from facelet"); + return -1; } + facelet_set_netdevice_type( + facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name)); + } #if 0 netdevice_type_t netdevice_type; @@ -1826,656 +1770,660 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) return 0; #endif - char facelet_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in); + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in); - facelet_t ** cached_facelets = NULL; - assert(facelet_in); + facelet_t **cached_facelets = NULL; + assert(facelet_in); - if (facelet_get_status(facelet_in) == FACELET_STATUS_UNDEFINED) { - facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN); - } + if (facelet_get_status(facelet_in) == FACELET_STATUS_UNDEFINED) { + facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN); + } - int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, &cached_facelets); - if (n < 0) { - ERROR("[facemgr_on_event] Error during cache lookup"); - free(facelet_in); - return -1; - } - if (n == 0) { - /* This is a new facelet... we expect a CREATE event. */ - switch(facelet_get_event(facelet_in)) { - case FACELET_EVENT_CREATE: - { - /* - * This is the first time we hear about a facelet, it will - * likely not have an address family - * - * Assumption: we should always see the link before the address - * assignment - */ - DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s); - - if (!facelet_has_family(facelet_in)) { - facemgr_assign_face_type(facemgr, facelet_in); - if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error processing new interface event"); - goto ERR; - } - goto DUMP_CACHE; - } + int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, + &cached_facelets); + if (n < 0) { + ERROR("[facemgr_on_event] Error during cache lookup"); + free(facelet_in); + return -1; + } + if (n == 0) { + /* This is a new facelet... we expect a CREATE event. */ + switch (facelet_get_event(facelet_in)) { + case FACELET_EVENT_CREATE: { + /* + * This is the first time we hear about a facelet, it will + * likely not have an address family + * + * Assumption: we should always see the link before the address + * assignment + */ + DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s); - if (facelet_set_add(facemgr->facelet_cache, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error adding facelet to cache"); - goto ERR; - } + if (!facelet_has_family(facelet_in)) { + facemgr_assign_face_type(facemgr, facelet_in); + if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < + 0) { + ERROR("[facemgr_on_event] Error processing new interface event"); + goto ERR; + } + goto DUMP_CACHE; + } - if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error processing facelet CREATE event"); - ret = -1; - } + if (facelet_set_add(facemgr->facelet_cache, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error adding facelet to cache"); + goto ERR; + } - remove_facelet = false; + if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error processing facelet CREATE event"); + ret = -1; + } - break; - } + remove_facelet = false; + + break; + } - case FACELET_EVENT_GET: - /* Insert new facelet in cached */ - //DEBUG("[facemgr_on_event] GET NEW %s", facelet_s); - rc = facemgr_process_facelet_get(facemgr, facelet_in); - if (rc == 0) - remove_facelet = false; -#if WITH_DUMP - dump = false; + case FACELET_EVENT_GET: + /* Insert new facelet in cached */ + // DEBUG("[facemgr_on_event] GET NEW %s", facelet_s); + rc = facemgr_process_facelet_get(facemgr, facelet_in); + if (rc == 0) remove_facelet = false; +#ifdef WITH_DUMP + dump = false; #endif - if (rc == -1) { - ERROR("[facemgr_on_event] Error processing GET event"); - goto ERR; - } - break; + if (rc == -1) { + ERROR("[facemgr_on_event] Error processing GET event"); + goto ERR; + } + break; - case FACELET_EVENT_UPDATE: - /* Might be because we previously ignored the facelet... */ - //ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist"); - //goto ERR; + case FACELET_EVENT_UPDATE: + /* Might be because we previously ignored the facelet... */ + // ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist"); + // goto ERR; #ifdef WITH_DEFAULT_PRIORITIES - if (facelet_has_netdevice_type(facelet_in) && !facelet_has_netdevice(facelet_in) && facelet_has_priority(facelet_in)) { - /* Remember last priority choice for newly created facelets */ - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; - u32 priority = 0; - if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) { - ERROR("[facelet_on_event] Error getting netdevice_type"); - goto ERR; - } - if (facelet_get_priority(facelet_in, &priority) < 0) { - ERROR("[facelet_on_event] Error getting priority"); - goto ERR; - } - facemgr->default_priority[netdevice_type] = priority; - } + if (facelet_has_netdevice_type(facelet_in) && + !facelet_has_netdevice(facelet_in) && + facelet_has_priority(facelet_in)) { + /* Remember last priority choice for newly created facelets */ + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + u32 priority = 0; + if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) { + ERROR("[facelet_on_event] Error getting netdevice_type"); + goto ERR; + } + if (facelet_get_priority(facelet_in, &priority) < 0) { + ERROR("[facelet_on_event] Error getting priority"); + goto ERR; + } + facemgr->default_priority[netdevice_type] = priority; + } #endif /* WITH_DEFAULT_PRIORITIES */ - DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s); - INFO("Ignored UPDATE for non-existing face"); - break; + DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s); + INFO("Ignored UPDATE for non-existing face"); + break; - case FACELET_EVENT_DELETE: - DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s); - ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist"); - goto ERR; - - case FACELET_EVENT_SET_UP: - case FACELET_EVENT_SET_DOWN: - ERROR("[facemgr_on_event] Unexpected event on a face that does not exist"); - goto ERR; + case FACELET_EVENT_DELETE: + DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s); + ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist"); + goto ERR; - case FACELET_EVENT_UNDEFINED: - case FACELET_EVENT_N: - ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); - ret = -1; - goto ERR; + case FACELET_EVENT_SET_UP: + case FACELET_EVENT_SET_DOWN: + ERROR( + "[facemgr_on_event] Unexpected event on a face that does not " + "exist"); + goto ERR; - } - goto DUMP_CACHE; + case FACELET_EVENT_UNDEFINED: + case FACELET_EVENT_N: + ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); + ret = -1; + goto ERR; } + goto DUMP_CACHE; + } + /* + * From now on, it should not make any difference whether we have one or + * more facelet. + */ + for (unsigned i = 0; i < n; i++) { /* - * From now on, it should not make any difference whether we have one or - * more facelet. + * We merge each cached facelet with incoming one, and perform state + * reconciliation by sending appropriate updates to the forwarder */ - for (unsigned i = 0; i < n; i ++) { + facelet_t *facelet = cached_facelets[i]; + + char facelet_old_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_old_s, MAXSZ_FACELET, facelet); + // DEBUG("Facelet from cache #%d %s", i, facelet_s); + + switch (facelet_get_event(facelet_in)) { + case FACELET_EVENT_CREATE: /* - * We merge each cached facelet with incoming one, and perform state - * reconciliation by sending appropriate updates to the forwarder + * This can occur for a facelet already in cache but that has + * been previously deleted... we need to be able to consider + * static facelets in this situation too... */ - facelet_t * facelet = cached_facelets[i]; - - char facelet_old_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_old_s, MAXSZ_FACELET, facelet); - //DEBUG("Facelet from cache #%d %s", i, facelet_s); - - switch(facelet_get_event(facelet_in)) { - case FACELET_EVENT_CREATE: - /* - * This can occur for a facelet already in cache but that has - * been previously deleted... we need to be able to consider - * static facelets in this situation too... - */ - DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s); - - if (!facelet_has_family(facelet_in)) { - if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error processing new interface event"); - goto ERR; - } - goto DUMP_CACHE; - } + DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s); - // This case will occur when we try to re-create existing faces, - // eg. in the situation of a forwarder restarting. - // likely this occurs when the interface receives a (potentially new) address - if (facelet_merge(facelet, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error merging facelets"); - continue; - } + if (!facelet_has_family(facelet_in)) { + if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < + 0) { + ERROR("[facemgr_on_event] Error processing new interface event"); + goto ERR; + } + goto DUMP_CACHE; + } - if (facemgr_process_facelet_create(facemgr, facelet) < 0) { - ERROR("[facemgr_on_event] Error processing facelet CREATE event"); - ret = -1; - } + // This case will occur when we try to re-create existing faces, + // eg. in the situation of a forwarder restarting. + // likely this occurs when the interface receives a (potentially new) + // address + if (facelet_merge(facelet, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error merging facelets"); + continue; + } - continue; + if (facemgr_process_facelet_create(facemgr, facelet) < 0) { + ERROR("[facemgr_on_event] Error processing facelet CREATE event"); + ret = -1; + } - case FACELET_EVENT_GET: /* should be an INFORM message */ - /* - * This happens due to polling of the forwarder (or when it - * restarts) - */ - //DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s); - //DEBUG(" WITH %s", facelet_s); - //ERROR("[facemgr_on_event] GET event for a face that already exists..."); + continue; + + case FACELET_EVENT_GET: /* should be an INFORM message */ + /* + * This happens due to polling of the forwarder (or when it + * restarts) + */ + // DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s); + // DEBUG(" WITH %s", facelet_s); + // ERROR("[facemgr_on_event] GET event for a face that already + // exists..."); #ifdef WITH_DUMP - dump = false; + // dump = false; #endif /* WITH_DUMP */ - continue; + continue; - case FACELET_EVENT_UPDATE: - DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_old_s); - DEBUG(" WITH %s", facelet_s); + case FACELET_EVENT_UPDATE: + DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_old_s); + DEBUG(" WITH %s", facelet_s); #ifdef WITH_DEFAULT_PRIORITIES - if (facelet_has_netdevice_type(facelet_in) && !facelet_has_netdevice(facelet_in) && facelet_has_priority(facelet_in)) { - /* Remember last priority choice for newly created facelets */ - netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; - u32 priority = 0; - if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) { - ERROR("[facelet_on_event] Error getting netdevice_type"); - goto ERR; - } - if (facelet_get_priority(facelet_in, &priority) < 0) { - ERROR("[facelet_on_event] Error getting priority"); - goto ERR; - } - facemgr->default_priority[netdevice_type] = priority; - } + if (facelet_has_netdevice_type(facelet_in) && + !facelet_has_netdevice(facelet_in) && + facelet_has_priority(facelet_in)) { + /* Remember last priority choice for newly created facelets */ + netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED; + u32 priority = 0; + if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) { + ERROR("[facelet_on_event] Error getting netdevice_type"); + goto ERR; + } + if (facelet_get_priority(facelet_in, &priority) < 0) { + ERROR("[facelet_on_event] Error getting priority"); + goto ERR; + } + facemgr->default_priority[netdevice_type] = priority; + } #endif /* WITH_DEFAULT_PRIORITIES */ - if (facelet_merge(facelet, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error merging facelets"); - continue; - } - if (facemgr_process_facelet_update(facemgr, facelet) < 0) { - ERROR("[facemgr_on_event] Error processing facelet UPDATE event"); - ret = -1; - } - continue; - - case FACELET_EVENT_DELETE: - DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_old_s); - DEBUG(" WITH %s", facelet_s); - if (facelet_merge(facelet, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error merging facelets"); - continue; - } - if (facemgr_process_facelet_delete(facemgr, facelet) < 0) { - ERROR("[facemgr_on_event] Error processing facelet DELETE event"); - ret = -1; - } - continue; - - case FACELET_EVENT_SET_UP: - ERROR("[facemgr_on_event] Not implemented\n"); - ret = -1; - continue; - - case FACELET_EVENT_SET_DOWN: - DEBUG("[facemgr_on_event] SET DOWN EXISTING %s", facelet_old_s); - DEBUG(" WITH %s", facelet_s); - /* We don't even need to merge */ - if (facelet_merge(facelet, facelet_in) < 0) { - ERROR("[facemgr_on_event] Error merging facelets"); - continue; - } - if (facemgr_process_facelet_delete(facemgr, facelet) < 0) { - ERROR("[facemgr_on_event] Error processing facelet DELETE event"); - continue; - } - continue; - - case FACELET_EVENT_UNDEFINED: - case FACELET_EVENT_N: - ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); - ret = -1; - goto ERR; - + if (facelet_merge(facelet, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error merging facelets"); + continue; + } + if (facemgr_process_facelet_update(facemgr, facelet) < 0) { + ERROR("[facemgr_on_event] Error processing facelet UPDATE event"); + ret = -1; } + continue; + + case FACELET_EVENT_DELETE: + DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_old_s); + DEBUG(" WITH %s", facelet_s); + if (facelet_merge(facelet, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error merging facelets"); + continue; + } + if (facemgr_process_facelet_delete(facemgr, facelet) < 0) { + ERROR("[facemgr_on_event] Error processing facelet DELETE event"); + ret = -1; + } + continue; + + case FACELET_EVENT_SET_UP: + ERROR("[facemgr_on_event] Not implemented\n"); + ret = -1; + continue; + + case FACELET_EVENT_SET_DOWN: + DEBUG("[facemgr_on_event] SET DOWN EXISTING %s", facelet_old_s); + DEBUG(" WITH %s", facelet_s); + /* We don't even need to merge */ + if (facelet_merge(facelet, facelet_in) < 0) { + ERROR("[facemgr_on_event] Error merging facelets"); + continue; + } + if (facemgr_process_facelet_delete(facemgr, facelet) < 0) { + ERROR("[facemgr_on_event] Error processing facelet DELETE event"); + continue; + } + continue; + case FACELET_EVENT_UNDEFINED: + case FACELET_EVENT_N: + ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); + ret = -1; + goto ERR; } - goto DUMP_CACHE; + } + goto DUMP_CACHE; ERR: - ret = -1; + ret = -1; DUMP_CACHE: -#if WITH_DUMP - if (dump) { - DEBUG(" <CACHE>"); - facelet_set_dump(facemgr->facelet_cache); - DEBUG(" </CACHE>"); - DEBUG("</EVENT ret=%d>", ret); - DEBUG("----------------------------------"); - } +#ifdef WITH_DUMP + if (dump) { + DEBUG(" <CACHE>"); + facelet_set_dump(facemgr->facelet_cache); + DEBUG(" </CACHE>"); + DEBUG("</EVENT ret=%d>", ret); + DEBUG("----------------------------------"); + } #endif /* WITH_DUMP */ - free(cached_facelets); + free(cached_facelets); - if (remove_facelet) - facelet_free(facelet_in); + if (remove_facelet) facelet_free(facelet_in); - if (ret == -1) { - INFO("Error... starting reattempts"); - facemgr_start_reattempts(facemgr); - } + if (ret == -1) { + INFO("Error... starting reattempts"); + facemgr_start_reattempts(facemgr); + } - return ret; + return ret; } -int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data) -{ - switch(type) { - case INTERFACE_CB_TYPE_RAISE_EVENT: - return facemgr_on_event(facemgr, data); - - case INTERFACE_CB_TYPE_REGISTER_FD: - { - /* Remember fd for further release */ - fd_callback_data_t * fd_callback_data = data; - interface_t * interface = (interface_t*)(fd_callback_data->owner); - - interface_map_data_t * interface_map_data = NULL; - if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) { - ERROR("[facemgr_callback] Error getting interface map data"); - return -1; - } - if (!interface_map_data) { - ERROR("[facemgr_callback] No entry in interface map data"); - return -1; - } - interface_map_data->fds[interface_map_data->num_fds++] = fd_callback_data->fd; +int facemgr_callback(facemgr_t *facemgr, interface_cb_type_t type, void *data) { + switch (type) { + case INTERFACE_CB_TYPE_RAISE_EVENT: + return facemgr_on_event(facemgr, data); - return facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_REGISTER_FD, data); - } + case INTERFACE_CB_TYPE_REGISTER_FD: { + /* Remember fd for further release */ + fd_callback_data_t *fd_callback_data = data; + interface_t *interface = (interface_t *)(fd_callback_data->owner); - case INTERFACE_CB_TYPE_UNREGISTER_FD: - { - fd_callback_data_t * fd_callback_data = data; - interface_t * interface = (interface_t*)(fd_callback_data->owner); + interface_map_data_t *interface_map_data = NULL; + if (interface_map_get(facemgr->interface_map, interface->name, + &interface_map_data) < 0) { + ERROR("[facemgr_callback] Error getting interface map data"); + return -1; + } + if (!interface_map_data) { + ERROR("[facemgr_callback] No entry in interface map data"); + return -1; + } + interface_map_data->fds[interface_map_data->num_fds++] = + fd_callback_data->fd; - interface_map_data_t * interface_map_data = NULL; - if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) { - ERROR("[facemgr_callback] Error getting interface map data"); - return -1; - } - if (!interface_map_data) { - ERROR("[facemgr_callback] No entry in interface map data"); - return -1; - } + return facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_REGISTER_FD, data); + } - for (unsigned i = 0; i < interface_map_data->num_fds; i++) { - if (interface_map_data->fds[i] == fd_callback_data->fd) { - interface_map_data->fds[i] = interface_map_data->fds[--interface_map_data->num_fds]; - break; - } - } + case INTERFACE_CB_TYPE_UNREGISTER_FD: { + fd_callback_data_t *fd_callback_data = data; + interface_t *interface = (interface_t *)(fd_callback_data->owner); - return facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_UNREGISTER_FD, data); + interface_map_data_t *interface_map_data = NULL; + if (interface_map_get(facemgr->interface_map, interface->name, + &interface_map_data) < 0) { + ERROR("[facemgr_callback] Error getting interface map data"); + return -1; + } + if (!interface_map_data) { + ERROR("[facemgr_callback] No entry in interface map data"); + return -1; + } + + for (unsigned i = 0; i < interface_map_data->num_fds; i++) { + if (interface_map_data->fds[i] == fd_callback_data->fd) { + interface_map_data->fds[i] = + interface_map_data->fds[--interface_map_data->num_fds]; + break; } + } - case INTERFACE_CB_TYPE_REGISTER_TIMER: - return facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_REGISTER_TIMER, data); + return facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_UNREGISTER_FD, data); + } - case INTERFACE_CB_TYPE_UNREGISTER_TIMER: - return facemgr->callback(facemgr->callback_owner, - FACEMGR_CB_TYPE_UNREGISTER_TIMER, data); + case INTERFACE_CB_TYPE_REGISTER_TIMER: + return facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_REGISTER_TIMER, data); - } - return -1; + case INTERFACE_CB_TYPE_UNREGISTER_TIMER: + return facemgr->callback(facemgr->callback_owner, + FACEMGR_CB_TYPE_UNREGISTER_TIMER, data); + } + return -1; } -int -facemgr_bootstrap(facemgr_t * facemgr) -{ - int rc; +int facemgr_bootstrap(facemgr_t *facemgr) { + int rc; - DEBUG("Registering interfaces..."); - rc = interface_register(&hicn_light_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering hicn_light interface"); - goto ERR_REGISTER; - } + DEBUG("Registering interfaces..."); + rc = interface_register(&hicn_light_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering hicn_light interface"); + goto ERR_REGISTER; + } #ifdef __APPLE__ - rc = interface_register(&network_framework_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering network_framework interface"); - goto ERR_REGISTER; - } + rc = interface_register(&network_framework_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering network_framework interface"); + goto ERR_REGISTER; + } #endif /* __APPLE__ */ #ifdef __linux__ - rc = interface_register(&netlink_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering netlink interface"); - goto ERR_REGISTER; - } +#ifdef __ANDROID__ + rc = interface_register(&android_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering android interface"); + goto ERR_REGISTER; + } +#else + rc = interface_register(&netlink_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering netlink interface"); + goto ERR_REGISTER; + } +#endif /* __ANDROID__ */ - rc = interface_register(&bonjour_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering bonjour interface"); - goto ERR_REGISTER; - } + rc = interface_register(&bonjour_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering bonjour interface"); + goto ERR_REGISTER; + } #endif /* __linux__ */ -#ifdef WITH_FACEMGR_UTILITY - rc = interface_register(&android_utility_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering android_utility interface"); - goto ERR_REGISTER; - } -#endif /* WITH_FACEMGR_UTILITY */ - #ifdef WITH_PRIORITY_CONTROLLER - INFO("[facemgr_bootstrap] registering priority_controller interface"); - rc = interface_register(&priority_controller_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering priority_controller interface"); - goto ERR_REGISTER; - } + INFO("[facemgr_bootstrap] registering priority_controller interface"); + rc = interface_register(&priority_controller_ops); + if (rc < 0) { + ERROR( + "[facemgr_bootstrap] Error registering priority_controller interface"); + goto ERR_REGISTER; + } #endif #ifdef WITH_EXAMPLE_DUMMY - rc = interface_register(&dummy_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering dummy interface"); - goto ERR_REGISTER; - } + rc = interface_register(&dummy_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering dummy interface"); + goto ERR_REGISTER; + } #endif #ifdef WITH_EXAMPLE_UPDOWN - rc = interface_register(&updown_ops); - if (rc < 0) { - ERROR("[facemgr_bootstrap] Error registering updown interface"); - goto ERR_REGISTER; - } + rc = interface_register(&updown_ops); + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering updown interface"); + goto ERR_REGISTER; + } #endif - rc = facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl); - if (rc < 0) { - ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n"); - goto ERR_HL_CREATE; - } - #ifdef __APPLE__ - network_framework_cfg_t nf_cfg = { - }; - rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg, &facemgr->nf); - if (rc < 0) { - ERROR("Error creating 'Apple Network Framework' interface\n"); - goto ERR_NF_CREATE; - } + network_framework_cfg_t nf_cfg = {}; + rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg, + &facemgr->nf); + if (rc < 0) { + ERROR("Error creating 'Apple Network Framework' interface\n"); + goto ERR_NF_CREATE; + } #endif /* __APPLE__ */ #ifdef __linux__ - rc = facemgr_create_interface(facemgr, "nl", "netlink", NULL, &facemgr->nl); - if (rc < 0) { - ERROR("Error creating 'Netlink' interface\n"); - goto ERR_NL_CREATE; - } +#ifdef __ANDROID__ + android_cfg_t android_cfg = { + .jvm = facemgr->jvm, + }; + rc = facemgr_create_interface(facemgr, "android", "android", &android_cfg, + &facemgr->android); + if (rc < 0) { + ERROR("Error creating 'Android' interface\n"); + goto ERR_ANDROID_CREATE; + } +#else + rc = facemgr_create_interface(facemgr, "nl", "netlink", NULL, &facemgr->nl); + if (rc < 0) { + ERROR("Error creating 'Netlink' interface\n"); + goto ERR_NL_CREATE; + } +#endif /* __ANDROID__ */ #endif /* __linux__ */ -#ifdef WITH_FACEMGR_UTILITY - android_utility_cfg_t au_cfg = { - .jvm = facemgr->jvm, - }; - rc = facemgr_create_interface(facemgr, "au", "android_utility", &au_cfg, &facemgr->au); - if (rc < 0) { - ERROR("Error creating 'Android Utility' interface\n"); - goto ERR_AU_CREATE; - } -#endif /* WITH_FACEMGR_UTILITY */ - #ifdef WITH_PRIORITY_CONTROLLER - INFO("[facemgr_bootstrap] creating priority_controller interface"); - priority_controller_cfg_t pc_cfg = { + INFO("[facemgr_bootstrap] creating priority_controller interface"); + priority_controller_cfg_t pc_cfg = { #ifdef PRIORITY_CONTROLLER_INTERNAL - .jvm = facemgr->jvm, + .jvm = facemgr->jvm, #endif /* PRIORITY_CONTROLLER_INTERNAL */ - }; - rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg, &facemgr->pc); - if (rc < 0) { - ERROR("Error creating 'Priority Controller' interface\n"); - goto ERR_PC_CREATE; - } + }; + rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg, + &facemgr->pc); + if (rc < 0) { + ERROR("Error creating 'Priority Controller' interface\n"); + goto ERR_PC_CREATE; + } #endif #ifdef WITH_EXAMPLE_DUMMY - rc = facemgr_create_interface(facemgr, "dummy0", "dummy", NULL, &facemgr->dummy); - if (rc < 0) { - ERROR("Error creating 'dummy' interface\n"); - goto ERR_DUMMY_CREATE; - } + rc = facemgr_create_interface(facemgr, "dummy0", "dummy", NULL, + &facemgr->dummy); + if (rc < 0) { + ERROR("Error creating 'dummy' interface\n"); + goto ERR_DUMMY_CREATE; + } #endif #ifdef WITH_EXAMPLE_UPDOWN - rc = facemgr_create_interface(facemgr, "updown0", "updown", NULL, &facemgr->updown); - if (rc < 0) { - ERROR("Error creating 'updown' interface\n"); - goto ERR_UPDOWN_CREATE; - } + rc = facemgr_create_interface(facemgr, "updown0", "updown", NULL, + &facemgr->updown); + if (rc < 0) { + ERROR("Error creating 'updown' interface\n"); + goto ERR_UPDOWN_CREATE; + } #endif - DEBUG("Facemgr successfully initialized..."); + rc = + facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl); + if (rc < 0) { + ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n"); + goto ERR_HL_CREATE; + } - return 0; + DEBUG("Facemgr successfully initialized..."); + + return 0; +ERR_HL_CREATE: #ifdef WITH_EXAMPLE_UPDOWN - facemgr_delete_interface(facemgr, facemgr->updown); + facemgr_delete_interface(facemgr, facemgr->updown); ERR_UPDOWN_CREATE: #endif + #ifdef WITH_EXAMPLE_DUMMY - facemgr_delete_interface(facemgr, facemgr->dummy); + facemgr_delete_interface(facemgr, facemgr->dummy); ERR_DUMMY_CREATE: #endif -#ifdef WITH_FACEMGR_UTILITY - facemgr_delete_interface(facemgr, facemgr->au); -ERR_AU_CREATE: -#endif /* WITH_FACEMGR_UTILITY */ + #ifdef WITH_PRIORITY_CONTROLLER - facemgr_delete_interface(facemgr, facemgr->pc); + facemgr_delete_interface(facemgr, facemgr->pc); ERR_PC_CREATE: #endif + #ifdef __linux__ - facemgr_delete_interface(facemgr, facemgr->nl); +#ifdef __ANDROID__ + facemgr_delete_interface(facemgr, facemgr->android); +ERR_ANDROID_CREATE: +#else + facemgr_delete_interface(facemgr, facemgr->nl); ERR_NL_CREATE: +#endif /* __ANDROID__ */ #endif /* __linux__ */ + #ifdef __APPLE__ - facemgr_delete_interface(facemgr, facemgr->nf); + facemgr_delete_interface(facemgr, facemgr->nf); ERR_NF_CREATE: #endif /* __APPLE__ */ - facemgr_delete_interface(facemgr, facemgr->hl); -ERR_HL_CREATE: ERR_REGISTER: - return -1; + return -1; } -void facemgr_stop(facemgr_t * facemgr) -{ - // FIXME we should iterate on interface map +void facemgr_stop(facemgr_t *facemgr) { + // FIXME we should iterate on interface map #ifdef __APPLE__ - facemgr_delete_interface(facemgr, facemgr->nf); + facemgr_delete_interface(facemgr, facemgr->nf); #endif /* __APPLE__ */ - #ifdef __linux__ - facemgr_delete_interface(facemgr, facemgr->nl); - - /* Delete all bonjour interfaces */ - interface_t ** bonjour_array = NULL; - int n = bonjour_map_get_value_array(facemgr->bonjour_map, &bonjour_array); - if (n >= 0) { - netdevice_t ** netdevice_array = NULL; - int m = bonjour_map_get_key_array(facemgr->bonjour_map, &netdevice_array); - if (m >= 0) { - assert(m == n); - for (int i = 0; i < n; i++) { /* Fail silently */ - DEBUG("Deleting bonjour interface associated to %s (%p)", - netdevice_array[i]->name, bonjour_array[i]); - facemgr_delete_interface(facemgr, bonjour_array[i]); - } - free(netdevice_array); - } - free(bonjour_array); - } -#endif /* __linux__ */ +#ifdef __ANDROID__ + facemgr_delete_interface(facemgr, facemgr->android); +#else + facemgr_delete_interface(facemgr, facemgr->nl); +#endif /* __ANDROID__ */ -#ifdef WITH_FACEMGR_UTILITY - facemgr_delete_interface(facemgr, facemgr->au); -#endif /* WITH_FACEMGR_UTILITY */ + /* Delete all bonjour interfaces */ + interface_t **bonjour_array = NULL; + int n = bonjour_map_get_value_array(facemgr->bonjour_map, &bonjour_array); + if (n >= 0) { + netdevice_t **netdevice_array = NULL; + int m = bonjour_map_get_key_array(facemgr->bonjour_map, &netdevice_array); + if (m >= 0) { + assert(m == n); + for (int i = 0; i < n; i++) { /* Fail silently */ + DEBUG("Deleting bonjour interface associated to %s (%p)", + netdevice_array[i]->name, bonjour_array[i]); + facemgr_delete_interface(facemgr, bonjour_array[i]); + } + free(netdevice_array); + } + free(bonjour_array); + } +#endif /* __linux__ */ #ifdef WITH_PRIORITY_CONTROLLER - facemgr_delete_interface(facemgr, facemgr->pc); + facemgr_delete_interface(facemgr, facemgr->pc); #endif - facemgr_delete_interface(facemgr, facemgr->hl); + facemgr_delete_interface(facemgr, facemgr->hl); #ifdef WITH_EXAMPLE_DUMMY - facemgr_delete_interface(facemgr, facemgr->dummy); + facemgr_delete_interface(facemgr, facemgr->dummy); #endif #ifdef WITH_EXAMPLE_UPDOWN - facemgr_delete_interface(facemgr, facemgr->updown); + facemgr_delete_interface(facemgr, facemgr->updown); #endif } #ifdef __ANDROID__ -void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm) -{ - facemgr->jvm = jvm; +void facemgr_set_jvm(facemgr_t *facemgr, JavaVM *jvm) { facemgr->jvm = jvm; } + +void facemgr_on_android_callback(facemgr_t *facemgr, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address) { + android_on_network_event(facemgr->android, interface_name, netdevice_type, up, + family, ip_address); } #endif /* __ANDROID__ */ -void -facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback) -{ - facemgr->callback = callback; - facemgr->callback_owner = callback_owner; +void facemgr_set_callback(facemgr_t *facemgr, void *callback_owner, + facemgr_cb_t callback) { + facemgr->callback = callback; + facemgr->callback_owner = callback_owner; } -void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data) -{ - facelet_t ** facelet_array; - if (!cb) - return; - int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); - if (n < 0) { - ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache"); - return; - } - for (unsigned i = 0; i < n; i++) { - facelet_t * facelet = facelet_array[i]; - cb(facemgr, facelet, user_data); - } - free(facelet_array); +void facemgr_list_facelets(const facemgr_t *facemgr, + facemgr_list_facelets_cb_t cb, void *user_data) { + facelet_t **facelet_array; + if (!cb) return; + int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); + if (n < 0) { + ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache"); + return; + } + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet = facelet_array[i]; + if (!facelet) continue; /* Should not occur */ + cb(facemgr, facelet, user_data); + } + free(facelet_array); } -int -facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer) -{ - char * cur; - char * s; - int rc; - - facelet_t ** facelet_array; - int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); - if (n < 0) { - ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache"); - return -1; - } - /* This should be enough for JSON overhead, refine later */ - size_t size = 2 * n * MAXSZ_FACELET; - *buffer = malloc(size); - if (!buffer) { - ERROR("[facemgr_list_facelets_json] Could not allocate JSON s"); - free(facelet_array); - return -1; - } - s = *buffer; - cur = s; +int facemgr_list_facelets_json(const facemgr_t *facemgr, char **buffer) { + char *cur; + char *s; + int rc; - rc = snprintf(cur, s + size - cur, "{\"facelets\": [\n"); - if (rc < 0) - goto ERR; - cur += rc; - if (size != 0 && cur >= s + size) - goto END; + facelet_t **facelet_array; + int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); + if (n < 0) { + ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache"); + return -1; + } + /* This should be enough for JSON overhead, refine later */ + size_t size = 2 * n * MAXSZ_FACELET; + *buffer = malloc(size); + if (!buffer) { + ERROR("[facemgr_list_facelets_json] Could not allocate JSON s"); + free(facelet_array); + return -1; + } + s = *buffer; + cur = s; - for (unsigned i = 0; i < n; i++) { - facelet_t * facelet = facelet_array[i]; + rc = snprintf(cur, s + size - cur, "{\"facelets\": [\n"); + if (rc < 0) goto ERR; + cur += rc; + if (size != 0 && cur >= s + size) goto END; - rc = facelet_snprintf_json(cur, s + size - cur, facelet, /* indent */ 1); - if (rc < 0) - goto ERR; - cur += rc; - if (size != 0 && cur >= s + size) - goto END; + for (unsigned i = 0; i < n; i++) { + facelet_t *facelet = facelet_array[i]; + if (!facelet) continue; /* Should not occur */ - rc = snprintf(cur, s + size - cur, (i == n-1) ? "\n" : ",\n"); - if (rc < 0) - goto ERR; - cur += rc; - if (size != 0 && cur >= s + size) - goto END; - } + rc = facelet_snprintf_json(cur, s + size - cur, facelet, /* indent */ 1); + if (rc < 0) goto ERR; + cur += rc; + if (size != 0 && cur >= s + size) goto END; - rc = snprintf(cur, s + size - cur, "]}\n"); - if (rc < 0) - goto ERR; + rc = snprintf(cur, s + size - cur, (i == n - 1) ? "\n" : ",\n"); + if (rc < 0) goto ERR; cur += rc; - if (size != 0 && cur >= s + size) - goto END; + if (size != 0 && cur >= s + size) goto END; + } + + rc = snprintf(cur, s + size - cur, "]}\n"); + if (rc < 0) goto ERR; + cur += rc; + if (size != 0 && cur >= s + size) goto END; END: - free(facelet_array); - return (int)(cur - s); + free(facelet_array); + return (int)(cur - s); ERR: - free(facelet_array); - return rc; + free(facelet_array); + return rc; } - diff --git a/ctrl/facemgr/src/cache.c b/ctrl/facemgr/src/cache.c index f994d7d37..98c68e9b0 100644 --- a/ctrl/facemgr/src/cache.c +++ b/ctrl/facemgr/src/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,106 +22,86 @@ * search.h). */ -#include <math.h> // log2 -#include <string.h> // memmove +#include <math.h> // log2 +#include <string.h> // memmove #include "cache.h" #define FACE_CACHE_MAX_SIZE_LOG_INIT 0 -face_cache_t * -face_cache_create() -{ - face_cache_t * face_cache = malloc(sizeof(face_cache_t)); - if (!face_cache) - goto ERR_MALLOC; +face_cache_t* face_cache_create() { + face_cache_t* face_cache = malloc(sizeof(face_cache_t)); + if (!face_cache) goto ERR_MALLOC; - face_cache->max_size_log = FACE_CACHE_MAX_SIZE_LOG_INIT; -#if(FACE_CACHE_MAX_SIZE_LOG_INIT == 0) - face_cache->faces = NULL; + face_cache->max_size_log = FACE_CACHE_MAX_SIZE_LOG_INIT; +#if (FACE_CACHE_MAX_SIZE_LOG_INIT == 0) + face_cache->faces = NULL; #else - face_cache->faces = malloc((1 << face_cache->max_size_log) * sizeof(face_t*)); - if (!face_cache->faces) - goto ERR_ARRAY: + face_cache->faces = malloc((1 << face_cache->max_size_log) * sizeof(face_t*)); + if (!face_cache->faces) + goto ERR_ARRAY : #endif - face_cache->size = 0; + face_cache->size = 0; - return face_cache; + return face_cache; -#if(FACE_CACHE_MAX_SIZE_LOG_INIT != 0) +#if (FACE_CACHE_MAX_SIZE_LOG_INIT != 0) ERR_ARRAY: - free(face_cache); + free(face_cache); #endif ERR_MALLOC: - return NULL; + return NULL; } -void -face_cache_free(face_cache_t * face_cache) -{ - free(face_cache->faces); +void face_cache_free(face_cache_t* face_cache) { + free(face_cache->faces); - free(face_cache); + free(face_cache); } -face_t * -face_cache_add(face_cache_t * face_cache, face_t * face) -{ - /* Ensure sufficient space for next addition */ - size_t new_size_log = (face_cache->size > 0) ? log2(face_cache->size) + 1 : 0; - if (new_size_log > face_cache->max_size_log) { - face_cache->max_size_log = new_size_log; - face_cache->faces = realloc(face_cache->faces, (1 << new_size_log) * sizeof(face_t*)); - } +face_t* face_cache_add(face_cache_t* face_cache, face_t* face) { + /* Ensure sufficient space for next addition */ + size_t new_size_log = (face_cache->size > 0) ? log2(face_cache->size) + 1 : 0; + if (new_size_log > face_cache->max_size_log) { + face_cache->max_size_log = new_size_log; + face_cache->faces = + realloc(face_cache->faces, (1 << new_size_log) * sizeof(face_t*)); + } - if (!face_cache->faces) - goto ERR_REALLOC; + if (!face_cache->faces) goto ERR_REALLOC; - face_cache->faces[face_cache->size++] = face; + face_cache->faces[face_cache->size++] = face; - return face; + return face; ERR_REALLOC: - return NULL; + return NULL; } -int face_cache_search(face_cache_t * face_cache, face_t * face, face_cmp_t face_cmp) -{ - for (int i = 0; i < face_cache->size; i++) - if (face_cmp(face, face_cache->faces[i])) - return i; - return -1; +int face_cache_search(face_cache_t* face_cache, face_t* face, + face_cmp_t face_cmp) { + for (int i = 0; i < face_cache->size; i++) + if (face_cmp(face, face_cache->faces[i])) return i; + return -1; } /* Remove a single occurrence */ -face_t * -face_cache_remove(face_cache_t * face_cache, face_t * face) -{ - int pos = face_cache_search(face_cache, face, face_cmp); - if (pos < 0) - return NULL; +face_t* face_cache_remove(face_cache_t* face_cache, face_t* face) { + int pos = face_cache_search(face_cache, face, face_cmp); + if (pos < 0) return NULL; - /* No need to move memory if last item is removed */ - if (pos < face_cache->size) - memmove(face_cache->faces+pos, face_cache->faces+pos+1, face_cache->size - pos); + /* No need to move memory if last item is removed */ + if (pos < face_cache->size) + memmove(face_cache->faces + pos, face_cache->faces + pos + 1, + face_cache->size - pos); - face_cache->size--; + face_cache->size--; - return face; + return face; } /* TODO : remove by ... */ -face_t * -face_cache_get_by_id(face_cache_t * face_cache, int id) -{ - return NULL; -} - - +face_t* face_cache_get_by_id(face_cache_t* face_cache, int id) { return NULL; } -void -face_cache_dump(face_cache_t * face_cache) -{ - -} +void face_cache_dump(face_cache_t* face_cache) {} diff --git a/ctrl/facemgr/src/cache.h b/ctrl/facemgr/src/cache.h index 1389ed6ec..ac14fabb8 100644 --- a/ctrl/facemgr/src/cache.h +++ b/ctrl/facemgr/src/cache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,22 +32,22 @@ * \brief Face cache */ typedef struct { - face_t ** faces; /**< array of _pointers_ to faces */ - size_t max_size_log; /**< log2 of allocated size */ - size_t size; /**< effective array size */ + face_t** faces; /**< array of _pointers_ to faces */ + size_t max_size_log; /**< log2 of allocated size */ + size_t size; /**< effective array size */ } face_cache_t; -face_cache_t * face_cache_create(); -void face_cache_free(face_cache_t * face_cache); +face_cache_t* face_cache_create(); +void face_cache_free(face_cache_t* face_cache); /* a la VPP vector, we never create a face outside of the vector */ /* problem is that face ptr can get invalid if we manipulate the vector */ -face_t * face_cache_get(face_cache_t * cache_cache); +face_t* face_cache_get(face_cache_t* cache_cache); -face_t * face_cache_add(face_cache_t * face_cache, face_t * face); -face_t * face_cache_remove(face_cache_t * face_cache, face_t * face); -face_t * face_cache_get_by_id(face_cache_t * face_cache, int id); +face_t* face_cache_add(face_cache_t* face_cache, face_t* face); +face_t* face_cache_remove(face_cache_t* face_cache, face_t* face); +face_t* face_cache_get_by_id(face_cache_t* face_cache, int id); -void face_cache_dump(face_cache_t * face_cache); +void face_cache_dump(face_cache_t* face_cache); #endif /* FACEMGR_CACHE_H */ diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c index df73acd1b..87a6279ca 100644 --- a/ctrl/facemgr/src/cfg.c +++ b/ctrl/facemgr/src/cfg.c @@ -4,7 +4,7 @@ */ #include <assert.h> -#include <hicn/ctrl.h> // HICN_DEFAULT_PORT +#include <hicn/ctrl.h> // HICN_DEFAULT_PORT #include <hicn/facemgr/cfg.h> #include <hicn/policy.h> #include <hicn/util/ip_address.h> @@ -14,691 +14,644 @@ /* Overlay */ typedef struct { - bool is_local_port; - uint16_t local_port; - bool is_local_addr; - ip_address_t local_addr; - bool is_remote_port; - uint16_t remote_port; - bool is_remote_addr; - ip_address_t remote_addr; + bool is_local_port; + uint16_t local_port; + bool is_local_addr; + hicn_ip_address_t local_addr; + bool is_remote_port; + uint16_t remote_port; + bool is_remote_addr; + hicn_ip_address_t remote_addr; } facemgr_cfg_overlay_t; -int facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t * overlay) -{ - overlay->is_local_port = false; - overlay->local_port = 0; - overlay->is_local_addr = false; - overlay->local_addr = IP_ADDRESS_EMPTY; +int facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t *overlay) { + overlay->is_local_port = false; + overlay->local_port = 0; + overlay->is_local_addr = false; + overlay->local_addr = IP_ADDRESS_EMPTY; - overlay->is_remote_port = false; - overlay->remote_port = 0; - overlay->is_remote_addr = false; - overlay->remote_addr = IP_ADDRESS_EMPTY; + overlay->is_remote_port = false; + overlay->remote_port = 0; + overlay->is_remote_addr = false; + overlay->remote_addr = IP_ADDRESS_EMPTY; - return 0; + return 0; } -int facemgr_cfg_overlay_finalize(facemgr_cfg_overlay_t * overlay) -{ - return 0; -} +int facemgr_cfg_overlay_finalize(facemgr_cfg_overlay_t *overlay) { return 0; } -facemgr_cfg_overlay_t * facemgr_cfg_overlay_create() -{ - facemgr_cfg_overlay_t * overlay = malloc(sizeof(facemgr_cfg_overlay_t)); - if (!overlay) - return NULL; +facemgr_cfg_overlay_t *facemgr_cfg_overlay_create() { + facemgr_cfg_overlay_t *overlay = malloc(sizeof(facemgr_cfg_overlay_t)); + if (!overlay) return NULL; - int rc = facemgr_cfg_overlay_initialize(overlay); - if (rc < 0) { - free(overlay); - return NULL; - } + int rc = facemgr_cfg_overlay_initialize(overlay); + if (rc < 0) { + free(overlay); + return NULL; + } - return overlay; + return overlay; } -void facemgr_cfg_overlay_free(facemgr_cfg_overlay_t * overlay) -{ - facemgr_cfg_overlay_finalize(overlay); - free(overlay); +void facemgr_cfg_overlay_free(facemgr_cfg_overlay_t *overlay) { + facemgr_cfg_overlay_finalize(overlay); + free(overlay); } typedef struct { - facemgr_cfg_overlay_t * v4; - facemgr_cfg_overlay_t * v6; + facemgr_cfg_overlay_t *v4; + facemgr_cfg_overlay_t *v6; } facemgr_cfg_overlays_t; typedef struct { - const char * interface_name; - netdevice_type_t interface_type; + const char *interface_name; + netdevice_type_t interface_type; } facemgr_cfg_match_t; - typedef struct { - /* Interface specific */ - bool is_face_type; // default is auto - facemgr_face_type_t face_type; - - /* This should be defaut for the global settings */ - bool is_ignore; - bool ignore; - bool is_discovery; - bool discovery; - bool is_ipv4; - bool ipv4; - bool is_ipv6; - bool ipv6; - - facemgr_cfg_overlays_t overlays; // fallback unless discovery is disabled + /* Interface specific */ + bool is_face_type; // default is auto + facemgr_face_type_t face_type; + + /* This should be defaut for the global settings */ + bool is_ignore; + bool ignore; + bool is_discovery; + bool discovery; + bool is_ipv4; + bool ipv4; + bool is_ipv6; + bool ipv6; + + facemgr_cfg_overlays_t overlays; // fallback unless discovery is disabled } facemgr_cfg_override_t; struct facemgr_cfg_rule_s { - facemgr_cfg_match_t match; - facemgr_cfg_override_t override; + facemgr_cfg_match_t match; + facemgr_cfg_override_t override; }; -int facemgr_cfg_override_initialize(facemgr_cfg_override_t * override) -{ - override->is_face_type = false; - override->face_type = FACEMGR_FACE_TYPE_UNDEFINED; +int facemgr_cfg_override_initialize(facemgr_cfg_override_t *override) { + override->is_face_type = false; + override->face_type = FACEMGR_FACE_TYPE_UNDEFINED; - override->is_ignore = false; - override->ignore = false; + override->is_ignore = false; + override->ignore = false; - override->is_discovery = false; - override->discovery = false; + override->is_discovery = false; + override->discovery = false; - override->is_ipv4 = false; - override->ipv6 = false; - override->is_ipv6 = false; - override->ipv6 = false; + override->is_ipv4 = false; + override->ipv6 = false; + override->is_ipv6 = false; + override->ipv6 = false; - override->overlays.v4 = NULL; - override->overlays.v6 = NULL; + override->overlays.v4 = NULL; + override->overlays.v6 = NULL; - return 0; + return 0; } -int facemgr_cfg_override_finalize(facemgr_cfg_override_t * override) -{ - if (override->overlays.v4) { - facemgr_cfg_overlay_free(override->overlays.v4); - override->overlays.v4 = NULL; - } - if (override->overlays.v6) { - facemgr_cfg_overlay_free(override->overlays.v6); - override->overlays.v6 = NULL; - } +int facemgr_cfg_override_finalize(facemgr_cfg_override_t *override) { + if (override->overlays.v4) { + facemgr_cfg_overlay_free(override->overlays.v4); + override->overlays.v4 = NULL; + } + if (override->overlays.v6) { + facemgr_cfg_overlay_free(override->overlays.v6); + override->overlays.v6 = NULL; + } - return 0; + return 0; } - /* Rule */ -facemgr_cfg_rule_t * facemgr_cfg_rule_create() -{ - facemgr_cfg_rule_t * rule = malloc(sizeof(facemgr_cfg_rule_t)); - if (!rule) - return NULL; +facemgr_cfg_rule_t *facemgr_cfg_rule_create() { + facemgr_cfg_rule_t *rule = malloc(sizeof(facemgr_cfg_rule_t)); + if (!rule) return NULL; - int rc = facemgr_cfg_rule_initialize(rule); - if (rc < 0) - return NULL; + int rc = facemgr_cfg_rule_initialize(rule); + if (rc < 0) return NULL; - return rule; + return rule; } -void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule) -{ - facemgr_cfg_rule_finalize(rule); - free(rule); +void facemgr_cfg_rule_free(facemgr_cfg_rule_t *rule) { + facemgr_cfg_rule_finalize(rule); + free(rule); } -int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule) -{ - rule->match.interface_name = NULL; - rule->match.interface_type = NETDEVICE_TYPE_UNDEFINED; +int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t *rule) { + rule->match.interface_name = NULL; + rule->match.interface_type = NETDEVICE_TYPE_UNDEFINED; - int rc = facemgr_cfg_override_initialize(&rule->override); - if (rc < 0) - return -1; + int rc = facemgr_cfg_override_initialize(&rule->override); + if (rc < 0) return -1; - return 0; + return 0; } -int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule) -{ - if (rule->match.interface_name) { - free((void*)rule->match.interface_name); - rule->match.interface_name = NULL; +int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t *rule) { + if (rule->match.interface_name) { + free((void *)rule->match.interface_name); + rule->match.interface_name = NULL; + } + return facemgr_cfg_override_finalize(&rule->override); +} + +void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) { + DEBUG(" <rule>"); + DEBUG(" <match interface_name=%s interface_type=%s>", + rule->match.interface_name, + netdevice_type_str(rule->match.interface_type)); + DEBUG(" <override>"); + if (rule->override.is_face_type) { + DEBUG(" <face_type>%d</face_type>", rule->override.face_type); + } + if (rule->override.is_ignore) { + DEBUG(" <ignore>%d</ignore>", rule->override.ignore); + } + if (rule->override.is_discovery) { + DEBUG(" <discovery>%d</discovery>", rule->override.discovery); + } + if (rule->override.is_ipv4) { + DEBUG(" <ipv4>%d</ipv4>", rule->override.ipv4); + } + if (rule->override.is_ipv6) { + DEBUG(" <ipv6>%d</ipv6>", rule->override.ipv6); + } + DEBUG(" <overlays>"); + if (rule->override.overlays.v4) { + DEBUG(" <ipv4>"); + if (rule->override.overlays.v4->is_local_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v4->local_addr); + DEBUG(" <local_addr>%s</local_addr>", buf); } - return facemgr_cfg_override_finalize(&rule->override); -} - -void facemgr_cfg_rule_dump(facemgr_cfg_rule_t * rule) -{ - DEBUG(" <rule>"); - DEBUG(" <match interface_name=%s interface_type=%s>", - rule->match.interface_name, - netdevice_type_str[rule->match.interface_type]); - DEBUG(" <override>"); - if (rule->override.is_face_type) { - DEBUG(" <face_type>%d</face_type>", rule->override.face_type); + if (rule->override.overlays.v4->is_local_port) { + DEBUG(" <local_port>%d</local_port>", + rule->override.overlays.v4->local_port); } - if (rule->override.is_ignore) { - DEBUG(" <ignore>%d</ignore>", rule->override.ignore); + if (rule->override.overlays.v4->is_remote_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v4->remote_addr); + DEBUG(" <remote_addr>%s</remote_addr>", buf); } - if (rule->override.is_discovery) { - DEBUG(" <discovery>%d</discovery>", rule->override.discovery); + if (rule->override.overlays.v4->is_remote_port) { + DEBUG(" <remote_port>%d</remote_port>", + rule->override.overlays.v4->remote_port); } - if (rule->override.is_ipv4) { - DEBUG(" <ipv4>%d</ipv4>", rule->override.ipv4); + DEBUG(" </ipv4>"); + } + if (rule->override.overlays.v6) { + DEBUG(" <ipv6>"); + if (rule->override.overlays.v6->is_local_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v6->local_addr); + DEBUG(" <local_addr>%s</local_addr>", buf); } - if (rule->override.is_ipv6) { - DEBUG(" <ipv6>%d</ipv6>", rule->override.ipv6); + if (rule->override.overlays.v6->is_local_port) { + DEBUG(" <local_port>%d</local_port>", + rule->override.overlays.v6->local_port); } - DEBUG(" <overlays>"); - if (rule->override.overlays.v4) { - DEBUG(" <ipv4>"); - if (rule->override.overlays.v4->is_local_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v4->local_addr, AF_INET); - DEBUG(" <local_addr>%s</local_addr>", buf); - } - if (rule->override.overlays.v4->is_local_port) { - DEBUG(" <local_port>%d</local_port>", - rule->override.overlays.v4->local_port); - } - if (rule->override.overlays.v4->is_remote_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v4->remote_addr, AF_INET); - DEBUG(" <remote_addr>%s</remote_addr>", buf); - } - if (rule->override.overlays.v4->is_remote_port) { - DEBUG(" <remote_port>%d</remote_port>", - rule->override.overlays.v4->remote_port); - } - DEBUG(" </ipv4>"); + if (rule->override.overlays.v6->is_remote_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v6->remote_addr); + DEBUG(" <remote_addr>%s</remote_addr>", buf); } - if (rule->override.overlays.v6) { - DEBUG(" <ipv6>"); - if (rule->override.overlays.v6->is_local_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v6->local_addr, AF_INET6); - DEBUG(" <local_addr>%s</local_addr>", buf); - } - if (rule->override.overlays.v6->is_local_port) { - DEBUG(" <local_port>%d</local_port>", - rule->override.overlays.v6->local_port); - } - if (rule->override.overlays.v6->is_remote_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v6->remote_addr, AF_INET6); - DEBUG(" <remote_addr>%s</remote_addr>", buf); - } - if (rule->override.overlays.v6->is_remote_port) { - DEBUG(" <remote_port>%d</remote_port>", - rule->override.overlays.v6->remote_port); - } - DEBUG(" </ipv6>"); + if (rule->override.overlays.v6->is_remote_port) { + DEBUG(" <remote_port>%d</remote_port>", + rule->override.overlays.v6->remote_port); } - DEBUG(" </overlays>"); - DEBUG(" </override>"); - DEBUG(" </rule>"); + DEBUG(" </ipv6>"); + } + DEBUG(" </overlays>"); + DEBUG(" </override>"); + DEBUG(" </rule>"); } -int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule, const char * interface_name, - netdevice_type_t interface_type) -{ - rule->match.interface_name = interface_name ? strdup(interface_name) : NULL; - rule->match.interface_type = interface_type; - return 0; +int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t *rule, + const char *interface_name, + netdevice_type_t interface_type) { + rule->match.interface_name = interface_name ? strdup(interface_name) : NULL; + rule->match.interface_type = interface_type; + return 0; } -int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * rule, facemgr_face_type_t * face_type) -{ - rule->override.is_face_type = true; - rule->override.face_type = *face_type; - return 0; +int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t *rule, + facemgr_face_type_t *face_type) { + rule->override.is_face_type = true; + rule->override.face_type = *face_type; + return 0; } -int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * rule) -{ - rule->override.is_face_type = false; - rule->override.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */ - return 0; +int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t *rule) { + rule->override.is_face_type = false; + rule->override.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */ + return 0; } -int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * rule, bool status) -{ - rule->override.is_discovery = true; - rule->override.discovery = status; - return 0; +int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t *rule, bool status) { + rule->override.is_discovery = true; + rule->override.discovery = status; + return 0; } -int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * rule) -{ - rule->override.is_discovery = false; - return 0; +int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t *rule) { + rule->override.is_discovery = false; + return 0; } -int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * rule, bool status) -{ - rule->override.is_ignore = true; - rule->override.ignore = status; - return 0; +int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t *rule, bool status) { + rule->override.is_ignore = true; + rule->override.ignore = status; + return 0; } -int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * rule) -{ - rule->override.is_ignore = false; - return 0; +int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t *rule) { + rule->override.is_ignore = false; + return 0; } -int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * rule, bool status) -{ - rule->override.is_ipv4 = true; - rule->override.ipv4 = status; - return 0; +int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t *rule, bool status) { + rule->override.is_ipv4 = true; + rule->override.ipv4 = status; + return 0; } -int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * rule) -{ - rule->override.is_ipv4 = false; - return 0; +int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t *rule) { + rule->override.is_ipv4 = false; + return 0; } -int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * rule, bool status) -{ - rule->override.is_ipv6 = true; - rule->override.ipv6 = status; - return 0; +int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t *rule, bool status) { + rule->override.is_ipv6 = true; + rule->override.ipv6 = status; + return 0; } -int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * rule) -{ - rule->override.is_ipv6 = false; - return 0; +int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t *rule) { + rule->override.is_ipv6 = false; + return 0; } -int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family, - ip_address_t * local_addr, uint16_t local_port, - ip_address_t * remote_addr, uint16_t remote_port) { - if ((family != AF_INET) && (family != AF_INET6)) - return -1; +int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t *rule, int family, + hicn_ip_address_t *local_addr, + uint16_t local_port, + hicn_ip_address_t *remote_addr, + uint16_t remote_port) { + if ((family != AF_INET) && (family != AF_INET6)) return -1; - facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create(); - if (local_addr) { - overlay->is_local_addr = true; - overlay->local_addr = *local_addr; - } - if (IS_VALID_PORT(local_port)) { - overlay->is_local_port = true; - overlay->local_port = local_port; - } - if (remote_addr) { - overlay->is_remote_addr = true; - overlay->remote_addr = *remote_addr; - } - if (IS_VALID_PORT(remote_port)) { - overlay->is_remote_port = true; - overlay->remote_port = remote_port; - } + facemgr_cfg_overlay_t *overlay = facemgr_cfg_overlay_create(); + if (local_addr) { + overlay->is_local_addr = true; + overlay->local_addr = *local_addr; + } + if (IS_VALID_PORT(local_port)) { + overlay->is_local_port = true; + overlay->local_port = local_port; + } + if (remote_addr) { + overlay->is_remote_addr = true; + overlay->remote_addr = *remote_addr; + } + if (IS_VALID_PORT(remote_port)) { + overlay->is_remote_port = true; + overlay->remote_port = remote_port; + } - switch(family) { - case AF_INET: - rule->override.overlays.v4 = overlay; - break; + switch (family) { + case AF_INET: + rule->override.overlays.v4 = overlay; + break; - case AF_INET6: - rule->override.overlays.v6 = overlay; - break; + case AF_INET6: + rule->override.overlays.v6 = overlay; + break; - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } -int facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family) -{ - if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC)) - return -1; +int facemgr_rule_unset_overlay(facemgr_cfg_rule_t *rule, int family) { + if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC)) + return -1; - if ((family == AF_UNSPEC) || (family == AF_INET)) { - if (rule->override.overlays.v4) { - facemgr_cfg_overlay_free(rule->override.overlays.v4); - rule->override.overlays.v4 = NULL; - } - } - if ((family == AF_UNSPEC) || (family == AF_INET6)) { - if (rule->override.overlays.v6) { - facemgr_cfg_overlay_free(rule->override.overlays.v6); - rule->override.overlays.v6 = NULL; - } + if ((family == AF_UNSPEC) || (family == AF_INET)) { + if (rule->override.overlays.v4) { + facemgr_cfg_overlay_free(rule->override.overlays.v4); + rule->override.overlays.v4 = NULL; } - return 0; -} - -int facemgr_cfg_rule_cmp(const facemgr_cfg_rule_t * r1, const facemgr_cfg_rule_t * r2) -{ - /* - * We implement a lexicographic order on the tuple (interface_name, - * interface_type) - */ - - /* We need to handle NULL cases out of strcmp */ - if (!r1->match.interface_name) { - if (r2->match.interface_name) - return 1; - else - goto BOTH_NULL; - } else { - if (!r2->match.interface_name) - return -1; + } + if ((family == AF_UNSPEC) || (family == AF_INET6)) { + if (rule->override.overlays.v6) { + facemgr_cfg_overlay_free(rule->override.overlays.v6); + rule->override.overlays.v6 = NULL; } - - - /* Only if both are non-NULL, we proceed to strcmp */ - int rc = strcmp(r1->match.interface_name, r2->match.interface_name); - if (rc != 0) - return rc; + } + return 0; +} + +int facemgr_cfg_rule_cmp(const facemgr_cfg_rule_t *r1, + const facemgr_cfg_rule_t *r2) { + /* + * We implement a lexicographic order on the tuple (interface_name, + * interface_type) + */ + + /* We need to handle NULL cases out of strcmp */ + if (!r1->match.interface_name) { + if (r2->match.interface_name) + return 1; + else + goto BOTH_NULL; + } else { + if (!r2->match.interface_name) return -1; + } + + /* Only if both are non-NULL, we proceed to strcmp */ + int rc = strcmp(r1->match.interface_name, r2->match.interface_name); + if (rc != 0) return rc; BOTH_NULL: - return r1->match.interface_type - r2->match.interface_type; + return r1->match.interface_type - r2->match.interface_type; } /* General */ TYPEDEF_SET_H(facemgr_cfg_rule_set, facemgr_cfg_rule_t *); -TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp, generic_snprintf); +TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp, + generic_snprintf); struct facemgr_cfg_s { - facemgr_cfg_override_t global; - facemgr_cfg_rule_set_t * rule_set; - facelet_array_t * static_facelets; - //log_cfg_t log; + facemgr_cfg_override_t global; + facemgr_cfg_rule_set_t *rule_set; + facelet_array_t *static_facelets; + // log_cfg_t log; }; -facemgr_cfg_t * facemgr_cfg_create() -{ - facemgr_cfg_t * cfg = malloc(sizeof(facemgr_cfg_t)); - if (!cfg) { - ERROR("[facemgr_cfg_create] Error allocating face manager configuration"); - goto ERR_MALLOC; - } +facemgr_cfg_t *facemgr_cfg_create() { + facemgr_cfg_t *cfg = malloc(sizeof(facemgr_cfg_t)); + if (!cfg) { + ERROR("[facemgr_cfg_create] Error allocating face manager configuration"); + goto ERR_MALLOC; + } - int rc = facemgr_cfg_initialize(cfg); - if (rc < 0) { - ERROR("[facemgr_cfg_create] Error initializing face manager configuration"); - goto ERR_INIT; - } + int rc = facemgr_cfg_initialize(cfg); + if (rc < 0) { + ERROR("[facemgr_cfg_create] Error initializing face manager configuration"); + goto ERR_INIT; + } - return cfg; + return cfg; ERR_INIT: - free(cfg); + free(cfg); ERR_MALLOC: - return NULL; + return NULL; } -void facemgr_cfg_free(facemgr_cfg_t * cfg) -{ - facemgr_cfg_finalize(cfg); - free(cfg); +void facemgr_cfg_free(facemgr_cfg_t *cfg) { + facemgr_cfg_finalize(cfg); + free(cfg); } -int facemgr_cfg_initialize(facemgr_cfg_t * cfg) -{ - int rc = facemgr_cfg_override_initialize(&cfg->global); - if (rc < 0) { - ERROR("[facemgr_cfg_initialize] Error initializing global values"); - goto ERR_OVERRIDE; - } +int facemgr_cfg_initialize(facemgr_cfg_t *cfg) { + int rc = facemgr_cfg_override_initialize(&cfg->global); + if (rc < 0) { + ERROR("[facemgr_cfg_initialize] Error initializing global values"); + goto ERR_OVERRIDE; + } - cfg->rule_set = facemgr_cfg_rule_set_create(); - if (!cfg->rule_set) { - ERROR("[facemgr_cfg_initialize] Error creating rule set"); - goto ERR_RULE_SET; - } + cfg->rule_set = facemgr_cfg_rule_set_create(); + if (!cfg->rule_set) { + ERROR("[facemgr_cfg_initialize] Error creating rule set"); + goto ERR_RULE_SET; + } - cfg->static_facelets = facelet_array_create(cfg->static_facelets); - if (!cfg->static_facelets) { - ERROR("[facemgr_cfg_initialize] Error creating static facelet set"); - goto ERR_STATIC; - } + cfg->static_facelets = facelet_array_create(); + if (!cfg->static_facelets) { + ERROR("[facemgr_cfg_initialize] Error creating static facelet set"); + goto ERR_STATIC; + } - return 0; + return 0; ERR_STATIC: - facemgr_cfg_rule_set_free(cfg->rule_set); + facemgr_cfg_rule_set_free(cfg->rule_set); ERR_RULE_SET: - facemgr_cfg_override_finalize(&cfg->global); + facemgr_cfg_override_finalize(&cfg->global); ERR_OVERRIDE: - return -1; -} - -int facemgr_cfg_finalize(facemgr_cfg_t * cfg) -{ - /* TODO Free all rules */ - facemgr_cfg_rule_t ** rule_array; - int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); - if (n < 0) { - ERROR("[facemgr_cfg_finalize] Could not retrieve rule set array from configuration"); - } else { - for (unsigned i = 0; i < n; i++) { - facemgr_cfg_rule_t * rule = rule_array[i]; - if (facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL) < 0) { - ERROR("[facemgr_cfg_finalize] Could not remove rule from set"); - } - facemgr_cfg_rule_free(rule); - } - free(rule_array); + return -1; +} + +int facemgr_cfg_finalize(facemgr_cfg_t *cfg) { + /* TODO Free all rules */ + facemgr_cfg_rule_t **rule_array; + int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); + if (n < 0) { + ERROR( + "[facemgr_cfg_finalize] Could not retrieve rule set array from " + "configuration"); + } else { + for (unsigned i = 0; i < n; i++) { + facemgr_cfg_rule_t *rule = rule_array[i]; + if (!rule) continue; /* Should not occur */ + if (facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL) < 0) { + ERROR("[facemgr_cfg_finalize] Could not remove rule from set"); + } + facemgr_cfg_rule_free(rule); + } + free(rule_array); + } + facemgr_cfg_rule_set_free(cfg->rule_set); + + /* Free all facelets from static array */ + for (unsigned i = 0; i < facelet_array_len(cfg->static_facelets); i++) { + facelet_t *facelet; + if (facelet_array_get_index(cfg->static_facelets, i, &facelet) < 0) { + ERROR("[facemgr_cfg_finalize] Error getting facelet in array"); + continue; } - facemgr_cfg_rule_set_free(cfg->rule_set); - - /* Free all facelets from static array */ - for (unsigned i = 0; i < facelet_array_len(cfg->static_facelets); i++) { - facelet_t * facelet; - if (facelet_array_get_index(cfg->static_facelets, i, &facelet) < 0) { - ERROR("[facemgr_cfg_finalize] Error getting facelet in array"); - continue; - } - if (facelet_array_remove_index(cfg->static_facelets, i, NULL)) { - ERROR("[facemgr_cfg_finalize] Could not purge facelet from static set"); - } - facelet_free(facelet); + if (facelet_array_remove_index(cfg->static_facelets, i, NULL)) { + ERROR("[facemgr_cfg_finalize] Could not purge facelet from static set"); } + facelet_free(facelet); + } - facelet_array_free(cfg->static_facelets); + facelet_array_free(cfg->static_facelets); - return facemgr_cfg_override_finalize(&cfg->global); + return facemgr_cfg_override_finalize(&cfg->global); } -void facemgr_cfg_dump(facemgr_cfg_t * cfg) -{ - return; /* NOT IMPLEMENTED */ -} +void facemgr_cfg_dump(facemgr_cfg_t *cfg) { return; /* NOT IMPLEMENTED */ } /* General */ -int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type) -{ - cfg->global.is_face_type = true; - cfg->global.face_type = *face_type; - return 0; -} - -int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg) -{ - cfg->global.is_face_type = false; - cfg->global.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */ - return 0; -} - -int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status) -{ - cfg->global.is_discovery = true; - cfg->global.discovery = status; - return 0; -} - -int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg) -{ - cfg->global.is_discovery = false; - return 0; -} - -int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status) -{ - cfg->global.is_ipv4 = true; - cfg->global.ipv4 = status; - DEBUG("<global>"); - DEBUG(" <ipv4>%d</ipv4>", cfg->global.ipv4); - DEBUG("</global>"); - return 0; -} - -int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg) -{ - cfg->global.is_ipv4 = false; - return 0; -} - -int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status) -{ - cfg->global.is_ipv6 = true; - cfg->global.ipv6 = status; - DEBUG("<global>"); - DEBUG(" <ipv6>%d</ipv6>", cfg->global.ipv6); - DEBUG("</global>"); - return 0; -} - -int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg) -{ - cfg->global.is_ipv6 = false; - return 0; -} - -int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family, - ip_address_t * local_addr, uint16_t local_port, - ip_address_t * remote_addr, uint16_t remote_port) -{ - if ((family != AF_INET) && (family != AF_INET6)) - return -1; - - facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create(); - if (local_addr) { - overlay->is_local_addr = true; - overlay->local_addr = *local_addr; - } - if (IS_VALID_PORT(local_port)) { - overlay->is_local_port = true; - overlay->local_port = local_port; - } - if (remote_addr) { - overlay->is_remote_addr = true; - overlay->remote_addr = *remote_addr; +int facemgr_cfg_set_face_type(facemgr_cfg_t *cfg, + facemgr_face_type_t *face_type) { + cfg->global.is_face_type = true; + cfg->global.face_type = *face_type; + return 0; +} + +int facemgr_cfg_unset_face_type(facemgr_cfg_t *cfg) { + cfg->global.is_face_type = false; + cfg->global.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */ + return 0; +} + +int facemgr_cfg_set_discovery(facemgr_cfg_t *cfg, bool status) { + cfg->global.is_discovery = true; + cfg->global.discovery = status; + return 0; +} + +int facemgr_cfg_unset_discovery(facemgr_cfg_t *cfg) { + cfg->global.is_discovery = false; + return 0; +} + +int facemgr_cfg_set_ipv4(facemgr_cfg_t *cfg, bool status) { + cfg->global.is_ipv4 = true; + cfg->global.ipv4 = status; + DEBUG("<global>"); + DEBUG(" <ipv4>%d</ipv4>", cfg->global.ipv4); + DEBUG("</global>"); + return 0; +} + +int facemgr_cfg_unset_ipv4(facemgr_cfg_t *cfg) { + cfg->global.is_ipv4 = false; + return 0; +} + +int facemgr_cfg_set_ipv6(facemgr_cfg_t *cfg, bool status) { + cfg->global.is_ipv6 = true; + cfg->global.ipv6 = status; + DEBUG("<global>"); + DEBUG(" <ipv6>%d</ipv6>", cfg->global.ipv6); + DEBUG("</global>"); + return 0; +} + +int facemgr_cfg_unset_ipv6(facemgr_cfg_t *cfg) { + cfg->global.is_ipv6 = false; + return 0; +} + +int facemgr_cfg_set_overlay(facemgr_cfg_t *cfg, int family, + hicn_ip_address_t *local_addr, uint16_t local_port, + hicn_ip_address_t *remote_addr, + uint16_t remote_port) { + if ((family != AF_INET) && (family != AF_INET6)) return -1; + + facemgr_cfg_overlay_t *overlay = facemgr_cfg_overlay_create(); + if (local_addr) { + overlay->is_local_addr = true; + overlay->local_addr = *local_addr; + } + if (IS_VALID_PORT(local_port)) { + overlay->is_local_port = true; + overlay->local_port = local_port; + } + if (remote_addr) { + overlay->is_remote_addr = true; + overlay->remote_addr = *remote_addr; + } + if (IS_VALID_PORT(remote_port)) { + overlay->is_remote_port = true; + overlay->remote_port = remote_port; + } + + DEBUG("facemgr_cfg_set_overlay"); + + switch (family) { + case AF_INET: + cfg->global.overlays.v4 = overlay; + break; + + case AF_INET6: + cfg->global.overlays.v6 = overlay; + break; + + default: + return -1; + } + + DEBUG("<global>"); + DEBUG(" <overlay>"); + if (overlay) { + DEBUG(" <ipv4>"); + if (overlay->is_local_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->local_addr); + DEBUG(" <local_addr>%s</local_addr>", buf); } - if (IS_VALID_PORT(remote_port)) { - overlay->is_remote_port = true; - overlay->remote_port = remote_port; + if (overlay->is_local_port) { + DEBUG(" <local_port>%d</local_port>", overlay->local_port); } - - DEBUG("facemgr_cfg_set_overlay"); - - switch(family) { - case AF_INET: - cfg->global.overlays.v4 = overlay; - break; - - case AF_INET6: - cfg->global.overlays.v6 = overlay; - break; - - default: - return -1; + if (overlay->is_remote_addr) { + char buf[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->remote_addr); + DEBUG(" <remote_addr>%s</remote_addr>", buf); } - - DEBUG("<global>"); - DEBUG(" <overlay>"); - if (overlay) { - DEBUG(" <ipv4>"); - if (overlay->is_local_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &overlay->local_addr, AF_INET); - DEBUG(" <local_addr>%s</local_addr>", buf); - } - if (overlay->is_local_port) { - DEBUG(" <local_port>%d</local_port>", - overlay->local_port); - } - if (overlay->is_remote_addr) { - char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &overlay->remote_addr, AF_INET); - DEBUG(" <remote_addr>%s</remote_addr>", buf); - } - if (overlay->is_remote_port) { - DEBUG(" <remote_port>%d</remote_port>", - overlay->remote_port); - } - DEBUG(" </ipv4>"); + if (overlay->is_remote_port) { + DEBUG(" <remote_port>%d</remote_port>", overlay->remote_port); } - DEBUG(" </overlay>"); - DEBUG("</global>"); + DEBUG(" </ipv4>"); + } + DEBUG(" </overlay>"); + DEBUG("</global>"); - return 0; + return 0; } -int facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family) -{ - if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC)) - return -1; +int facemgr_cfg_unset_overlay(facemgr_cfg_t *cfg, int family) { + if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC)) + return -1; - if ((family == AF_UNSPEC) || (family == AF_INET)) { - if (cfg->global.overlays.v4) { - facemgr_cfg_overlay_free(cfg->global.overlays.v4); - cfg->global.overlays.v4 = NULL; - } + if ((family == AF_UNSPEC) || (family == AF_INET)) { + if (cfg->global.overlays.v4) { + facemgr_cfg_overlay_free(cfg->global.overlays.v4); + cfg->global.overlays.v4 = NULL; } - if ((family == AF_UNSPEC) || (family == AF_INET6)) { - if (cfg->global.overlays.v6) { - facemgr_cfg_overlay_free(cfg->global.overlays.v6); - cfg->global.overlays.v6 = NULL; - } + } + if ((family == AF_UNSPEC) || (family == AF_INET6)) { + if (cfg->global.overlays.v6) { + facemgr_cfg_overlay_free(cfg->global.overlays.v6); + cfg->global.overlays.v6 = NULL; } - return 0; + } + return 0; } -int facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule) -{ - facemgr_cfg_rule_dump(rule); - return facemgr_cfg_rule_set_add(cfg->rule_set, rule); +int facemgr_cfg_add_rule(facemgr_cfg_t *cfg, facemgr_cfg_rule_t *rule) { + facemgr_cfg_rule_dump(rule); + return facemgr_cfg_rule_set_add(cfg->rule_set, rule); } -int facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule) -{ - return facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL); +int facemgr_cfg_del_rule(facemgr_cfg_t *cfg, facemgr_cfg_rule_t *rule) { + return facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL); } -int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name, - netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule) { - facemgr_cfg_rule_t rule_search = { - .match = { - .interface_name = interface_name, - .interface_type = interface_type, - }, - }; - return facemgr_cfg_rule_set_get(cfg->rule_set, &rule_search, rule); +int facemgr_cfg_get_rule(const facemgr_cfg_t *cfg, const char *interface_name, + netdevice_type_t interface_type, + facemgr_cfg_rule_t **rule) { + facemgr_cfg_rule_t rule_search = { + .match = + { + .interface_name = interface_name, + .interface_type = interface_type, + }, + }; + return facemgr_cfg_rule_set_get(cfg->rule_set, &rule_search, rule); } /* Query API */ @@ -709,506 +662,473 @@ int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name, * TODO: * - until we have proper indexes we loop through the whole structure */ -int facemgr_cfg_get_override(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - facemgr_cfg_override_t ** override) -{ - if (!netdevice) { - *override = NULL; - return 0; - } - - facemgr_cfg_rule_t **rule_array; - int rc = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); - if (rc < 0) { - ERROR("facemgr_cfg_rule_set_get_array failed"); - return rc; - } - for (unsigned i = 0; i < rc; i++) { - const char * interface_name = rule_array[i]->match.interface_name; - /* Check match for interface name */ - if (interface_name && (strcmp(interface_name, netdevice->name) != 0)) - continue; - /* Check match for interface type */ - if (rule_array[i]->match.interface_type != NETDEVICE_TYPE_UNDEFINED) { -//#ifdef __ANDROID__ - if (netdevice_type != rule_array[i]->match.interface_type) - continue; -//#else -// ERROR("Match on interface type is currently not implemented"); -// goto ERR_ARRAY; -//#endif /* __ANDROID__ */ - } - /* Found match... do we have an override for face_type */ - *override = &rule_array[i]->override; - goto FOUND; - } - +int facemgr_cfg_get_override(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + facemgr_cfg_override_t **override) { + if (!netdevice) { *override = NULL; - -FOUND: - free(rule_array); return 0; - -//#ifndef __ANDROID__ -//ERR_ARRAY: -// free(rule_array); -// return -1; -//#endif /* __ANDROID__ */ -} - -int facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - facemgr_face_type_t * face_type) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) { - ERROR("get override failed"); - return rc; - } - - if ((override) && (override->is_face_type)) { - *face_type = override->face_type; - return 0; + } + + facemgr_cfg_rule_t **rule_array; + int rc = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); + if (rc < 0) { + ERROR("facemgr_cfg_rule_set_get_array failed"); + return rc; + } + for (unsigned i = 0; i < rc; i++) { + facemgr_cfg_rule_t *rule = rule_array[i]; + if (!rule) continue; /* Should not occur */ + const char *interface_name = rule->match.interface_name; + /* Check match for interface name */ + if (interface_name && (strcmp(interface_name, netdevice->name) != 0)) + continue; + /* Check match for interface type */ + if (rule->match.interface_type != NETDEVICE_TYPE_UNDEFINED) { + //#ifdef __ANDROID__ + if (netdevice_type != rule->match.interface_type) continue; + //#else + // ERROR("Match on interface type is currently not + // implemented"); goto ERR_ARRAY; + //#endif /* __ANDROID__ */ } + /* Found match... do we have an override for face_type */ + *override = &rule->override; + goto FOUND; + } - *face_type = cfg->global.is_face_type - ? cfg->global.face_type - : FACEMGR_FACE_TYPE_DEFAULT; + *override = NULL; +FOUND: + free(rule_array); + return 0; + + //#ifndef __ANDROID__ + // ERR_ARRAY: + // free(rule_array); + // return -1; + //#endif /* __ANDROID__ */ +} + +int facemgr_cfg_get_face_type(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + facemgr_face_type_t *face_type) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) { + ERROR("get override failed"); + return rc; + } + + if ((override) && (override->is_face_type)) { + *face_type = override->face_type; return 0; -} + } -int facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * discovery) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - if ((override) && (override->is_discovery)) { - *discovery = override->discovery; - return 0; - } + *face_type = cfg->global.is_face_type ? cfg->global.face_type + : FACEMGR_FACE_TYPE_DEFAULT; - *discovery = cfg->global.is_discovery - ? cfg->global.discovery - : FACEMGR_CFG_DEFAULT_DISCOVERY; - return 0; + return 0; } -int facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ipv4) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - if ((override) && (override->is_ipv4)) { - *ipv4 = override->ipv4; - return 0; - } +int facemgr_cfg_get_discovery(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + bool *discovery) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; - *ipv4 = cfg->global.is_ipv4 - ? cfg->global.ipv4 - : FACEMGR_CFG_DEFAULT_IPV4; + if ((override) && (override->is_discovery)) { + *discovery = override->discovery; return 0; -} + } -int facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ipv6) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - if ((override) && (override->is_ipv6)) { - *ipv6 = override->ipv6; - return 0; - } - - *ipv6 = cfg->global.is_ipv6 - ? cfg->global.ipv6 - : FACEMGR_CFG_DEFAULT_IPV6; - return 0; + *discovery = cfg->global.is_discovery ? cfg->global.discovery + : FACEMGR_CFG_DEFAULT_DISCOVERY; + return 0; } -int facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - bool * ignore) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - if ((override) && (override->is_ignore)) { - *ignore = override->ignore; - return 0; - } - - assert (!cfg->global.is_ignore); - - *ignore = (netdevice && (netdevice->name[0] != '\0') && strcmp(netdevice->name, "lo") == 0); +int facemgr_cfg_get_ipv4(const facemgr_cfg_t *cfg, const netdevice_t *netdevice, + netdevice_type_t netdevice_type, bool *ipv4) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; + if ((override) && (override->is_ipv4)) { + *ipv4 = override->ipv4; return 0; -} + } -int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t * addr) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - switch (family) { - case AF_INET: - if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_addr)) { - *addr = override->overlays.v4->local_addr; - return 0; - } - if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_addr)) { - *addr = cfg->global.overlays.v4->local_addr; - return 0; - } - break; - case AF_INET6: - if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_addr)) { - *addr = override->overlays.v6->local_addr; - return 0; - } - if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_addr)) { - *addr = cfg->global.overlays.v6->local_addr; - return 0; - } - break; - case AF_UNSPEC: - break; - default: - return -1; - } - - *addr = IP_ADDRESS_EMPTY; - return 0; + *ipv4 = cfg->global.is_ipv4 ? cfg->global.ipv4 : FACEMGR_CFG_DEFAULT_IPV4; + return 0; } -int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, u16 * port) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - switch (family) { - case AF_INET: - if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_port)) { - *port = override->overlays.v4->local_port; - return 0; - } - if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_port)) { - *port = cfg->global.overlays.v4->local_port; - return 0; - } - break; - case AF_INET6: - if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_port)) { - *port = override->overlays.v6->local_port; - return 0; - } - if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_port)) { - *port = cfg->global.overlays.v6->local_port; - return 0; - } - break; - case AF_UNSPEC: - break; - default: - return -1; - } +int facemgr_cfg_get_ipv6(const facemgr_cfg_t *cfg, const netdevice_t *netdevice, + netdevice_type_t netdevice_type, bool *ipv6) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; - *port = HICN_DEFAULT_PORT; + if ((override) && (override->is_ipv6)) { + *ipv6 = override->ipv6; return 0; -} - -int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t * addr) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - switch (family) { - case AF_INET: - if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_addr)) { - DEBUG("remote addr v4 from override"); - *addr = override->overlays.v4->remote_addr; - return 0; - } - if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_addr)) { - DEBUG("remote addr v4 from global"); - *addr = cfg->global.overlays.v4->remote_addr; - return 0; - } - break; - case AF_INET6: - if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_addr)) { - DEBUG("remote addr v6 from override"); - *addr = override->overlays.v6->remote_addr; - return 0; - } - if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_addr)) { - DEBUG("remote addr v6 from global"); - *addr = cfg->global.overlays.v6->remote_addr; - return 0; - } - break; - case AF_UNSPEC: - break; - default: - return -1; - } + } - DEBUG("remote addr empty"); - *addr = IP_ADDRESS_EMPTY; - return 0; + *ipv6 = cfg->global.is_ipv6 ? cfg->global.ipv6 : FACEMGR_CFG_DEFAULT_IPV6; + return 0; } -int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg, - const netdevice_t * netdevice, netdevice_type_t netdevice_type, - int family, u16 * port) -{ - facemgr_cfg_override_t * override; - int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, - &override); - if (rc < 0) - return rc; - - switch (family) { - case AF_INET: - if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_port)) { - *port = override->overlays.v4->remote_port; - return 0; - } - if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_port)) { - *port = cfg->global.overlays.v4->remote_port; - return 0; - } - break; - case AF_INET6: - if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_port)) { - *port = override->overlays.v6->remote_port; - return 0; - } - if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_port)) { - *port = cfg->global.overlays.v6->remote_port; - return 0; - } - break; - case AF_UNSPEC: - break; - default: - return -1; - } +int facemgr_cfg_get_ignore(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, bool *ignore) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; - *port = HICN_DEFAULT_PORT; + if ((override) && (override->is_ignore)) { + *ignore = override->ignore; return 0; -} + } -int facemgr_cfg_rule_get(const facemgr_cfg_t * cfg, const netdevice_t netdevice, netdevice_type_t - netdevice_type, facemgr_cfg_rule_t ** rule) -{ - facemgr_cfg_rule_t **rule_array; - *rule = NULL; - int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); - if (n < 0) { - ERROR("facemgr_cfg_rule_set_get_array failed"); - return n; - } - for (unsigned i = 0; i < n; i++) { - const char * interface_name = rule_array[i]->match.interface_name; - /* Check match for interface name */ - if (netdevice.name[0] != '\0') { - if (!interface_name) - continue; - if (strcmp(netdevice.name, interface_name) != 0) - continue; - } else { - if (interface_name && interface_name[0] != '\0') - continue; - } - - /* Check match for netdevice_type */ - if (netdevice_type != rule_array[i]->match.interface_type) - continue; - - /* Found */ - *rule = rule_array[i]; - break; - } - return 0; -} + assert(!cfg->global.is_ignore); -int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t * rule, - facemgr_face_type_t * face_type) -{ - if (!rule->override.is_face_type) - return -1; - *face_type = rule->override.face_type; - return 0; -} - -int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t * rule, bool * discovery) -{ - if (!rule->override.is_discovery) - return -1; - *discovery = rule->override.discovery; - return 0; -} - -int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t * rule, bool * ignore) -{ - if (!rule->override.is_ignore) - return -1; - *ignore = rule->override.ignore; - return 0; -} - -int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t * rule, bool * ipv4) -{ - if (!rule->override.is_ipv4) - return -1; - *ipv4 = rule->override.ipv4; - return 0; -} - -int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t * rule, bool * ipv6) -{ - if (!rule->override.is_ipv6) - return -1; - *ipv6 = rule->override.ipv6; - return 0; -} - -int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t * rule, int family, - ip_address_t * addr) -{ - facemgr_cfg_overlay_t * overlay = NULL; - switch(family) { - case AF_INET: - overlay = rule->override.overlays.v4; - break; - case AF_INET6: - overlay = rule->override.overlays.v6; - break; - default: - return -1; - } - if (!overlay->is_local_addr) - return -1; - *addr = overlay->local_addr; - return 0; -} + *ignore = (netdevice && (netdevice->name[0] != '\0') && + strcmp(netdevice->name, "lo") == 0); -int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t * rule, int family, - uint16_t * port) -{ - facemgr_cfg_overlay_t * overlay = NULL; - switch(family) { - case AF_INET: - overlay = rule->override.overlays.v4; - break; - case AF_INET6: - overlay = rule->override.overlays.v6; - break; - default: - return -1; - } - if (!overlay->is_local_port) - return -1; - *port = overlay->local_port; - return 0; + return 0; } -int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t * rule, int family, - ip_address_t * addr) -{ - facemgr_cfg_overlay_t * overlay = NULL; - switch(family) { - case AF_INET: - overlay = rule->override.overlays.v4; - break; - case AF_INET6: - overlay = rule->override.overlays.v6; - break; - default: - return -1; - } - if (!overlay->is_remote_addr) - return -1; - *addr = overlay->remote_addr; - return 0; -} +int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + int family, hicn_ip_address_t *addr) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; -int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t * rule, int family, - uint16_t * port) -{ - facemgr_cfg_overlay_t * overlay = NULL; - switch(family) { - case AF_INET: - overlay = rule->override.overlays.v4; - break; - case AF_INET6: - overlay = rule->override.overlays.v6; - break; - default: - return -1; + switch (family) { + case AF_INET: + if ((override) && (override->overlays.v4) && + (override->overlays.v4->is_local_addr)) { + *addr = override->overlays.v4->local_addr; + return 0; + } + if ((cfg->global.overlays.v4) && + (cfg->global.overlays.v4->is_local_addr)) { + *addr = cfg->global.overlays.v4->local_addr; + return 0; + } + break; + case AF_INET6: + if ((override) && (override->overlays.v6) && + (override->overlays.v6->is_local_addr)) { + *addr = override->overlays.v6->local_addr; + return 0; + } + if ((cfg->global.overlays.v6) && + (cfg->global.overlays.v6->is_local_addr)) { + *addr = cfg->global.overlays.v6->local_addr; + return 0; + } + break; + case AF_UNSPEC: + break; + default: + return -1; + } + + *addr = IP_ADDRESS_EMPTY; + return 0; +} + +int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + int family, u16 *port) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; + + switch (family) { + case AF_INET: + if ((override) && (override->overlays.v4) && + (override->overlays.v4->is_local_port)) { + *port = override->overlays.v4->local_port; + return 0; + } + if ((cfg->global.overlays.v4) && + (cfg->global.overlays.v4->is_local_port)) { + *port = cfg->global.overlays.v4->local_port; + return 0; + } + break; + case AF_INET6: + if ((override) && (override->overlays.v6) && + (override->overlays.v6->is_local_port)) { + *port = override->overlays.v6->local_port; + return 0; + } + if ((cfg->global.overlays.v6) && + (cfg->global.overlays.v6->is_local_port)) { + *port = cfg->global.overlays.v6->local_port; + return 0; + } + break; + case AF_UNSPEC: + break; + default: + return -1; + } + + *port = HICN_DEFAULT_PORT; + return 0; +} + +int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + int family, hicn_ip_address_t *addr) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; + + switch (family) { + case AF_INET: + if ((override) && (override->overlays.v4) && + (override->overlays.v4->is_remote_addr)) { + DEBUG("remote addr v4 from override"); + *addr = override->overlays.v4->remote_addr; + return 0; + } + if ((cfg->global.overlays.v4) && + (cfg->global.overlays.v4->is_remote_addr)) { + DEBUG("remote addr v4 from global"); + *addr = cfg->global.overlays.v4->remote_addr; + return 0; + } + break; + case AF_INET6: + if ((override) && (override->overlays.v6) && + (override->overlays.v6->is_remote_addr)) { + DEBUG("remote addr v6 from override"); + *addr = override->overlays.v6->remote_addr; + return 0; + } + if ((cfg->global.overlays.v6) && + (cfg->global.overlays.v6->is_remote_addr)) { + DEBUG("remote addr v6 from global"); + *addr = cfg->global.overlays.v6->remote_addr; + return 0; + } + break; + case AF_UNSPEC: + break; + default: + return -1; + } + + DEBUG("remote addr empty"); + *addr = IP_ADDRESS_EMPTY; + return 0; +} + +int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t *cfg, + const netdevice_t *netdevice, + netdevice_type_t netdevice_type, + int family, u16 *port) { + facemgr_cfg_override_t *override; + int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); + if (rc < 0) return rc; + + switch (family) { + case AF_INET: + if ((override) && (override->overlays.v4) && + (override->overlays.v4->is_remote_port)) { + *port = override->overlays.v4->remote_port; + return 0; + } + if ((cfg->global.overlays.v4) && + (cfg->global.overlays.v4->is_remote_port)) { + *port = cfg->global.overlays.v4->remote_port; + return 0; + } + break; + case AF_INET6: + if ((override) && (override->overlays.v6) && + (override->overlays.v6->is_remote_port)) { + *port = override->overlays.v6->remote_port; + return 0; + } + if ((cfg->global.overlays.v6) && + (cfg->global.overlays.v6->is_remote_port)) { + *port = cfg->global.overlays.v6->remote_port; + return 0; + } + break; + case AF_UNSPEC: + break; + default: + return -1; + } + + *port = HICN_DEFAULT_PORT; + return 0; +} + +int facemgr_cfg_rule_get(const facemgr_cfg_t *cfg, const netdevice_t netdevice, + netdevice_type_t netdevice_type, + facemgr_cfg_rule_t **rule_p) { + facemgr_cfg_rule_t **rule_array; + *rule_p = NULL; + int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array); + if (n < 0) { + ERROR("facemgr_cfg_rule_set_get_array failed"); + return n; + } + for (unsigned i = 0; i < n; i++) { + facemgr_cfg_rule_t *rule = rule_array[i]; + if (!rule) continue; /* Should not occur */ + const char *interface_name = rule->match.interface_name; + /* Check match for interface name */ + if (netdevice.name[0] != '\0') { + if (!interface_name) continue; + if (strcmp(netdevice.name, interface_name) != 0) continue; + } else { + if (interface_name && interface_name[0] != '\0') continue; } - if (!overlay->is_remote_port) - return -1; - *port = overlay->remote_port; - return 0; -} -int facemgr_cfg_add_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet) -{ - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - DEBUG("STATIC FACELET: %s", buf); - return facelet_array_add(cfg->static_facelets, facelet); -} - -int facemgr_cfg_remove_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet, - facelet_t ** removed_facelet) -{ - return facelet_array_remove(cfg->static_facelets, facelet, removed_facelet); -} - -int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t * cfg, facelet_t *** array) -{ - if (facelet_array_get_elements(cfg->static_facelets, array) < 0) { - ERROR("[facemgr_cfg_get_static_facelet_array] Error getting array elements"); - return -1; - } - return (int)facelet_array_len(cfg->static_facelets); + /* Check match for netdevice_type */ + if (netdevice_type != rule->match.interface_type) continue; + + /* Found */ + *rule_p = rule; + break; + } + return 0; +} + +int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t *rule, + facemgr_face_type_t *face_type) { + if (!rule->override.is_face_type) return -1; + *face_type = rule->override.face_type; + return 0; +} + +int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t *rule, + bool *discovery) { + if (!rule->override.is_discovery) return -1; + *discovery = rule->override.discovery; + return 0; +} + +int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t *rule, bool *ignore) { + if (!rule->override.is_ignore) return -1; + *ignore = rule->override.ignore; + return 0; +} + +int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t *rule, bool *ipv4) { + if (!rule->override.is_ipv4) return -1; + *ipv4 = rule->override.ipv4; + return 0; +} + +int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t *rule, bool *ipv6) { + if (!rule->override.is_ipv6) return -1; + *ipv6 = rule->override.ipv6; + return 0; +} + +int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t *rule, + int family, + hicn_ip_address_t *addr) { + facemgr_cfg_overlay_t *overlay = NULL; + switch (family) { + case AF_INET: + overlay = rule->override.overlays.v4; + break; + case AF_INET6: + overlay = rule->override.overlays.v6; + break; + default: + return -1; + } + if (!overlay->is_local_addr) return -1; + *addr = overlay->local_addr; + return 0; +} + +int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t *rule, + int family, uint16_t *port) { + facemgr_cfg_overlay_t *overlay = NULL; + switch (family) { + case AF_INET: + overlay = rule->override.overlays.v4; + break; + case AF_INET6: + overlay = rule->override.overlays.v6; + break; + default: + return -1; + } + if (!overlay->is_local_port) return -1; + *port = overlay->local_port; + return 0; +} + +int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t *rule, + int family, + hicn_ip_address_t *addr) { + facemgr_cfg_overlay_t *overlay = NULL; + switch (family) { + case AF_INET: + overlay = rule->override.overlays.v4; + break; + case AF_INET6: + overlay = rule->override.overlays.v6; + break; + default: + return -1; + } + if (!overlay->is_remote_addr) return -1; + *addr = overlay->remote_addr; + return 0; +} + +int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t *rule, + int family, uint16_t *port) { + facemgr_cfg_overlay_t *overlay = NULL; + switch (family) { + case AF_INET: + overlay = rule->override.overlays.v4; + break; + case AF_INET6: + overlay = rule->override.overlays.v6; + break; + default: + return -1; + } + if (!overlay->is_remote_port) return -1; + *port = overlay->remote_port; + return 0; +} + +int facemgr_cfg_add_static_facelet(facemgr_cfg_t *cfg, facelet_t *facelet) { + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + DEBUG("STATIC FACELET: %s", buf); + return facelet_array_add(cfg->static_facelets, facelet); +} + +int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t *cfg, + facelet_t ***array) { + if (facelet_array_get_elements(cfg->static_facelets, array) < 0) { + ERROR( + "[facemgr_cfg_get_static_facelet_array] Error getting array elements"); + return -1; + } + return (int)facelet_array_len(cfg->static_facelets); } diff --git a/ctrl/facemgr/src/cfg_file.c b/ctrl/facemgr/src/cfg_file.c index cb1ded1c9..9b5f592dd 100644 --- a/ctrl/facemgr/src/cfg_file.c +++ b/ctrl/facemgr/src/cfg_file.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -18,338 +18,311 @@ * \brief Implementation of configuration file parsing */ -#include <unistd.h> // access +#include <unistd.h> // access #include <libconfig.h> #include <hicn/ctrl/route.h> #include "cfg_file.h" -#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x)) +#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x)) -static const char * DEFAULT_CFGFILES[] = { +static const char *DEFAULT_CFGFILES[] = { "/etc/facemgr.conf", "~/facemgr.conf", }; -int -probe_cfgfile(char * f) -{ - for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) { - if (access(DEFAULT_CFGFILES[i], F_OK ) != -1) { - if (!realpath(DEFAULT_CFGFILES[i], f)) - continue; - return 0; - } +int probe_cfgfile(char *f) { + for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) { + if (access(DEFAULT_CFGFILES[i], F_OK) != -1) { + if (!realpath(DEFAULT_CFGFILES[i], f)) continue; + return 0; } - return -1; + } + return -1; } -int -parse_config_global(facemgr_cfg_t * cfg, config_setting_t * setting) -{ - /* - face_type */ - - const char *face_type_str; - facemgr_face_type_t face_type; - if (config_setting_lookup_string(setting, "face_type", &face_type_str)) { - if (strcasecmp(face_type_str, "auto") == 0) { - face_type = FACEMGR_FACE_TYPE_DEFAULT; - } else - if (strcasecmp(face_type_str, "native-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; - } else - if (strcasecmp(face_type_str, "native-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; - } else - if (strcasecmp(face_type_str, "overlay-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; - } else - if (strcasecmp(face_type_str, "overlay-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; - } else { - ERROR("Invalid face type in section 'global'"); - return -1; - } - - int rc = facemgr_cfg_set_face_type(cfg, &face_type); - if (rc < 0) - goto ERR; +int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) { + /* - face_type */ + + const char *face_type_str; + facemgr_face_type_t face_type; + if (config_setting_lookup_string(setting, "face_type", &face_type_str)) { + if (strcasecmp(face_type_str, "auto") == 0) { + face_type = FACEMGR_FACE_TYPE_DEFAULT; + } else if (strcasecmp(face_type_str, "native-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; + } else if (strcasecmp(face_type_str, "native-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; + } else if (strcasecmp(face_type_str, "overlay-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; + } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; + } else { + ERROR("Invalid face type in section 'global'"); + return -1; } - /* - disable_discovery */ - - int disable_discovery; - if (config_setting_lookup_bool(setting, "disable_discovery", - &disable_discovery)) { - int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery); - if (rc < 0) - goto ERR; - } - - /* - disable_ipv4 */ - - int disable_ipv4; - if (config_setting_lookup_bool(setting, "disable_ipv4", - &disable_ipv4)) { - int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4); - if (rc < 0) - goto ERR; - } - - /* - disable ipv6 */ - - int disable_ipv6; - if (config_setting_lookup_bool(setting, "disable_ipv6", - &disable_ipv6)) { - int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6); - if (rc < 0) - goto ERR; + int rc = facemgr_cfg_set_face_type(cfg, &face_type); + if (rc < 0) goto ERR; + } + + /* - disable_discovery */ + + int disable_discovery; + if (config_setting_lookup_bool(setting, "disable_discovery", + &disable_discovery)) { + int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery); + if (rc < 0) goto ERR; + } + + /* - disable_ipv4 */ + + int disable_ipv4; + if (config_setting_lookup_bool(setting, "disable_ipv4", &disable_ipv4)) { + int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4); + if (rc < 0) goto ERR; + } + + /* - disable ipv6 */ + + int disable_ipv6; + if (config_setting_lookup_bool(setting, "disable_ipv6", &disable_ipv6)) { + int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6); + if (rc < 0) goto ERR; + } + + /* - overlay */ + config_setting_t *overlay = config_setting_get_member(setting, "overlay"); + if (overlay) { + /* ipv4 */ + config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); + if (overlay_v4) { + const char *local_addr_str, *remote_addr_str; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; + int local_port = 0; + int remote_port = 0; + + if (config_setting_lookup_string(overlay_v4, "local_addr", + &local_addr_str)) { + if (hicn_ip_address_pton(local_addr_str, &local_addr) < 0) { + ERROR("Error parsing v4 local addr"); + goto ERR; + } + local_addr_p = &local_addr; + } + + if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) { + if (!IS_VALID_PORT(local_port)) goto ERR; + } + + if (config_setting_lookup_string(overlay_v4, "remote_addr", + &remote_addr_str)) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { + ERROR("Error parsing v4 remote addr"); + goto ERR; + } + remote_addr_p = &remote_addr; + } + + if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) { + if (!IS_VALID_PORT(remote_port)) goto ERR; + } + int rc = facemgr_cfg_set_overlay(cfg, AF_INET, local_addr_p, local_port, + remote_addr_p, remote_port); + if (rc < 0) goto ERR; } - /* - overlay */ - config_setting_t *overlay = config_setting_get_member(setting, "overlay"); - if (overlay) { - - /* ipv4 */ - config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); - if (overlay_v4) { - const char * local_addr_str, * remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t * local_addr_p = NULL; - ip_address_t * remote_addr_p = NULL; - int local_port = 0; - int remote_port = 0; - - if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) { - if (ip_address_pton(local_addr_str, &local_addr) < 0) { - ERROR("Error parsing v4 local addr"); - goto ERR; - } - local_addr_p = &local_addr; - } - - if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) { - if (!IS_VALID_PORT(local_port)) - goto ERR; - } - - if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { - ERROR("Error parsing v4 remote addr"); - goto ERR; - } - remote_addr_p = &remote_addr; - } - - if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) { - if (!IS_VALID_PORT(remote_port)) - goto ERR; - } - int rc = facemgr_cfg_set_overlay(cfg, AF_INET, - local_addr_p, local_port, - remote_addr_p, remote_port); - if (rc < 0) - goto ERR; + /* ipv6 */ + config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); + if (overlay_v6) { + const char *local_addr_str, *remote_addr_str; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; + int local_port = 0; + int remote_port = 0; + + if (config_setting_lookup_string(overlay_v6, "local_addr", + &local_addr_str)) { + if (hicn_ip_address_pton(local_addr_str, &local_addr) < 0) { + ERROR("Error parsing v6 local addr"); + goto ERR; } - - /* ipv6 */ - config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); - if (overlay_v6) { - const char * local_addr_str, * remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t * local_addr_p = NULL; - ip_address_t * remote_addr_p = NULL; - int local_port = 0; - int remote_port = 0; - - if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) { - if (ip_address_pton(local_addr_str, &local_addr) < 0) { - ERROR("Error parsing v6 local addr"); - goto ERR; - } - local_addr_p = &local_addr; - } - - if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) { - if (!IS_VALID_PORT(local_port)) - goto ERR; - } - - if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { - ERROR("Error parsing v6 remote addr"); - goto ERR; - } - remote_addr_p = &remote_addr; - } - - if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) { - if (!IS_VALID_PORT(remote_port)) - goto ERR; - } - int rc = facemgr_cfg_set_overlay(cfg, AF_INET6, - local_addr_p, local_port, - remote_addr_p, remote_port); - if (rc < 0) - goto ERR; + local_addr_p = &local_addr; + } + + if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) { + if (!IS_VALID_PORT(local_port)) goto ERR; + } + + if (config_setting_lookup_string(overlay_v6, "remote_addr", + &remote_addr_str)) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { + ERROR("Error parsing v6 remote addr"); + goto ERR; } + remote_addr_p = &remote_addr; + } + + if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) { + if (!IS_VALID_PORT(remote_port)) goto ERR; + } + int rc = facemgr_cfg_set_overlay(cfg, AF_INET6, local_addr_p, local_port, + remote_addr_p, remote_port); + if (rc < 0) goto ERR; + } - } /* overlay */ + } /* overlay */ - return 0; + return 0; ERR: - return -1; + return -1; } -int -parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting) -{ - /* List of match-override tuples */ - facemgr_cfg_rule_t * rule; +int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) { + /* List of match-override tuples */ + facemgr_cfg_rule_t *rule; - int count = config_setting_length(setting); - for (unsigned i = 0; i < count; ++i) { - config_setting_t * rule_setting = config_setting_get_elem(setting, i); + int count = config_setting_length(setting); + for (unsigned i = 0; i < count; ++i) { + config_setting_t *rule_setting = config_setting_get_elem(setting, i); - /* Sanity check */ + /* Sanity check */ - config_setting_t * match_setting = config_setting_get_member(rule_setting, "match"); - if (!match_setting) { - ERROR("Missing match section in rule #%d", i); - goto ERR_CHECK; - } + config_setting_t *match_setting = + config_setting_get_member(rule_setting, "match"); + if (!match_setting) { + ERROR("Missing match section in rule #%d", i); + goto ERR_CHECK; + } - config_setting_t * override_setting = config_setting_get_member(rule_setting, "override"); - if (!override_setting) { - ERROR("Missing override section in rule #%d", i); - goto ERR_CHECK; - } + config_setting_t *override_setting = + config_setting_get_member(rule_setting, "override"); + if (!override_setting) { + ERROR("Missing override section in rule #%d", i); + goto ERR_CHECK; + } - rule = facemgr_cfg_rule_create(); - if (!rule) - goto ERR_RULE; - - /* Parse match */ - - const char * interface_name = NULL; - config_setting_lookup_string(match_setting, "interface_name", &interface_name); - - const char * interface_type_str; - netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED; - if (config_setting_lookup_string(match_setting, "interface_type", &interface_type_str)) { - if (strcasecmp(interface_type_str, "wired") == 0) { - interface_type = NETDEVICE_TYPE_WIRED; - } else - if (strcasecmp(interface_type_str, "wifi") == 0) { - interface_type = NETDEVICE_TYPE_WIFI; - } else - if (strcasecmp(interface_type_str, "cellular") == 0) { - interface_type = NETDEVICE_TYPE_CELLULAR; - } else { - ERROR("Unknown interface type in rule #%d", i); - goto ERR; - } - } + rule = facemgr_cfg_rule_create(); + if (!rule) goto ERR_RULE; + + /* Parse match */ + + const char *interface_name = NULL; + config_setting_lookup_string(match_setting, "interface_name", + &interface_name); + + const char *interface_type_str; + netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED; + if (config_setting_lookup_string(match_setting, "interface_type", + &interface_type_str)) { + if (strcasecmp(interface_type_str, "wired") == 0) { + interface_type = NETDEVICE_TYPE_WIRED; + } else if (strcasecmp(interface_type_str, "wifi") == 0) { + interface_type = NETDEVICE_TYPE_WIFI; + } else if (strcasecmp(interface_type_str, "cellular") == 0) { + interface_type = NETDEVICE_TYPE_CELLULAR; + } else { + ERROR("Unknown interface type in rule #%d", i); + goto ERR; + } + } - if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) { - ERROR("Empty match section in rule #%d", i); - goto ERR; - } + if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) { + ERROR("Empty match section in rule #%d", i); + goto ERR; + } - /* Associate match to rule */ + /* Associate match to rule */ - int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type); - if (rc < 0) - goto ERR; + int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type); + if (rc < 0) goto ERR; - /* Parse override */ + /* Parse override */ - /* - face_type */ + /* - face_type */ - const char *face_type_str; - facemgr_face_type_t face_type; - if (config_setting_lookup_string(override_setting, "face_type", &face_type_str)) { - if (strcasecmp(face_type_str, "auto")) { - /* We currently hardcode different behaviours based on the OS */ + const char *face_type_str; + facemgr_face_type_t face_type; + if (config_setting_lookup_string(override_setting, "face_type", + &face_type_str)) { + if (strcasecmp(face_type_str, "auto")) { + /* We currently hardcode different behaviours based on the OS */ #ifdef __ANDROID__ - face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; + face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; #else - face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; + face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; #endif - } else - if (strcasecmp(face_type_str, "native-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; - } else - if (strcasecmp(face_type_str, "native-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; - } else - if (strcasecmp(face_type_str, "overlay-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; - } else - if (strcasecmp(face_type_str, "overlay-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; - } else { - ERROR("Invalid face type in section 'global'"); - return -1; - } + } else if (strcasecmp(face_type_str, "native-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; + } else if (strcasecmp(face_type_str, "native-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; + } else if (strcasecmp(face_type_str, "overlay-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; + } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; + } else { + ERROR("Invalid face type in section 'global'"); + return -1; + } - int rc = facemgr_cfg_rule_set_face_type(rule, &face_type); - if (rc < 0) - goto ERR; - } + int rc = facemgr_cfg_rule_set_face_type(rule, &face_type); + if (rc < 0) goto ERR; + } - /* - disable_discovery */ + /* - disable_discovery */ - int disable_discovery; - if (config_setting_lookup_bool(override_setting, "disable_discovery", - &disable_discovery)) { - int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery); - if (rc < 0) - goto ERR; - } + int disable_discovery; + if (config_setting_lookup_bool(override_setting, "disable_discovery", + &disable_discovery)) { + int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery); + if (rc < 0) goto ERR; + } - /* - disable_ipv4 */ + /* - disable_ipv4 */ - int disable_ipv4; - if (config_setting_lookup_bool(override_setting, "disable_ipv4", - &disable_ipv4)) { - INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i); + int disable_ipv4; + if (config_setting_lookup_bool(override_setting, "disable_ipv4", + &disable_ipv4)) { + INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i); #if 0 int rc = facemgr_cfg_rule_set_ipv4(rule, !disable_ipv4); if (rc < 0) goto ERR; #endif - } + } - /* - disable ipv6 */ + /* - disable ipv6 */ - int disable_ipv6; - if (config_setting_lookup_bool(override_setting, "disable_ipv6", - &disable_ipv6)) { - INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i); + int disable_ipv6; + if (config_setting_lookup_bool(override_setting, "disable_ipv6", + &disable_ipv6)) { + INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i); #if 0 int rc = facemgr_cfg_rule_set_ipv6(rule, !disable_ipv6); if (rc < 0) goto ERR; #endif - } + } - /* - ignore */ - int ignore; - if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) { - int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore); - if (rc < 0) - goto ERR; - } + /* - ignore */ + int ignore; + if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) { + int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore); + if (rc < 0) goto ERR; + } - /* - tags */ - config_setting_t *tag_settings = config_setting_get_member(override_setting, "tags"); - if (tag_settings) { - INFO("Ignored setting 'tags' in rule #%d (not implemented).", i); + /* - tags */ + config_setting_t *tag_settings = + config_setting_get_member(override_setting, "tags"); + if (tag_settings) { + INFO("Ignored setting 'tags' in rule #%d (not implemented).", i); #if 0 policy_tags_t tags = POLICY_TAGS_EMPTY; for (unsigned j = 0; j < config_setting_length(tag_settings); j++) { @@ -370,361 +343,337 @@ parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting) DEBUG("Added tags tags=%s", tags_str); #endif #endif + } + + /* - overlay */ + config_setting_t *overlay = + config_setting_get_member(override_setting, "overlay"); + if (overlay) { + /* ipv4 */ + config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); + if (overlay_v4) { + const char *local_addr_str, *remote_addr_str; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; + int local_port = 0; + int remote_port = 0; + + if (config_setting_lookup_string(overlay_v4, "local_addr", + &local_addr_str)) { + hicn_ip_address_pton(local_addr_str, &local_addr); + local_addr_p = &local_addr; } - /* - overlay */ - config_setting_t *overlay = config_setting_get_member(override_setting, "overlay"); - if (overlay) { - - /* ipv4 */ - config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); - if (overlay_v4) { - const char * local_addr_str, * remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t * local_addr_p = NULL; - ip_address_t * remote_addr_p = NULL; - int local_port = 0; - int remote_port = 0; - - if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) { - ip_address_pton(local_addr_str, &local_addr); - local_addr_p = &local_addr; - } - - if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) { - if (!IS_VALID_PORT(local_port)) - goto ERR; - } - - if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) { - ip_address_pton(remote_addr_str, &remote_addr); - remote_addr_p = &remote_addr; - } - - if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) { - if (!IS_VALID_PORT(remote_port)) - goto ERR; - } - int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET, - local_addr_p, local_port, - remote_addr_p, remote_port); - if (rc < 0) - goto ERR; - } + if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) { + if (!IS_VALID_PORT(local_port)) goto ERR; + } - /* ipv6 */ - config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); - if (overlay_v6) { - const char * local_addr_str, * remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t * local_addr_p = NULL; - ip_address_t * remote_addr_p = NULL; - int local_port = 0; - int remote_port = 0; - - if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) { - ip_address_pton(local_addr_str, &local_addr); - local_addr_p = &local_addr; - } - - if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) { - if (!IS_VALID_PORT(local_port)) - goto ERR; - } - - if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) { - ip_address_pton(remote_addr_str, &remote_addr); - remote_addr_p = &remote_addr; - } - - if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) { - if (!IS_VALID_PORT(remote_port)) - goto ERR; - } - int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6, - local_addr_p, local_port, - remote_addr_p, remote_port); - if (rc < 0) - goto ERR; - } + if (config_setting_lookup_string(overlay_v4, "remote_addr", + &remote_addr_str)) { + hicn_ip_address_pton(remote_addr_str, &remote_addr); + remote_addr_p = &remote_addr; + } + + if (config_setting_lookup_int(overlay_v4, "remote_port", + &remote_port)) { + if (!IS_VALID_PORT(remote_port)) goto ERR; + } + int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET, local_addr_p, + local_port, remote_addr_p, + remote_port); + if (rc < 0) goto ERR; + } + + /* ipv6 */ + config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); + if (overlay_v6) { + const char *local_addr_str, *remote_addr_str; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; + int local_port = 0; + int remote_port = 0; - } /* overlay */ + if (config_setting_lookup_string(overlay_v6, "local_addr", + &local_addr_str)) { + hicn_ip_address_pton(local_addr_str, &local_addr); + local_addr_p = &local_addr; + } - /* Add newly created rule */ + if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) { + if (!IS_VALID_PORT(local_port)) goto ERR; + } - rc = facemgr_cfg_add_rule(cfg, rule); - if (rc < 0) - goto ERR; - } - return 0; + if (config_setting_lookup_string(overlay_v6, "remote_addr", + &remote_addr_str)) { + hicn_ip_address_pton(remote_addr_str, &remote_addr); + remote_addr_p = &remote_addr; + } + + if (config_setting_lookup_int(overlay_v6, "remote_port", + &remote_port)) { + if (!IS_VALID_PORT(remote_port)) goto ERR; + } + int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6, local_addr_p, + local_port, remote_addr_p, + remote_port); + if (rc < 0) goto ERR; + } + + } /* overlay */ + + /* Add newly created rule */ + + rc = facemgr_cfg_add_rule(cfg, rule); + if (rc < 0) goto ERR; + } + return 0; ERR: - facemgr_cfg_rule_free(rule); + facemgr_cfg_rule_free(rule); ERR_RULE: ERR_CHECK: - return -1; + return -1; } -int parse_config_static_facelets(facemgr_cfg_t * cfg, config_setting_t * setting) -{ - int count = config_setting_length(setting); - for (unsigned i = 0; i < count; ++i) { - config_setting_t * static_setting = config_setting_get_elem(setting, i); - - const char *face_type_str; - facemgr_face_type_t face_type; - const char * family_str; - int family; - const char * remote_addr_str; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - int remote_port = 0; - const char * interface_name; - const char * interface_type_str; - - facelet_t * facelet = facelet_create(); - - /* Face type */ - if (config_setting_lookup_string(static_setting, "face_type", &face_type_str)) { - if (strcasecmp(face_type_str, "auto") == 0) { - face_type = FACEMGR_FACE_TYPE_DEFAULT; - } else - if (strcasecmp(face_type_str, "native-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; - } else - if (strcasecmp(face_type_str, "native-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; - } else - if (strcasecmp(face_type_str, "overlay-udp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; - } else - if (strcasecmp(face_type_str, "overlay-tcp") == 0) { - face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; - } else { - ERROR("Invalid face type in section 'global'"); - goto ERR_FACELET; - } +int parse_config_static_facelets(facemgr_cfg_t *cfg, + config_setting_t *setting) { + int count = config_setting_length(setting); + for (unsigned i = 0; i < count; ++i) { + config_setting_t *static_setting = config_setting_get_elem(setting, i); - int rc = facelet_set_face_type(facelet, face_type); - if (rc < 0) - goto ERR_FACELET; - } + const char *face_type_str; + facemgr_face_type_t face_type; + const char *family_str; + int family; + const char *remote_addr_str; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + int remote_port = 0; + const char *interface_name; + const char *interface_type_str; + + facelet_t *facelet = facelet_create(); + + /* Face type */ + if (config_setting_lookup_string(static_setting, "face_type", + &face_type_str)) { + if (strcasecmp(face_type_str, "auto") == 0) { + face_type = FACEMGR_FACE_TYPE_DEFAULT; + } else if (strcasecmp(face_type_str, "native-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_UDP; + } else if (strcasecmp(face_type_str, "native-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; + } else if (strcasecmp(face_type_str, "overlay-udp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; + } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) { + face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; + } else { + ERROR("Invalid face type in section 'global'"); + goto ERR_FACELET; + } + + int rc = facelet_set_face_type(facelet, face_type); + if (rc < 0) goto ERR_FACELET; + } - /* Family */ - if (config_setting_lookup_string(static_setting, "family", &family_str)) { - if (strcasecmp(family_str, "AF_INET") == 0) { - family = AF_INET; - } else - if (strcasecmp(family_str, "AF_INET6") == 0) { - family = AF_INET6; - } else { - ERROR("Invalid family in section 'static', items #%d", i+1); - goto ERR_FACELET; - } - int rc = facelet_set_family(facelet, family); - if (rc < 0) - goto ERR_FACELET; - } + /* Family */ + if (config_setting_lookup_string(static_setting, "family", &family_str)) { + if (strcasecmp(family_str, "AF_INET") == 0) { + family = AF_INET; + } else if (strcasecmp(family_str, "AF_INET6") == 0) { + family = AF_INET6; + } else { + ERROR("Invalid family in section 'static', items #%d", i + 1); + goto ERR_FACELET; + } + int rc = facelet_set_family(facelet, family); + if (rc < 0) goto ERR_FACELET; + } - /* Remote address */ - if (config_setting_lookup_string(static_setting, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { - ERROR("Error parsing v4 remote addr"); - goto ERR_FACELET; - } + /* Remote address */ + if (config_setting_lookup_string(static_setting, "remote_addr", + &remote_addr_str)) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { + ERROR("Error parsing v4 remote addr"); + goto ERR_FACELET; + } - int rc = facelet_set_remote_addr(facelet, remote_addr); - if (rc < 0) - goto ERR_FACELET; - } + int rc = facelet_set_remote_addr(facelet, remote_addr); + if (rc < 0) goto ERR_FACELET; + } - /* Remote port */ - if (config_setting_lookup_int(static_setting, "remote_port", &remote_port)) { - if (!IS_VALID_PORT(remote_port)) - goto ERR_FACELET; - int rc = facelet_set_remote_port(facelet, remote_port); - if (rc < 0) - goto ERR_FACELET; - } + /* Remote port */ + if (config_setting_lookup_int(static_setting, "remote_port", + &remote_port)) { + if (!IS_VALID_PORT(remote_port)) goto ERR_FACELET; + int rc = facelet_set_remote_port(facelet, remote_port); + if (rc < 0) goto ERR_FACELET; + } - /* Interface name */ - if (config_setting_lookup_string(static_setting, "interface_name", &interface_name)) { - netdevice_t netdevice; - /* Warning: interface might not exist when we create the facelet */ - snprintf(netdevice.name, IFNAMSIZ, "%s", interface_name); - netdevice.index = 0; - int rc = facelet_set_netdevice(facelet, netdevice); - if (rc < 0) - goto ERR_FACELET; - } + /* Interface name */ + if (config_setting_lookup_string(static_setting, "interface_name", + &interface_name)) { + netdevice_t netdevice; + /* Warning: interface might not exist when we create the facelet */ + snprintf(netdevice.name, IFNAMSIZ, "%s", interface_name); + netdevice.index = 0; + int rc = facelet_set_netdevice(facelet, netdevice); + if (rc < 0) goto ERR_FACELET; + } - /* Interface type */ - netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED; - if (config_setting_lookup_string(static_setting, "interface_type", &interface_type_str)) { - if (strcasecmp(interface_type_str, "wired") == 0) { - interface_type = NETDEVICE_TYPE_WIRED; - } else - if (strcasecmp(interface_type_str, "wifi") == 0) { - interface_type = NETDEVICE_TYPE_WIFI; - } else - if (strcasecmp(interface_type_str, "cellular") == 0) { - interface_type = NETDEVICE_TYPE_CELLULAR; - } else { - ERROR("Unknown interface type in rule #%d", i); - goto ERR_FACELET; - } + /* Interface type */ + netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED; + if (config_setting_lookup_string(static_setting, "interface_type", + &interface_type_str)) { + if (strcasecmp(interface_type_str, "wired") == 0) { + interface_type = NETDEVICE_TYPE_WIRED; + } else if (strcasecmp(interface_type_str, "wifi") == 0) { + interface_type = NETDEVICE_TYPE_WIFI; + } else if (strcasecmp(interface_type_str, "cellular") == 0) { + interface_type = NETDEVICE_TYPE_CELLULAR; + } else { + ERROR("Unknown interface type in rule #%d", i); + goto ERR_FACELET; + } + + int rc = facelet_set_netdevice_type(facelet, interface_type); + if (rc < 0) goto ERR_FACELET; + } - int rc = facelet_set_netdevice_type(facelet, interface_type); - if (rc < 0) - goto ERR_FACELET; + /* Routes */ + config_setting_t *routes_static_setting = + config_setting_get_member(static_setting, "routes"); + if (routes_static_setting) { + /* ... */ + int count_routes = config_setting_length(routes_static_setting); + for (unsigned j = 0; j < count_routes; ++j) { + config_setting_t *route_static_setting = + config_setting_get_elem(routes_static_setting, j); + + const char *prefix_str; + hicn_ip_prefix_t prefix; + int cost = 0; /* default */ + + if (config_setting_lookup_string(route_static_setting, "prefix", + &prefix_str)) { + if (hicn_ip_prefix_pton(prefix_str, &prefix) < 0) { + ERROR("Error parsing prefix in route #%d, rule #%d", j, i); + goto ERR_FACELET; + } + } else { + ERROR("Cannot add route without prefix"); + goto ERR_FACELET; } - /* Routes */ - config_setting_t * routes_static_setting = config_setting_get_member(static_setting, "routes"); - if (routes_static_setting) { - /* ... */ - int count_routes = config_setting_length(routes_static_setting); - for (unsigned j = 0; j < count_routes; ++j) { - config_setting_t * route_static_setting = config_setting_get_elem(routes_static_setting, j); - - const char * prefix_str; - ip_prefix_t prefix; - int cost = 0; /* default */ - - if (config_setting_lookup_string(route_static_setting, "prefix", &prefix_str)) { - if (ip_prefix_pton(prefix_str, &prefix) < 0) { - ERROR("Error parsing prefix in route #%d, rule #%d", j, i); - goto ERR_FACELET; - } - } else { - ERROR("Cannot add route without prefix"); - goto ERR_FACELET; - } - - config_setting_lookup_int(static_setting, "cost", &cost); - - hicn_route_t * route = hicn_route_create(&prefix, 0, cost); - if (!route) { - ERROR("Could not create hICN route"); - goto ERR_FACELET; - } - - int rc = facelet_add_route(facelet, route); - if (rc < 0) { - ERROR("Could not add route to facelet"); - goto ERR_ROUTE; - } - - continue; - -ERR_ROUTE: - hicn_route_free(route); - goto ERR_FACELET; - } + config_setting_lookup_int(static_setting, "cost", &cost); + + hicn_route_t *route = hicn_route_create(&prefix, 0, cost); + if (!route) { + ERROR("Could not create hICN route"); + goto ERR_FACELET; } - if (facemgr_cfg_add_static_facelet(cfg, facelet) < 0) { - ERROR("Could not add static facelet to configuration"); - goto ERR_FACELET; + int rc = facelet_add_route(facelet, route); + if (rc < 0) { + ERROR("Could not add route to facelet"); + goto ERR_ROUTE; } continue; -ERR_FACELET: - facelet_free(facelet); - return -1; + ERR_ROUTE: + hicn_route_free(route); + goto ERR_FACELET; + } + } - } - return 0; + if (facemgr_cfg_add_static_facelet(cfg, facelet) < 0) { + ERROR("Could not add static facelet to configuration"); + goto ERR_FACELET; + } + + continue; + + ERR_FACELET: + facelet_free(facelet); + return -1; + } + return 0; } /* Currently not using facemgr_cfg_t */ -int -parse_config_log(facemgr_cfg_t * cfg, config_setting_t * setting) -{ - const char *log_level_str; - if (config_setting_lookup_string(setting, "log_level", &log_level_str)) { - if (strcasecmp(log_level_str, "FATAL") == 0) { - log_conf.log_level = LOG_FATAL; - } else - if (strcasecmp(log_level_str, "ERROR") == 0) { - log_conf.log_level = LOG_ERROR; - } else - if (strcasecmp(log_level_str, "WARN") == 0) { - log_conf.log_level = LOG_WARN; - } else - if (strcasecmp(log_level_str, "INFO") == 0) { - log_conf.log_level = LOG_INFO; - } else - if (strcasecmp(log_level_str, "DEBUG") == 0) { - log_conf.log_level = LOG_DEBUG; - } else - if (strcasecmp(log_level_str, "TRACE") == 0) { - log_conf.log_level = LOG_TRACE; - } else { - ERROR("Invalid log level in section 'log'"); - return -1; - } +int parse_config_log(facemgr_cfg_t *cfg, config_setting_t *setting) { + const char *log_level_str; + if (config_setting_lookup_string(setting, "log_level", &log_level_str)) { + if (strcasecmp(log_level_str, "FATAL") == 0) { + log_conf.log_level = LOG_FATAL; + } else if (strcasecmp(log_level_str, "ERROR") == 0) { + log_conf.log_level = LOG_ERROR; + } else if (strcasecmp(log_level_str, "WARN") == 0) { + log_conf.log_level = LOG_WARN; + } else if (strcasecmp(log_level_str, "INFO") == 0) { + log_conf.log_level = LOG_INFO; + } else if (strcasecmp(log_level_str, "DEBUG") == 0) { + log_conf.log_level = LOG_DEBUG; + } else if (strcasecmp(log_level_str, "TRACE") == 0) { + log_conf.log_level = LOG_TRACE; + } else { + ERROR("Invalid log level in section 'log'"); + return -1; } - return 0; + } + return 0; } -int -parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg) -{ - /* Reading configuration file */ - config_t cfgfile; - config_setting_t *setting; +int parse_config_file(const char *cfgpath, facemgr_cfg_t *cfg) { + /* Reading configuration file */ + config_t cfgfile; + config_setting_t *setting; - config_init(&cfgfile); + config_init(&cfgfile); - /* Read the file. If there is an error, report it and exit. */ - if(!config_read_file(&cfgfile, cfgpath)) - goto ERR_FILE; + /* Read the file. If there is an error, report it and exit. */ + if (!config_read_file(&cfgfile, cfgpath)) goto ERR_FILE; - setting = config_lookup(&cfgfile, "global"); - if (setting) { - int rc = parse_config_global(cfg, setting); - if (rc < 0) - goto ERR_PARSE; - } + setting = config_lookup(&cfgfile, "global"); + if (setting) { + int rc = parse_config_global(cfg, setting); + if (rc < 0) goto ERR_PARSE; + } - setting = config_lookup(&cfgfile, "rules"); - if (setting) { - int rc = parse_config_rules(cfg, setting); - if (rc < 0) - goto ERR_PARSE; - } + setting = config_lookup(&cfgfile, "rules"); + if (setting) { + int rc = parse_config_rules(cfg, setting); + if (rc < 0) goto ERR_PARSE; + } - setting = config_lookup(&cfgfile, "static"); - if (setting) { - int rc = parse_config_static_facelets(cfg, setting); - if (rc < 0) - goto ERR_PARSE; - } + setting = config_lookup(&cfgfile, "static"); + if (setting) { + int rc = parse_config_static_facelets(cfg, setting); + if (rc < 0) goto ERR_PARSE; + } - setting = config_lookup(&cfgfile, "log"); - if (setting) { - int rc = parse_config_log(cfg, setting); - if (rc < 0) - goto ERR_PARSE; - } + setting = config_lookup(&cfgfile, "log"); + if (setting) { + int rc = parse_config_log(cfg, setting); + if (rc < 0) goto ERR_PARSE; + } - config_destroy(&cfgfile); - return 0; + config_destroy(&cfgfile); + return 0; ERR_FILE: - ERROR("Could not read configuration file %s", cfgpath); - fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile), - config_error_line(&cfgfile), config_error_text(&cfgfile)); - config_destroy(&cfgfile); - exit(EXIT_FAILURE); - return -1; + ERROR("Could not read configuration file %s", cfgpath); + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile), + config_error_line(&cfgfile), config_error_text(&cfgfile)); + config_destroy(&cfgfile); + return -1; ERR_PARSE: - fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile), - config_error_line(&cfgfile), config_error_text(&cfgfile)); - config_destroy(&cfgfile); - return -1; + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile), + config_error_line(&cfgfile), config_error_text(&cfgfile)); + config_destroy(&cfgfile); + return -1; } - diff --git a/ctrl/facemgr/src/cfg_file.h b/ctrl/facemgr/src/cfg_file.h index dfce041d8..fea6a84a6 100644 --- a/ctrl/facemgr/src/cfg_file.h +++ b/ctrl/facemgr/src/cfg_file.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -28,7 +28,7 @@ * \param [in] f - File name * \return 0 in case of success, -1 otherwise. */ -int probe_cfgfile(char * f); +int probe_cfgfile(char* f); /** * \brief Parses the provided configuration file into the facemgr configuration @@ -37,6 +37,6 @@ int probe_cfgfile(char * f); * \param [out] cfg - Pre-allocated configuration data structure * \return 0 in case of success, -1 otherwise. */ -int parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg); +int parse_config_file(const char* cfgpath, facemgr_cfg_t* cfg); #endif /* FACEMGR_CFG_FILE_H */ diff --git a/ctrl/facemgr/src/common.h b/ctrl/facemgr/src/common.h index 56bd706f1..2adbc9a23 100644 --- a/ctrl/facemgr/src/common.h +++ b/ctrl/facemgr/src/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,71 +32,56 @@ /* Dump with indent */ #define INDENT(n, fmt) "%*s" fmt, n, "" -#define printfi(n, fmt, ...) printf(INDENT(n*4, fmt), ##__VA_ARGS__) - -#define _unused(x) ((void)(x)) +#define printfi(n, fmt, ...) printf(INDENT(n * 4, fmt), ##__VA_ARGS__) /* Random strings */ -static inline -void rand_str(char *dest, size_t length) { - char charset[] = "0123456789" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - while (length-- > 0) { - size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1); - *dest++ = charset[index]; - } - *dest = '\0'; +static inline void rand_str(char *dest, size_t length) { + char charset[] = + "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + while (length-- > 0) { + size_t index = (double)rand() / RAND_MAX * (sizeof charset - 1); + *dest++ = charset[index]; + } + *dest = '\0'; } /* Boilerplate code */ -#define NO_INITIALIZE(NAME) \ -int \ -NAME ## _initialize(NAME ## _t * obj) { \ - return 0; \ -} - -#define NO_FINALIZE(NAME) \ -int \ -NAME ## _finalize(NAME ## _t * obj) { \ - return 0; \ -} - -#define AUTOGENERATE_CREATE_FREE(NAME) \ - \ -NAME ## _t * \ -NAME ## _create() \ -{ \ - NAME ## _t * obj = malloc(sizeof(NAME ## _t)); \ - if (!obj) \ - goto ERR_MALLOC; \ - \ - if (NAME ## _initialize(obj) < 0) \ - goto ERR_INIT; \ - \ - return obj; \ - \ -ERR_INIT: \ - free(obj); \ -ERR_MALLOC: \ - return NULL; \ -} \ - \ -void \ -NAME ## _free(NAME ## _t * obj) \ -{ \ - if (NAME ## _finalize(obj) < 0) \ - (void)0; /* XXX */ \ - free(obj); \ -} \ - -#define AUTOGENERATE_DEFS(NAME) \ -int NAME ## _initialize(NAME ## _t *); \ -int NAME ## _finalize(NAME ## _t *); \ -NAME ## _t * NAME ## _create(); \ -void NAME ## _free(NAME ## _t *); \ +#define NO_INITIALIZE(NAME) \ + int NAME##_initialize(NAME##_t *obj) { return 0; } + +#define NO_FINALIZE(NAME) \ + int NAME##_finalize(NAME##_t *obj) { return 0; } + +#define AUTOGENERATE_CREATE_FREE(NAME) \ + \ + NAME##_t *NAME##_create() { \ + NAME##_t *obj = malloc(sizeof(NAME##_t)); \ + if (!obj) goto ERR_MALLOC; \ + \ + if (NAME##_initialize(obj) < 0) goto ERR_INIT; \ + \ + return obj; \ + \ + ERR_INIT: \ + free(obj); \ + ERR_MALLOC: \ + return NULL; \ + } \ + \ + void NAME##_free(NAME##_t *obj) { \ + if (NAME##_finalize(obj) < 0) (void)0; /* XXX */ \ + free(obj); \ + } + +#define AUTOGENERATE_DEFS(NAME) \ + int NAME##_initialize(NAME##_t *); \ + int NAME##_finalize(NAME##_t *); \ + NAME##_t *NAME##_create(); \ + void NAME##_free(NAME##_t *); #endif /* FACEMGR_COMMON_H */ diff --git a/ctrl/facemgr/src/error.c b/ctrl/facemgr/src/error.c index 4dcea6e1f..36ce5f561 100644 --- a/ctrl/facemgr/src/error.c +++ b/ctrl/facemgr/src/error.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,8 +21,7 @@ #include "error.h" const char *FACEMGR_ERROR_STRING[] = { -#define _(a,b,c) [b] = c, - foreach_facemgr_error +#define _(a, b, c) [b] = c, + foreach_facemgr_error #undef _ }; - diff --git a/ctrl/facemgr/src/error.h b/ctrl/facemgr/src/error.h index a0d76b3e5..7fadea49f 100644 --- a/ctrl/facemgr/src/error.h +++ b/ctrl/facemgr/src/error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -16,15 +16,13 @@ #ifndef FACEMGR_ERROR_H #define FACEMGR_ERROR_H -#define foreach_facemgr_error \ -_(NONE, 0, "OK") \ - +#define foreach_facemgr_error _(NONE, 0, "OK") typedef enum { -#define _(a,b,c) FACEMGR_ERROR_##a = (-b), - foreach_facemgr_error +#define _(a, b, c) FACEMGR_ERROR_##a = (-b), + foreach_facemgr_error #undef _ - FACEMGR_ERROR_N, + FACEMGR_ERROR_N, } facemgr_error_t; extern const char *HICN_LIB_ERROR_STRING[]; diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c index 9e9f3f67f..4723b8940 100644 --- a/ctrl/facemgr/src/facelet.c +++ b/ctrl/facemgr/src/facelet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -20,7 +20,7 @@ #include <assert.h> #include <stdbool.h> -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include <hicn/ctrl/route.h> #include <hicn/facemgr/cfg.h> #include <hicn/facemgr/facelet.h> @@ -32,152 +32,130 @@ TYPEDEF_SET_H(route_set, hicn_route_t *); TYPEDEF_SET(route_set, hicn_route_t *, hicn_route_cmp, generic_snprintf); -const char * face_type_layer_str[] = { -#define _(x) [FACE_TYPE_LAYER_ ## x] = STRINGIZE(x), +const char *face_type_layer_str[] = { +#define _(x) [FACE_TYPE_LAYER_##x] = STRINGIZE(x), foreach_face_type_layer #undef _ }; -const char * face_type_encap_str[] = { -#define _(x) [FACE_TYPE_ENCAP_ ## x] = STRINGIZE(x), +const char *face_type_encap_str[] = { +#define _(x) [FACE_TYPE_ENCAP_##x] = STRINGIZE(x), foreach_face_type_encap #undef _ }; -const char * facelet_status_str[] = { -#define _(x) [FACELET_STATUS_ ## x] = STRINGIZE(x), +const char *facelet_status_str[] = { +#define _(x) [FACELET_STATUS_##x] = STRINGIZE(x), foreach_facelet_status #undef _ }; -const char * facelet_error_reason_str[] = { -#define _(x) [FACELET_ERROR_REASON_ ## x] = STRINGIZE(x), +const char *facelet_error_reason_str[] = { +#define _(x) [FACELET_ERROR_REASON_##x] = STRINGIZE(x), foreach_facelet_error_reason #undef _ }; /* Facelet attribute status */ -const char * facelet_attr_status_str[] = { -#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(x), +const char *facelet_attr_status_str[] = { +#define _(x, str) [FACELET_ATTR_STATUS_##x] = STRINGIZE(x), foreach_facelet_attr_status #undef _ }; -const char * facelet_attr_status_str_short[] = { -#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(str), +const char *facelet_attr_status_str_short[] = { +#define _(x, str) [FACELET_ATTR_STATUS_##x] = STRINGIZE(str), foreach_facelet_attr_status #undef _ }; - /* Facelet */ struct facelet_s { - unsigned id; + unsigned id; #define _(TYPE, NAME) TYPE NAME; - foreach_facelet_attr + foreach_facelet_attr #undef _ -#define _(TYPE, NAME) facelet_attr_status_t NAME ## _status; - foreach_facelet_attr +#define _(TYPE, NAME) facelet_attr_status_t NAME##_status; + foreach_facelet_attr #undef _ + facelet_status_t status; + int error; + facelet_event_t event; - facelet_status_t status; - int error; - - facelet_event_t event; - - route_set_t * routes; - bool routes_done; + route_set_t *routes; + bool routes_done; - bool bj_done; - bool au_done; + bool bj_done; }; -const char * facelet_event_str[] = { -#define _(x) [FACELET_EVENT_ ## x] = STRINGIZE(x), -foreach_facelet_event +const char *facelet_event_str[] = { +#define _(x) [FACELET_EVENT_##x] = STRINGIZE(x), + foreach_facelet_event #undef _ }; -facelet_t * -facelet_create() -{ - facelet_t * facelet = calloc(1, sizeof(facelet_t)); - if (!facelet) - goto ERR_MALLOC; +facelet_t *facelet_create() { + facelet_t *facelet = calloc(1, sizeof(facelet_t)); + if (!facelet) goto ERR_MALLOC; - facelet->id = 0; + facelet->id = 0; - facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET; - facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET; - facelet->family_status = FACELET_ATTR_STATUS_UNSET; - facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; - facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; - facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; - facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; - facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; - facelet->state_status = FACELET_ATTR_STATUS_UNSET; -#ifdef WITH_POLICY - facelet->priority_status = FACELET_ATTR_STATUS_UNSET; -#endif /* WITH_POLICY */ - facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; + facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET; + facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET; + facelet->family_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; + facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; + facelet->state_status = FACELET_ATTR_STATUS_UNSET; + facelet->priority_status = FACELET_ATTR_STATUS_UNSET; + facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; - facelet->status = FACELET_STATUS_UNDEFINED; - facelet->error = 0; + facelet->status = FACELET_STATUS_UNDEFINED; + facelet->error = 0; - facelet->bj_done = false; - facelet->au_done = false; + facelet->bj_done = false; - facelet->event = FACELET_EVENT_UNDEFINED; + facelet->event = FACELET_EVENT_UNDEFINED; - facelet->routes = route_set_create(); - if (!facelet->routes) { - ERROR("[facelet_create] Cannot create route set"); - goto ERR_ROUTE_SET; - } - facelet->routes_done = false; + facelet->routes = route_set_create(); + if (!facelet->routes) { + ERROR("[facelet_create] Cannot create route set"); + goto ERR_ROUTE_SET; + } + facelet->routes_done = false; - return facelet; + return facelet; ERR_ROUTE_SET: - free(facelet); + free(facelet); ERR_MALLOC: - return NULL; + return NULL; } -unsigned -facelet_get_id(facelet_t * facelet) -{ - return facelet->id; -} +unsigned facelet_get_id(facelet_t *facelet) { return facelet->id; } -void -facelet_set_id(facelet_t * facelet, unsigned id) -{ - facelet->id = id; -} +void facelet_set_id(facelet_t *facelet, unsigned id) { facelet->id = id; } -facelet_t * -facelet_create_from_netdevice(netdevice_t * netdevice) -{ - facelet_t * facelet = facelet_create(); - if (!facelet) - goto ERR_FACELET; +facelet_t *facelet_create_from_netdevice(netdevice_t *netdevice) { + facelet_t *facelet = facelet_create(); + if (!facelet) goto ERR_FACELET; - int rc = facelet_set_netdevice(facelet, *netdevice); - if (rc < 0) - goto ERR_NETDEV; + int rc = facelet_set_netdevice(facelet, *netdevice); + if (rc < 0) goto ERR_NETDEV; - return facelet; + return facelet; ERR_NETDEV: - facelet_free(facelet); + facelet_free(facelet); ERR_FACELET: - return NULL; + return NULL; } /** @@ -186,368 +164,334 @@ ERR_FACELET: * \param [in] facelet - Pointer to the facelet to verify * \return 0 in case of success, -1 otherwise */ -int -facelet_validate_face(const facelet_t * facelet) -{ - if (!facelet_has_face_type(facelet)) - return false; - switch(facelet->face_type.layer) { - case FACE_TYPE_LAYER_4: - if (!facelet_has_remote_port(facelet)) - return false; - if (!facelet_has_remote_addr(facelet)) - return false; - case FACE_TYPE_LAYER_3: - if (!facelet_has_local_port(facelet)) - return false; - if (!facelet_has_local_addr(facelet)) - return false; - if (!facelet_has_netdevice(facelet)) - return false; - return true; - - default: - return false; /* Error */ - } - // FIXME Not implemented - return 0; +int facelet_validate_face(const facelet_t *facelet) { + if (!facelet_has_face_type(facelet)) return false; + + switch (facelet->face_type.layer) { + case FACE_TYPE_LAYER_4: + if (!facelet_has_remote_port(facelet)) return false; + if (!facelet_has_remote_addr(facelet)) return false; + case FACE_TYPE_LAYER_3: + if (!facelet_has_local_port(facelet)) return false; + if (!facelet_has_local_addr(facelet)) return false; + if (!facelet_has_netdevice(facelet)) return false; + break; + + default: + return false; + } + + return true; } - -netdevice_type_t -netdevice_type_from_face_tags(const face_t * face) -{ - policy_tags_t tags = face->tags; - if (policy_tags_has(tags, POLICY_TAG_WIRED)) - return NETDEVICE_TYPE_WIRED; - else if (policy_tags_has(tags, POLICY_TAG_WIFI)) - return NETDEVICE_TYPE_WIFI; - else if (policy_tags_has(tags, POLICY_TAG_CELLULAR)) - return NETDEVICE_TYPE_CELLULAR; - return NETDEVICE_TYPE_UNDEFINED; +netdevice_type_t netdevice_type_from_face_tags(const face_t *face) { + policy_tags_t tags = face->tags; + if (policy_tags_has(tags, POLICY_TAG_WIRED)) + return NETDEVICE_TYPE_WIRED; + else if (policy_tags_has(tags, POLICY_TAG_WIFI)) + return NETDEVICE_TYPE_WIFI; + else if (policy_tags_has(tags, POLICY_TAG_CELLULAR)) + return NETDEVICE_TYPE_CELLULAR; + return NETDEVICE_TYPE_UNDEFINED; } -facelet_t * -facelet_create_from_face(face_t * face) -{ - facelet_t * facelet = malloc(sizeof(facelet_t)); - if (!facelet) - goto ERR_MALLOC; +facelet_t *facelet_create_from_face(face_t *face) { + facelet_t *facelet = malloc(sizeof(facelet_t)); + if (!facelet) goto ERR_MALLOC; - facelet->id = 0; + facelet->id = 0; - /* Go through the face attributes to update the local representation */ + /* Go through the face attributes to update the local representation */ - /* Attribute : netdevice */ - /* NOTE index is not set */ - if (IS_VALID_NETDEVICE(face->netdevice)) { - /* /!\ A face has only the netdevice name */ - netdevice_set_name(&facelet->netdevice, face->netdevice.name); - facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET; - } - - /* Attribute : netdevice_type */ - facelet->netdevice_type = netdevice_type_from_face_tags(face); - if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) { - facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->netdevice_type = NETDEVICE_TYPE_UNDEFINED; - facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET; - } + /* Attribute : netdevice */ + /* NOTE index is not set */ + if (IS_VALID_NETDEVICE(face->netdevice)) { + /* /!\ A face has only the netdevice name */ + netdevice_set_name(&facelet->netdevice, face->netdevice.name); + facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET; + } + + /* Attribute : netdevice_type */ + facelet->netdevice_type = netdevice_type_from_face_tags(face); + if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) { + facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->netdevice_type = NETDEVICE_TYPE_UNDEFINED; + facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET; + } - /* Attribute : family */ - if (IS_VALID_FAMILY(face->family)) { - facelet->family = face->family; - facelet->family_status = FACELET_ATTR_STATUS_CLEAN; - - /* Attribute : local_addr */ - if (ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY, face->family) != 0) { - facelet->local_addr = face->local_addr; - facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; - } - - /* Attribute : local_port */ - if (IS_VALID_PORT(face->local_port)) { - facelet->local_port = face->local_port; - facelet->local_port_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; - } - - /* Attribute : remote_addr */ - if (ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY, face->family) != 0) { - facelet->remote_addr = face->remote_addr; - facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; - } - - /* Attribute : remote_port */ - if (IS_VALID_PORT(face->remote_port)) { - facelet->remote_port = face->remote_port; - facelet->remote_port_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; - } + /* Attribute : family */ + if (IS_VALID_FAMILY(face->family)) { + facelet->family = face->family; + facelet->family_status = FACELET_ATTR_STATUS_CLEAN; + /* Attribute : local_addr */ + if (hicn_ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY) != 0) { + facelet->local_addr = face->local_addr; + facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN; } else { - facelet->family_status = FACELET_ATTR_STATUS_UNSET; - facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; - facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; - facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; - facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; } - /* Attribute : admin_state */ - if ((face->admin_state == FACE_STATE_UP) || - (face->admin_state == FACE_STATE_DOWN)) { - facelet->admin_state = face->admin_state; - facelet->admin_state_status = FACELET_ATTR_STATUS_CLEAN; + /* Attribute : local_port */ + if (IS_VALID_PORT(face->local_port)) { + facelet->local_port = face->local_port; + facelet->local_port_status = FACELET_ATTR_STATUS_CLEAN; } else { - facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; } - /* Attribute : state */ - if ((face->state == FACE_STATE_UP) || - (face->state == FACE_STATE_DOWN)) { - facelet->state = face->state; - facelet->state_status = FACELET_ATTR_STATUS_CLEAN; + /* Attribute : remote_addr */ + if (hicn_ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY) != 0) { + facelet->remote_addr = face->remote_addr; + facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN; } else { - facelet->state_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; } -#ifdef WITH_POLICY - /* Attribute : priority */ - if (face->priority > 0) { - facelet->priority = face->priority; - facelet->priority_status = FACELET_ATTR_STATUS_CLEAN; - } else { - facelet->priority_status = FACELET_ATTR_STATUS_UNSET; - } -#endif /* WITH_POLICY */ - - /* Attribute : face_type */ - if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) { - switch(face->type) { - case FACE_TYPE_UDP: - facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; - break; - case FACE_TYPE_TCP: - facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; - break; - case FACE_TYPE_HICN: - facelet->face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; - break; - default: - ERROR("[facelet_create_from_face] Face type not (yet) implemented"); - goto ERR_FACE; - } - facelet->face_type_status = FACELET_ATTR_STATUS_CLEAN; + /* Attribute : remote_port */ + if (IS_VALID_PORT(face->remote_port)) { + facelet->remote_port = face->remote_port; + facelet->remote_port_status = FACELET_ATTR_STATUS_CLEAN; } else { - facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; } - /* Status */ - facelet->status = FACELET_STATUS_CLEAN; - facelet->error = 0; + } else { + facelet->family_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET; + facelet->local_port_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET; + facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; + } + + /* Attribute : admin_state */ + if ((face->admin_state == FACE_STATE_UP) || + (face->admin_state == FACE_STATE_DOWN)) { + facelet->admin_state = face->admin_state; + facelet->admin_state_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; + } + + /* Attribute : state */ + if ((face->state == FACE_STATE_UP) || (face->state == FACE_STATE_DOWN)) { + facelet->state = face->state; + facelet->state_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->state_status = FACELET_ATTR_STATUS_UNSET; + } - /* TODO Consistency check between face type and found attributes */ - if (facelet_validate_face(facelet) < 0) { - ERROR("[facelet_create_from_face] Cannot validate face"); + /* Attribute : priority */ + if (face->priority > 0) { + facelet->priority = face->priority; + facelet->priority_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->priority_status = FACELET_ATTR_STATUS_UNSET; + } + + /* Attribute : face_type */ + if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) { + switch (face->type) { + case FACE_TYPE_UDP: + facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP; + break; + case FACE_TYPE_TCP: + facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP; + break; + case FACE_TYPE_HICN: + facelet->face_type = FACEMGR_FACE_TYPE_NATIVE_TCP; + break; + default: + ERROR("[facelet_create_from_face] Face type not (yet) implemented"); goto ERR_FACE; } + facelet->face_type_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; + } - facelet->bj_done = false; - facelet->au_done = false; + /* Status */ + facelet->status = FACELET_STATUS_CLEAN; + facelet->error = 0; - facelet->event = FACELET_EVENT_UNDEFINED; + /* TODO Consistency check between face type and found attributes */ + if (facelet_validate_face(facelet) < 0) { + ERROR("[facelet_create_from_face] Cannot validate face"); + goto ERR_FACE; + } - /* We need to get route set */ - facelet->routes = route_set_create(); - if (!facelet->routes) { - ERROR("[facelet_create_from_face] Cannot create route set"); - goto ERR_ROUTE_SET; - } - facelet->routes_done = false; + facelet->bj_done = false; + + facelet->event = FACELET_EVENT_UNDEFINED; - return facelet; + /* We need to get route set */ + facelet->routes = route_set_create(); + if (!facelet->routes) { + ERROR("[facelet_create_from_face] Cannot create route set"); + goto ERR_ROUTE_SET; + } + facelet->routes_done = false; + + return facelet; ERR_ROUTE_SET: ERR_FACE: - free(facelet); + free(facelet); ERR_MALLOC: - return NULL; + return NULL; } +void facelet_free(facelet_t *facelet) { + /* Workaround: investigate how routes could be NULL */ + if (!facelet->routes) return; -void -facelet_free(facelet_t * facelet) -{ - /* Free up routes */ - route_set_clear(facelet->routes); - route_set_free(facelet->routes); - free(facelet); + /* Free up routes */ + route_set_clear(facelet->routes); + route_set_free(facelet->routes); + free(facelet); } -facelet_t * -facelet_dup(const facelet_t * current_facelet) -{ - facelet_t * facelet = facelet_create(); - if (!facelet) - goto ERR_CREATE; +facelet_t *facelet_dup(const facelet_t *current_facelet) { + facelet_t *facelet = facelet_create(); + if (!facelet) goto ERR_CREATE; -#define _(TYPE, NAME) facelet-> NAME = current_facelet-> NAME; - foreach_facelet_attr +#define _(TYPE, NAME) facelet->NAME = current_facelet->NAME; + foreach_facelet_attr #undef _ -#define _(TYPE, NAME) facelet-> NAME ## _status = current_facelet-> NAME ## _status; - foreach_facelet_attr +#define _(TYPE, NAME) facelet->NAME##_status = current_facelet->NAME##_status; + foreach_facelet_attr #undef _ - facelet->status = current_facelet->status; - facelet->event = current_facelet->event; - - facelet->bj_done = current_facelet->bj_done; - facelet->au_done = current_facelet->au_done; - - /* Routes */ - hicn_route_t ** route_array; - int n = route_set_get_array(current_facelet->routes, &route_array); - if (n < 0) { - ERROR("[facelet_free] Error getting route set associated to facelet"); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * route = route_array[i]; - hicn_route_t * new_route = hicn_route_dup(route); - if (!new_route) - goto ERR_ROUTE; - route_set_add(facelet->routes, new_route); - } + facelet->status = current_facelet->status; + facelet->event = current_facelet->event; + + facelet->bj_done = current_facelet->bj_done; + + /* Routes */ + hicn_route_t **route_array; + int n = route_set_get_array(current_facelet->routes, &route_array); + if (n < 0) { + ERROR("[facelet_free] Error getting route set associated to facelet %p", + current_facelet); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *route = route_array[i]; + if (!route) continue; /* Should not occur */ + hicn_route_t *new_route = hicn_route_dup(route); + if (!new_route) goto ERR_ROUTE; + route_set_add(facelet->routes, new_route); } - free(route_array); + } + free(route_array); - return facelet; + return facelet; ERR_ROUTE: - /* This will free all routes */ - facelet_free(facelet); + /* This will free all routes */ + facelet_free(facelet); ERR_CREATE: - return NULL; + return NULL; } -int -facelet_cmp(const facelet_t * f1, const facelet_t * f2) -{ - /* - * Under the assumption we only create a face per physical interface, a - * facelet is uniquely identified by its netdevice attribute, and address - * family if any. - * - * Because of additional static faces, we introduce a unique facelet id - * - * This function is mostly used for lookups into the cache, and the face - * thus needs to have a netdevice associated, and optionally, an address - * family. - * - * For other situations, the `facelet_match` function is more appropriate. +int facelet_cmp(const facelet_t *f1, const facelet_t *f2) { + /* + * Under the assumption we only create a face per physical interface, a + * facelet is uniquely identified by its netdevice attribute, and address + * family if any. + * + * Because of additional static faces, we introduce a unique facelet id + * + * This function is mostly used for lookups into the cache, and the face + * thus needs to have a netdevice associated, and optionally, an address + * family. + * + * For other situations, the `facelet_match` function is more appropriate. + */ + + if (f1->id != f2->id) return f1->id > f2->id ? 1 : -1; + + if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) && + (f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) { + int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice); + if (rc != 0) return rc; + + } else { + /* Both unset : we might have the face without netdevice due to hicn + * light not returning it currently, but we cannot skip it in the match + * otherwise we cannot distinguish with other faces except matching on + * other fields which might unfortunately not be determined yet... */ + return (f1->netdevice_status == FACELET_ATTR_STATUS_UNSET) ? -1 : 1; + } - if (f1->id != f2->id) - return f1->id > f2->id ? 1 : -1; - - if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) && - (f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) { - int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice); - if (rc != 0) - return rc; - - } else { - /* Both unset : we might have the face without netdevice due to hicn - * light not returning it currently, but we cannot skip it in the match - * otherwise we cannot distinguish with other faces except matching on - * other fields which might unfortunately not be determined yet... - */ - return (f1->netdevice_status == FACELET_ATTR_STATUS_UNSET) ? -1 : 1; - } + assert(f1->family_status != FACELET_ATTR_STATUS_UNSET); + assert(f2->family_status != FACELET_ATTR_STATUS_UNSET); - assert(f1->family_status != FACELET_ATTR_STATUS_UNSET); - assert(f2->family_status != FACELET_ATTR_STATUS_UNSET); - - if ((f1->family == AF_UNSPEC) || (f2->family == AF_UNSPEC)) - return 0; - int diff = f1->family - f2->family; - return (diff > 0) ? 1 : - (diff < 0) ? -1 : 0; + if ((f1->family == AF_UNSPEC) || (f2->family == AF_UNSPEC)) return 0; + int diff = f1->family - f2->family; + return (diff > 0) ? 1 : (diff < 0) ? -1 : 0; } /* * If the match has a field set, then the facelet only matches iif it has the * same field set, and both values are equal */ -#define EQUALS_ATTRIBUTE(TYPE, NAME) \ -do { \ - if (facelet_has_ ## NAME(facelet1)) { \ - if (facelet_has_ ## NAME(facelet2)) { \ - TYPE NAME ## 1; \ - TYPE NAME ## 2; \ - if (facelet_get_ ## NAME (facelet1, & NAME ## 1) < 0) \ - return false; \ - if (facelet_get_ ## NAME (facelet2, & NAME ## 2) < 0) \ - return false; \ - if (memcmp(& NAME ## 1, & NAME ## 2, sizeof(TYPE)) != 0) \ - return false; \ - } else { \ - return false; \ - } \ - } else { \ - if (facelet_has_ ## NAME(facelet2)) { \ - return false; \ - } \ - } \ -} while(0) - -bool -facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2) -{ +#define EQUALS_ATTRIBUTE(TYPE, NAME) \ + do { \ + if (facelet_has_##NAME(facelet1)) { \ + if (facelet_has_##NAME(facelet2)) { \ + TYPE NAME##1; \ + TYPE NAME##2; \ + if (facelet_get_##NAME(facelet1, &NAME##1) < 0) return false; \ + if (facelet_get_##NAME(facelet2, &NAME##2) < 0) return false; \ + if (memcmp(&NAME##1, &NAME##2, sizeof(TYPE)) != 0) return false; \ + } else { \ + return false; \ + } \ + } else { \ + if (facelet_has_##NAME(facelet2)) { \ + return false; \ + } \ + } \ + } while (0) + +bool facelet_equals(const facelet_t *facelet1, const facelet_t *facelet2) { #define _(TYPE, NAME) EQUALS_ATTRIBUTE(TYPE, NAME); - foreach_facelet_attr + foreach_facelet_attr #undef _ - return true; + return true; } /* * If the match has a field set, then the facelet only matches iif it has the * same field set, and both values are equal */ -#define MATCH_ATTRIBUTE(TYPE, NAME) \ -do { \ - if (facelet_match->NAME ## _status == FACELET_ATTR_STATUS_CLEAN) { \ - if (facelet_has_ ## NAME(facelet_match)) { \ - TYPE NAME; \ - TYPE NAME ## _match; \ - if (!facelet_has_ ## NAME(facelet)) { \ - continue; /* return false; */ \ - } \ - if (facelet_get_ ## NAME (facelet, & NAME) < 0) \ - return false; \ - if (facelet_get_ ## NAME (facelet_match, & NAME ## _match) < 0) \ - return false; \ - if (memcmp(& NAME, & NAME ## _match, sizeof(NAME)) != 0) { \ - return false; \ - } \ - } \ - } \ -} while(0) +#define MATCH_ATTRIBUTE(TYPE, NAME) \ + do { \ + if (facelet_match->NAME##_status == FACELET_ATTR_STATUS_CLEAN) { \ + if (facelet_has_##NAME(facelet_match)) { \ + TYPE NAME; \ + TYPE NAME##_match; \ + if (!facelet_has_##NAME(facelet)) { \ + continue; /* return false; */ \ + } \ + if (facelet_get_##NAME(facelet, &NAME) < 0) return false; \ + if (facelet_get_##NAME(facelet_match, &NAME##_match) < 0) \ + return false; \ + if (memcmp(&NAME, &NAME##_match, sizeof(NAME)) != 0) { \ + return false; \ + } \ + } \ + } \ + } while (0) /* facelet_match is the incoming one */ -bool -facelet_match(const facelet_t * facelet, const facelet_t * facelet_match) -{ +bool facelet_match(const facelet_t *facelet, const facelet_t *facelet_match) { #define _(TYPE, NAME) MATCH_ATTRIBUTE(TYPE, NAME); - foreach_facelet_attr + foreach_facelet_attr #undef _ #if 0 @@ -557,117 +501,101 @@ facelet_match(const facelet_t * facelet, const facelet_t * facelet_match) facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); DEBUG(" WITH %s", facelet_s); #endif - return true; + return true; } -bool facelet_has_key(const facelet_t * facelet) { - return (facelet_has_netdevice(facelet) && facelet_has_family(facelet)); +bool facelet_has_key(const facelet_t *facelet) { + return (facelet_has_netdevice(facelet) && facelet_has_family(facelet)); } /* * Implementation note: * - facelet_set_* is equivalent to merge with a CLEAN remote attribute */ -#define FACELET_ACCESSORS(TYPE, NAME) \ -bool \ -facelet_has_ ## NAME(const facelet_t * facelet) \ -{ \ - assert(facelet); \ - assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_UNDEFINED); \ - assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_N); \ - return ((facelet-> NAME ## _status != FACELET_ATTR_STATUS_UNSET)); \ -} \ - \ -facelet_attr_status_t \ -facelet_get_ ## NAME ## _status(const facelet_t * facelet) \ -{ \ - return (facelet->NAME ## _status); \ -} \ - \ -void \ -facelet_set_ ## NAME ## _status(facelet_t * facelet, \ - facelet_attr_status_t status) \ -{ \ - facelet->NAME ## _status = status; \ -} \ - \ -int \ -facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME) \ -{ \ - assert(facelet); \ - if (!facelet_has_ ## NAME(facelet)) \ - return -1; \ - *NAME = facelet-> NAME; \ - return 0; \ -} \ - \ -int \ -facelet_set_local_ ## NAME(facelet_t * facelet, TYPE NAME) \ -{ \ - assert(facelet); \ - switch(facelet->NAME ## _status) { \ - case FACELET_ATTR_STATUS_UNSET: \ - case FACELET_ATTR_STATUS_CLEAN: \ - case FACELET_ATTR_STATUS_DIRTY: \ - case FACELET_ATTR_STATUS_PENDING: \ - facelet-> NAME = NAME; \ - facelet->NAME ## _status = FACELET_ATTR_STATUS_DIRTY; \ - if (facelet->status == FACELET_STATUS_CLEAN) \ - facelet->status = FACELET_STATUS_UPDATE; \ - break; \ - case FACELET_ATTR_STATUS_CONFLICT: \ - break; \ - case FACELET_ATTR_STATUS_UNDEFINED: \ - case FACELET_ATTR_STATUS_N: \ - ERROR("Unexpected attribute status value"); \ - return -1; \ - } \ - return 0; \ -} \ - \ -int \ -facelet_set_remote_ ## NAME(facelet_t * facelet, TYPE NAME) \ -{ \ - assert(facelet); \ - switch(facelet->NAME ## _status) { \ - case FACELET_ATTR_STATUS_UNSET: \ - facelet-> NAME = NAME; \ - facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \ - break; \ - case FACELET_ATTR_STATUS_CLEAN: \ - facelet->NAME = NAME; \ - break; \ - case FACELET_ATTR_STATUS_DIRTY: \ - ERROR("Discarded remote value for status reasons"); \ - break; \ - case FACELET_ATTR_STATUS_PENDING: \ - ERROR("Received remote value on pending attribute"); \ - facelet->NAME ## _status = FACELET_ATTR_STATUS_CONFLICT; \ - /* We need to proceed to an update of the face */ \ - if (facelet->status != FACELET_STATUS_UPDATE) \ - facelet->status = FACELET_STATUS_UPDATE; \ - break; \ - case FACELET_ATTR_STATUS_CONFLICT: \ - return -1; \ - case FACELET_ATTR_STATUS_UNDEFINED: \ - case FACELET_ATTR_STATUS_N: \ - ERROR("Unexpected attribute status value"); \ - return -1; \ - } \ - return 0; \ -} \ - \ -int \ -facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME) \ -{ \ - return facelet_set_local_ ## NAME(facelet, NAME); \ -} \ - \ -int \ -facelet_unset_ ## NAME(facelet_t * facelet) \ -{ \ - return facelet->NAME ## _status = FACELET_ATTR_STATUS_UNSET; \ -} +#define FACELET_ACCESSORS(TYPE, NAME) \ + bool facelet_has_##NAME(const facelet_t *facelet) { \ + assert(facelet); \ + assert(facelet->NAME##_status != FACELET_ATTR_STATUS_UNDEFINED); \ + assert(facelet->NAME##_status != FACELET_ATTR_STATUS_N); \ + return ((facelet->NAME##_status != FACELET_ATTR_STATUS_UNSET)); \ + } \ + \ + facelet_attr_status_t facelet_get_##NAME##_status( \ + const facelet_t *facelet) { \ + return (facelet->NAME##_status); \ + } \ + \ + void facelet_set_##NAME##_status(facelet_t *facelet, \ + facelet_attr_status_t status) { \ + facelet->NAME##_status = status; \ + } \ + \ + int facelet_get_##NAME(const facelet_t *facelet, TYPE *NAME) { \ + assert(facelet); \ + if (!facelet_has_##NAME(facelet)) return -1; \ + *NAME = facelet->NAME; \ + return 0; \ + } \ + \ + int facelet_set_local_##NAME(facelet_t *facelet, TYPE NAME) { \ + assert(facelet); \ + switch (facelet->NAME##_status) { \ + case FACELET_ATTR_STATUS_UNSET: \ + case FACELET_ATTR_STATUS_CLEAN: \ + case FACELET_ATTR_STATUS_DIRTY: \ + case FACELET_ATTR_STATUS_PENDING: \ + facelet->NAME = NAME; \ + facelet->NAME##_status = FACELET_ATTR_STATUS_DIRTY; \ + if (facelet->status == FACELET_STATUS_CLEAN) \ + facelet->status = FACELET_STATUS_UPDATE; \ + break; \ + case FACELET_ATTR_STATUS_CONFLICT: \ + break; \ + case FACELET_ATTR_STATUS_UNDEFINED: \ + case FACELET_ATTR_STATUS_N: \ + ERROR("Unexpected attribute status value"); \ + return -1; \ + } \ + return 0; \ + } \ + \ + int facelet_set_remote_##NAME(facelet_t *facelet, TYPE NAME) { \ + assert(facelet); \ + switch (facelet->NAME##_status) { \ + case FACELET_ATTR_STATUS_UNSET: \ + facelet->NAME = NAME; \ + facelet->NAME##_status = FACELET_ATTR_STATUS_CLEAN; \ + break; \ + case FACELET_ATTR_STATUS_CLEAN: \ + facelet->NAME = NAME; \ + break; \ + case FACELET_ATTR_STATUS_DIRTY: \ + ERROR("Discarded remote value for status reasons"); \ + break; \ + case FACELET_ATTR_STATUS_PENDING: \ + ERROR("Received remote value on pending attribute"); \ + facelet->NAME##_status = FACELET_ATTR_STATUS_CONFLICT; \ + /* We need to proceed to an update of the face */ \ + if (facelet->status != FACELET_STATUS_UPDATE) \ + facelet->status = FACELET_STATUS_UPDATE; \ + break; \ + case FACELET_ATTR_STATUS_CONFLICT: \ + return -1; \ + case FACELET_ATTR_STATUS_UNDEFINED: \ + case FACELET_ATTR_STATUS_N: \ + ERROR("Unexpected attribute status value"); \ + return -1; \ + } \ + return 0; \ + } \ + \ + int facelet_set_##NAME(facelet_t *facelet, TYPE NAME) { \ + return facelet_set_local_##NAME(facelet, NAME); \ + } \ + \ + int facelet_unset_##NAME(facelet_t *facelet) { \ + return facelet->NAME##_status = FACELET_ATTR_STATUS_UNSET; \ + } #define _(TYPE, NAME) FACELET_ACCESSORS(TYPE, NAME) foreach_facelet_attr @@ -681,773 +609,616 @@ foreach_facelet_attr // FIXME CLEAN for key fields, dirty for fields to update. -#define MERGE_ATTRIBUTE(TYPE, NAME) \ -do { \ - switch(facelet_to_merge->NAME ## _status) { \ - case FACELET_ATTR_STATUS_UNDEFINED: \ - case FACELET_ATTR_STATUS_N: \ - case FACELET_ATTR_STATUS_PENDING: \ - case FACELET_ATTR_STATUS_CONFLICT: \ - ERROR("Unexpected facelet attribute status"); \ - return -1; \ - case FACELET_ATTR_STATUS_UNSET: \ - break; \ - case FACELET_ATTR_STATUS_CLEAN: \ - case FACELET_ATTR_STATUS_DIRTY: \ - facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \ - break; \ - } \ -} while (0) - -int facelet_merge(facelet_t * facelet, facelet_t * facelet_to_merge) -{ - assert(facelet && facelet_to_merge); +#define MERGE_ATTRIBUTE(TYPE, NAME) \ + do { \ + switch (facelet_to_merge->NAME##_status) { \ + case FACELET_ATTR_STATUS_UNDEFINED: \ + case FACELET_ATTR_STATUS_N: \ + case FACELET_ATTR_STATUS_PENDING: \ + case FACELET_ATTR_STATUS_CONFLICT: \ + ERROR("Unexpected facelet attribute status"); \ + return -1; \ + case FACELET_ATTR_STATUS_UNSET: \ + break; \ + case FACELET_ATTR_STATUS_CLEAN: \ + case FACELET_ATTR_STATUS_DIRTY: \ + facelet_set_##NAME(facelet, facelet_to_merge->NAME); \ + break; \ + } \ + } while (0) + + int + facelet_merge(facelet_t *facelet, facelet_t *facelet_to_merge) { + assert(facelet && facelet_to_merge); #define _(TYPE, NAME) MERGE_ATTRIBUTE(TYPE, NAME); - foreach_facelet_attr + foreach_facelet_attr #undef _ - facelet->event = facelet_to_merge->event; - - /* Routes */ - hicn_route_t ** route_array; - int n = route_set_get_array(facelet_to_merge->routes, &route_array); - if (n < 0) { - ERROR("[facelet_free] Error getting route set associated to facelet"); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * route = route_array[i]; - hicn_route_t * route_found = NULL; - if (route_set_get(facelet->routes, route, &route_found) < 0) { - ERROR("Error searching for route"); - continue; - } - if (route_found) - continue; - route_set_add(facelet->routes, hicn_route_dup(route)); - } + facelet->event = facelet_to_merge->event; + + /* Routes */ + hicn_route_t **route_array; + int n = route_set_get_array(facelet_to_merge->routes, &route_array); + if (n < 0) { + ERROR("[facelet_free] Error getting route set associated to facelet"); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *route = route_array[i]; + if (!route) continue; /* Should not occur */ + hicn_route_t *route_found = NULL; + if (route_set_get(facelet->routes, route, &route_found) < 0) { + ERROR("Error searching for route"); + continue; + } + if (route_found) continue; + route_set_add(facelet->routes, hicn_route_dup(route)); } - free(route_array); + } + free(route_array); - return 0; + return 0; } -#define MERGE_ATTRIBUTE_REMOTE(TYPE, NAME) \ -do { \ - switch(facelet_to_merge->NAME ## _status) { \ - case FACELET_ATTR_STATUS_UNDEFINED: \ - case FACELET_ATTR_STATUS_N: \ - case FACELET_ATTR_STATUS_DIRTY: \ - case FACELET_ATTR_STATUS_PENDING: \ - case FACELET_ATTR_STATUS_CONFLICT: \ - ERROR("Unexpected facelet attribute status"); \ - return -1; \ - case FACELET_ATTR_STATUS_UNSET: \ - break; \ - case FACELET_ATTR_STATUS_CLEAN: \ - facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \ - break; \ - \ - } \ -} while (0) - -int facelet_merge_remote(facelet_t * facelet, const facelet_t * facelet_to_merge) -{ - assert(facelet && facelet_to_merge); +#define MERGE_ATTRIBUTE_REMOTE(TYPE, NAME) \ + do { \ + switch (facelet_to_merge->NAME##_status) { \ + case FACELET_ATTR_STATUS_UNDEFINED: \ + case FACELET_ATTR_STATUS_N: \ + case FACELET_ATTR_STATUS_DIRTY: \ + case FACELET_ATTR_STATUS_PENDING: \ + case FACELET_ATTR_STATUS_CONFLICT: \ + ERROR("Unexpected facelet attribute status"); \ + return -1; \ + case FACELET_ATTR_STATUS_UNSET: \ + break; \ + case FACELET_ATTR_STATUS_CLEAN: \ + facelet_set_##NAME(facelet, facelet_to_merge->NAME); \ + break; \ + } \ + } while (0) + +int facelet_merge_remote(facelet_t *facelet, + const facelet_t *facelet_to_merge) { + assert(facelet && facelet_to_merge); #define _(TYPE, NAME) MERGE_ATTRIBUTE_REMOTE(TYPE, NAME); - foreach_facelet_attr + foreach_facelet_attr #undef _ - facelet->event = facelet_to_merge->event; - return 0; + facelet->event = facelet_to_merge->event; + return 0; } -int -facelet_get_face(const facelet_t * facelet, face_t ** pface) -{ - assert(pface); +int facelet_get_face(const facelet_t *facelet, face_t **pface) { + assert(pface); - /* Facelet has all the required information to create a face */ - if (facelet_validate_face(facelet) < 0) { - ERROR("[facelet_get_face] Face does not validate"); - return 0; - } - - face_t * face = face_create(); - if (!face) - goto ERR_CREATE; - - assert(facelet_has_netdevice(facelet)); - face->netdevice = facelet->netdevice; - - /* Face type */ - switch(facelet->face_type.layer) { - case FACE_TYPE_LAYER_4: - switch(facelet->face_type.encap) { - case FACE_TYPE_ENCAP_UDP: - face->type = FACE_TYPE_UDP; - break; - case FACE_TYPE_ENCAP_TCP: - face->type = FACE_TYPE_TCP; - break; - case FACE_TYPE_ENCAP_UNDEFINED: - case FACE_TYPE_ENCAP_N: - ERROR("[facelet_get_face] Unsupported face encapsulation"); - goto ERR; - } - - if (facelet_get_family(facelet, &face->family) < 0) { - ERROR("[facelet_get_face] Error retrieving face family"); - goto ERR; - } - if (facelet_get_local_addr(facelet, &face->local_addr) < 0) { - ERROR("[facelet_get_face] Error retrieving face local address"); - goto ERR; - } - if (facelet_get_local_port(facelet, &face->local_port) < 0) { - ERROR("[facelet_get_face] Error retrieving face local port"); - goto ERR; - } - if (facelet_get_remote_addr(facelet, &face->remote_addr) < 0) { - ERROR("[facelet_get_face] Error retrieving face remote address"); - goto ERR; - } - if (facelet_get_remote_port(facelet, &face->remote_port) < 0) { - ERROR("[facelet_get_face] Error retrieving face remote port"); - goto ERR; - } - break; - - case FACE_TYPE_LAYER_3: - ERROR("{facelet_get_face] hICN face not (yet) implemented"); - goto ERR; - - case FACE_TYPE_LAYER_UNDEFINED: - case FACE_TYPE_LAYER_N: - ERROR("[facelet_get_face] Unsupported face type"); - goto ERR; + /* Facelet has all the required information to create a face */ + if (facelet_validate_face(facelet) < 0) { + ERROR("[facelet_get_face] Face does not validate"); + return 0; + } + + face_t *face = face_create(); + if (!face) goto ERR_CREATE; + + assert(facelet_has_netdevice(facelet)); + face->netdevice = facelet->netdevice; + + /* Face type */ + switch (facelet->face_type.layer) { + case FACE_TYPE_LAYER_4: + switch (facelet->face_type.encap) { + case FACE_TYPE_ENCAP_UDP: + face->type = FACE_TYPE_UDP; + break; + case FACE_TYPE_ENCAP_TCP: + face->type = FACE_TYPE_TCP; + break; + case FACE_TYPE_ENCAP_UNDEFINED: + case FACE_TYPE_ENCAP_N: + ERROR("[facelet_get_face] Unsupported face encapsulation"); + goto ERR; + } + + if (facelet_get_family(facelet, &face->family) < 0) { + ERROR("[facelet_get_face] Error retrieving face family"); + goto ERR; + } + if (facelet_get_local_addr(facelet, &face->local_addr) < 0) { + ERROR("[facelet_get_face] Error retrieving face local address"); + goto ERR; + } + if (facelet_get_local_port(facelet, &face->local_port) < 0) { + ERROR("[facelet_get_face] Error retrieving face local port"); + goto ERR; + } + if (facelet_get_remote_addr(facelet, &face->remote_addr) < 0) { + ERROR("[facelet_get_face] Error retrieving face remote address"); + goto ERR; + } + if (facelet_get_remote_port(facelet, &face->remote_port) < 0) { + ERROR("[facelet_get_face] Error retrieving face remote port"); + goto ERR; + } + break; + + case FACE_TYPE_LAYER_3: + ERROR("{facelet_get_face] hICN face not (yet) implemented"); + goto ERR; + + case FACE_TYPE_LAYER_UNDEFINED: + case FACE_TYPE_LAYER_N: + ERROR("[facelet_get_face] Unsupported face type"); + goto ERR; + } + + if (facelet_has_admin_state(facelet)) { + if (facelet_get_admin_state(facelet, &face->admin_state) < 0) { + ERROR("[facelet_get_face] Error getting face admin state"); + goto ERR; } - - if (facelet_has_admin_state(facelet)) { - if (facelet_get_admin_state(facelet, &face->admin_state) < 0) { - ERROR("[facelet_get_face] Error getting face admin state"); - goto ERR; - } - } else { - face->admin_state = FACE_STATE_UP; + } else { + face->admin_state = FACE_STATE_UP; + } + + if (facelet_has_state(facelet)) { + if (facelet_get_state(facelet, &face->state) < 0) { + ERROR("[facelet_get_face] Error getting face state"); + goto ERR; } - - if (facelet_has_state(facelet)) { - if (facelet_get_state(facelet, &face->state) < 0) { - ERROR("[facelet_get_face] Error getting face state"); - goto ERR; - } - } else { - face->state = FACE_STATE_UP; + } else { + face->state = FACE_STATE_UP; + } + + /* Priority */ + if (facelet_has_priority(facelet)) { + if (facelet_get_priority(facelet, &face->priority) < 0) { + ERROR("[facelet_get_face] Error getting face priority"); + goto ERR; } - -#ifdef WITH_POLICY - /* Priority */ - if (facelet_has_priority(facelet)) { - if (facelet_get_priority(facelet, &face->priority) < 0) { - ERROR("[facelet_get_face] Error getting face priority"); - goto ERR; - } - } else { - face->priority = 0; + } else { + face->priority = 0; + } + + /* Tags */ + + /* - based on netdevice type */ + policy_tags_t tags = POLICY_TAGS_EMPTY; + if (facelet_has_netdevice_type(facelet)) { + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("error getting netdevice_type"); + goto ERR; } - /* Tags */ - - /* - based on netdevice type */ - policy_tags_t tags = POLICY_TAGS_EMPTY; - if (facelet_has_netdevice_type(facelet)) { - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("error getting netdevice_type"); - goto ERR; - } - - - switch(netdevice_type) { - case NETDEVICE_TYPE_UNDEFINED: - case NETDEVICE_TYPE_LOOPBACK: - break; - case NETDEVICE_TYPE_WIRED: - policy_tags_add(&tags, POLICY_TAG_WIRED); - break; - case NETDEVICE_TYPE_WIFI: - policy_tags_add(&tags, POLICY_TAG_WIFI); - break; - case NETDEVICE_TYPE_CELLULAR: - policy_tags_add(&tags, POLICY_TAG_CELLULAR); - break; - default: - goto ERR; - } + switch (netdevice_type) { + case NETDEVICE_TYPE_UNDEFINED: + case NETDEVICE_TYPE_LOOPBACK: + break; + case NETDEVICE_TYPE_WIRED: + policy_tags_add(&tags, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + policy_tags_add(&tags, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + policy_tags_add(&tags, POLICY_TAG_CELLULAR); + break; + default: + goto ERR; } - face->tags = tags; -#endif /* WITH_POLICY */ + } + face->tags = tags; - *pface = face; + *pface = face; - return 0; + return 0; ERR: - free(face); + free(face); ERR_CREATE: - *pface = NULL; - return -1; + *pface = NULL; + return -1; } -facelet_status_t -facelet_get_status(const facelet_t * facelet) -{ - return facelet->status; +facelet_status_t facelet_get_status(const facelet_t *facelet) { + return facelet->status; } -void -facelet_set_status(facelet_t * facelet, facelet_status_t status) -{ - facelet->status = status; +void facelet_set_status(facelet_t *facelet, facelet_status_t status) { + facelet->status = status; } -#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \ -do { \ - if (facelet->NAME ## _status == FACELET_ATTR_STATUS_DIRTY) \ - facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \ -} while (0) +#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \ + do { \ + if (facelet->NAME##_status == FACELET_ATTR_STATUS_DIRTY) \ + facelet->NAME##_status = FACELET_ATTR_STATUS_CLEAN; \ + } while (0) -void -facelet_set_attr_clean(facelet_t * facelet) -{ +void facelet_set_attr_clean(facelet_t *facelet) { #define _(TYPE, NAME) SET_ATTR_STATUS_CLEAN(TYPE, NAME); - foreach_facelet_attr + foreach_facelet_attr #undef _ } -void -facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason) -{ - facelet->error++; - switch(reason) { - case FACELET_ERROR_REASON_UNSPECIFIED_ERROR: - case FACELET_ERROR_REASON_INTERNAL_ERROR: - case FACELET_ERROR_REASON_PERMISSION_DENIED: - if (facelet->error >= FACELET_MAX_ERRORS) - facelet_set_status(facelet, FACELET_STATUS_IGNORED); - break; - case FACELET_ERROR_REASON_FORWARDER_OFFLINE: - break; - case FACELET_ERROR_REASON_UNDEFINED: - case FACELET_ERROR_REASON_N: - ERROR("facelet_set_error] Unexpected error reason"); - break; - } +void facelet_set_error(facelet_t *facelet, facelet_error_reason_t reason) { + facelet->error++; + switch (reason) { + case FACELET_ERROR_REASON_UNSPECIFIED_ERROR: + case FACELET_ERROR_REASON_INTERNAL_ERROR: + case FACELET_ERROR_REASON_PERMISSION_DENIED: + if (facelet->error >= FACELET_MAX_ERRORS) + facelet_set_status(facelet, FACELET_STATUS_IGNORED); + break; + case FACELET_ERROR_REASON_FORWARDER_OFFLINE: + break; + case FACELET_ERROR_REASON_UNDEFINED: + case FACELET_ERROR_REASON_N: + ERROR("facelet_set_error] Unexpected error reason"); + break; + } } -void -facelet_unset_error(facelet_t * facelet) -{ - facelet->error = 0; -} +void facelet_unset_error(facelet_t *facelet) { facelet->error = 0; } -bool -facelet_get_error(const facelet_t * facelet) -{ - return facelet->error; -} +bool facelet_get_error(const facelet_t *facelet) { return facelet->error; } -void -facelet_set_bj_done(facelet_t * facelet) -{ - facelet->bj_done = true; -} +void facelet_set_bj_done(facelet_t *facelet) { facelet->bj_done = true; } -void -facelet_unset_bj_done(facelet_t * facelet) -{ - facelet->bj_done = false; -} +void facelet_unset_bj_done(facelet_t *facelet) { facelet->bj_done = false; } -bool -facelet_is_bj_done(const facelet_t * facelet) -{ - return facelet->bj_done; -} +bool facelet_is_bj_done(const facelet_t *facelet) { return facelet->bj_done; } -void -facelet_set_au_done(facelet_t * facelet) -{ - facelet->au_done = true; +facelet_event_t facelet_get_event(const facelet_t *facelet) { + return facelet->event; } -bool -facelet_is_au_done(const facelet_t * facelet) -{ - return facelet->au_done; +void facelet_set_event(facelet_t *facelet, facelet_event_t event) { + facelet->event = event; } -facelet_event_t -facelet_get_event(const facelet_t * facelet) -{ - return facelet->event; +int facelet_add_route(facelet_t *facelet, hicn_route_t *route) { + return route_set_add(facelet->routes, route); } -void -facelet_set_event(facelet_t * facelet, facelet_event_t event) -{ - facelet->event = event; +int facelet_remove_route(facelet_t *facelet, hicn_route_t *route, + hicn_route_t **route_removed) { + return route_set_remove(facelet->routes, route, route_removed); } -int -facelet_add_route(facelet_t * facelet, hicn_route_t * route) -{ - return route_set_add(facelet->routes, route); +int facelet_clear_routes(facelet_t *facelet) { + return route_set_clear(facelet->routes); } -int -facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed) -{ - return route_set_remove(facelet->routes, route, route_removed); +int facelet_get_route_array(const facelet_t *facelet, + hicn_route_t ***route_array) { + return route_set_get_array(facelet->routes, route_array); } -int -facelet_clear_routes(facelet_t * facelet) -{ - return route_set_clear(facelet->routes); -} - -int -facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array) -{ - return route_set_get_array(facelet->routes, route_array); -} +int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) { + char *cur = s; + int rc; + + assert(facelet); + + /* Header + key attributes (netdevice + family) */ + rc = snprintf(cur, s + size - cur, "<Facelet [%d] %s %s (%s)", facelet->id, + facelet_status_str[facelet->status], + facelet_get_error(facelet) ? "/!\\" : "", + (facelet->family == AF_INET) ? "AF_INET" + : (facelet->family == AF_INET6) ? "AF_INET6" + : (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" + : "unknown"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* Netdevice */ + if (facelet_has_netdevice(facelet)) { + rc = snprintf(cur, s + size - cur, " netdevice=%s", + facelet->netdevice.name[0] ? facelet->netdevice.name : "*"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); -int -facelet_snprintf(char * s, size_t size, const facelet_t * facelet) -{ - char * cur = s; - int rc; - - assert(facelet); - - /* Header + key attributes (netdevice + family) */ - rc = snprintf(cur, s + size - cur, "<Facelet [%d] %s %s (%s)", - facelet->id, - facelet_status_str[facelet->status], - facelet_get_error(facelet) ? "/!\\" : "", - (facelet->family == AF_INET) ? "AF_INET" : - (facelet->family == AF_INET6) ? "AF_INET6" : - (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" : - "unknown"); - if (rc < 0) - return rc; + rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* Netdevice */ - if (facelet_has_netdevice(facelet)) { - rc = snprintf(cur, s + size - cur, " netdevice=%s", - facelet->netdevice.name[0] ? facelet->netdevice.name : "*"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); + if (cur >= s + size) return (int)(cur - s); - } else { - rc = snprintf(cur, s + size - cur, " netdevice=*/*"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + } else { + rc = snprintf(cur, s + size - cur, " netdevice=*/*"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Netdevice type */ + if (facelet_has_netdevice_type(facelet)) { + rc = snprintf(cur, s + size - cur, " type=%s", + netdevice_type_str(facelet->netdevice_type)); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } - /* Netdevice type */ - if (facelet_has_netdevice_type(facelet)) { - rc = snprintf(cur, s + size - cur, " type=%s", - netdevice_type_str[facelet->netdevice_type]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + /* Local ip address */ + if (facelet_has_local_addr(facelet)) { + rc = snprintf(cur, s + size - cur, " local_addr="); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); - /* Local ip address */ - if (facelet_has_local_addr(facelet)) { - rc = snprintf(cur, s + size - cur, " local_addr="); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr, - facelet->family); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->local_addr); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } - /* Local port */ - if (facelet_has_local_port(facelet)) { - rc = snprintf(cur, s + size - cur, " local_port=%d", - facelet->local_port); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + /* Local port */ + if (facelet_has_local_port(facelet)) { + rc = snprintf(cur, s + size - cur, " local_port=%d", facelet->local_port); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } - /* Remote ip address */ - if (facelet_has_remote_addr(facelet)) { - rc = snprintf(cur, s + size - cur, " remote_addr="); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr, - facelet->family); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + /* Remote ip address */ + if (facelet_has_remote_addr(facelet)) { + rc = snprintf(cur, s + size - cur, " remote_addr="); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); - /* Remote port */ - if (facelet_has_remote_port(facelet)) { - rc = snprintf(cur, s + size - cur, " remote_port=%d", - facelet->remote_port); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } - /* Admin state */ - if (facelet_has_admin_state(facelet)) { - rc = snprintf(cur, s + size - cur, " admin_state=%s", - face_state_str[facelet->admin_state]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + /* Remote port */ + if (facelet_has_remote_port(facelet)) { + rc = snprintf(cur, s + size - cur, " remote_port=%d", facelet->remote_port); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Admin state */ + if (facelet_has_admin_state(facelet)) { + rc = snprintf(cur, s + size - cur, " admin_state=%s", + face_state_str(facelet->admin_state)); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* State */ + if (facelet_has_state(facelet)) { + rc = snprintf(cur, s + size - cur, " state=%s", + face_state_str(facelet->state)); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } - /* State */ - if (facelet_has_state(facelet)) { - rc = snprintf(cur, s + size - cur, " state=%s", - face_state_str[facelet->state]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); + /* Priority */ + if (facelet_has_priority(facelet)) { + rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Face type */ + if (facelet_has_face_type(facelet)) { + rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s", + FACEMGR_FACE_TYPE_STR(facelet->face_type)); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Routes */ + rc = snprintf(cur, s + size - cur, " routes={ "); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + hicn_route_t **route_array; + int n = route_set_get_array(facelet->routes, &route_array); + if (n < 0) { + ERROR("[facelet_free] Error getting route set associated to facelet"); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *route = route_array[i]; + if (!route) continue; /* Should not occur */ + rc = (int)hicn_route_snprintf(cur, s + size - cur, route); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + rc = snprintf(cur, s + size - cur, ", "); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); } + } + free(route_array); -#ifdef WITH_POLICY - /* Priority */ - if (facelet_has_priority(facelet)) { - rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } -#endif /* WITH_POLICY */ - - /* Face type */ - if (facelet_has_face_type(facelet)) { - rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s", - FACEMGR_FACE_TYPE_STR(facelet->face_type)); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } + rc = snprintf(cur, s + size - cur, "}>"); + if (rc < 0) return rc; + cur += rc; + return (int)(cur - s); +} - /* Routes */ - rc = snprintf(cur, s + size - cur, " routes={ "); - if (rc < 0) - return rc; +int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet, + int indent) { + char *cur = s; + int rc; + + assert(facelet); + + /* Header + key attributes (netdevice + family) */ + rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "{\n"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* id */ + rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "", + "\"id\"", facelet->id); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* Status */ + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"status\"", facelet_status_str[facelet->status]); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* Family */ + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"family\"", + (facelet->family == AF_INET) ? "AF_INET" + : (facelet->family == AF_INET6) ? "AF_INET6" + : (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" + : "unknown"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* Netdevice */ + if (facelet_has_netdevice(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"netdevice\"", + facelet->netdevice.name[0] ? facelet->netdevice.name : "*"); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - hicn_route_t ** route_array; - int n = route_set_get_array(facelet->routes, &route_array); - if (n < 0) { - ERROR("[facelet_free] Error getting route set associated to facelet"); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * route = route_array[i]; - rc = (int)hicn_route_snprintf(cur, s + size - cur, route); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = snprintf(cur, s + size - cur, ", "); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - } - free(route_array); + if (cur >= s + size) return (int)(cur - s); - rc = snprintf(cur, s + size - cur, "}>"); - if (rc < 0) - return rc; + } else { + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"netdevice\"", "*"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Netdevice type */ + if (facelet_has_netdevice_type(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"netdevice_type\"", + netdevice_type_str(facelet->netdevice_type)); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Local ip address */ + if (facelet_has_local_addr(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent + 1), "", + "\"local_addr\""); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); + if (cur >= s + size) return (int)(cur - s); - return (int)(cur - s); -} + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->local_addr); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); -int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int indent) -{ - char * cur = s; - int rc; + rc = snprintf(cur, s + size - cur, "\",\n"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Local port */ + if (facelet_has_local_port(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "", + "\"local_port\"", facelet->local_port); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Remote ip address */ + if (facelet_has_remote_addr(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent + 1), "", + "\"remote_addr\""); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); - assert(facelet); + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); - /* Header + key attributes (netdevice + family) */ - rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "{\n"); - if (rc < 0) - return rc; + rc = snprintf(cur, s + size - cur, "\",\n"); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* id */ - rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", "\"id\"", - facelet->id); - if (rc < 0) - return rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Remote port */ + if (facelet_has_remote_port(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "", + "\"remote_port\"", facelet->remote_port); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* Status */ - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"status\"", - facelet_status_str[facelet->status]); - if (rc < 0) - return rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Admin state */ + if (facelet_has_admin_state(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"admin_state\"", face_state_str(facelet->admin_state)); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* Family */ - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"family\"", - (facelet->family == AF_INET) ? "AF_INET" : - (facelet->family == AF_INET6) ? "AF_INET6" : - (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" : - "unknown"); - if (rc < 0) - return rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* State */ + if (facelet_has_state(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "", + "\"state\"", face_state_str(facelet->state)); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* Netdevice */ - if (facelet_has_netdevice(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", - "\"netdevice\"", - facelet->netdevice.name[0] ? facelet->netdevice.name : "*"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - } else { - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", - "\"netdevice\"", "*"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Netdevice type */ - if (facelet_has_netdevice_type(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", - "\"netdevice_type\"", - netdevice_type_str[facelet->netdevice_type]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Local ip address */ - if (facelet_has_local_addr(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "", - "\"local_addr\""); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr, - facelet->family); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = snprintf(cur, s + size - cur, "\",\n"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Local port */ - if (facelet_has_local_port(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", - "\"local_port\"", - facelet->local_port); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Remote ip address */ - if (facelet_has_remote_addr(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "", - "\"remote_addr\""); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr, - facelet->family); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - rc = snprintf(cur, s + size - cur, "\",\n"); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Remote port */ - if (facelet_has_remote_port(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", - "\"remote_port\"", - facelet->remote_port); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Admin state */ - if (facelet_has_admin_state(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", - "\"admin_state\"", - face_state_str[facelet->admin_state]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* State */ - if (facelet_has_state(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", - "\"state\"", - face_state_str[facelet->state]); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - -#ifdef WITH_POLICY - /* Priority */ - if (facelet_has_priority(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", - "\"priority\"", facelet->priority); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } -#endif /* WITH_POLICY */ - - if (facelet_has_face_type(facelet)) { - rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", 4 * (indent+1), "", - "\"face_type\"", - FACEMGR_FACE_TYPE_STR(facelet->face_type)); - if (rc < 0) - return rc; - cur += rc; - if (cur >= s + size) - return (int)(cur - s); - } - - /* Status error */ - rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent+1), "", - "\"error\"", - facelet_get_error(facelet) ? "true" : "false"); - if (rc < 0) - return rc; + if (cur >= s + size) return (int)(cur - s); + } + + /* Priority */ + if (facelet_has_priority(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "", + "\"priority\"", facelet->priority); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - /* Routes */ - // TODO - - rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}"); - if (rc < 0) - return rc; + if (cur >= s + size) return (int)(cur - s); + } + + if (facelet_has_face_type(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", + 4 * (indent + 1), "", "\"face_type\"", + FACEMGR_FACE_TYPE_STR(facelet->face_type)); + if (rc < 0) return rc; cur += rc; - if (cur >= s + size) - return (int)(cur - s); - - return (int)(cur - s); + if (cur >= s + size) return (int)(cur - s); + } + + /* Status error */ + rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent + 1), "", + "\"error\"", facelet_get_error(facelet) ? "true" : "false"); + if (rc < 0) return rc; + cur += rc; + if (cur >= s + size) return (int)(cur - s); + + /* Routes */ + // TODO + + rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}"); + if (rc < 0) return rc; + cur += rc; + return (int)(cur - s); } diff --git a/ctrl/facemgr/src/facelet_array.c b/ctrl/facemgr/src/facelet_array.c index 3ee110b8e..d48625979 100644 --- a/ctrl/facemgr/src/facelet_array.c +++ b/ctrl/facemgr/src/facelet_array.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -23,4 +23,3 @@ #include "facelet_array.h" TYPEDEF_ARRAY(facelet_array, facelet_t *, facelet_equals, facelet_snprintf); - diff --git a/ctrl/facemgr/src/facelet_array.h b/ctrl/facemgr/src/facelet_array.h index 099774691..b3b17e88b 100644 --- a/ctrl/facemgr/src/facelet_array.h +++ b/ctrl/facemgr/src/facelet_array.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interface.c b/ctrl/facemgr/src/interface.c index 7f95be4ce..a9aeeaf33 100644 --- a/ctrl/facemgr/src/interface.c +++ b/ctrl/facemgr/src/interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -29,170 +29,144 @@ #include "interface.h" TYPEDEF_MAP_H(interface_ops_map, const char *, const interface_ops_t *); -TYPEDEF_MAP(interface_ops_map, const char *, const interface_ops_t *, strcmp, string_snprintf, generic_snprintf); - -static interface_ops_map_t * interface_ops_map = NULL; - -int -interface_register(const interface_ops_t * ops) -{ - if (!interface_ops_map) { - interface_ops_map = interface_ops_map_create(); - if (!interface_ops_map) - return -1; - } - interface_ops_map_add(interface_ops_map, ops->type, ops); - return 0; +TYPEDEF_MAP(interface_ops_map, const char *, const interface_ops_t *, strcmp, + string_snprintf, generic_snprintf); + +static interface_ops_map_t *interface_ops_map = NULL; + +int interface_register(const interface_ops_t *ops) { + if (!interface_ops_map) { + interface_ops_map = interface_ops_map_create(); + if (!interface_ops_map) return -1; + } + interface_ops_map_add(interface_ops_map, ops->type, ops); + return 0; } -int -interface_unregister_all() -{ - int ret = 0; - const char ** ops_name_array = NULL; - int n = interface_ops_map_get_key_array(interface_ops_map, &ops_name_array); - if (n < 0) { - ERROR("[interface_unregister_all] Could not get interface ops array"); - return -1; - } - - for (unsigned i = 0; i < n; i++) { - const char * ops_name = ops_name_array[i]; - if (interface_ops_map_remove(interface_ops_map, ops_name, NULL) < 0) { - ERROR("[interface_unregister_all] Could not remove %s from interface ops map", ops_name); - ret = -1; - } +int interface_unregister_all() { + int ret = 0; + const char **ops_name_array = NULL; + int n = interface_ops_map_get_key_array(interface_ops_map, &ops_name_array); + if (n < 0) { + ERROR("[interface_unregister_all] Could not get interface ops array"); + return -1; + } + + for (unsigned i = 0; i < n; i++) { + const char *ops_name = ops_name_array[i]; + if (interface_ops_map_remove(interface_ops_map, ops_name, NULL) < 0) { + ERROR( + "[interface_unregister_all] Could not remove %s from interface ops " + "map", + ops_name); + ret = -1; } - free(ops_name_array); + } + free(ops_name_array); - interface_ops_map_free(interface_ops_map); - interface_ops_map = NULL; + interface_ops_map_free(interface_ops_map); + interface_ops_map = NULL; - return ret; + return ret; } -interface_t * -interface_create(const char * name, const char * type) -{ - - const interface_ops_t * ops = NULL; - int rc = interface_ops_map_get(interface_ops_map, type, &ops); - if (rc < 0) { - printf("Interface type not found %s\n", type); - return NULL; - } - - interface_t * interface = malloc(sizeof(interface_t)); - if (!interface) - return NULL; - - interface->name = strdup(name); - /* this should use type */ - interface->ops = ops; - interface->callback = NULL; - interface->callback_owner = NULL; - interface->data = NULL; - - return interface; +interface_t *interface_create(const char *name, const char *type) { + const interface_ops_t *ops = NULL; + int rc = interface_ops_map_get(interface_ops_map, type, &ops); + if (rc < 0) { + printf("Interface type not found %s\n", type); + return NULL; + } + + interface_t *interface = malloc(sizeof(interface_t)); + if (!interface) return NULL; + + interface->name = strdup(name); + /* this should use type */ + interface->ops = ops; + interface->callback = NULL; + interface->callback_owner = NULL; + interface->data = NULL; + + return interface; } -void -interface_free(interface_t * interface) -{ - free(interface->name); - free(interface); +void interface_free(interface_t *interface) { + free(interface->name); + free(interface); } -void -interface_set_callback(interface_t * interface, void * callback_owner, - interface_cb_t callback) -{ - interface->callback = callback; - interface->callback_owner = callback_owner; +void interface_set_callback(interface_t *interface, void *callback_owner, + interface_cb_t callback) { + interface->callback = callback; + interface->callback_owner = callback_owner; } -int -interface_initialize(interface_t * interface, void * cfg) -{ - if (!interface->ops->initialize) - return -1; - return interface->ops->initialize(interface, cfg); +int interface_initialize(interface_t *interface, void *cfg) { + if (!interface->ops->initialize) return -1; + return interface->ops->initialize(interface, cfg); } -int -interface_finalize(interface_t * interface) -{ - if (!interface->ops->finalize) - return -1; - return interface->ops->finalize(interface); +int interface_finalize(interface_t *interface) { + if (!interface->ops->finalize) return -1; + return interface->ops->finalize(interface); } -int -interface_on_event(interface_t * interface, facelet_t * facelet) -{ - if (!interface->ops->on_event) - return -1; - return interface->ops->on_event(interface, facelet); +int interface_on_event(interface_t *interface, facelet_t *facelet) { + if (!interface->ops->on_event) return -1; + return interface->ops->on_event(interface, facelet); } -int -interface_raise_event(interface_t * interface, facelet_t * facelet) -{ - assert(interface->callback); - return interface->callback(interface->callback_owner, - INTERFACE_CB_TYPE_RAISE_EVENT, facelet); +int interface_raise_event(interface_t *interface, facelet_t *facelet) { + assert(interface->callback); + return interface->callback(interface->callback_owner, + INTERFACE_CB_TYPE_RAISE_EVENT, facelet); } -int -interface_register_fd(interface_t * interface, int fd, void * data) -{ - assert(interface->callback); - fd_callback_data_t fd_callback = { - .fd = fd, - .owner = interface, - .callback = (fd_callback_t)interface->ops->callback, - .data = data, - }; - return interface->callback(interface->callback_owner, - INTERFACE_CB_TYPE_REGISTER_FD, &fd_callback); +int interface_register_fd(interface_t *interface, int fd, void *data) { + assert(interface->callback); + fd_callback_data_t fd_callback = { + .fd = fd, + .owner = interface, + .callback = (fd_callback_t)interface->ops->callback, + .data = data, + }; + return interface->callback(interface->callback_owner, + INTERFACE_CB_TYPE_REGISTER_FD, &fd_callback); } -int -interface_unregister_fd(interface_t * interface, int fd) -{ - assert(interface->callback); - fd_callback_data_t fd_callback = { - .fd = fd, - .owner = interface, - .callback = NULL, - .data = NULL, - }; - return interface->callback(interface->callback_owner, - INTERFACE_CB_TYPE_UNREGISTER_FD, &fd_callback); +int interface_unregister_fd(interface_t *interface, int fd) { + assert(interface->callback); + fd_callback_data_t fd_callback = { + .fd = fd, + .owner = interface, + .callback = NULL, + .data = NULL, + }; + return interface->callback(interface->callback_owner, + INTERFACE_CB_TYPE_UNREGISTER_FD, &fd_callback); } -typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused); - -int -interface_register_timer(interface_t * interface, unsigned delay_ms, - interface_fd_callback_t callback, void * data) -{ - assert(interface->callback); - timer_callback_data_t timer_callback = { - .delay_ms = delay_ms, - .owner = interface, - .callback = (fd_callback_t)callback, - .data = data, - }; - int rc = interface->callback(interface->callback_owner, - INTERFACE_CB_TYPE_REGISTER_TIMER, &timer_callback); - return rc; +typedef int (*interface_fd_callback_t)(interface_t *interface, int fd, + void *unused); + +int interface_register_timer(interface_t *interface, unsigned delay_ms, + interface_fd_callback_t callback, void *data) { + assert(interface->callback); + timer_callback_data_t timer_callback = { + .delay_ms = delay_ms, + .owner = interface, + .callback = (fd_callback_t)callback, + .data = data, + }; + int rc = + interface->callback(interface->callback_owner, + INTERFACE_CB_TYPE_REGISTER_TIMER, &timer_callback); + return rc; } -int -interface_unregister_timer(interface_t * interface, int fd) -{ - assert(interface->callback); - return interface->callback(interface->callback_owner, - INTERFACE_CB_TYPE_UNREGISTER_TIMER, &fd); +int interface_unregister_timer(interface_t *interface, int fd) { + assert(interface->callback); + return interface->callback(interface->callback_owner, + INTERFACE_CB_TYPE_UNREGISTER_TIMER, &fd); } diff --git a/ctrl/facemgr/src/interface.h b/ctrl/facemgr/src/interface.h index a4fbda1fb..a999036d5 100644 --- a/ctrl/facemgr/src/interface.h +++ b/ctrl/facemgr/src/interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,40 +32,41 @@ #include <hicn/facemgr/loop.h> typedef enum { - INTERFACE_CB_TYPE_REGISTER_FD, - INTERFACE_CB_TYPE_UNREGISTER_FD, - INTERFACE_CB_TYPE_RAISE_EVENT, - INTERFACE_CB_TYPE_REGISTER_TIMER, - INTERFACE_CB_TYPE_UNREGISTER_TIMER, + INTERFACE_CB_TYPE_REGISTER_FD, + INTERFACE_CB_TYPE_UNREGISTER_FD, + INTERFACE_CB_TYPE_RAISE_EVENT, + INTERFACE_CB_TYPE_REGISTER_TIMER, + INTERFACE_CB_TYPE_UNREGISTER_TIMER, } interface_cb_type_t; -typedef int (*interface_cb_t)(facemgr_t * facemgr, interface_cb_type_t type, void * data); +typedef int (*interface_cb_t)(facemgr_t* facemgr, interface_cb_type_t type, + void* data); /** * \brief Interface operations */ struct interface_s; typedef struct { - /** The type given to the interfaces */ - char * type; - /* Constructor */ - int (*initialize)(struct interface_s * interface, void * cfg); - /* Destructor */ - int (*finalize)(struct interface_s * interface); - /* Callback upon file descriptor event (iif previously registered) */ - int (*callback)(struct interface_s * interface, int fd, void * data); - /* Callback upon face events coming from the face manager */ - int (*on_event)(struct interface_s * interface, struct facelet_s * facelet); + /** The type given to the interfaces */ + char* type; + /* Constructor */ + int (*initialize)(struct interface_s* interface, void* cfg); + /* Destructor */ + int (*finalize)(struct interface_s* interface); + /* Callback upon file descriptor event (iif previously registered) */ + int (*callback)(struct interface_s* interface, int fd, void* data); + /* Callback upon face events coming from the face manager */ + int (*on_event)(struct interface_s* interface, struct facelet_s* facelet); } interface_ops_t; typedef struct interface_s { - char * name; - const interface_ops_t * ops; + char* name; + const interface_ops_t* ops; - interface_cb_t callback; - void * callback_owner; + interface_cb_t callback; + void* callback_owner; - void * data; + void* data; } interface_t; /** @@ -75,7 +76,7 @@ typedef struct interface_s { * \return Flag indicating the success (FACEMGR_SUCCESS=0), or failure (any * other value) of the operation. */ -int interface_register(const interface_ops_t * ops); +int interface_register(const interface_ops_t* ops); int interface_unregister_all(); @@ -91,22 +92,22 @@ int interface_unregister_all(); * \return A a pointer to the newly created instance of the requested type, or * NULL in case of failure. */ -interface_t * interface_create(const char * name, const char * type); +interface_t* interface_create(const char* name, const char* type); /** * \brief Free an interface instance. * \param [in] interface - Pointer to the instance to free. */ -void interface_free(interface_t * interface); +void interface_free(interface_t* interface); +void interface_set_callback(interface_t* interface, void* callback_owner, + interface_cb_t callback); -void interface_set_callback(interface_t * interface, void * callback_owner, interface_cb_t callback); +int interface_initialize(interface_t* interface, void* cfg); -int interface_initialize(interface_t * interface, void * cfg); +int interface_finalize(interface_t* interface); -int interface_finalize(interface_t * interface); - -int interface_on_event(interface_t * interface, struct facelet_s * facelet); +int interface_on_event(interface_t* interface, struct facelet_s* facelet); /** * \brief Raises a facelet event to the face manager @@ -115,15 +116,17 @@ int interface_on_event(interface_t * interface, struct facelet_s * facelet); * \param [in] facelet - Facelet to communicate with the event * \return Error code */ -int interface_callback(interface_t * interface, interface_cb_type_t type, void * data); +int interface_callback(interface_t* interface, interface_cb_type_t type, + void* data); -int interface_raise_event(interface_t * interface, facelet_t * facelet); +int interface_raise_event(interface_t* interface, facelet_t* facelet); -int interface_register_fd(interface_t * interface, int fd, void * data); +int interface_register_fd(interface_t* interface, int fd, void* data); -int interface_unregister_fd(interface_t * interface, int fd); +int interface_unregister_fd(interface_t* interface, int fd); -typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused); +typedef int (*interface_fd_callback_t)(interface_t* interface, int fd, + void* unused); /** * \brief Registers a timer event @@ -135,8 +138,8 @@ typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * u * \return A positive value uniquely identifying the timer, or -1 in case of * error */ -int interface_register_timer(interface_t * interface, unsigned delay_ms, - interface_fd_callback_t callback, void * data); +int interface_register_timer(interface_t* interface, unsigned delay_ms, + interface_fd_callback_t callback, void* data); /** * \brief Unregisters a timer event @@ -144,6 +147,6 @@ int interface_register_timer(interface_t * interface, unsigned delay_ms, * \param [in] fd - Timer identifier * \return 0 in case of success, -1 otherwise */ -int interface_unregister_timer(interface_t * interface, int fd); +int interface_unregister_timer(interface_t* interface, int fd); #endif /* FACEMGR_INTERFACE_H */ diff --git a/ctrl/facemgr/src/interfaces/CMakeLists.txt b/ctrl/facemgr/src/interfaces/CMakeLists.txt index e4d4423e9..02fb0eb48 100644 --- a/ctrl/facemgr/src/interfaces/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -16,28 +16,33 @@ list(APPEND SOURCE_FILES) list(APPEND INCLUDE_DIRS) list(APPEND LIBRARIES) + +############################################################## +# Add components +############################################################## add_subdirectory(hicn_light) if(APPLE) -add_subdirectory(network_framework) + add_subdirectory(network_framework) endif() if(LINUX) -add_subdirectory(netlink) -add_subdirectory(bonjour) -endif() - -if(ANDROID) -add_subdirectory(android_utility) -add_subdirectory(priority_controller) + if(ANDROID) + add_subdirectory(android) + add_subdirectory(priority_controller) + else() + add_subdirectory(netlink) + endif() + + add_subdirectory(bonjour) endif() if(WITH_EXAMPLE_DUMMY) -add_subdirectory(dummy) + add_subdirectory(dummy) endif() if(WITH_EXAMPLE_UPDOWN) -add_subdirectory(updown) + add_subdirectory(updown) endif() set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt index 0ebe87745..beabc1280 100644 --- a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: @@ -11,16 +11,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/android_utility.c +list(APPEND HEADER_FILES ) -list(APPEND INCLUDE_DIRS +list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/android.c ) list(APPEND LIBRARIES ) +list(APPEND INCLUDE_DIRS +) + set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/android/android.c b/ctrl/facemgr/src/interfaces/android/android.c new file mode 100644 index 000000000..578e7472a --- /dev/null +++ b/ctrl/facemgr/src/interfaces/android/android.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2021 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 interfaces/android/android.c + * \brief Netlink interface + */ + +#include <assert.h> +#include <pthread.h> +#include <sys/eventfd.h> +#include <unistd.h> // close + +#include <hicn/facemgr.h> +#include <hicn/util/ip_address.h> +#include <hicn/util/log.h> + +#include "../../common.h" +#include "../../interface.h" +#include "../../facelet_array.h" + +#include "android.h" + +/* + * aar_modules/FaceMgrLibrary/facemgrLibrary/src/main/java/com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility.java + */ +#define FACEMGR_ANDROID_CLASS \ + "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" + +/* Internal data storage */ +typedef struct { + int fd; + android_cfg_t cfg; + JNIEnv *env; + jclass cls; + bool attached_to_vm; + facelet_array_t *facelets; + pthread_mutex_t mutex; +} android_data_t; + +// might replace android utility + +jclass find_class_global(JNIEnv *env, const char *name) { + jclass c = (*env)->FindClass(env, name); + jclass c_global = 0; + if (c) { + c_global = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + } + return c_global; +} + +int android_on_network_event(interface_t *interface, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address) { + android_data_t *data = (android_data_t *)interface->data; + + netdevice_t *netdevice = netdevice_create_from_name(interface_name); + if (!netdevice) { + ERROR("[android_on_network_event] error creating netdevice '%s'", + interface_name); + goto ERR_ND; + } + + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + if (ip_address) { + if (hicn_ip_address_pton(ip_address, &local_addr) < 0) { + ERROR("[android_on_network_event] error processing IP address"); + goto ERR_IP_ADDRESS; + } + } + + facelet_t *facelet = facelet_create(); + if (!facelet) { + ERROR("[android_on_network_event] error creating facelet"); + goto ERR_FACELET; + } + + if (facelet_set_netdevice(facelet, *netdevice) < 0) { + ERROR("[android_on_network_event] error setting netdevice"); + goto ERR; + } + + if (netdevice_type != NETDEVICE_TYPE_UNDEFINED) { + if (facelet_set_netdevice_type(facelet, netdevice_type) < 0) { + ERROR("[android_on_network_event] error setting netdevice type"); + goto ERR; + } + } + + if (facelet_set_family(facelet, family) < 0) { + ERROR("[android_on_network_event] error setting family"); + goto ERR; + } + + if (ip_address) { + if (facelet_set_local_addr(facelet, local_addr) < 0) { + ERROR("[android_on_network_event] error setting local address"); + goto ERR; + } + } + netdevice_free(netdevice); + + facelet_set_event(facelet, up ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); + // FACELET_EVENT_UPDATE, FACELET_EVENT_SET_DOWN + facelet_set_attr_clean(facelet); + + pthread_mutex_lock(&data->mutex); + if (facelet_array_add(data->facelets, facelet)) { + ERROR("[android_on_network_event] Could not add facelet to buffer"); + goto ERR_ADD; + } + + pthread_mutex_unlock(&data->mutex); + + eventfd_write(data->fd, 1); + return 0; + +ERR_ADD: + pthread_mutex_unlock(&data->mutex); +ERR: + facelet_free(facelet); +ERR_FACELET: +ERR_IP_ADDRESS: + netdevice_free(netdevice); +ERR_ND: + return -1; +} + +bool get_jni_env(JavaVM *jvm, JNIEnv **env) { + bool did_attach_thread = false; + INFO("initialize: get_jni_env"); + *env = NULL; + // Check if the current thread is attached to the VM + int get_env_result = (*jvm)->GetEnv(jvm, (void **)env, JNI_VERSION_1_6); + if (get_env_result == JNI_EDETACHED) { + INFO("initialize: detached!"); + if ((*jvm)->AttachCurrentThread(jvm, env, NULL) == JNI_OK) { + INFO("initialize: attached..."); + did_attach_thread = true; + } else { + INFO("initialize: failed to attach"); + // Failed to attach thread. Throw an exception if you want to. + } + } else if (get_env_result == JNI_EVERSION) { + // Unsupported JNI version. Throw an exception if you want to. + INFO("initialize: unsupported"); + } + return did_attach_thread; +} + +int android_initialize(interface_t *interface, void *cfg) { + android_data_t *data = malloc(sizeof(android_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + if (!cfg) goto ERR_CFG; + data->cfg = *(android_cfg_t *)cfg; + + JavaVM *jvm = data->cfg.jvm; + if (!jvm) goto ERR_JVM; + + data->facelets = facelet_array_create(); + if (!data->facelets) goto ERR_FACELETS; + + if ((data->fd = eventfd(0, EFD_SEMAPHORE)) == -1) goto ERR_EVENTFD; + + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[android_initialize] Error registering fd"); + goto ERR_REGISTER_FD; + } + + pthread_mutex_init(&data->mutex, NULL); + + data->attached_to_vm = get_jni_env(jvm, &data->env); + + if (!data->env) goto ERR_ENV; + + data->cls = find_class_global(data->env, FACEMGR_ANDROID_CLASS); + if (data->cls == 0) goto ERR_CLS; + + jmethodID mid_initialize = + (*data->env) + ->GetStaticMethodID(data->env, data->cls, "initialize", "()I"); + if (!mid_initialize) goto ERR_MID; + + (*data->env) + ->CallStaticIntMethod(data->env, data->cls, mid_initialize, + &android_on_network_event, interface); + + return 0; + +ERR_MID: + (*data->env)->DeleteGlobalRef(data->env, data->cls); +ERR_CLS: + if (data->attached_to_vm) { + (*jvm)->DetachCurrentThread(jvm); + data->attached_to_vm = false; + } + data->env = NULL; +ERR_ENV: + interface_unregister_fd(interface, data->fd); +ERR_REGISTER_FD: + close(data->fd); +ERR_EVENTFD: + facelet_array_free(data->facelets); +ERR_FACELETS: +ERR_JVM: +ERR_CFG: + free(data); +ERR_MALLOC: + return -1; +} + +int android_finalize(interface_t *interface) { + android_data_t *data = (android_data_t *)interface->data; + + jmethodID mid_terminate = + (*data->env)->GetStaticMethodID(data->env, data->cls, "terminate", "()I"); + if (mid_terminate) { + (*data->env) + ->CallStaticIntMethod(data->env, data->cls, mid_terminate, + &android_on_network_event, interface); + } + + (*data->env)->DeleteGlobalRef(data->env, data->cls); + + JavaVM *jvm = data->cfg.jvm; + if (data->attached_to_vm) { + (*jvm)->DetachCurrentThread(jvm); + data->attached_to_vm = false; + } + data->env = NULL; + + pthread_mutex_destroy(&data->mutex); + + // interface_unregister_fd(interface, data->fd); // XXX done in + // facemgr_delete_interface... + close(data->fd); + facelet_array_free(data->facelets); + + free(data); + + return 0; +} + +int android_callback(interface_t *interface, int fd, void *unused) { + android_data_t *data = (android_data_t *)interface->data; + + uint64_t ret; + if (read(data->fd, &ret, sizeof(ret)) < 0) return -1; + if (ret == 0) // EOF + return 0; + + pthread_mutex_lock(&data->mutex); + for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) { + facelet_t *facelet; + if (facelet_array_get_index(data->facelets, i, &facelet) < 0) { + ERROR("[android_callback] Error getting facelet in array"); + continue; + } + + interface_raise_event(interface, facelet); + } + + for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) { + if (facelet_array_remove_index(data->facelets, i, NULL) < 0) { + ERROR("[android_callback] Could not purge facelet from array"); + } + } + pthread_mutex_unlock(&data->mutex); + + return 0; +} + +const interface_ops_t android_ops = { + .type = "android", + .initialize = android_initialize, + .callback = android_callback, + .finalize = android_finalize, + .on_event = NULL, +}; diff --git a/ctrl/facemgr/src/interfaces/android/android.h b/ctrl/facemgr/src/interfaces/android/android.h new file mode 100644 index 000000000..319bfe10a --- /dev/null +++ b/ctrl/facemgr/src/interfaces/android/android.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 android/android.h + * \brief Android utility. + */ + +#ifndef FACEMGR_INTERFACE_ANDROID_H +#define FACEMGR_INTERFACE_ANDROID_H + +#ifdef __ANDROID__ + +#include <jni.h> +#include "../../interface.h" + +typedef struct { + JavaVM *jvm; +} android_cfg_t; + +int android_on_network_event(interface_t *interface, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address); + +#endif /* __ANDROID__ */ + +#endif /* FACEMGR_INTERFACE_ANDROID_H */ diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c deleted file mode 100644 index d8e20659a..000000000 --- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 interfaces/android_utility/android_utility.c - * \brief Implementation of Android utility. - */ - -#include <assert.h> - -#include <hicn/facemgr.h> -#include <hicn/ctrl/face.h> -#include <hicn/util/log.h> -#include "../../common.h" -#include "../../interface.h" - -#include "android_utility.h" - -#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" - - -#define AU_INTERFACE_TYPE_UNDEFINED 0 -#define AU_INTERFACE_TYPE_WIRED 1 -#define AU_INTERFACE_TYPE_WIFI 2 -#define AU_INTERFACE_TYPE_CELLULAR 3 -#define AU_INTERFACE_TYPE_LOOPBACK 4 -#define AU_INTERFACE_TYPE_UNAVAILABLE 5 - -#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration." - -typedef struct { - android_utility_cfg_t cfg; -} au_data_t; - -int au_initialize(interface_t * interface, void * cfg) -{ - au_data_t * data = malloc(sizeof(au_data_t)); - if (!data) - return -1; - interface->data = data; - - if (!cfg) - goto ERR_CFG; - - data->cfg = * (android_utility_cfg_t *) cfg; - - if (!data->cfg.jvm) - goto ERR_CFG; - - return 0; - -ERR_CFG: - fprintf(stderr, ERR_STR_JAVA); - return -1; -} - -int au_finalize(interface_t * interface) -{ - /* Nothing to do */ - return 0; -} - -int au_on_event(interface_t * interface, facelet_t * facelet) -{ - /* - * This function is responsible to annotate every face we receive with the - * correct interface type, based on the value returned by the Android - * utility shipped with the Android forwarder. - */ - au_data_t * data = (au_data_t*)interface->data; - - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) - return -1; - - JNIEnv *env; - JavaVM *jvm = data->cfg.jvm; - (*jvm)->AttachCurrentThread(jvm, &env, NULL); - jclass cls = (*env)->FindClass(env, FACEMGR_UTILITY_CLASS); - jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls, - "getNetworkType", "(Ljava/lang/String;)I"); - jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType, - (*env)->NewStringUTF(env, netdevice.name)); - - netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED; - switch(interface_type) { - case AU_INTERFACE_TYPE_UNDEFINED: - break; - case AU_INTERFACE_TYPE_WIRED: - netdevice_type = NETDEVICE_TYPE_WIRED; - break; - case AU_INTERFACE_TYPE_WIFI: - netdevice_type = NETDEVICE_TYPE_WIFI; - break; - case AU_INTERFACE_TYPE_CELLULAR: - netdevice_type = NETDEVICE_TYPE_CELLULAR; - break; - case AU_INTERFACE_TYPE_LOOPBACK: - netdevice_type = NETDEVICE_TYPE_LOOPBACK; - break; - default: - DEBUG("AU RETURNED ERROR"); - return -1; - } - - DEBUG("AU RETURNED %s : %s", netdevice.name, netdevice_type_str[netdevice_type]); - - facelet_t * facelet_new = facelet_create(); - facelet_set_netdevice(facelet_new, netdevice); - facelet_set_attr_clean(facelet_new); - facelet_set_netdevice_type(facelet_new, netdevice_type); - - facelet_set_event(facelet_new, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet_new); - - return 0; -} - -const interface_ops_t android_utility_ops = { - .type = "android_utility", - .initialize = au_initialize, - .finalize = au_finalize, - .callback = NULL, - .on_event = au_on_event, -}; diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h b/ctrl/facemgr/src/interfaces/android_utility/android_utility.h deleted file mode 100644 index 53adfedf6..000000000 --- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 android_utility/android_utility.h - * \brief Android utility. - * - * This class relies on a small utility wrapper shipped with the Android - * application to access to Java SDK APIs for information not available to - * native code. - * - * For instance, we currently don't have on Linux any mean to get the type - * associated to an interface, especially for cellular interfaces. WiFi and - * Bluetooth information is for instance available through specific netlink - * subsystems, or by means of a support library, but cellular detection mostly - * relies on heuristics based on interface names (eg. in network manager). - * - * Android ship a Radio Interface Layer (RIL) daemon that exposes a control - * socket to the Java API to control the radio layer, but there is no working - * code exploiting it and no proper documentation. - */ - -#ifndef FACEMGR_INTERFACE_ANDROID_UTILITY_H -#define FACEMGR_INTERFACE_ANDROID_UTILITY_H - -#ifdef __ANDROID__ - -#include <jni.h> - -typedef struct { - JavaVM *jvm; -} android_utility_cfg_t; - -#endif /* __ANDROID__ */ - -#endif /* FACEMGR_INTERFACE_ANDROID_UTILITY_H */ diff --git a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt index 8a0ddc888..90ca0e47f 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c index 40b7f5f90..e7de5d648 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,6 +25,7 @@ #include <hicn/facemgr.h> #include <hicn/util/log.h> #include <hicn/util/map.h> +#include <hicn/util/sstrncpy.h> #include "../../common.h" #include "../../interface.h" @@ -40,368 +41,358 @@ #define DEFAULT_SERVICE_DOMAIN "local" typedef struct { - bonjour_cfg_t cfg; - int sock; - size_t buffer_size; - void* buffer; + bonjour_cfg_t cfg; + int sock; + size_t buffer_size; + void* buffer; - /* The face being resolved, non-NULL values indicate interface is busy... */ - face_t * face; + /* The face being resolved, non-NULL values indicate interface is busy... */ + face_t* face; } bj_data_t; -int bj_initialize(interface_t * interface, void * cfg) -{ - bj_data_t * data = malloc(sizeof(bj_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; +int bj_initialize(interface_t* interface, void* cfg) { + bj_data_t* data = malloc(sizeof(bj_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; - if (cfg) { + if (cfg) { #ifndef __linux__ - if (cfg->netdevice) - WARN("Binding to interface is (currently) only supported on Linux"); + if (cfg->netdevice) + WARN("Binding to interface is (currently) only supported on Linux"); #endif /* ! __linux__ */ - data->cfg = * (bonjour_cfg_t *) cfg; - } else { - memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); - } + data->cfg = *(bonjour_cfg_t*)cfg; + } else { + memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); + } - if (!data->cfg.service_name) - data->cfg.service_name = DEFAULT_SERVICE_NAME; + if (!data->cfg.service_name) data->cfg.service_name = DEFAULT_SERVICE_NAME; - if (!data->cfg.service_protocol) - data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; + if (!data->cfg.service_protocol) + data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; - if (!data->cfg.service_domain) - data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; + if (!data->cfg.service_domain) + data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; - data->sock = mdns_socket_open_ipv4(); - if (data->sock < 0) { - printf("Failed to open socket: %s\n", strerror(errno)); - goto ERR_SOCK; - } + data->sock = mdns_socket_open_ipv4(); + if (data->sock < 0) { + printf("Failed to open socket: %s\n", strerror(errno)); + goto ERR_SOCK; + } - /* Netdevice configuration */ + /* Netdevice configuration */ #ifdef __linux__ #ifndef __ANDROID__ - if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { - int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, - &data->cfg.netdevice.name, strlen(data->cfg.netdevice.name) + 1); - if (rc == -1) { - ERROR("setsockopt"); - goto ERR_SOCK_OPT; - } + if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { + int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, + &data->cfg.netdevice.name, + strnlen_s(data->cfg.netdevice.name, IFNAMSIZ)); + if (rc == -1) { + ERROR("setsockopt"); + goto ERR_SOCK_OPT; } + } #endif #endif /* __linux__ */ - data->buffer_size = DEFAULT_BUFFER_SIZE; - data->buffer = malloc(data->buffer_size); - if (!data->buffer) - goto ERR_BUFFER; + data->buffer_size = DEFAULT_BUFFER_SIZE; + data->buffer = malloc(data->buffer_size); + if (!data->buffer) goto ERR_BUFFER; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - if (interface_register_fd(interface, data->sock, NULL) < 0) { - ERROR("[bj_initialize] Error registering fd"); - goto ERR_FD; - } + if (interface_register_fd(interface, data->sock, NULL) < 0) { + ERROR("[bj_initialize] Error registering fd"); + goto ERR_FD; + } - return 0; + return 0; ERR_FD: - free(data->buffer); + free(data->buffer); ERR_BUFFER: #ifndef __ANDROID__ ERR_SOCK_OPT: #endif - mdns_socket_close(data->sock); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif ERR_SOCK: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } /* * We reuse the callback to be triggered upon external events * TODO: move to a cleaner interface architecture later... */ -int bj_on_event(interface_t * interface, facelet_t * facelet) -{ - bj_data_t * data = (bj_data_t*)interface->data; - - /* - printf("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - printf("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - DEBUG("Sending mDNS query"); - char service_string[SERVICE_STRING_SIZE]; - - int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", - data->cfg.service_name, data->cfg.service_protocol, - data->cfg.service_domain); - if (rc < 0) - ; // error - else if (rc >= SERVICE_STRING_SIZE) - ; //truncated - - if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, - service_string, - strlen(service_string), - data->buffer, data->buffer_size)) { - printf("Failed to send mDNS query: %s\n", strerror(errno)); - return -1; - } - return 0; +int bj_on_event(interface_t* interface, facelet_t* facelet) { + bj_data_t* data = (bj_data_t*)interface->data; + + /* + printf("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); + goto quit; + } + + printf("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, callback, + user_data); + sleep(1); + } + */ + + DEBUG("Sending mDNS query"); + char service_string[SERVICE_STRING_SIZE]; + + int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", + data->cfg.service_name, data->cfg.service_protocol, + data->cfg.service_domain); + if (rc < 0) + ; // error + else if (rc >= SERVICE_STRING_SIZE) + ; // truncated + + if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, service_string, + strnlen_s(service_string, SERVICE_STRING_SIZE), + data->buffer, data->buffer_size)) { + printf("Failed to send mDNS query: %s\n", strerror(errno)); + return -1; + } + return 0; } static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t hicn_ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -int -ip_address_set_sockaddr(ip_address_t * ip_address, struct sockaddr * sa) -{ - switch(sa->sa_family) { - case AF_INET: - ip_address->v4.as_inaddr = ((struct sockaddr_in *)sa)->sin_addr; - break; - case AF_INET6: - ip_address->v6.as_in6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; - break; - default: - return -1; - } - - return 0; +int hicn_ip_address_set_sockaddr(hicn_ip_address_t* ip_address, + struct sockaddr* sa) { + switch (sa->sa_family) { + case AF_INET: + ip_address->v4.as_inaddr = ((struct sockaddr_in*)sa)->sin_addr; + break; + case AF_INET6: + ip_address->v6.as_in6addr = ((struct sockaddr_in6*)sa)->sin6_addr; + break; + default: + return -1; + } + + return 0; } -static int -callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, const void* data, size_t size, size_t - offset, size_t length, void* user_data) -{ - interface_t * interface = (interface_t*)user_data; - bj_data_t * bj_data = (bj_data_t *)interface->data; - - struct sockaddr_storage addr; - - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - - switch(type) { - case MDNS_RECORDTYPE_A: - { - ip_address_t ip_address; - mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), (struct sockaddr_in *)&addr); - DEBUG("%.*s : %s A %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + interface_t* interface = (interface_t*)user_data; + bj_data_t* bj_data = (bj_data_t*)interface->data; + + struct sockaddr_storage addr; + + mdns_string_t fromaddrstr = + hicn_ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + + switch (type) { + case MDNS_RECORDTYPE_A: { + hicn_ip_address_t ip_address; + mdns_record_parse_a(data, size, offset, length, + (struct sockaddr_in*)&addr); + hicn_ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv4_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in*)&addr); + DEBUG("%.*s : %s A %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in*)&addr)->sin_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_AAAA: - { - ip_address_t ip_address; - mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, - sizeof(namebuffer), (struct sockaddr_in6*)&addr); - DEBUG("%.*s : %s AAAA %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_AAAA: { + hicn_ip_address_t ip_address; + mdns_record_parse_aaaa(data, size, offset, length, + (struct sockaddr_in6*)&addr); + hicn_ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv6_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in6*)&addr); + DEBUG("%.*s : %s AAAA %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in6*)&addr)->sin6_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ - { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - - DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - - /* We raise both v4 and v6 - * - * Unless we choose whether we query A and/or AAAA, this might leave - * us with an unused pending facelet, eg. we might not have an IPv6 - * but we raise an IPv6 bonjour event... - */ - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - - facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ + { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + + DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + + /* We raise both v4 and v6 + * + * Unless we choose whether we query A and/or AAAA, this might leave + * us with an unused pending facelet, eg. we might not have an IPv6 + * but we raise an IPv6 bonjour event... + */ + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + + facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_PTR: - { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - break; - } + case MDNS_RECORDTYPE_PTR: { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + break; + } - case MDNS_RECORDTYPE_TXT: - { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - DEBUG("%.*s : %s TXT %.*s = %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - DEBUG("%.*s : %s TXT %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - break; + case MDNS_RECORDTYPE_TXT: { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + DEBUG("%.*s : %s TXT %.*s = %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + DEBUG("%.*s : %s TXT %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key)); } - - default: - /* Silently ignore the received record */ - DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - return 0; + } + break; } - return 0; + default: + /* Silently ignore the received record */ + DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + return 0; + } + return 0; } /* * The fact we use a single fd does not allow us to get user_data associated to * the query. */ -int bj_callback(interface_t * interface, int fd, void * unused) -{ - bj_data_t * data = (bj_data_t*)interface->data; - DEBUG("Got an mDNS reply"); - /* size_t records = */ mdns_query_recv(data->sock, data->buffer, data->buffer_size, callback, interface, 1); +int bj_callback(interface_t* interface, int fd, void* unused) { + bj_data_t* data = (bj_data_t*)interface->data; + DEBUG("Got an mDNS reply"); + /* size_t records = */ mdns_query_recv( + data->sock, data->buffer, data->buffer_size, callback, interface, 1); - return 0; + return 0; } -int bj_finalize(interface_t * interface) -{ - bj_data_t * data = (bj_data_t*)interface->data; +int bj_finalize(interface_t* interface) { + bj_data_t* data = (bj_data_t*)interface->data; - free(data->buffer); - mdns_socket_close(data->sock); + free(data->buffer); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; - + return 0; } const interface_ops_t bonjour_ops = { @@ -410,5 +401,5 @@ const interface_ops_t bonjour_ops = { .on_event = bj_on_event, .callback = bj_callback, .finalize = bj_finalize, - // .on_event = NULL, + // .on_event = NULL, }; diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h index fe053079d..6458423ea 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,11 +25,11 @@ * queries... */ -#include <hicn/ctrl/face.h> /* netdevice_t */ +#include <hicn/face.h> /* netdevice_t */ typedef struct { - netdevice_t netdevice; - char * service_name; - char * service_protocol; - char * service_domain; + netdevice_t netdevice; + char* service_name; + char* service_protocol; + char* service_domain; } bonjour_cfg_t; diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c index a8e97e8e0..e2bb4f432 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c @@ -1,6 +1,6 @@ #ifdef _WIN32 -# define _CRT_SECURE_NO_WARNINGS 1 +#define _CRT_SECURE_NO_WARNINGS 1 #endif #include "mdns.h" @@ -9,184 +9,176 @@ #include <errno.h> #ifdef _WIN32 -# define sleep(x) Sleep(x * 1000) +#define sleep(x) Sleep(x * 1000) #else -# include <netdb.h> +#include <netdb.h> #endif static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -static int -callback(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data) { - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - if (type == MDNS_RECORDTYPE_PTR) { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - } - else if (type == MDNS_RECORDTYPE_SRV) { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - } - else if (type == MDNS_RECORDTYPE_A) { - struct sockaddr_in addr; - mdns_record_parse_a(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s A %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_AAAA) { - struct sockaddr_in6 addr; - mdns_record_parse_aaaa(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s AAAA %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_TXT) { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - INFO("%.*s : %s TXT %.*s = %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - INFO("%.*s : %s TXT %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - } - else { - INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - } - return 0; +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + mdns_string_t fromaddrstr = + ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + if (type == MDNS_RECORDTYPE_PTR) { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + } else if (type == MDNS_RECORDTYPE_SRV) { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + } else if (type == MDNS_RECORDTYPE_A) { + struct sockaddr_in addr; + mdns_record_parse_a(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s A %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_AAAA) { + struct sockaddr_in6 addr; + mdns_record_parse_aaaa(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s AAAA %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_TXT) { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + INFO("%.*s : %s TXT %.*s = %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + INFO("%.*s : %s TXT %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(txtbuffer[itxt].key)); + } + } + } else { + INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + } + return 0; } -int -main() { - size_t capacity = 2048; - void* buffer = 0; - void* user_data = 0; - size_t records; +int main() { + size_t capacity = 2048; + void* buffer = 0; + void* user_data = 0; + size_t records; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - int sock = mdns_socket_open_ipv4(); - if (sock < 0) { - INFO("Failed to open socket: %s\n", strerror(errno)); - return -1; - } - INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); - buffer = malloc(capacity); -/* - INFO("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - INFO("Sending mDNS query\n"); - if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, - MDNS_STRING_CONST("_hicn._udp.local."), - buffer, capacity)) { - INFO("Failed to send mDNS query: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading mDNS replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); - sleep(1); - } + int sock = mdns_socket_open_ipv4(); + if (sock < 0) { + INFO("Failed to open socket: %s\n", strerror(errno)); + return -1; + } + INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); + buffer = malloc(capacity); + /* + INFO("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + INFO("Failed to send DNS-DS discovery: %s\n", + strerror(errno)); goto quit; + } + + INFO("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, + callback, user_data); sleep(1); + } + */ + + INFO("Sending mDNS query\n"); + if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, + MDNS_STRING_CONST("_hicn._udp.local."), buffer, + capacity)) { + INFO("Failed to send mDNS query: %s\n", strerror(errno)); + goto quit; + } + + INFO("Reading mDNS replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); + sleep(1); + } quit: - free(buffer); + free(buffer); - mdns_socket_close(sock); - INFO("Closed socket\n"); + mdns_socket_close(sock); + INFO("Closed socket\n"); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; + return 0; } diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h index ff04b5d72..4b8e7a7f4 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h @@ -7,7 +7,8 @@ * * https://github.com/mjansson/mdns * - * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * This library is put in the public domain; you can redistribute it and/or + * modify it without any restrictions. * */ @@ -31,76 +32,73 @@ #define MDNS_INVALID_POS ((size_t)-1) -#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1) +#define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1) #define MDNS_STRING_FORMAT(s) (int)((s).length), s.str enum mdns_record_type { - MDNS_RECORDTYPE_IGNORE = 0, - //Address - MDNS_RECORDTYPE_A = 1, - //Domain Name pointer - MDNS_RECORDTYPE_PTR = 12, - //Arbitrary text string - MDNS_RECORDTYPE_TXT = 16, - //IP6 Address [Thomson] - MDNS_RECORDTYPE_AAAA = 28, - //Server Selection [RFC2782] - MDNS_RECORDTYPE_SRV = 33 + MDNS_RECORDTYPE_IGNORE = 0, + // Address + MDNS_RECORDTYPE_A = 1, + // Domain Name pointer + MDNS_RECORDTYPE_PTR = 12, + // Arbitrary text string + MDNS_RECORDTYPE_TXT = 16, + // IP6 Address [Thomson] + MDNS_RECORDTYPE_AAAA = 28, + // Server Selection [RFC2782] + MDNS_RECORDTYPE_SRV = 33 }; enum mdns_entry_type { - MDNS_ENTRYTYPE_ANSWER = 1, - MDNS_ENTRYTYPE_AUTHORITY = 2, - MDNS_ENTRYTYPE_ADDITIONAL = 3 + MDNS_ENTRYTYPE_ANSWER = 1, + MDNS_ENTRYTYPE_AUTHORITY = 2, + MDNS_ENTRYTYPE_ADDITIONAL = 3 }; -enum mdns_class { - MDNS_CLASS_IN = 1 -}; +enum mdns_class { MDNS_CLASS_IN = 1 }; -typedef enum mdns_record_type mdns_record_type_t; -typedef enum mdns_entry_type mdns_entry_type_t; -typedef enum mdns_class mdns_class_t; +typedef enum mdns_record_type mdns_record_type_t; +typedef enum mdns_entry_type mdns_entry_type_t; +typedef enum mdns_class mdns_class_t; -typedef int (* mdns_record_callback_fn)(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data); +typedef int (*mdns_record_callback_fn)(const struct sockaddr* from, + mdns_entry_type_t entry, uint16_t type, + uint16_t rclass, uint32_t ttl, + const void* data, size_t size, + size_t offset, size_t length, + void* user_data); -typedef struct mdns_string_t mdns_string_t; -typedef struct mdns_string_pair_t mdns_string_pair_t; -typedef struct mdns_record_srv_t mdns_record_srv_t; -typedef struct mdns_record_txt_t mdns_record_txt_t; +typedef struct mdns_string_t mdns_string_t; +typedef struct mdns_string_pair_t mdns_string_pair_t; +typedef struct mdns_record_srv_t mdns_record_srv_t; +typedef struct mdns_record_txt_t mdns_record_txt_t; struct mdns_string_t { - const char* str; - size_t length; + const char* str; + size_t length; }; struct mdns_string_pair_t { - size_t offset; - size_t length; - int ref; + size_t offset; + size_t length; + int ref; }; struct mdns_record_srv_t { - uint16_t priority; - uint16_t weight; - uint16_t port; - mdns_string_t name; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_string_t name; }; struct mdns_record_txt_t { - mdns_string_t key; - mdns_string_t value; + mdns_string_t key; + mdns_string_t value; }; -static int -mdns_socket_open_ipv4(void); +static int mdns_socket_open_ipv4(void); -static int -mdns_socket_setup_ipv4(int sock); +static int mdns_socket_setup_ipv4(int sock); #if 0 static int @@ -112,8 +110,7 @@ static int mdns_socket_setup_ipv6(int sock); #endif -static void -mdns_socket_close(int sock); +static void mdns_socket_close(int sock); #if 0 static int @@ -125,21 +122,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callback_fn callback, void* user_data); #endif -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity); +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity); -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot); +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot); -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity); +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity); -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset); +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset); #if 0 static int @@ -147,78 +141,80 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs); #endif -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length); +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length); -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity); -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity); -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr); +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr); -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr); +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr); -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity); +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity); // Implementations -static int -mdns_socket_open_ipv4(void) { - int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - return -1; - if (mdns_socket_setup_ipv4(sock)) { - mdns_socket_close(sock); - return -1; - } - return sock; +static int mdns_socket_open_ipv4(void) { + int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) return -1; + if (mdns_socket_setup_ipv4(sock)) { + mdns_socket_close(sock); + return -1; + } + return sock; } -static int -mdns_socket_setup_ipv4(int sock) { - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = INADDR_ANY; +static int mdns_socket_setup_ipv4(int sock) { + struct sockaddr_in saddr; + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; #ifdef __APPLE__ - saddr.sin_len = sizeof(saddr); + saddr.sin_len = sizeof(saddr); #endif - if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) - return -1; + if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) return -1; #ifdef _WIN32 - unsigned long param = 1; - ioctlsocket(sock, FIONBIO, ¶m); + unsigned long param = 1; + ioctlsocket(sock, FIONBIO, ¶m); #else - const int flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + const int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); #endif - unsigned char ttl = 1; - unsigned char loopback = 1; - struct ip_mreq req; + unsigned char ttl = 1; + unsigned char loopback = 1; + struct ip_mreq req; - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, + sizeof(ttl)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, + sizeof(loopback)); - memset(&req, 0, sizeof(req)); - req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - req.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) - return -1; + memset(&req, 0, sizeof(req)); + req.imr_multiaddr.s_addr = + htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + req.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) + return -1; - return 0; + return 0; } #if 0 @@ -274,67 +270,58 @@ mdns_socket_setup_ipv6(int sock) { } #endif -static void -mdns_socket_close(int sock) { +static void mdns_socket_close(int sock) { #ifdef _WIN32 - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif } -static int -mdns_is_string_ref(uint8_t val) { - return (0xC0 == (val & 0xC0)); -} +static int mdns_is_string_ref(uint8_t val) { return (0xC0 == (val & 0xC0)); } -static mdns_string_pair_t -mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) { - const uint8_t* buffer = rawdata; - mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; - if (!buffer[offset]) { - pair.offset = offset; - return pair; - } - if (mdns_is_string_ref(buffer[offset])) { - if (size < offset + 2) - return pair; +static mdns_string_pair_t mdns_get_next_substring(const void* rawdata, + size_t size, size_t offset) { + const uint8_t* buffer = rawdata; + mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; + if (!buffer[offset]) { + pair.offset = offset; + return pair; + } + if (mdns_is_string_ref(buffer[offset])) { + if (size < offset + 2) return pair; - offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); - if (offset >= size) - return pair; + offset = + (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); + if (offset >= size) return pair; - pair.ref = 1; - } + pair.ref = 1; + } - size_t length = (size_t)buffer[offset++]; - if (size < offset + length) - return pair; + size_t length = (size_t)buffer[offset++]; + if (size < offset + length) return pair; - pair.offset = offset; - pair.length = length; + pair.offset = offset; + pair.length = length; - return pair; + return pair; } -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset) { - size_t cur = *offset; - mdns_string_pair_t substr; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return 0; - if (substr.ref) { - *offset = cur + 2; - return 1; - } - cur = substr.offset + substr.length; - } - while (substr.length); - - *offset = cur + 1; - return 1; +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset) { + size_t cur = *offset; + mdns_string_pair_t substr; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return 0; + if (substr.ref) { + *offset = cur + 2; + return 1; + } + cur = substr.offset + substr.length; + } while (substr.length); + + *offset = cur + 1; + return 1; } #if 0 @@ -378,142 +365,133 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, } #endif -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity) { - size_t cur = *offset; - size_t end = MDNS_INVALID_POS; - mdns_string_pair_t substr; - mdns_string_t result = {str, 0}; - char* dst = str; - size_t remain = capacity; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return result; - if (substr.ref && (end == MDNS_INVALID_POS)) - end = cur + 2; - if (substr.length) { - size_t to_copy = (substr.length < remain) ? substr.length : remain; - memcpy(dst, (const char*)buffer + substr.offset, to_copy); - dst += to_copy; - remain -= to_copy; - if (remain) { - *dst++ = '.'; - --remain; - } - } - cur = substr.offset + substr.length; - } - while (substr.length); - - if (end == MDNS_INVALID_POS) - end = cur + 1; - *offset = end; - - result.length = capacity - remain; - return result; +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity) { + size_t cur = *offset; + size_t end = MDNS_INVALID_POS; + mdns_string_pair_t substr; + mdns_string_t result = {str, 0}; + char* dst = str; + size_t remain = capacity; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return result; + if (substr.ref && (end == MDNS_INVALID_POS)) end = cur + 2; + if (substr.length) { + size_t to_copy = (substr.length < remain) ? substr.length : remain; + memcpy(dst, (const char*)buffer + substr.offset, to_copy); + dst += to_copy; + remain -= to_copy; + if (remain) { + *dst++ = '.'; + --remain; + } + } + cur = substr.offset + substr.length; + } while (substr.length); + + if (end == MDNS_INVALID_POS) end = cur + 1; + *offset = end; + + result.length = capacity - remain; + return result; } -static size_t -mdns_string_find(const char* str, size_t length, char c, size_t offset) { - const void* found; - if (offset >= length) - return MDNS_INVALID_POS; - found = memchr(str + offset, c, length - offset); - if (found) - return (size_t)((const char*)found - str); - return MDNS_INVALID_POS; +static size_t mdns_string_find(const char* str, size_t length, char c, + size_t offset) { + const void* found; + if (offset >= length) return MDNS_INVALID_POS; + found = memchr(str + offset, c, length - offset); + if (found) return (size_t)((const char*)found - str); + return MDNS_INVALID_POS; } -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length) { - size_t pos = 0; - size_t last_pos = 0; - size_t remain = capacity; - unsigned char* dest = data; - while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) { - size_t sublength = pos - last_pos; - if (sublength < remain) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - last_pos = pos + 1; - } - if (last_pos < length) { - size_t sublength = length - last_pos; - if (sublength < capacity) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - } - if (!remain) - return 0; - *dest++ = 0; - return dest; +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length) { + size_t pos = 0; + size_t last_pos = 0; + size_t remain = capacity; + unsigned char* dest = data; + while ((last_pos < length) && + ((pos = mdns_string_find(name, length, '.', last_pos)) != + MDNS_INVALID_POS)) { + size_t sublength = pos - last_pos; + if (sublength < remain) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + last_pos = pos + 1; + } + if (last_pos < length) { + size_t sublength = length - last_pos; + if (sublength < capacity) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + } + if (!remain) return 0; + *dest++ = 0; + return dest; } -static size_t -mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset, - mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback, - void* user_data) { - size_t parsed = 0; - int do_callback = 1; - for (size_t i = 0; i < records; ++i) { - mdns_string_skip(buffer, size, offset); - const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); - - uint16_t rtype = ntohs(*data++); - uint16_t rclass = ntohs(*data++); - uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2; - uint16_t length = ntohs(*data++); - - *offset += 10; - - if (do_callback) { - ++parsed; - if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length, - user_data)) - do_callback = 0; - } - - *offset += length; - } - return parsed; +static size_t mdns_records_parse(const struct sockaddr* from, + const void* buffer, size_t size, + size_t* offset, mdns_entry_type_t type, + size_t records, + mdns_record_callback_fn callback, + void* user_data) { + size_t parsed = 0; + int do_callback = 1; + for (size_t i = 0; i < records; ++i) { + mdns_string_skip(buffer, size, offset); + const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); + + uint16_t rtype = ntohs(*data++); + uint16_t rclass = ntohs(*data++); + uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); + data += 2; + uint16_t length = ntohs(*data++); + + *offset += 10; + + if (do_callback) { + ++parsed; + if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, + length, user_data)) + do_callback = 0; + } + + *offset += length; + } + return parsed; } static const uint8_t mdns_services_query[] = { - // Transaction ID - 0x00, 0x00, - // Flags - 0x00, 0x00, - // 1 question - 0x00, 0x01, - // No answer, authority or additional RRs - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - // _services._dns-sd._udp.local. - 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', - 0x07, '_', 'd', 'n', 's', '-', 's', 'd', - 0x04, '_', 'u', 'd', 'p', - 0x05, 'l', 'o', 'c', 'a', 'l', - 0x00, - // PTR record - 0x00, MDNS_RECORDTYPE_PTR, - // QU (unicast response) and class IN - 0x80, MDNS_CLASS_IN -}; + // Transaction ID + 0x00, 0x00, + // Flags + 0x00, 0x00, + // 1 question + 0x00, 0x01, + // No answer, authority or additional RRs + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // _services._dns-sd._udp.local. + 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', 0x07, '_', 'd', 'n', 's', + '-', 's', 'd', 0x04, '_', 'u', 'd', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + // PTR record + 0x00, MDNS_RECORDTYPE_PTR, + // QU (unicast response) and class IN + 0x80, MDNS_CLASS_IN}; #if 0 static int @@ -645,233 +623,223 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, static uint16_t mdns_transaction_id = 0; -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity) { - if (capacity < (17 + length)) - return -1; - - uint16_t* data = buffer; - //Transaction ID - *data++ = htons(++mdns_transaction_id); - //Flags - *data++ = 0; - //Questions - *data++ = htons(1); - //No answer, authority or additional RRs - *data++ = 0; - *data++ = 0; - *data++ = 0; - //Name string - data = mdns_string_make(data, capacity - 17, name, length); - if (!data) - return -1; - //Record type - *data++ = htons(type); - //! Unicast response, class IN - *data++ = htons(0x8000U | MDNS_CLASS_IN); - - struct sockaddr_storage addr_storage; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - struct sockaddr* saddr = (struct sockaddr*)&addr_storage; - socklen_t saddrlen = sizeof(struct sockaddr_storage); - if (getsockname(sock, saddr, &saddrlen)) - return -1; - if (saddr->sa_family == AF_INET6) { - memset(&addr6, 0, sizeof(struct sockaddr_in6)); - addr6.sin6_family = AF_INET6; +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity) { + if (capacity < (17 + length)) return -1; + + uint16_t* data = buffer; + // Transaction ID + *data++ = htons(++mdns_transaction_id); + // Flags + *data++ = 0; + // Questions + *data++ = htons(1); + // No answer, authority or additional RRs + *data++ = 0; + *data++ = 0; + *data++ = 0; + // Name string + data = mdns_string_make(data, capacity - 17, name, length); + if (!data) return -1; + // Record type + *data++ = htons(type); + //! Unicast response, class IN + *data++ = htons(0x8000U | MDNS_CLASS_IN); + + struct sockaddr_storage addr_storage; + struct sockaddr_in addr; + struct sockaddr_in6 addr6; + struct sockaddr* saddr = (struct sockaddr*)&addr_storage; + socklen_t saddrlen = sizeof(struct sockaddr_storage); + if (getsockname(sock, saddr, &saddrlen)) return -1; + if (saddr->sa_family == AF_INET6) { + memset(&addr6, 0, sizeof(struct sockaddr_in6)); + addr6.sin6_family = AF_INET6; #ifdef __APPLE__ - addr6.sin6_len = sizeof(struct sockaddr_in6); + addr6.sin6_len = sizeof(struct sockaddr_in6); #endif - addr6.sin6_addr.s6_addr[0] = 0xFF; - addr6.sin6_addr.s6_addr[1] = 0x02; - addr6.sin6_addr.s6_addr[15] = 0xFB; - addr6.sin6_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr6; - saddrlen = sizeof(struct sockaddr_in6); - } - else { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; + addr6.sin6_addr.s6_addr[0] = 0xFF; + addr6.sin6_addr.s6_addr[1] = 0x02; + addr6.sin6_addr.s6_addr[15] = 0xFB; + addr6.sin6_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr6; + saddrlen = sizeof(struct sockaddr_in6); + } else { + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; #ifdef __APPLE__ - addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - addr.sin_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr; - saddrlen = sizeof(struct sockaddr_in); - } - - if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, - saddr, saddrlen) < 0) - return -1; - return 0; + addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + addr.sin_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr; + saddrlen = sizeof(struct sockaddr_in); + } + + if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, saddr, saddrlen) < 0) + return -1; + return 0; } -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot) { - struct sockaddr_in6 addr; - struct sockaddr* saddr = (struct sockaddr*)&addr; - memset(&addr, 0, sizeof(addr)); - saddr->sa_family = AF_INET; +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot) { + struct sockaddr_in6 addr; + struct sockaddr* saddr = (struct sockaddr*)&addr; + memset(&addr, 0, sizeof(addr)); + saddr->sa_family = AF_INET; #ifdef __APPLE__ - saddr->sa_len = sizeof(addr); + saddr->sa_len = sizeof(addr); #endif - socklen_t addrlen = sizeof(addr); - int ret = recvfrom(sock, buffer, capacity, 0, - saddr, &addrlen); - if (ret <= 0) - return 0; - - size_t data_size = (size_t)ret; - uint16_t* data = (uint16_t*)buffer; - - uint16_t transaction_id = ntohs(*data++); - ++data;// uint16_t flags = ntohs(*data++); - uint16_t questions = ntohs(*data++); - uint16_t answer_rrs = ntohs(*data++); - uint16_t authority_rrs = ntohs(*data++); - uint16_t additional_rrs = ntohs(*data++); - - if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400)) - return 0; //Not a reply to our last question - - if (questions > 1) - return 0; - - //Skip questions part - int i; - for (i = 0; i < questions; ++i) { - size_t ofs = (size_t)((char*)data - (char*)buffer); - if (!mdns_string_skip(buffer, data_size, &ofs)) - return 0; - data = (void*)((char*)buffer + ofs); - ++data; - ++data; - } - - size_t records = 0; - size_t offset = (size_t)((char*)data - (char*)buffer); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ANSWER, answer_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, - callback, user_data); - return records; + socklen_t addrlen = sizeof(addr); + int ret = recvfrom(sock, buffer, capacity, 0, saddr, &addrlen); + if (ret <= 0) return 0; + + size_t data_size = (size_t)ret; + uint16_t* data = (uint16_t*)buffer; + + uint16_t transaction_id = ntohs(*data++); + ++data; // uint16_t flags = ntohs(*data++); + uint16_t questions = ntohs(*data++); + uint16_t answer_rrs = ntohs(*data++); + uint16_t authority_rrs = ntohs(*data++); + uint16_t additional_rrs = ntohs(*data++); + + if (one_shot && + transaction_id != mdns_transaction_id) // || (flags != 0x8400)) + return 0; // Not a reply to our last question + + if (questions > 1) return 0; + + // Skip questions part + int i; + for (i = 0; i < questions; ++i) { + size_t ofs = (size_t)((char*)data - (char*)buffer); + if (!mdns_string_skip(buffer, data_size, &ofs)) return 0; + data = (void*)((char*)buffer + ofs); + ++data; + ++data; + } + + size_t records = 0; + size_t offset = (size_t)((char*)data - (char*)buffer); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ANSWER, answer_rrs, callback, + user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, + callback, user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, + callback, user_data); + return records; } -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - //PTR record is just a string - if ((size >= offset + length) && (length >= 2)) - return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - mdns_string_t empty = {0, 0}; - return empty; +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity) { + // PTR record is just a string + if ((size >= offset + length) && (length >= 2)) + return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + mdns_string_t empty = {0, 0}; + return empty; } -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - mdns_record_srv_t srv; - memset(&srv, 0, sizeof(mdns_record_srv_t)); - // Read the priority, weight, port number and the discovery name - // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): - // 2 bytes network-order unsigned priority - // 2 bytes network-order unsigned weight - // 2 bytes network-order unsigned port - // string: discovery (domain) name, minimum 2 bytes when compressed - if ((size >= offset + length) && (length >= 8)) { - const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset); - srv.priority = ntohs(*recorddata++); - srv.weight = ntohs(*recorddata++); - srv.port = ntohs(*recorddata++); - offset += 6; - srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - } - return srv; +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity) { + mdns_record_srv_t srv; + memset(&srv, 0, sizeof(mdns_record_srv_t)); + // Read the priority, weight, port number and the discovery name + // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): + // 2 bytes network-order unsigned priority + // 2 bytes network-order unsigned weight + // 2 bytes network-order unsigned port + // string: discovery (domain) name, minimum 2 bytes when compressed + if ((size >= offset + length) && (length >= 8)) { + const uint16_t* recorddata = + (const uint16_t*)((const char*)buffer + offset); + srv.priority = ntohs(*recorddata++); + srv.weight = ntohs(*recorddata++); + srv.port = ntohs(*recorddata++); + offset += 6; + srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + } + return srv; } -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr) { - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr) { + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; #ifdef __APPLE__ - addr->sin_len = sizeof(struct sockaddr_in); + addr->sin_len = sizeof(struct sockaddr_in); #endif - if ((size >= offset + length) && (length == 4)) - addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 4)) + addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); + return addr; } -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr) { - memset(addr, 0, sizeof(struct sockaddr_in6)); - addr->sin6_family = AF_INET6; +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr) { + memset(addr, 0, sizeof(struct sockaddr_in6)); + addr->sin6_family = AF_INET6; #ifdef __APPLE__ - addr->sin6_len = sizeof(struct sockaddr_in6); + addr->sin6_len = sizeof(struct sockaddr_in6); #endif - if ((size >= offset + length) && (length == 16)) - addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 16)) + addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); + return addr; } -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity) { - size_t parsed = 0; - const char* strdata; - size_t separator, sublength; - size_t end = offset + length; - - if (size < end) - end = size; - - while ((offset < end) && (parsed < capacity)) { - strdata = (const char*)buffer + offset; - sublength = *(const unsigned char*)strdata; - - ++strdata; - offset += sublength + 1; - - separator = 0; - for (size_t c = 0; c < sublength; ++c) { - //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] - if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) - break; - if (strdata[c] == '=') { - separator = c; - break; - } - } - - if (!separator) - continue; - - if (separator < sublength) { - records[parsed].key.str = strdata; - records[parsed].key.length = separator; - records[parsed].value.str = strdata + separator + 1; - records[parsed].value.length = sublength - (separator + 1); - } - else { - records[parsed].key.str = strdata; - records[parsed].key.length = sublength; - } - - ++parsed; - } - - return parsed; +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity) { + size_t parsed = 0; + const char* strdata; + size_t separator, sublength; + size_t end = offset + length; + + if (size < end) end = size; + + while ((offset < end) && (parsed < capacity)) { + strdata = (const char*)buffer + offset; + sublength = *(const unsigned char*)strdata; + + ++strdata; + offset += sublength + 1; + + separator = 0; + for (size_t c = 0; c < sublength; ++c) { + // DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] + if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) break; + if (strdata[c] == '=') { + separator = c; + break; + } + } + + if (!separator) continue; + + if (separator < sublength) { + records[parsed].key.str = strdata; + records[parsed].key.length = separator; + records[parsed].value.str = strdata + separator + 1; + records[parsed].value.length = sublength - (separator + 1); + } else { + records[parsed].key.str = strdata; + records[parsed].key.length = sublength; + } + + ++parsed; + } + + return parsed; } #ifdef _WIN32 diff --git a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt index 05276bc5a..c68c39273 100644 --- a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.c b/ctrl/facemgr/src/interfaces/dummy/dummy.c index 69c336e57..df63eef17 100644 --- a/ctrl/facemgr/src/interfaces/dummy/dummy.c +++ b/ctrl/facemgr/src/interfaces/dummy/dummy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -19,7 +19,7 @@ */ #include <stdlib.h> -#include <unistd.h> // close +#include <unistd.h> // close #include <hicn/facemgr.h> @@ -36,34 +36,32 @@ * Internal data */ typedef struct { - /* The configuration data will likely be allocated on the stack (or should - * be freed) by the caller, we recommend to make a copy of this data. - * This copy can further be altered with default values. - */ - dummy_cfg_t cfg; + /* The configuration data will likely be allocated on the stack (or should + * be freed) by the caller, we recommend to make a copy of this data. + * This copy can further be altered with default values. + */ + dummy_cfg_t cfg; - /* ... */ + /* ... */ - int fd; /* Sample internal data: file descriptor */ + int fd; /* Sample internal data: file descriptor */ } dummy_data_t; -int dummy_initialize(interface_t * interface, void * cfg) -{ - dummy_data_t * data = malloc(sizeof(dummy_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; - - /* Use default values for unspecified configuration parameters */ - if (cfg) { - data->cfg = *(dummy_cfg_t *)cfg; - } else { - memset(&data->cfg, 0, sizeof(data->cfg)); - } +int dummy_initialize(interface_t *interface, void *cfg) { + dummy_data_t *data = malloc(sizeof(dummy_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + /* Use default values for unspecified configuration parameters */ + if (cfg) { + data->cfg = *(dummy_cfg_t *)cfg; + } else { + memset(&data->cfg, 0, sizeof(data->cfg)); + } - /* ... */ + /* ... */ - data->fd = 0; + data->fd = 0; #if 0 if (interface_register_fd(interface, data->fd, NULL) < 0) { ERROR("[dummy_initialize] Error registering fd"); @@ -71,49 +69,45 @@ int dummy_initialize(interface_t * interface, void * cfg) } #endif - /* ... */ + /* ... */ - /* - * We should return a negative value in case of error, and a positive value - * otherwise: - * - a file descriptor (>0) will be added to the event loop; or - * - 0 if we don't use any file descriptor - */ - return 0; + /* + * We should return a negative value in case of error, and a positive value + * otherwise: + * - a file descriptor (>0) will be added to the event loop; or + * - 0 if we don't use any file descriptor + */ + return 0; ERR_FD: ERR_MALLOC: - return -1; + return -1; } -int dummy_finalize(interface_t * interface) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; +int dummy_finalize(interface_t *interface) { + dummy_data_t *data = (dummy_data_t *)interface->data; - if (data->fd > 0) - close(data->fd); + if (data->fd > 0) close(data->fd); - return 0; + return 0; } -int dummy_callback(interface_t * interface) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; - UNUSED(data); +int dummy_callback(interface_t *interface) { + dummy_data_t *data = (dummy_data_t *)interface->data; + UNUSED(data); - /* ... */ + /* ... */ - return 0; + return 0; } -int dummy_on_event(interface_t * interface, facelet_t * facelet) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; - UNUSED(data); +int dummy_on_event(interface_t *interface, facelet_t *facelet) { + dummy_data_t *data = (dummy_data_t *)interface->data; + UNUSED(data); - /* ... */ + /* ... */ - return 0; + return 0; } interface_ops_t dummy_ops = { diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.h b/ctrl/facemgr/src/interfaces/dummy/dummy.h index 22fe5d1a6..f930ead58 100644 --- a/ctrl/facemgr/src/interfaces/dummy/dummy.h +++ b/ctrl/facemgr/src/interfaces/dummy/dummy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -28,7 +28,7 @@ * Configuration data */ typedef struct { - /* ... */ + /* ... */ } dummy_cfg_t; #endif /* FACEMGR_INTERFACE_DUMMY_H */ diff --git a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt index ef839a69c..a0fb3e351 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,20 +11,23 @@ # See the License for the specific language governing permissions and # limitations under the License. + +############################################################## +# Sources +############################################################## list(APPEND HEADER_FILES ) list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c ) list(APPEND LIBRARIES - ${HICNCTRL_LIBRARIES} + ${LIBHICNCTRL_LIBRARIES} ) - list(APPEND INCLUDE_DIRS - ${HICNCTRL_INCLUDE_DIR} + ${LIBHICNCTRL_INCLUDE_DIR} ) set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index b6e0e605a..25cc44caf 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -19,10 +19,11 @@ */ #include <assert.h> #include <stdbool.h> -#include <stdio.h> // snprintf -#include <time.h> // time +#include <stdio.h> // snprintf +#include <time.h> // time #include <hicn/ctrl.h> +#include <hicn/ctrl/socket.h> #include <hicn/facemgr.h> #include <hicn/util/ip_address.h> #include <hicn/util/log.h> @@ -38,578 +39,631 @@ #define WITH_POLL typedef enum { - HL_STATE_UNDEFINED, - HL_STATE_IDLE, - HL_STATE_ROUTES_SENT, - HL_STATE_ROUTES_RECEIVED, - HL_STATE_FACES_SENT, - HL_STATE_FACES_RECEIVED, - HL_STATE_N + HL_STATE_UNDEFINED, + HL_STATE_IDLE, + HL_STATE_ROUTES_SENT, + HL_STATE_ROUTES_RECEIVED, + HL_STATE_FACES_SENT, + HL_STATE_FACES_RECEIVED, + HL_STATE_N } hl_state_t; typedef struct { - hc_sock_t * s; /* NULL means no active socket */ - hl_state_t state; + hc_sock_t *s; /* NULL means no active socket */ - /* Timer used for forwarder reconnection */ - int reconnect_timer_fd; /* 0 means no active timer */ + /* Socket for polling, dependent on s */ + hc_sock_t *sp; /* NULL means no active socket */ - /* Timer used to periodically poll the forwarder face and routing tables */ - int poll_timer_fd; - hc_data_t * polled_routes; -} hl_data_t; + hl_state_t state; + + /* Timer used for forwarder reconnection */ + int reconnect_timer_fd; /* 0 means no active timer */ -/* Forward declarations */ -int hl_timeout(interface_t * interface, int fd, void * unused); + /* Timer used to periodically poll the forwarder face and routing tables */ + int poll_timer_fd; + hc_data_t *polled_routes; +} hl_data_t; #ifdef WITH_POLL -int hl_process_state(interface_t * interface, int fd, void * unused) +int hl_process_state(interface_t *interface, int fd, void *unused); #else -int hl_process_state(interface_t * interface) +int hl_process_state(interface_t *interface); #endif -{ - hl_data_t * data = (hl_data_t *)interface->data; - - /* - * Every tick we need to probe the forwarder for the list of faces and - * associated routes. - * - * This is used to guess manually added faces and routes - * - * TODO ensure we are idle at tick time - */ - - switch(data->state) - { - case HL_STATE_IDLE: - assert(!data->polled_routes); - - //DEBUG("[hl_process_state] Querying route list"); - if (hc_route_list_async(data->s) < 0) { - DEBUG("[hl_process_state] Error querying route list"); - return -1; - } - data->state = HL_STATE_ROUTES_SENT; - break; +void start_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - case HL_STATE_ROUTES_RECEIVED: - //DEBUG("[hl_process_state] Querying face list"); - if (hc_face_list_async(data->s) < 0) { - DEBUG("[hl_process_state] Error querying face list"); - return -1; - } - data->state = HL_STATE_FACES_SENT; - break; - - case HL_STATE_FACES_RECEIVED: - data->state = HL_STATE_IDLE; - break; - - case HL_STATE_ROUTES_SENT: - case HL_STATE_FACES_SENT: - INFO("[hl_process_state] Out of sync... resetting state"); - if (data->polled_routes) { - hc_data_free(data->polled_routes); - data->polled_routes = NULL; - } - data->state = HL_STATE_IDLE; - break; + data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_process_state, interface); + if (data->poll_timer_fd < 0) { + ERROR("[start_poll_timer) Could not start polling timer"); + } +} - case HL_STATE_UNDEFINED: - case HL_STATE_N: - ERROR("[hl_process_state] Unexpected state"); - return -1; - } +void stop_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - return 0; + if (data->poll_timer_fd > 0) + if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { + ERROR("[stop_poll_timer] Could not stop polling timer"); + } } - -int -hl_after_connect(interface_t * interface) +#ifdef WITH_POLL +int hl_process_state(interface_t *interface, int fd, void *unused) +#else +int hl_process_state(interface_t *interface) +#endif { - hl_data_t * data = interface->data; + hl_data_t *data = (hl_data_t *)interface->data; + + /* + * Every tick we need to probe the forwarder for the list of faces and + * associated routes. + * + * This is used to guess manually added faces and routes + * + * TODO ensure we are idle at tick time + */ + + switch (data->state) { + case HL_STATE_IDLE: + assert(!data->polled_routes); + stop_poll_timer(interface); + + DEBUG("[hl_process_state] Querying route list"); + if (hc_route_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying route list"); + return -1; + } + data->state = HL_STATE_ROUTES_SENT; + break; + + case HL_STATE_ROUTES_RECEIVED: + DEBUG("[hl_process_state] Got route list"); + DEBUG("[hl_process_state] Querying face list"); + if (hc_face_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying face list"); + return -1; + } + data->state = HL_STATE_FACES_SENT; + break; + + case HL_STATE_FACES_RECEIVED: + DEBUG("[hl_process_state] Got face list"); + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_ROUTES_SENT: + case HL_STATE_FACES_SENT: + WARN("[hl_process_state] Out of sync... resetting state"); + if (data->polled_routes) { + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + } + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_process_state] Unexpected state"); + return -1; + } + + return 0; +} - /* File descriptor for control socket operations */ - if (interface_register_fd(interface, hc_sock_get_fd(data->s), NULL) < 0) { - ERROR("[hc_connect] Error registering fd"); - goto ERR_FD; - } +/* + * Called whenever a connection to both sockets succeeds. + * Polling will be useful to detect when connection to the forwarder is lost, + * and will allow to try reconnect both sockets (the control socket being UDP / + * in blocking mode will not detect such loss of connection). Operations on the + * control socket that will fail will be reattempted by higher layers. + */ +int hl_after_connect(interface_t *interface) { + hl_data_t *data = interface->data; - /* We always restart from the idle phase */ - data->state = HL_STATE_IDLE; + /* File descriptor for polling socket operations */ + if (interface_register_fd(interface, hc_sock_get_fd(data->sp), NULL) < 0) { + ERROR("[hc_connect] Error registering fd"); + goto ERR_FD; + } + /* We always restart from the idle phase */ + data->state = HL_STATE_IDLE; /* poll will replace the original get, ideally we would get notifications */ #ifdef WITH_POLL - data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, - hl_process_state, interface); - if (data->poll_timer_fd < 0) { - ERROR("[hc_connect] Could not initialize polling timer"); - return -1; - } + start_poll_timer(interface); #else - hl_process_state(interface); + hl_process_state(interface); #endif - return 0; + return 0; - //interface_unregister_fd(interface, hc_sock_get_fd(data->s)); + // interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); ERR_FD: - return -1; + return -1; } -int _hl_connect(interface_t * interface); +int _hl_connect(interface_t *interface); -int -hl_connect_timeout(interface_t * interface, int fd, void * unused) -{ - hl_data_t * data = interface->data; - assert(fd == data->reconnect_timer_fd); - _unused(data); +int hl_connect_timeout(interface_t *interface, int fd, void *unused) { + hl_data_t *data = interface->data; + assert(fd == data->reconnect_timer_fd); + _unused(data); - int rc = _hl_connect(interface); - if (rc < 0) { - DEBUG("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000); - return -1; - } + int rc = _hl_connect(interface); + if (rc < 0) { + DEBUG( + "[hl_initialize] Error during connection reattempt; next attempt in " + "%ds", + INTERVAL_MS / 1000); + return -1; + } - if (interface_unregister_timer(interface, fd) < 0) { - ERROR("[hl_connect_timeout] Could not cancel timer after successful connect"); - } + if (interface_unregister_timer(interface, fd) < 0) { + ERROR( + "[hl_connect_timeout] Could not cancel timer after successful connect"); + } - /* Connect success */ - return hl_after_connect(interface); + /* Connect success */ + return hl_after_connect(interface); } +/* + * Connection without reattempt. Both control and polling sockets should be + * connected to succeed. + */ +int _hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; + assert(!data->s); + assert(!data->sp); + + data->s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); + if (data->s <= 0) { + ERROR("[hc_connect] Could not create control socket"); + goto ERR_SOCK; + } + + if (hc_sock_connect(data->s) < 0) { + DEBUG("[hc_connect] Could not connect control socket"); + goto ERR_CONNECT; + } + + data->sp = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); + if (data->sp <= 0) { + ERROR("[hc_connect] Could not create polling socket"); + goto ERR_SOCK_POLL; + } + + if (hc_sock_connect(data->sp) < 0) { + DEBUG("[hc_connect] Could not connect polling socket"); + goto ERR_CONNECT_POLL; + } + + return 0; + +ERR_CONNECT_POLL: + hc_sock_free(data->sp); + data->sp = NULL; +ERR_SOCK_POLL: +ERR_CONNECT: + hc_sock_free(data->s); + data->s = NULL; +ERR_SOCK: + return -1; +} -int -_hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; - assert(!data->s); - - data->s = hc_sock_create(); - if (data->s <= 0) { - ERROR("[hc_connect] Could not create control socket"); - goto ERR_SOCK; - } +int hl_disconnect(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; + if (data->reconnect_timer_fd > 0) + interface_unregister_timer(interface, data->reconnect_timer_fd); - if (hc_sock_connect(data->s) < 0) { - DEBUG("[hc_connect] Could not connect control socket"); - goto ERR_CONNECT; - } + stop_poll_timer(interface); - return 0; + if (data->polled_routes) hc_data_free(data->polled_routes); -ERR_CONNECT: + if (data->s) { hc_sock_free(data->s); data->s = NULL; -ERR_SOCK: + } + + if (data->sp) { + interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); + hc_sock_free(data->sp); + data->sp = NULL; + } + + return 0; +} + +/* Connection with reattempts */ +int hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; + + if (_hl_connect(interface) >= 0) return hl_after_connect(interface); + + /* Timer for managing the connection to the forwarder */ + DEBUG("Connection to forwarder failed... next retry in %ds", + INTERVAL_MS / 1000); + data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_connect_timeout, NULL); + if (data->reconnect_timer_fd < 0) { + ERROR("[hc_connect] Could not initialize reattempt timer"); return -1; + } + return 0; } -int hl_disconnect(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; - if (data->reconnect_timer_fd > 0) - interface_unregister_timer(interface, data->reconnect_timer_fd); +int hl_initialize(interface_t *interface, void *cfg) { + hl_data_t *data = malloc(sizeof(hl_data_t)); + if (!data) { + ERROR("[hicn_light] Out of memory!"); + goto ERR_MALLOC; + } - if (data->poll_timer_fd > 0) - interface_unregister_timer(interface, data->poll_timer_fd); + data->s = NULL; + data->sp = NULL; + data->reconnect_timer_fd = 0; + data->poll_timer_fd = 0; + data->polled_routes = NULL; + data->state = HL_STATE_UNDEFINED; - if (data->polled_routes) - hc_data_free(data->polled_routes); + interface->data = data; - if (data->s) { - interface_unregister_fd(interface, hc_sock_get_fd(data->s)); - hc_sock_free(data->s); - } + /* Connect both control and polling sockets */ + if (hl_connect(interface) < 0) { + ERROR("[hl_initialize] Error during connection to forwarder"); + goto ERR_CONNECT; + } - return 0; + return 0; + +ERR_CONNECT: + free(data); +ERR_MALLOC: + return -1; } -int -hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; +int hl_finalize(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - if (_hl_connect(interface) >= 0) - return hl_after_connect(interface); + hl_disconnect(interface); - /* Timer for managing the connection to the forwarder */ - DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000); - data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL); - if (data->reconnect_timer_fd < 0) { - ERROR("[hc_connect] Could not initialize reattempt timer"); - return -1; - } + if (data->polled_routes) hc_data_free(data->polled_routes); - return 0; + free(data); + + return 0; } -int -hl_initialize(interface_t * interface, void * cfg) -{ - hl_data_t * data = malloc(sizeof(hl_data_t)); - if (!data) { - ERROR("[hicn_light] Out of memory!"); - goto ERR_MALLOC; +int hl_on_event(interface_t *interface, facelet_t *facelet) { + hc_route_t route; + int rc; + int ret = 0; + hl_data_t *data = (hl_data_t *)interface->data; + face_t *face = NULL; + + /* NOTE + * - One example where this fails (and it is normal) is when we delete a + * face that was not completely created, because for instance bonjour did + * not give any data + */ + if (facelet_get_face(facelet, &face) < 0) { + ERROR("Could not retrieve face from facelet"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR_FACE; + } + + if (!data->s) { + /* We are not connected to the forwarder */ + ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; + goto ERR; + } + + switch (facelet_get_event(facelet)) { + case FACELET_EVENT_CREATE: { + /* Create face */ + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + DEBUG("Create facelet %s", buf); + + rc = hc_face_create(data->s, face); + if (rc < 0) { + ERROR("Failed to create face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + INFO("Created face id=%d - %s", face->id, buf); } - data->s = NULL; - data->reconnect_timer_fd = 0; - data->poll_timer_fd = 0; + hicn_route_t **route_array; + int n = facelet_get_route_array(facelet, &route_array); + if (n < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + if (n == 0) { + /* Adding default routes */ + route = (hc_route_t){ + .face_id = face->id, + .family = AF_INET, + .remote_addr = IPV4_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -1; + } - interface->data = data; + route = (hc_route_t){ + .face_id = face->id, + .family = AF_INET6, + .remote_addr = IPV6_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv6 route"); + ret = -1; + } - if (hl_connect(interface) < 0) { - ERROR("[hl_initialize] Error during connection to forwarder"); - goto ERR_CONNECT; - } + INFO("Successfully created default route(s)."); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *hicn_route = route_array[i]; + hicn_ip_prefix_t prefix; + int cost; + if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { + ERROR("Failed to get route prefix"); + ret = -1; + continue; + } + if (hicn_route_get_cost(hicn_route, &cost) < 0) { + ERROR("Failed to get route cost"); + ret = -1; + continue; + } + route = (hc_route_t){ + .face_id = face->id, + .face_name = "", /* take face_id into account */ + .family = prefix.family, + .remote_addr = prefix.address, + .len = prefix.len, + .cost = cost, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create static route route"); + ret = -1; + continue; + } + } + } + free(route_array); - data->polled_routes = NULL; + break; - return 0; + case FACELET_EVENT_DELETE: + /* Removing a face should also remove associated routes */ + rc = hc_face_delete(data->s, face); // delete_listener= */ 1); + if (rc < 0) { + ERROR("Failed to delete face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } -ERR_CONNECT: - free(data); -ERR_MALLOC: - return -1; -} + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + INFO("Deleted face id=%d", face->id); -int hl_finalize(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; + break; - hl_disconnect(interface); + case FACELET_EVENT_UPDATE: + /* Currently, only admin_state & priority are supported */ + if (facelet_get_admin_state_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_data_t *face_found; - if (data->polled_routes) - hc_data_free(data->polled_routes); + rc = hc_face_get(data->s, face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; - free(data); + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); - return 0; -} + face_state_t admin_state; + if (facelet_get_admin_state(facelet, &admin_state) < 0) { + ERROR("Failed to retrieve facelet admin state"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } -int hl_on_event(interface_t * interface, facelet_t * facelet) -{ - hc_face_t hc_face; - hc_route_t route; - int rc; - int ret = 0; - hl_data_t * data = (hl_data_t *)interface->data; - face_t * face = NULL; - - hc_face.id = 0; - memset(hc_face.name, 0, sizeof(hc_face.name)); - - - /* NOTE - * - One example where this fails (and it is normal) is when we delete a - * face that was not completely created, because for instance bonjour did - * not give any data - */ - if (facelet_get_face(facelet, &face) < 0) { - ERROR("Could not retrieve face from facelet"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR_FACE; - } + if (hc_connection_set_admin_state(data->s, conn_id_or_name, + admin_state) < 0) { + ERROR("Failed to update admin state"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - admin_state=%s", face->id, + face_state_str(admin_state)); + } + if (facelet_get_netdevice_type_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_data_t *face_found; + + rc = hc_face_get(data->s, face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); + + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("Failed to retrieve facelet netdevice_type"); + goto ERR; + } - if (!data->s) { - /* We are not connected to the forwarder */ - ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; - goto ERR; - } + /* Encode netdevice type into tags */ + policy_tags_t tags = POLICY_TAGS_EMPTY; + if (facelet_has_netdevice_type(facelet)) { + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("error getting netdevice_type"); + goto ERR; + } + + switch (netdevice_type) { + case NETDEVICE_TYPE_UNDEFINED: + case NETDEVICE_TYPE_LOOPBACK: + break; + case NETDEVICE_TYPE_WIRED: + policy_tags_add(&tags, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + policy_tags_add(&tags, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + policy_tags_add(&tags, POLICY_TAG_CELLULAR); + break; + default: + goto ERR; + } + } + // face->tags = tags; - switch(facelet_get_event(facelet)) { - - case FACELET_EVENT_CREATE: - { - /* Create face */ - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - DEBUG("Create facelet %s", buf); - - hc_face.face = *face; - rc = hc_face_create(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to create face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - INFO("Created face id=%d - %s", hc_face.id, buf); - } + if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { + ERROR("Failed to update tags"); + goto ERR; + } + facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - netdevice_type=%s", face->id, + netdevice_type_str(netdevice_type)); + } + if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { + INFO("Updating priority..."); + hc_data_t *face_found; + + rc = hc_face_get(data->s, face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); + + uint32_t priority; + if (facelet_get_priority(facelet, &priority) < 0) { + ERROR("Failed to retrieve facelet priority"); + goto ERR; + } - hicn_route_t ** route_array; - int n = facelet_get_route_array(facelet, &route_array); - if (n < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - if (n == 0) { - /* Adding default routes */ - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET, - .remote_addr = IPV4_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -1; - } - - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET6, - .remote_addr = IPV6_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv6 route"); - ret = -1; - } - - INFO("Successfully created default route(s)."); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * hicn_route = route_array[i]; - ip_prefix_t prefix; - int cost; - if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { - ERROR("Failed to get route prefix"); - ret = -1; - continue; - } - if (hicn_route_get_cost(hicn_route, &cost) < 0) { - ERROR("Failed to get route cost"); - ret = -1; - continue; - } - route = (hc_route_t) { - .face_id = hc_face.id, - .family = prefix.family, - .remote_addr = prefix.address, - .len = prefix.len, - .cost = cost, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create static route route"); - ret = -1; - continue; - } - } - } - free(route_array); - - break; - - case FACELET_EVENT_DELETE: - /* Removing a face should also remove associated routes */ - hc_face.face = *face; - rc = hc_face_delete(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to delete face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } + INFO("Changing connection %s priority to %d", conn_id_or_name, + priority); + if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < + 0) { + ERROR("Failed to update priority"); + goto ERR; + } + facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - INFO("Deleted face id=%d", hc_face.id); - - break; - - case FACELET_EVENT_UPDATE: - /* Currently, only admin_state & priority are supported */ - if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - face_state_t admin_state; - if (facelet_get_admin_state(facelet, &admin_state) < 0) { - ERROR("Failed to retrieve facelet admin state"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - - if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) { - ERROR("Failed to update admin state"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - admin_state=%s", hc_face.id, - face_state_str[admin_state]); - } -#ifdef WITH_POLICY - if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("Failed to retrieve facelet netdevice_type"); - goto ERR; - } - - /* Encode netdevice type into tags */ - policy_tags_t tags = POLICY_TAGS_EMPTY; - if (facelet_has_netdevice_type(facelet)) { - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("error getting netdevice_type"); - goto ERR; - } - - - switch(netdevice_type) { - case NETDEVICE_TYPE_UNDEFINED: - case NETDEVICE_TYPE_LOOPBACK: - break; - case NETDEVICE_TYPE_WIRED: - policy_tags_add(&tags, POLICY_TAG_WIRED); - break; - case NETDEVICE_TYPE_WIFI: - policy_tags_add(&tags, POLICY_TAG_WIFI); - break; - case NETDEVICE_TYPE_CELLULAR: - policy_tags_add(&tags, POLICY_TAG_CELLULAR); - break; - default: - goto ERR; - } - } - //face->tags = tags; - - if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { - ERROR("Failed to update tags"); - goto ERR; - } - facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, - netdevice_type_str[netdevice_type]); - } - if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - INFO("Updating priority..."); - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - uint32_t priority; - if (facelet_get_priority(facelet, &priority) < 0) { - ERROR("Failed to retrieve facelet priority"); - goto ERR; - } - - INFO("Changing connection %s priority to %d", conn_id_or_name, priority); - if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) { - ERROR("Failed to update priority"); - goto ERR; - } - facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); - - INFO("Updated face id=%d - priority=%d", hc_face.id, priority); - } -#endif /* WITH_POLICY */ - break; + INFO("Updated face id=%d - priority=%d", face->id, priority); + } + break; - default: - ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]); - /* Unsupported events */ - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } + default: + ERROR("Unknown event %s\n", + facelet_event_str[facelet_get_event(facelet)]); + /* Unsupported events */ + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } ERR: - face_free(face); + face_free(face); ERR_FACE: - return ret; + return ret; } -int hl_callback(interface_t * interface, int fd, void * unused) -{ - hl_data_t * data = (hl_data_t*)interface->data; - hc_data_t * results; - int ret = 0; - - /* In case of error, reconnect to forwarder */ - if (hc_sock_callback(data->s, &results) < 0) { - DEBUG("Closing socket... reconnecting..."); - if (interface_unregister_fd(interface, hc_sock_get_fd(data->s)) < 0) { - ERROR("[hl_callback] Error unregistering fd"); - } - - /* Stopping poll timer */ - if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { - ERROR("[hl_callback] Could not cancel polling timer after forwarder disconnect"); - } - if (data->polled_routes) - hc_data_free(data->polled_routes); +/* + * This should only receive data from the polling socket which is asynchronous, + * while all face creation, etc. operations are done synchronously in this + * version. + */ +int hl_callback(interface_t *interface, int fd, void *unused) { + hl_data_t *data = (hl_data_t *)interface->data; + hc_data_t *results; + int ret = 0; + + /* Workaround: sometimes this is called with data = NULL */ + if (!data) { + INFO("[hl_callback] no data"); + return 0; + } - hc_sock_free(data->s); - data->s = NULL; - hl_connect(interface); - return ret; + /* In case of error, reconnect to forwarder */ + if (hc_sock_receive_all(data->sp, &results) < 0) { + INFO("Closing socket... reconnecting..."); + if (interface_unregister_fd(interface, hc_sock_get_fd(data->sp)) < 0) { + ERROR("[hl_callback] Error unregistering fd"); } - /* Shall we wait for more data ? */ - if (!results->complete) - return ret; + /* Stopping poll timer */ + stop_poll_timer(interface); + if (data->polled_routes) hc_data_free(data->polled_routes); + + hc_sock_free(data->s); + data->s = NULL; + hc_sock_free(data->sp); + data->sp = NULL; - /* Process returned data */ - switch(data->state) { + hl_connect(interface); + return ret; + } + + /* Shall we wait for more data ? */ + if (!hc_data_is_complete(results)) { + INFO("[hl_callback] results incomplete"); + return ret; + } - case HL_STATE_ROUTES_SENT: - //DEBUG("[hl_callback] Processing routes"); - data->polled_routes = results; + /* Process returned data */ + // DEBUG("Processing data"); + switch (data->state) { + case HL_STATE_ROUTES_SENT: + // DEBUG("[hl_callback] Processing routes"); + data->polled_routes = results; #if 0 foreach_route(r, results) { @@ -622,19 +676,17 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Route: %s", buf); } #endif - data->state = HL_STATE_ROUTES_RECEIVED; - if (hl_process_state(interface, fd, unused) < 0) { - ERROR("[hl_callback] Error processing state after routes received"); - ret = -1; - } - break; - - - case HL_STATE_FACES_SENT: - //DEBUG("[hl_callback] Processing faces"); - assert(data->polled_routes); - foreach_face(f, results) { - + data->state = HL_STATE_ROUTES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after routes received"); + ret = -1; + } + break; + + case HL_STATE_FACES_SENT: + // DEBUG("[hl_callback] Processing faces"); + assert(data->polled_routes); + foreach_face(f, results) { #if 0 char buf[MAXSZ_FACE]; int rc = hc_face_snprintf(buf, MAXSZ_FACE, f); @@ -646,17 +698,16 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Face: %s", buf); #endif - /* We can ignore faces on localhost */ + /* We can ignore faces on localhost */ - facelet_t * facelet = facelet_create_from_face(&f->face); - if (!facelet) { - ERROR("[hl_callback] Could not create facelet... skipping"); - continue; - } + facelet_t *facelet = facelet_create_from_face(f); + if (!facelet) { + ERROR("[hl_callback] Could not create facelet... skipping"); + continue; + } - foreach_route(r, data->polled_routes) { - if (r->face_id != f->id) - continue; + foreach_route(r, data->polled_routes) { + if (r->face_id != f->id) continue; #if 0 char route_s[MAXSZ_HC_ROUTE]; @@ -668,41 +719,40 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Associated route: %s", route_s); #endif - if (r->len == 0) - continue; - - ip_prefix_t prefix = { - .family = r->family, - .address = r->remote_addr, - .len = r->len, - }; - hicn_route_t * route = hicn_route_create(&prefix, r->face_id, r->cost); - facelet_add_route(facelet, route); - } + if (r->len == 0) continue; - facelet_set_event(facelet, FACELET_EVENT_GET); - interface_raise_event(interface, facelet); - } - hc_data_free(results); - hc_data_free(data->polled_routes); - data->polled_routes = NULL; - data->state = HL_STATE_FACES_RECEIVED; - if (hl_process_state(interface, fd, unused) < 0) { - ERROR("[hl_callback] Error processing state after faces received"); - ret = -1; - } - break; - - case HL_STATE_IDLE: - case HL_STATE_FACES_RECEIVED: - case HL_STATE_ROUTES_RECEIVED: - case HL_STATE_UNDEFINED: - case HL_STATE_N: - ERROR("[hl_callback] Unexpected state"); - ret = -1; - } + hicn_ip_prefix_t prefix = { + .family = r->family, + .address = r->remote_addr, + .len = r->len, + }; + hicn_route_t *route = hicn_route_create(&prefix, r->face_id, r->cost); + facelet_add_route(facelet, route); + } - return ret; + facelet_set_event(facelet, FACELET_EVENT_GET); + interface_raise_event(interface, facelet); + } + hc_data_free(results); + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + data->state = HL_STATE_FACES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after faces received"); + ret = -1; + } + break; + + case HL_STATE_IDLE: + case HL_STATE_FACES_RECEIVED: + case HL_STATE_ROUTES_RECEIVED: + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_callback] Unexpected state"); + ret = -1; + } + + return ret; } const interface_ops_t hicn_light_ops = { diff --git a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt index 7f44d87fe..5d46cb8b6 100644 --- a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c index a1affd719..3c99dc5cc 100644 --- a/ctrl/facemgr/src/interfaces/netlink/netlink.c +++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -20,9 +20,9 @@ #include <assert.h> #include <linux/rtnetlink.h> -#include <net/if_arp.h> // ARPHRD_LOOPBACK -#include <sys/types.h> // getpid -#include <unistd.h> // getpid +#include <net/if_arp.h> // ARPHRD_LOOPBACK +#include <sys/types.h> // getpid +#include <unistd.h> // getpid #include <hicn/facemgr.h> #include <hicn/util/ip_address.h> @@ -32,202 +32,188 @@ #include "../../interface.h" typedef enum { - NL_STATE_UNDEFINED, - NL_STATE_LINK_SENT, - NL_STATE_ADDR_SENT, - NL_STATE_DONE, + NL_STATE_UNDEFINED, + NL_STATE_LINK_SENT, + NL_STATE_ADDR_SENT, + NL_STATE_DONE, } nl_state_t; /* Internal data storage */ typedef struct { - int fd; - nl_state_t state; + int fd; + nl_state_t state; } nl_data_t; -static inline void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len, - unsigned short flags) -{ - unsigned short type; - - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - while (RTA_OK(rta, len)) { - type = rta->rta_type & ~flags; - if (type <= max) - tb[type] = rta; - rta = RTA_NEXT(rta, len); - } +static inline void parse_rtattr(struct rtattr *tb[], int max, + struct rtattr *rta, int len, + unsigned short flags) { + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) { + type = rta->rta_type & ~flags; + if (type <= max) tb[type] = rta; + rta = RTA_NEXT(rta, len); + } } -int nl_process_state(interface_t * interface) -{ - nl_data_t * data = (nl_data_t*)interface->data; - int rc; - - switch(data->state) { - case NL_STATE_UNDEFINED: - { - DEBUG("[nl_process_state] UNDEFINED->LINK_SENT"); - struct { - struct nlmsghdr header; - struct rtgenmsg payload; - } msg2 = { - .header = { - .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_type = RTM_GETLINK, - .nlmsg_pid = getpid(), - .nlmsg_seq = 3, - }, +int nl_process_state(interface_t *interface) { + nl_data_t *data = (nl_data_t *)interface->data; + int rc; + + switch (data->state) { + case NL_STATE_UNDEFINED: { + DEBUG("[nl_process_state] UNDEFINED->LINK_SENT"); + struct { + struct nlmsghdr header; + struct rtgenmsg payload; + } msg2 = {.header = + { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_type = RTM_GETLINK, + .nlmsg_pid = getpid(), + .nlmsg_seq = 3, + }, .payload = { .rtgen_family = AF_PACKET, - } - }; - - rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0); - if (rc < 0) - printf("E: Error sending netlink query\n"); + }}; - data->state = NL_STATE_LINK_SENT; - break; - } - - case NL_STATE_LINK_SENT: - { - DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT"); - /* Issue a first query to receive static state */ - struct { - struct nlmsghdr header; - struct ifaddrmsg payload; - } msg = { - .header = { - .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_type = RTM_GETADDR, - .nlmsg_pid = getpid(), - .nlmsg_seq = 7, - }, - .payload = { - .ifa_family = AF_INET, - } - }; + rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0); + if (rc < 0) printf("E: Error sending netlink query\n"); - rc = send(data->fd, &msg, msg.header.nlmsg_len, 0); - if (rc < 0) - printf("E: Error sending netlink query\n"); - - data->state = NL_STATE_ADDR_SENT; - break; - } + data->state = NL_STATE_LINK_SENT; + break; + } - case NL_STATE_ADDR_SENT: - { - DEBUG("[nl_process_state] ADDR_SENT->DONE"); - data->state = NL_STATE_DONE; - break; - } + case NL_STATE_LINK_SENT: { + DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT"); + /* Issue a first query to receive static state */ + struct { + struct nlmsghdr header; + struct ifaddrmsg payload; + } msg = {.header = + { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_type = RTM_GETADDR, + .nlmsg_pid = getpid(), + .nlmsg_seq = 7, + }, + .payload = { + .ifa_family = AF_INET, + }}; + + rc = send(data->fd, &msg, msg.header.nlmsg_len, 0); + if (rc < 0) printf("E: Error sending netlink query\n"); + + data->state = NL_STATE_ADDR_SENT; + break; + } - default: /* NL_STATE_DONE never called */ - break; + case NL_STATE_ADDR_SENT: { + DEBUG("[nl_process_state] ADDR_SENT->DONE"); + data->state = NL_STATE_DONE; + break; } - return 0; + default: /* NL_STATE_DONE never called */ + break; + } + + return 0; } -int nl_initialize(interface_t * interface, void * cfg) -{ - nl_data_t * data = malloc(sizeof(nl_data_t)); - if (!data) - goto ERR_MALLOC; +int nl_initialize(interface_t *interface, void *cfg) { + nl_data_t *data = malloc(sizeof(nl_data_t)); + if (!data) goto ERR_MALLOC; - data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (data->fd < 0) { - ERROR("[nl_initialize] Failed to create netlink socket: %s", (char*)strerror(errno)); - goto ERR_SOCKET; - } + data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (data->fd < 0) { + ERROR("[nl_initialize] Failed to create netlink socket: %s", + (char *)strerror(errno)); + goto ERR_SOCKET; + } - data->state = NL_STATE_UNDEFINED; + data->state = NL_STATE_UNDEFINED; - struct sockaddr_nl local; // local addr struct - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; // set protocol family - // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc - local.nl_groups = 0 - | RTMGRP_LINK - | RTMGRP_IPV4_IFADDR - | RTMGRP_IPV6_IFADDR + struct sockaddr_nl local; // local addr struct + memset(&local, 0, sizeof(local)); + local.nl_family = AF_NETLINK; // set protocol family + // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc + local.nl_groups = 0 | RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR #if 0 | RTMGRP_IPV4_ROUTE; | RTMGRP_IPV6_ROUTE; #endif - ; - local.nl_pid = getpid(); // set out id using current process id + ; + local.nl_pid = getpid(); // set out id using current process id - if (bind(data->fd, (struct sockaddr*)&local, sizeof(local)) < 0) { // bind socket - ERROR("[nl_initialize] Failed to bind netlink socket: %s", (char*)strerror(errno)); - goto ERR_BIND; - } + if (bind(data->fd, (struct sockaddr *)&local, sizeof(local)) < + 0) { // bind socket + ERROR("[nl_initialize] Failed to bind netlink socket: %s", + (char *)strerror(errno)); + goto ERR_BIND; + } - interface->data = data; + interface->data = data; - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[nl_initialize] Error registering fd"); - goto ERR_FD; - } + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[nl_initialize] Error registering fd"); + goto ERR_FD; + } #if 1 - nl_process_state(interface); + nl_process_state(interface); #endif - return 0; + return 0; ERR_FD: ERR_BIND: - close(data->fd); + close(data->fd); ERR_SOCKET: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int parse_link(struct nlmsghdr * h, facelet_t ** facelet, - char * interface_name, size_t interface_name_size, - bool * up, bool * running) -{ - struct ifinfomsg *ifi; // structure for network interface info - struct rtattr *tb[IFLA_MAX + 1]; +int parse_link(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, + size_t interface_name_size, bool *up, bool *running) { + struct ifinfomsg *ifi; // structure for network interface info + struct rtattr *tb[IFLA_MAX + 1]; - assert(facelet); + assert(facelet); - ifi = (struct ifinfomsg*) NLMSG_DATA(h); // get information about changed network interface - parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1<<15); + ifi = (struct ifinfomsg *)NLMSG_DATA( + h); // get information about changed network interface + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1 << 15); - if (interface_name) { - assert(tb[IFLA_IFNAME]); - snprintf(interface_name, interface_name_size, "%s", (char*)RTA_DATA(tb[IFLA_IFNAME])); - } + if (interface_name) { + assert(tb[IFLA_IFNAME]); + snprintf(interface_name, interface_name_size, "%s", + (char *)RTA_DATA(tb[IFLA_IFNAME])); + } - if (up) - *up = ifi->ifi_flags & IFF_UP; - if (running) - *running = ifi->ifi_flags & IFF_RUNNING; + if (up) *up = ifi->ifi_flags & IFF_UP; + if (running) *running = ifi->ifi_flags & IFF_RUNNING; + netdevice_t *netdevice = netdevice_create_from_name(interface_name); + if (!netdevice) { + ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name); + goto ERR_ND; + } - netdevice_t * netdevice = netdevice_create_from_name(interface_name); - if (!netdevice) { - ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name); - goto ERR_ND; - } + *facelet = facelet_create(); + if (!*facelet) { + ERROR("[netlink.parse_link] error creating facelet"); + goto ERR_FACELET; + } - *facelet = facelet_create(); - if (!*facelet) { - ERROR("[netlink.parse_link] error creating facelet"); - goto ERR_FACELET; - } - - if (facelet_set_netdevice(*facelet, *netdevice) < 0) { - ERROR("[netlink.parse_link] error setting netdevice"); - goto ERR; - } + if (facelet_set_netdevice(*facelet, *netdevice) < 0) { + ERROR("[netlink.parse_link] error setting netdevice"); + goto ERR; + } // FIXME Tags #if 0 @@ -252,160 +238,162 @@ int parse_link(struct nlmsghdr * h, facelet_t ** facelet, #endif - // TODO - // - ifi_change - // - IFLA_PROTINFO + // TODO + // - ifi_change + // - IFLA_PROTINFO - netdevice_free(netdevice); - return 0; + netdevice_free(netdevice); + return 0; ERR: - facelet_free(*facelet); - *facelet = NULL; + facelet_free(*facelet); + *facelet = NULL; ERR_FACELET: - netdevice_free(netdevice); + netdevice_free(netdevice); ERR_ND: - return -1; + return -1; } -int parse_addr(struct nlmsghdr * h, facelet_t ** facelet, - char * interface_name, size_t interface_name_size, - char * interface_address, size_t interface_address_size) -{ - ip_address_t local_addr = IP_ADDRESS_EMPTY; - struct ifaddrmsg *ifa; // structure for network interface data - struct rtattr *tba[IFA_MAX+1]; - - assert(facelet); - - ifa = (struct ifaddrmsg*)NLMSG_DATA(h); // get data from the network interface - - parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0); - - /* FIXME - * - * IFA_LOCAL ok for v4, not there for v6 - * - * IFA_ADDRESS seems to work for both but with the following precaution - * - * IFA_ADDRESS is prefix address, rather than local interface address. - * It makes no difference for normally configured broadcast interfaces, - * but for point-to-point IFA_ADDRESS is DESTINATION address, - * local address is supplied in IFA_LOCAL attribute. - */ - if (!tba[IFA_ADDRESS]) { - ERROR("[netlink.parse_addr] No local address"); - return -1; - } - - switch(ifa->ifa_family) { - case AF_INET: - local_addr.v4.as_inaddr = *(struct in_addr*)RTA_DATA(tba[IFA_ADDRESS]); - break; - case AF_INET6: - local_addr.v6.as_in6addr = *(struct in6_addr*)RTA_DATA(tba[IFA_ADDRESS]); - break; - default: - return 0; - } - - /* See comment in parse_link */ - if (interface_address) { - assert(tba[IFA_ADDRESS]); - ip_address_snprintf(interface_address, interface_address_size, &local_addr, ifa->ifa_family); - } - - netdevice_t * netdevice = netdevice_create_from_index(ifa->ifa_index); - if (!netdevice) { - ERROR("[netlink.parse_addr] error creating netdevice from index '%d'", ifa->ifa_index); - goto ERR_ND; - } - - if (interface_name) { - snprintf(interface_name, interface_name_size, "%s", netdevice->name); - } - - *facelet = facelet_create(); - if (!*facelet) { - ERROR("[netlink.parse_addr] error creating facelet"); - goto ERR_FACELET; - } - if (facelet_set_netdevice(*facelet, *netdevice) < 0) { - ERROR("[netlink.parse_addr] error setting netdevice"); - goto ERR; - } - if (facelet_set_family(*facelet, ifa->ifa_family) < 0) { - ERROR("[netlink.parse_addr] error setting family"); - goto ERR; - } - if (facelet_set_local_addr(*facelet, local_addr) < 0) { - ERROR("[netlink.parse_addr] error setting local address"); - goto ERR; - } - - netdevice_free(netdevice); - return 0; +int parse_addr(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, + size_t interface_name_size, char *interface_address, + size_t interface_address_size) { + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + struct ifaddrmsg *ifa; // structure for network interface data + struct rtattr *tba[IFA_MAX + 1]; + + assert(facelet); + + ifa = + (struct ifaddrmsg *)NLMSG_DATA(h); // get data from the network interface + + parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0); + + /* FIXME + * + * IFA_LOCAL ok for v4, not there for v6 + * + * IFA_ADDRESS seems to work for both but with the following precaution + * + * IFA_ADDRESS is prefix address, rather than local interface address. + * It makes no difference for normally configured broadcast interfaces, + * but for point-to-point IFA_ADDRESS is DESTINATION address, + * local address is supplied in IFA_LOCAL attribute. + */ + if (!tba[IFA_ADDRESS]) { + ERROR("[netlink.parse_addr] No local address"); + return -1; + } + + switch (ifa->ifa_family) { + case AF_INET: + local_addr.v4.as_inaddr = *(struct in_addr *)RTA_DATA(tba[IFA_ADDRESS]); + break; + case AF_INET6: + local_addr.v6.as_in6addr = *(struct in6_addr *)RTA_DATA(tba[IFA_ADDRESS]); + break; + default: + return 0; + } + + /* See comment in parse_link */ + if (interface_address) { + assert(tba[IFA_ADDRESS]); + hicn_ip_address_snprintf(interface_address, interface_address_size, + &local_addr); + } + + netdevice_t *netdevice = netdevice_create_from_index(ifa->ifa_index); + if (!netdevice) { + ERROR("[netlink.parse_addr] error creating netdevice from index '%d'", + ifa->ifa_index); + goto ERR_ND; + } + + if (interface_name) { + snprintf(interface_name, interface_name_size, "%s", netdevice->name); + } + + *facelet = facelet_create(); + if (!*facelet) { + ERROR("[netlink.parse_addr] error creating facelet"); + goto ERR_FACELET; + } + if (facelet_set_netdevice(*facelet, *netdevice) < 0) { + ERROR("[netlink.parse_addr] error setting netdevice"); + goto ERR; + } + if (facelet_set_family(*facelet, ifa->ifa_family) < 0) { + ERROR("[netlink.parse_addr] error setting family"); + goto ERR; + } + if (facelet_set_local_addr(*facelet, local_addr) < 0) { + ERROR("[netlink.parse_addr] error setting local address"); + goto ERR; + } + + netdevice_free(netdevice); + return 0; ERR: - facelet_free(*facelet); - *facelet = NULL; + facelet_free(*facelet); + *facelet = NULL; ERR_FACELET: - netdevice_free(netdevice); + netdevice_free(netdevice); ERR_ND: - return -1; + return -1; } -int nl_callback(interface_t * interface, int fd, void * unused) -{ - nl_data_t * data = (nl_data_t*)interface->data; +int nl_callback(interface_t *interface, int fd, void *unused) { + nl_data_t *data = (nl_data_t *)interface->data; - struct sockaddr_nl local; // local addr struct - memset(&local, 0, sizeof(local)); + struct sockaddr_nl local; // local addr struct + memset(&local, 0, sizeof(local)); - char buf[8192]; // message buffer - struct iovec iov; // message structure - iov.iov_base = buf; // set message buffer as io - iov.iov_len = sizeof(buf); // set size + char buf[8192]; // message buffer + struct iovec iov; // message structure + iov.iov_base = buf; // set message buffer as io + iov.iov_len = sizeof(buf); // set size - // initialize protocol message header - struct msghdr msg = { - .msg_name = &local, // local address - .msg_namelen = sizeof(local), // address size - .msg_iov = &iov, // io vector - .msg_iovlen = 1, // io size - }; + // initialize protocol message header + struct msghdr msg = { + .msg_name = &local, // local address + .msg_namelen = sizeof(local), // address size + .msg_iov = &iov, // io vector + .msg_iovlen = 1, // io size + }; - ssize_t status = recvmsg(data->fd, &msg, 0); + ssize_t status = recvmsg(data->fd, &msg, 0); - // check status - if (status < 0) { -/* - if (errno == EINTR || errno == EAGAIN) - continue; -*/ + // check status + if (status < 0) { + /* + if (errno == EINTR || errno == EAGAIN) + continue; + */ - printf("Failed to read netlink: %s", (char*)strerror(errno)); - return -1; - } + printf("Failed to read netlink: %s", (char *)strerror(errno)); + return -1; + } - if (msg.msg_namelen != sizeof(local)) { // check message length, just in case - printf("Invalid length of the sender address struct\n"); - return -1; - } + if (msg.msg_namelen != sizeof(local)) { // check message length, just in case + printf("Invalid length of the sender address struct\n"); + return -1; + } - // message parser - struct nlmsghdr *h; + // message parser + struct nlmsghdr *h; - for (h = (struct nlmsghdr*)buf; status >= (ssize_t)sizeof(*h); ) { // read all messagess headers - int len = h->nlmsg_len; - int l = len - sizeof(*h); + for (h = (struct nlmsghdr *)buf; + status >= (ssize_t)sizeof(*h);) { // read all messagess headers + int len = h->nlmsg_len; + int l = len - sizeof(*h); - if ((l < 0) || (len > status)) { - printf("Invalid message length: %i\n", len); - continue; - } + if ((l < 0) || (len > status)) { + printf("Invalid message length: %i\n", len); + continue; + } - switch(h->nlmsg_type) { + switch (h->nlmsg_type) { #if 0 case RTM_NEWROUTE: case RTM_DELROUTE: @@ -413,147 +401,123 @@ int nl_callback(interface_t * interface, int fd, void * unused) break; #endif - case RTM_DELADDR: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - char interface_address[MAXSZ_IP_ADDRESS] = {0}; - - if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, - interface_address, MAXSZ_IP_ADDRESS) < 0) { - ERROR("Error parsing address message"); - break; - } - - DEBUG("[NETLINK] Interface %s: address was removed", interface_name); - if (facelet) { - facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); - } - break; - } - - case RTM_NEWADDR: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - char interface_address[MAXSZ_IP_ADDRESS] = {0}; - - if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, - interface_address, MAXSZ_IP_ADDRESS) < 0) { - ERROR("Error parsing address message"); - break; - } - - DEBUG("[NETLINK] Interface %s: new address was assigned: %s", interface_name, interface_address); - - if (facelet) { - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); - } - break; - } + case RTM_DELADDR: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + char interface_address[MAXSZ_IP_ADDRESS] = {0}; - case RTM_DELLINK: - { - /* This does not always seem to be called, hence we rely on - * down, not running */ - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - if (parse_link(h, &facelet, interface_name, IFNAMSIZ, - NULL, NULL) < 0) { - ERROR("Error parsing link message"); - break; - } + if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address, + MAXSZ_IP_ADDRESS) < 0) { + ERROR("Error parsing address message"); + break; + } - DEBUG("[NETLINK] Network interface %s was removed", interface_name); + DEBUG("[NETLINK] Interface %s: address was removed", interface_name); + if (facelet) { + facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } + break; + } + + case RTM_NEWADDR: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + char interface_address[MAXSZ_IP_ADDRESS] = {0}; + + if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address, + MAXSZ_IP_ADDRESS) < 0) { + ERROR("Error parsing address message"); + break; + } - if (!facelet) - break; + DEBUG("[NETLINK] Interface %s: new address was assigned: %s", + interface_name, interface_address); - facelet_set_event(facelet, FACELET_EVENT_DELETE); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); + if (facelet) { + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } + break; + } + + case RTM_DELLINK: { + /* This does not always seem to be called, hence we rely on + * down, not running */ + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + if (parse_link(h, &facelet, interface_name, IFNAMSIZ, NULL, NULL) < 0) { + ERROR("Error parsing link message"); + break; + } - break; - } - - case RTM_NEWLINK: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - bool up, running; - - if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < 0) { - ERROR("Error parsing link message"); - break; - } - - // UP RUNNING - // UP NOT RUNNING - // DOWN NOT RUNNING -#if 1 - DEBUG("[NETLINK] New network interface %s, state: %s %s", interface_name, - up ? "UP" : "DOWN", - running ? "RUNNING" : "NOT_RUNNING"); -#endif + DEBUG("[NETLINK] Network interface %s was removed", interface_name); - if (!facelet) - break; - if (up && running) { - facelet_set_event(facelet, FACELET_EVENT_CREATE); - //facelet_set_family(facelet, AF_INET); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); + if (!facelet) break; -#if 0 - facelet_t * facelet6 = facelet_dup(facelet); - if (!facelet6) { - ERROR("Could not duplicate face for v6"); - break; - } - facelet_set_family(facelet6, AF_INET6); - interface_raise_event(interface, facelet6); -#endif -// } else { -//#if 1 -// facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); -// facelet_set_attr_clean(facelet); -// interface_raise_event(interface, facelet); -//#else -// facelet_free(facelet); -//#endif - } - break; - } + facelet_set_event(facelet, FACELET_EVENT_DELETE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); - case NLMSG_ERROR: - break; - case NLMSG_DONE: - nl_process_state(interface); - break; - default: - break; + break; + } + + case RTM_NEWLINK: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + bool up, running; + if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < + 0) { + ERROR("Error parsing link message"); + break; } - status -= NLMSG_ALIGN(len); // align offsets by the message length, this is important + // UP RUNNING + // UP NOT RUNNING + // DOWN NOT RUNNING +#if 1 + DEBUG("[NETLINK] New network interface %s, state: %s %s", + interface_name, up ? "UP" : "DOWN", + running ? "RUNNING" : "NOT_RUNNING"); +#endif - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); // get next message + if (!facelet) break; + if (up && running) { + facelet_set_event(facelet, FACELET_EVENT_CREATE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } else { + facelet_free(facelet); + } + break; + } + + case NLMSG_ERROR: + break; + case NLMSG_DONE: + nl_process_state(interface); + break; + default: + break; } - return 0; -} + status -= NLMSG_ALIGN( + len); // align offsets by the message length, this is important -int nl_finalize(interface_t * interface) -{ - nl_data_t * data = (nl_data_t*)interface->data; - close(data->fd); - free(interface->data); - return 0; + h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); // get next message + } + + return 0; +} +int nl_finalize(interface_t *interface) { + nl_data_t *data = (nl_data_t *)interface->data; + close(data->fd); + free(interface->data); + return 0; } const interface_ops_t netlink_ops = { diff --git a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt index e8b0144b1..db96e390f 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c index 2c4bff513..7f4a26c56 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,7 +32,7 @@ #include <hicn/util/map.h> #include "../../common.h" -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include "../../interface.h" #include "network_framework.h" @@ -41,7 +41,6 @@ #error "Network frameork requires MacOSX 10.14+" #endif /* !defined(MAC_OS_X_VERSION_10_14) */ - /* * Bonjour service discovery for hICN forwarder * @@ -70,347 +69,339 @@ /* Generated variables */ #define BONJOUR_SERVICE_TYPE "_hicn._" STRINGIZE(BONJOUR_PROTOCOL) #define BONJOUR_PROTOCOL_NAME STRINGIZE(BONJOUR_PROTOCOL) -#define nw_parameters_create_fn PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL) +#define nw_parameters_create_fn \ + PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL) #define DEFAULT_PORT 9695 typedef enum { - INTERFACE_TYPE_OTHER, - INTERFACE_TYPE_WIFI, - INTERFACE_TYPE_CELLULAR, - INTERFACE_TYPE_WIRED, - INTERFACE_TYPE_LOOPBACK, + INTERFACE_TYPE_OTHER, + INTERFACE_TYPE_WIFI, + INTERFACE_TYPE_CELLULAR, + INTERFACE_TYPE_WIRED, + INTERFACE_TYPE_LOOPBACK, } _nw_interface_type_t; -const char * interface_type_str[] = { +const char *interface_type_str[] = { "OTHER", "WIFI", "CELLULAR", "WIRED", "LOOPBACK", }; #if 1 typedef enum { - PATH_STATUS_INVALID, - PATH_STATUS_SATISTIED, - PATH_STATUS_UNSATISFIED, - PATH_STATUS_SATISFIABLE, + PATH_STATUS_INVALID, + PATH_STATUS_SATISTIED, + PATH_STATUS_UNSATISFIED, + PATH_STATUS_SATISFIABLE, } _nw_path_status_t; #endif -const char * path_status_str[] = { - "INVALID", "SATISFIED", "UNSATISFIED", "SATISFIABLE", +const char *path_status_str[] = { + "INVALID", + "SATISFIED", + "UNSATISFIED", + "SATISFIABLE", }; -const char * endpoint_type_str[] = { - "INVALID", "ADDRESS", "HOST", "BONJOUR", +const char *endpoint_type_str[] = { + "INVALID", + "ADDRESS", + "HOST", + "BONJOUR", }; -const char * connection_state_str[] = { +const char *connection_state_str[] = { "INVALID", "WAITING", "PREPARING", "READY", "FAILED", "CANCELLED", }; -int -cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2) -{ - return INT_CMP(nw_interface_get_index(iface1), nw_interface_get_index(iface2)); +int cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2) { + return INT_CMP(nw_interface_get_index(iface1), + nw_interface_get_index(iface2)); } -//TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface); +// TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface); typedef struct { - network_framework_cfg_t cfg; - nw_path_monitor_t pm; /**< Main path monitor */ -// map_cnx_t map_cnx; /**< Map: interface -> connection for face status */ + network_framework_cfg_t cfg; + nw_path_monitor_t pm; /**< Main path monitor */ + // map_cnx_t map_cnx; /**< Map: interface -> connection for face status + // */ } nf_data_t; -void -dump_interface(nw_interface_t interface, int indent) -{ - uint32_t index = nw_interface_get_index(interface); - const char * name = nw_interface_get_name(interface); - nw_interface_type_t type = nw_interface_get_type(interface); +void dump_interface(nw_interface_t interface, int indent) { + uint32_t index = nw_interface_get_index(interface); + const char *name = nw_interface_get_name(interface); + nw_interface_type_t type = nw_interface_get_type(interface); - printfi(indent+1, "%d: %s [%s]\n", index, name, interface_type_str[type]); + printfi(indent + 1, "%d: %s [%s]\n", index, name, interface_type_str[type]); } -void -dump_endpoint(nw_endpoint_t endpoint, int indent) -{ - if (!endpoint) { - printfi(indent, "N/A\n"); - return; - } - - nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint); - const char * hostname = nw_endpoint_get_hostname(endpoint); - short port = nw_endpoint_get_port(endpoint); - const struct sockaddr * address = nw_endpoint_get_address(endpoint); - - printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]); - printfi(indent, "Hostname: %s\n", hostname); - printfi(indent, "Port: %d\n", port); - - if (address) { - char *s = NULL; - switch(address->sa_family) { - case AF_INET: { - struct sockaddr_in *addr_in = (struct sockaddr_in *)address; - s = malloc(INET_ADDRSTRLEN); - inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN); - break; - } - case AF_INET6: { - struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address; - s = malloc(INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN); - break; - } - default: - break; - } +void dump_endpoint(nw_endpoint_t endpoint, int indent) { + if (!endpoint) { + printfi(indent, "N/A\n"); + return; + } + + nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint); + const char *hostname = nw_endpoint_get_hostname(endpoint); + short port = nw_endpoint_get_port(endpoint); + const struct sockaddr *address = nw_endpoint_get_address(endpoint); + + printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]); + printfi(indent, "Hostname: %s\n", hostname); + printfi(indent, "Port: %d\n", port); + + if (address) { + char *s = NULL; + switch (address->sa_family) { + case AF_INET: { + struct sockaddr_in *addr_in = (struct sockaddr_in *)address; + s = malloc(INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN); + break; + } + case AF_INET6: { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address; + s = malloc(INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN); + break; + default: + break; + } printfi(indent, "IP address: %s\n", s); free(s); } + } } -void -dump_path(nw_path_t path, int indent) -{ - /* nw_path_enumerate_interfaces : not interesting */ - nw_path_status_t path_status = nw_path_get_status(path); - printfi(indent, "Status: %s\n", path_status_str[path_status]); - printfi(indent, "Expensive: %s\n", nw_path_is_expensive(path) ? "true" : "false"); - printfi(indent, "IPv4 enabled: %s\n", nw_path_has_ipv4(path) ? "true" : "false"); - printfi(indent, "IPv6 enabled: %s\n", nw_path_has_ipv6(path) ? "true" : "false"); - printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false"); - printfi(indent, "Interfaces:\n"); - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) { - dump_interface(interface, indent+1); +void dump_path(nw_path_t path, int indent) { + /* nw_path_enumerate_interfaces : not interesting */ + nw_path_status_t path_status = nw_path_get_status(path); + printfi(indent, "Status: %s\n", path_status_str[path_status]); + printfi(indent, "Expensive: %s\n", + nw_path_is_expensive(path) ? "true" : "false"); + printfi(indent, "IPv4 enabled: %s\n", + nw_path_has_ipv4(path) ? "true" : "false"); + printfi(indent, "IPv6 enabled: %s\n", + nw_path_has_ipv6(path) ? "true" : "false"); + printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false"); + printfi(indent, "Interfaces:\n"); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + dump_interface(interface, indent + 1); return true; - }); + }); - nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); - printfi(indent, "Effective local endpoint:\n"); - dump_endpoint(local, indent+1); - nw_release(local); + nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); + printfi(indent, "Effective local endpoint:\n"); + dump_endpoint(local, indent + 1); + nw_release(local); - nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); - printfi(indent, "Effective remote endpoint:\n"); - dump_endpoint(remote, indent+1); - nw_release(remote); + nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); + printfi(indent, "Effective remote endpoint:\n"); + dump_endpoint(remote, indent + 1); + nw_release(remote); } -void -dump_connection(nw_connection_t connection, int indent) -{ - nw_endpoint_t remote = nw_connection_copy_endpoint(connection); - nw_path_t path = nw_connection_copy_current_path(connection); +void dump_connection(nw_connection_t connection, int indent) { + nw_endpoint_t remote = nw_connection_copy_endpoint(connection); + nw_path_t path = nw_connection_copy_current_path(connection); - printfi(indent, "Remote endpoint:\n"); - dump_endpoint(remote, indent+1); - printfi(indent, "Path:\n"); - dump_path(path, indent+1); + printfi(indent, "Remote endpoint:\n"); + dump_endpoint(remote, indent + 1); + printfi(indent, "Path:\n"); + dump_path(path, indent + 1); - /* - nw_connection_copy_protocol_metadata(); - nw_connection_get_maximum_datagram_size(); - */ + /* + nw_connection_copy_protocol_metadata(); + nw_connection_get_maximum_datagram_size(); + */ - nw_release(remote); - nw_release(path); + nw_release(remote); + nw_release(path); } #if defined(MAC_OS_X_VERSION_10_15) -void -dump_browse_result(nw_browse_result_t result, int indent) -{ - /* Endpoint */ - nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result); - if (!browse_endpoint) { - ERROR("[network_framework.dump_result] Failed to retrieve endpoint from Bonjour browse result"); - return; - } - printfi(indent + 1, "Endpoint:"); - dump_endpoint(browse_endpoint, indent + 2); - - /* Interfaces */ - printfi(indent + 1, "Interfaces:"); - nw_browse_result_enumerate_interfaces(result, (nw_browse_result_enumerate_interface_t) ^(nw_interface_t interface) { +void dump_browse_result(nw_browse_result_t result, int indent) { + /* Endpoint */ + nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result); + if (!browse_endpoint) { + ERROR( + "[network_framework.dump_result] Failed to retrieve endpoint from " + "Bonjour browse result"); + return; + } + printfi(indent + 1, "Endpoint:"); + dump_endpoint(browse_endpoint, indent + 2); + + /* Interfaces */ + printfi(indent + 1, "Interfaces:"); + nw_browse_result_enumerate_interfaces( + result, + (nw_browse_result_enumerate_interface_t) ^ (nw_interface_t interface) { dump_interface(interface, indent + 2); return true; - }); + }); } #endif /* defined(MAC_OS_X_VERSION_10_15) */ -facelet_t * -facelet_create_from_connection(nw_connection_t connection) -{ - facelet_t * facelet; - ip_address_t local_addr, remote_addr; - uint16_t remote_port; - - nw_path_t path = nw_connection_copy_current_path(connection); - nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); - nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); - __block nw_interface_t interface; - - const struct sockaddr * local_sa = nw_endpoint_get_address(local); - const struct sockaddr * remote_sa = nw_endpoint_get_address(remote); - - assert (local_sa->sa_family == remote_sa->sa_family); - switch(local_sa->sa_family) { - case AF_INET: - local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; - remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; - remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; - break; - case AF_INET6: - local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; - remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr; - remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; - break; - default: - ERROR("Unsupported address family: %d\n", local_sa->sa_family); - return NULL; - } - - - /* Retrieving path interface type (a single one expected */ - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t path_interface) { +facelet_t *facelet_create_from_connection(nw_connection_t connection) { + facelet_t *facelet; + hicn_ip_address_t local_addr, remote_addr; + uint16_t remote_port; + + nw_path_t path = nw_connection_copy_current_path(connection); + nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); + nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); + __block nw_interface_t interface; + + const struct sockaddr *local_sa = nw_endpoint_get_address(local); + const struct sockaddr *remote_sa = nw_endpoint_get_address(remote); + + assert(local_sa->sa_family == remote_sa->sa_family); + switch (local_sa->sa_family) { + case AF_INET: + local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; + remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; + remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; + break; + case AF_INET6: + local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; + remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr; + remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; + break; + default: + ERROR("Unsupported address family: %d\n", local_sa->sa_family); + return NULL; + } + + /* Retrieving path interface type (a single one expected */ + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t path_interface) { interface = path_interface; return false; - }); - - const char * name = nw_interface_get_name(interface); - netdevice_t netdevice; - snprintf(netdevice.name, IFNAMSIZ, "%s", name); - netdevice_update_index(&netdevice); - - netdevice_type_t netdevice_type; - nw_interface_type_t type = nw_interface_get_type(interface); - - switch(type) { - case INTERFACE_TYPE_OTHER: - netdevice_type = NETDEVICE_TYPE_UNDEFINED; - break; - case INTERFACE_TYPE_WIFI: - netdevice_type = NETDEVICE_TYPE_WIFI; - break; - case INTERFACE_TYPE_CELLULAR: - netdevice_type = NETDEVICE_TYPE_CELLULAR; - break; - case INTERFACE_TYPE_WIRED: - netdevice_type = NETDEVICE_TYPE_WIRED; - break; - case INTERFACE_TYPE_LOOPBACK: - netdevice_type = NETDEVICE_TYPE_LOOPBACK; - break; - default: - break; - - } - - nw_release(local); - nw_release(remote); - nw_release(path); - - facelet = facelet_create(); - if (!facelet) - return NULL; - - facelet_set_netdevice(facelet, netdevice); - facelet_set_netdevice_type(facelet, netdevice_type); - facelet_set_family(facelet, local_sa->sa_family); - facelet_set_local_addr(facelet, local_addr); - facelet_set_remote_addr(facelet, remote_addr); - facelet_set_remote_port(facelet, remote_port); - - return facelet; + }); + + const char *name = nw_interface_get_name(interface); + netdevice_t netdevice; + snprintf(netdevice.name, IFNAMSIZ, "%s", name); + netdevice_update_index(&netdevice); + + netdevice_type_t netdevice_type; + nw_interface_type_t type = nw_interface_get_type(interface); + + switch (type) { + case INTERFACE_TYPE_OTHER: + netdevice_type = NETDEVICE_TYPE_UNDEFINED; + break; + case INTERFACE_TYPE_WIFI: + netdevice_type = NETDEVICE_TYPE_WIFI; + break; + case INTERFACE_TYPE_CELLULAR: + netdevice_type = NETDEVICE_TYPE_CELLULAR; + break; + case INTERFACE_TYPE_WIRED: + netdevice_type = NETDEVICE_TYPE_WIRED; + break; + case INTERFACE_TYPE_LOOPBACK: + netdevice_type = NETDEVICE_TYPE_LOOPBACK; + break; + default: + break; + } + + nw_release(local); + nw_release(remote); + nw_release(path); + + facelet = facelet_create(); + if (!facelet) return NULL; + + facelet_set_netdevice(facelet, netdevice); + facelet_set_netdevice_type(facelet, netdevice_type); + facelet_set_family(facelet, local_sa->sa_family); + facelet_set_local_addr(facelet, local_addr); + facelet_set_remote_addr(facelet, remote_addr); + facelet_set_remote_port(facelet, remote_port); + + return facelet; } -void -on_connection_state_event(interface_t * interface, nw_interface_t iface, - nw_connection_t cnx, nw_connection_state_t state, nw_error_t error) -{ +void on_connection_state_event(interface_t *interface, nw_interface_t iface, + nw_connection_t cnx, nw_connection_state_t state, + nw_error_t error) { #if 1 - DEBUG("Connection [new state = %s]:\n", connection_state_str[state]); - nw_path_t path = nw_connection_copy_current_path(cnx); - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) { - const char * name = nw_interface_get_name(interface); + DEBUG("Connection [new state = %s]:\n", connection_state_str[state]); + nw_path_t path = nw_connection_copy_current_path(cnx); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + const char *name = nw_interface_get_name(interface); printf("NAME=%s\n", name); return true; - }); + }); #endif - /* We should get enough information to create the face and set if up - * asap */ + /* We should get enough information to create the face and set if up + * asap */ - nw_endpoint_t remote = nw_connection_copy_endpoint(cnx); - errno = error ? nw_error_get_error_code(error) : 0; + nw_endpoint_t remote = nw_connection_copy_endpoint(cnx); + errno = error ? nw_error_get_error_code(error) : 0; - switch(state) { - case nw_connection_state_waiting: - warn("connect to %s port %u (%s) failed, is waiting", - nw_endpoint_get_hostname(remote), - nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; + switch (state) { + case nw_connection_state_waiting: + warn("connect to %s port %u (%s) failed, is waiting", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; - case nw_connection_state_preparing: - break; + case nw_connection_state_preparing: + break; - case nw_connection_state_ready: - { - printf("info:\n"); - warn("connection ready"); + case nw_connection_state_ready: { + printf("info:\n"); + warn("connection ready"); #if 1 - WITH_DEBUG({ - dump_connection(cnx, 1); - }); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - facelet_t * facelet = facelet_create_from_connection(cnx); - if (!facelet) - return; - facelet_set_event(facelet, FACELET_EVENT_CREATE); - interface_raise_event(interface, facelet); - break; - } - case nw_connection_state_failed: - /* Can we fail with bonjour, or are we always waiting ? */ - warn("connect to %s port %u (%s) failed", - nw_endpoint_get_hostname(remote), - nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; - - case nw_connection_state_cancelled: - // Release the primary reference on the connection - // that was taken at creation time - nw_release(cnx); - break; - - default: /* nw_connection_state_invalid */ - /* Should never be called */ - break; - + facelet_t *facelet = facelet_create_from_connection(cnx); + if (!facelet) return; + facelet_set_event(facelet, FACELET_EVENT_CREATE); + interface_raise_event(interface, facelet); + break; } - - nw_release(remote); - + case nw_connection_state_failed: + /* Can we fail with bonjour, or are we always waiting ? */ + warn("connect to %s port %u (%s) failed", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; + + case nw_connection_state_cancelled: + // Release the primary reference on the connection + // that was taken at creation time + nw_release(cnx); + break; + + default: /* nw_connection_state_invalid */ + /* Should never be called */ + break; + } + + nw_release(remote); } -void -on_connection_path_event(interface_t * interface, nw_interface_t iface, - nw_connection_t cnx, nw_path_t path) -{ +void on_connection_path_event(interface_t *interface, nw_interface_t iface, + nw_connection_t cnx, nw_path_t path) { #if 1 - DEBUG("Connection [path changed]:\n"); - WITH_DEBUG({ - dump_connection(cnx, 1); - }); + DEBUG("Connection [path changed]:\n"); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - /* redundant *//* - DEBUG(1, "Path:\n"); - dump_path(path, 2); - */ + /* redundant */ /* + DEBUG(1, "Path:\n"); + dump_path(path, 2); + */ } /** @@ -422,257 +413,254 @@ on_connection_path_event(interface_t * interface, nw_interface_t iface, * Currently we only use Bonjour/TCP for remote hICN discovery and connection * path monitoring. */ -void on_interface_event(interface_t * interface, nw_interface_t iface) -{ - /* We can create an hICN face on this interface that will be down until - * connected - * It is however possible to have two default gateways on the same - * interface, or more, or even zero. Somehow we need a strategy, timers, etc - * to properly do the job. - * - * We have to determine: - * - how many faces to build - * - the face type : hICN, tunnel (TCP/UDP) - * - the underlying protocol : v4, v6 - * - * This depends on the configuration, end host and network capabilities. - * - * We can rely on several types of discovery: - * - DHCP - * - Bonjour - * - ... - * - * So far: - * - bonjour discovery attempt, we expect to discover one hICN interface - * (how bonjour works with more than one is unclear), after a certain - * time, if none is discovered, we cannot do any tunnel face. - */ - - // OLD CODE - - /* nw_parameters_create_secure_{udp,tcp} */ - nw_parameters_t parameters = nw_parameters_create_fn( - NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ - NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); - - if (!parameters) - goto ERR_PARAMETERS; - - nw_parameters_require_interface(parameters, iface); - nw_parameters_set_reuse_local_address(parameters, true); +void on_interface_event(interface_t *interface, nw_interface_t iface) { + /* We can create an hICN face on this interface that will be down until + * connected + * It is however possible to have two default gateways on the same + * interface, or more, or even zero. Somehow we need a strategy, timers, etc + * to properly do the job. + * + * We have to determine: + * - how many faces to build + * - the face type : hICN, tunnel (TCP/UDP) + * - the underlying protocol : v4, v6 + * + * This depends on the configuration, end host and network capabilities. + * + * We can rely on several types of discovery: + * - DHCP + * - Bonjour + * - ... + * + * So far: + * - bonjour discovery attempt, we expect to discover one hICN interface + * (how bonjour works with more than one is unclear), after a certain + * time, if none is discovered, we cannot do any tunnel face. + */ + + // OLD CODE + + /* nw_parameters_create_secure_{udp,tcp} */ + nw_parameters_t parameters = nw_parameters_create_fn( + NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ + NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); + + if (!parameters) goto ERR_PARAMETERS; + + nw_parameters_require_interface(parameters, iface); + nw_parameters_set_reuse_local_address(parameters, true); #if defined(MAC_OS_X_VERSION_10_15) - /* - * Before being able to create a bonjour endpoint, we need to browse for - * available services on the local network using the parameters specified - * before. - */ - nw_browse_descriptor_t descriptor = nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); - if (!descriptor) { - ERROR("[network_framework.on_interface_event] Failed to create a bonjour browse descriptor"); - goto ERR_DESCRIPTOR; + /* + * Before being able to create a bonjour endpoint, we need to browse for + * available services on the local network using the parameters specified + * before. + */ + nw_browse_descriptor_t descriptor = + nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, + BONJOUR_SERVICE_DOMAIN); + if (!descriptor) { + ERROR( + "[network_framework.on_interface_event] Failed to create a bonjour " + "browse descriptor"); + goto ERR_DESCRIPTOR; + } + + nw_browser_t browser = nw_browser_create(descriptor, parameters); + nw_browser_set_queue(browser, dispatch_get_main_queue()); + nw_browser_set_browse_results_changed_handler(browser, ^( + nw_browse_result_t result, + nw_browse_result_t result2, + bool flag) { + /* Dump result */ + printfi(0, "NEW BROWSE RESULT"); + printfi(1, "Result:"); + dump_browse_result(result, 2); + printfi(1, "Result2:"); + dump_browse_result(result2, 2); + printfi(1, "Flag: %s\n", (flag ? "ON" : "OFF")); + + /* Changes */ + nw_browse_result_change_t change = + nw_browse_result_get_changes(result, result2); + switch (change) { + case nw_browse_result_change_identical: + printfi(2, "The compared services are identical."); + break; + case nw_browse_result_change_result_added: + printfi(2, "A new service was discovered."); + break; + + case nw_browse_result_change_result_removed: + printfi(2, "A previously discovered service was removed."); + break; + + case nw_browse_result_change_txt_record_changed: + printfi(2, "The service's associated TXT record changed."); + break; + + case nw_browse_result_change_interface_added: + printfi(2, "The service was discovered over a new interface."); + break; + + case nw_browse_result_change_interface_removed: + printfi( + 2, + "The service was no longer discovered over a certain interface."); + break; } + }); - nw_browser_t browser = nw_browser_create(descriptor, parameters); - nw_browser_set_queue(browser, dispatch_get_main_queue()); - nw_browser_set_browse_results_changed_handler(browser, ^(nw_browse_result_t result, nw_browse_result_t result2, bool flag) { - /* Dump result */ - printfi(0, "NEW BROWSE RESULT"); - printfi(1, "Result:"); - dump_browse_result(result, 2); - printfi(1, "Result2:"); - dump_browse_result(result2, 2); - printfi(1, "Flag: %s\n", (flag?"ON":"OFF")); - - /* Changes */ - nw_browse_result_change_t change = nw_browse_result_get_changes(result, result2); - switch(change) { - case nw_browse_result_change_identical: - printfi(2, "The compared services are identical."); - break; - case nw_browse_result_change_result_added: - printfi(2, "A new service was discovered."); - break; - - case nw_browse_result_change_result_removed: - printfi(2, "A previously discovered service was removed."); - break; - - case nw_browse_result_change_txt_record_changed: - printfi(2, "The service's associated TXT record changed."); - break; - - case nw_browse_result_change_interface_added: - printfi(2, "The service was discovered over a new interface."); - break; - - case nw_browse_result_change_interface_removed: - printfi(2, "The service was no longer discovered over a certain interface."); - break; - } - }); - - nw_browser_start(browser); + nw_browser_start(browser); //#else //#warning "Bonjour discovery only available in MacOS 10.15+" #endif /* defined(MAC_OS_X_VERSION_10_15) */ - /* - * Now that we have resolve the name of a bonjour remote, we can create a - * connection to the corresponding endpoint identified by its name. - */ - nw_endpoint_t endpoint; - - DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s", - BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); - endpoint = nw_endpoint_create_bonjour_service( - BONJOUR_SERVICE_NAME, - BONJOUR_SERVICE_TYPE, - BONJOUR_SERVICE_DOMAIN); - - if (!endpoint) { - ERROR("[network_framework.on_interface_event] Failed to create bound Bonjour connection"); - goto ERR_ENDPOINT; - } + /* + * Now that we have resolve the name of a bonjour remote, we can create a + * connection to the corresponding endpoint identified by its name. + */ + nw_endpoint_t endpoint; + + DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s", + BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); + endpoint = nw_endpoint_create_bonjour_service( + BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); + + if (!endpoint) { + ERROR( + "[network_framework.on_interface_event] Failed to create bound " + "Bonjour " + "connection"); + goto ERR_ENDPOINT; + } - nw_connection_t connection = nw_connection_create(endpoint, parameters); - if (!connection) - goto ERR_CONNECTION; + nw_connection_t connection = nw_connection_create(endpoint, parameters); + if (!connection) goto ERR_CONNECTION; - nw_release(endpoint); - nw_release(parameters); + nw_release(endpoint); + nw_release(parameters); - /* Remember not to recreate connection */ - // XXX TODO + /* Remember not to recreate connection */ + // XXX TODO - /* Setup connection handlers */ + /* Setup connection handlers */ - nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) { + nw_connection_set_state_changed_handler( + connection, ^(nw_connection_state_t state, nw_error_t error) { on_connection_state_event(interface, iface, connection, state, error); - }); + }); - nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) { - on_connection_path_event(interface, iface, connection, path); - }); + nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) { + on_connection_path_event(interface, iface, connection, path); + }); - nw_connection_set_better_path_available_handler(connection, ^(bool value) { + nw_connection_set_better_path_available_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ - dump_connection(connection, 1); - }); + DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ dump_connection(connection, 1); }); #endif - }); + }); - nw_connection_set_viability_changed_handler(connection, ^(bool value) { + nw_connection_set_viability_changed_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ - //dump_connection(connection, 1); - }); + DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ + // dump_connection(connection, 1); + }); #endif - /* - * This is the first time we have a connection with address and port - * and thus the full identification of an hICN face - */ - facelet_t * facelet = facelet_create_from_connection(connection); - if (!facelet) - return; - facelet_set_event(facelet, value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); - interface_raise_event(interface, facelet); - - }); + /* + * This is the first time we have a connection with address and port + * and thus the full identification of an hICN face + */ + facelet_t *facelet = facelet_create_from_connection(connection); + if (!facelet) return; + facelet_set_event(facelet, + value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); + interface_raise_event(interface, facelet); + }); - nw_connection_start(connection); + nw_connection_start(connection); - nw_connection_set_queue(connection, dispatch_get_main_queue()); - nw_retain(connection); // Hold a reference until cancelled + nw_connection_set_queue(connection, dispatch_get_main_queue()); + nw_retain(connection); // Hold a reference until cancelled #if 1 - DEBUG("Created Bonjour cnx on interface:"); - WITH_DEBUG({ - dump_interface(iface, 1); - }); + DEBUG("Created Bonjour cnx on interface:"); + WITH_DEBUG({ dump_interface(iface, 1); }); #endif - return; + return; - nw_release(connection); + nw_release(connection); ERR_CONNECTION: - nw_release(endpoint); + nw_release(endpoint); ERR_ENDPOINT: #if defined(MAC_OS_X_VERSION_10_15) - nw_release(descriptor); + nw_release(descriptor); ERR_DESCRIPTOR: #endif /* defined(MAC_OS_X_VERSION_10_15) */ - nw_release(parameters); + nw_release(parameters); ERR_PARAMETERS: - return; + return; } -void on_path_event(interface_t * interface, nw_path_t path) -{ - /* Simplification: we handle path event only once. - * Ideally, test whether we discover new interfaces or not - */ +void on_path_event(interface_t *interface, nw_path_t path) { + /* Simplification: we handle path event only once. + * Ideally, test whether we discover new interfaces or not + */ #if 1 - DEBUG("Path [event]:\n"); - WITH_DEBUG({ - dump_path(path, 1); - }); + DEBUG("Path [event]:\n"); + WITH_DEBUG({ dump_path(path, 1); }); #endif - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t iface) { - on_interface_event(interface, iface); - return true; - }); - + nw_path_enumerate_interfaces( + path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t iface) { + on_interface_event(interface, iface); + return true; + }); } -int nf_initialize(interface_t * interface, void * cfg) -{ - nf_data_t * data = malloc(sizeof(nf_data_t)); - if (!data) - goto ERR_MALLOC; +int nf_initialize(interface_t *interface, void *cfg) { + nf_data_t *data = malloc(sizeof(nf_data_t)); + if (!data) goto ERR_MALLOC; - if (cfg) - data->cfg = * (network_framework_cfg_t *)cfg; + if (cfg) data->cfg = *(network_framework_cfg_t *)cfg; - data->pm = nw_path_monitor_create(); - if (!data->pm) - goto ERR_PM; + data->pm = nw_path_monitor_create(); + if (!data->pm) goto ERR_PM; - nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue()); - nw_path_monitor_set_cancel_handler(data->pm, ^() { }); - nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) { - on_path_event(interface, path); - }); + nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue()); + nw_path_monitor_set_cancel_handler(data->pm, ^(){ + }); + nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) { + on_path_event(interface, path); + }); - // XXX NEEDED ? - nw_retain(data->pm); + // XXX NEEDED ? + nw_retain(data->pm); - DEBUG("Starting network path monitor"); - nw_path_monitor_start(data->pm); + DEBUG("Starting network path monitor"); + nw_path_monitor_start(data->pm); - interface->data = data; - return 0; + interface->data = data; + return 0; ERR_PM: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int nf_finalize(interface_t * interface) -{ - nf_data_t * data = (nf_data_t*)interface->data; - if (data->pm) { - nw_path_monitor_cancel(data->pm); - data->pm = NULL; - } - return 0; +int nf_finalize(interface_t *interface) { + nf_data_t *data = (nf_data_t *)interface->data; + if (data->pm) { + nw_path_monitor_cancel(data->pm); + data->pm = NULL; + } + return 0; } const interface_ops_t network_framework_ops = { diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h index edb35e904..768edc253 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -19,4 +19,5 @@ */ typedef struct { + void *_; } network_framework_cfg_t; diff --git a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt index 8d18800db..43ba31b0b 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c index 67edc5e39..5d2f695f9 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c +++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -34,20 +34,21 @@ #define PC_DEFAULT_PORT 9533 typedef struct { - priority_controller_cfg_t cfg; - int fd; + priority_controller_cfg_t cfg; + int fd; #ifdef PRIORITY_CONTROLLER_INTERNAL - unsigned state; - JNIEnv * env; - jclass cls; - jmethodID mid; + unsigned state; + JNIEnv *env; + jclass cls; + jmethodID mid; #endif /* PRIORITY_CONTROLLER_INTERNAL */ } pc_data_t; #ifdef PRIORITY_CONTROLLER_INTERNAL #include <jni.h> -#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration." +#define ERR_STR_JAVA \ + "Java VM parameters are required in the interface configuration." #define PREFER_CELLULAR 0 #define PREFER_WIFI 1 @@ -55,147 +56,146 @@ typedef struct { #define INTERVAL_MS 500 -const char * prefer_str[] = { "Cellular", "WiFi", "both" }; +const char *prefer_str[] = {"Cellular", "WiFi", "both"}; -jclass find_class_global(JNIEnv* env, const char *name){ - jclass c = (*env)->FindClass(env, name); - jclass c_global = 0; - if (c){ - c_global = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - } - return c_global; +jclass find_class_global(JNIEnv *env, const char *name) { + jclass c = (*env)->FindClass(env, name); + jclass c_global = 0; + if (c) { + c_global = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + } + return c_global; } +int priority_controller_tick(interface_t *interface, int fd, void *unused) { + pc_data_t *data = (pc_data_t *)interface->data; + unsigned new_state = PREFER_BOTH; -int priority_controller_tick(interface_t * interface, int fd, void * unused) -{ - pc_data_t * data = (pc_data_t*)interface->data; - unsigned new_state = PREFER_BOTH; - - jint rssi = (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid); - DEBUG("[priority_controller_tick] rssi=%d\n", rssi); - if (rssi > -67) { - new_state = PREFER_WIFI; + jint rssi = + (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid); + DEBUG("[priority_controller_tick] rssi=%d\n", rssi); + if (rssi > -67) { + new_state = PREFER_WIFI; #if 0 } else if ((rssi < -67) && (rssi > -70)) { new_state = PREFER_BOTH; #endif - } else { /* rssi < -70 */ - new_state = PREFER_CELLULAR; - } + } else { /* rssi < -70 */ + new_state = PREFER_CELLULAR; + } - if (new_state == data->state) - return 0; + if (new_state == data->state) return 0; - ERROR("[priority_controller_tick] Setting priority to %s", prefer_str[new_state]); + ERROR("[priority_controller_tick] Setting priority to %s", + prefer_str[new_state]); - /* XXX Factor this */ + /* XXX Factor this */ - facelet_t * facelet_w = facelet_create(); - facelet_t * facelet_c = facelet_create(); - facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); - facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); - facelet_set_attr_clean(facelet_w); - facelet_set_attr_clean(facelet_c); + facelet_t *facelet_w = facelet_create(); + facelet_t *facelet_c = facelet_create(); + facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); + facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); + facelet_set_attr_clean(facelet_w); + facelet_set_attr_clean(facelet_c); - switch(new_state) { - case PREFER_CELLULAR: - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 10); - break; - case PREFER_WIFI: - facelet_set_priority(facelet_w, 10); - facelet_set_priority(facelet_c, 0); - break; - case PREFER_BOTH: - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 0); - break; - } + switch (new_state) { + case PREFER_CELLULAR: + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 10); + break; + case PREFER_WIFI: + facelet_set_priority(facelet_w, 10); + facelet_set_priority(facelet_c, 0); + break; + case PREFER_BOTH: + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 0); + break; + } - facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); - facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet_w); - interface_raise_event(interface, facelet_c); + interface_raise_event(interface, facelet_w); + interface_raise_event(interface, facelet_c); - data->state = new_state; + data->state = new_state; - return 0; + return 0; } #endif /* PRIORITY_CONTROLLER_INTERNAL */ -int priority_controller_initialize(interface_t * interface, void * cfg) -{ - INFO("Initializing priority controller"); +int priority_controller_initialize(interface_t *interface, void *cfg) { + INFO("Initializing priority controller"); - pc_data_t * data = malloc(sizeof(pc_data_t)); - if (!data) { - INFO("Priority controller data memory allocation error"); - goto ERR_MALLOC; - } + pc_data_t *data = malloc(sizeof(pc_data_t)); + if (!data) { + INFO("Priority controller data memory allocation error"); + goto ERR_MALLOC; + } - interface->data = data; + interface->data = data; - data->cfg = * (priority_controller_cfg_t *) cfg; + data->cfg = *(priority_controller_cfg_t *)cfg; #ifdef PRIORITY_CONTROLLER_INTERNAL - if (!cfg) { - ERROR(ERR_STR_JAVA); - goto ERR_CFG; - } - - /* Retrieve RSSI information from SDK through AndroidUtility class */ - (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL); - data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS); - if (data->cls == 0) - goto ERR_JAVA; - data->mid = (*data->env)->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I"); - - data->fd = interface_register_timer(interface, INTERVAL_MS, - priority_controller_tick, interface); - if (data->fd < 0) { - ERROR("[priority_controller_initialize] Could not initialize timer"); - goto ERR_FD; - } - data->state = PREFER_BOTH; + if (!cfg) { + ERROR(ERR_STR_JAVA); + goto ERR_CFG; + } + + /* Retrieve RSSI information from SDK through AndroidUtility class */ + (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL); + data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS); + if (data->cls == 0) goto ERR_JAVA; + data->mid = + (*data->env) + ->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I"); + + data->fd = interface_register_timer(interface, INTERVAL_MS, + priority_controller_tick, interface); + if (data->fd < 0) { + ERROR("[priority_controller_initialize] Could not initialize timer"); + goto ERR_FD; + } + data->state = PREFER_BOTH; #else /* PRIORITY_CONTROLLER_INTERNAL */ - struct sockaddr_in addr; - - data->fd = socket(AF_INET, SOCK_DGRAM, 0); - //data->fd = socket(AF_INET, SOCK_STREAM, 0); - if (data->fd < 0) { - INFO("Priority controller socket error"); - perror("socket error"); - goto ERR_SOCKET; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - addr.sin_port = htons(PC_DEFAULT_PORT); - - if (bind(data->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - INFO("Priority controller socket bind error"); - perror("bind error"); - goto ERR_BIND; - } - - DEBUG("[priority_controller_initialize] register fd"); - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[priority_controller_initialize] Error registering fd"); - goto ERR_FD; - } + struct sockaddr_in addr; + + data->fd = socket(AF_INET, SOCK_DGRAM, 0); + // data->fd = socket(AF_INET, SOCK_STREAM, 0); + if (data->fd < 0) { + INFO("Priority controller socket error"); + perror("socket error"); + goto ERR_SOCKET; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(PC_DEFAULT_PORT); + + if (bind(data->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + INFO("Priority controller socket bind error"); + perror("bind error"); + goto ERR_BIND; + } + + DEBUG("[priority_controller_initialize] register fd"); + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[priority_controller_initialize] Error registering fd"); + goto ERR_FD; + } #endif /* PRIORITY_CONTROLLER_INTERNAL */ - INFO("Priority controller successfully initialized"); - return 0; + INFO("Priority controller successfully initialized"); + return 0; #ifdef PRIORITY_CONTROLLER_INTERNAL ERR_CFG: @@ -204,86 +204,86 @@ ERR_JAVA: ERR_FD: #ifndef PRIORITY_CONTROLLER_INTERNAL ERR_BIND: - close(data->fd); + close(data->fd); ERR_SOCKET: #endif /* ! PRIORITY_CONTROLLER_INTERNAL */ - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int priority_controller_finalize(interface_t * interface) -{ - pc_data_t * data = (pc_data_t*)interface->data; +int priority_controller_finalize(interface_t *interface) { + pc_data_t *data = (pc_data_t *)interface->data; #ifdef PRIORITY_CONTROLLER_INTERNAL - DEBUG("[priority_controller_finalize] unregister timer"); - interface_unregister_timer(interface, data->fd); + DEBUG("[priority_controller_finalize] unregister timer"); + interface_unregister_timer(interface, data->fd); #else - if (data->fd > 0) { - interface_unregister_fd(interface, data->fd); - close(data->fd); - } - free(data); + if (data->fd > 0) { + interface_unregister_fd(interface, data->fd); + close(data->fd); + } + free(data); #endif /* PRIORITY_CONTROLLER_INTERNAL */ - return 0; + return 0; } #ifndef PRIORITY_CONTROLLER_INTERNAL -int priority_controller_callback(interface_t * interface, int fd, void * unused) -{ - pc_data_t * data = (pc_data_t*)interface->data; - char buf[100]; - int rc; - - INFO("Priority controller receiving command"); - - rc = recv(data->fd, buf, 100, 0); - - if (rc < 0) { - INFO("Priority controller read error"); - return -1; - } - - INFO("Priority controller received command: %02X", buf[0]); - - facelet_t * facelet_w = facelet_create(); - facelet_t * facelet_c = facelet_create(); - facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); - facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); - facelet_set_attr_clean(facelet_w); - facelet_set_attr_clean(facelet_c); - switch(buf[0]) { - case '\0': - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 10); - INFO("Priority controller configuring Cellular preferred"); - break; - case '\1': - facelet_set_priority(facelet_w, 10); - facelet_set_priority(facelet_c, 0); - INFO("Priority controller configuring Wi-Fi preferred"); - break; - case '\2': - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 0); - INFO("Priority controller configuring both Cellular and Wi-Fi preferred"); - break; - default: - INFO("Priority controller invalid data received from updown server. Ignoring..."); - facelet_free(facelet_w); - facelet_free(facelet_c); - return 0; - } - - facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); - facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); - - interface_raise_event(interface, facelet_w); - interface_raise_event(interface, facelet_c); - - return 0; +int priority_controller_callback(interface_t *interface, int fd, void *unused) { + pc_data_t *data = (pc_data_t *)interface->data; + char buf[100]; + int rc; + + INFO("Priority controller receiving command"); + + rc = recv(data->fd, buf, 100, 0); + + if (rc < 0) { + INFO("Priority controller read error"); + return -1; + } + + INFO("Priority controller received command: %02X", buf[0]); + + facelet_t *facelet_w = facelet_create(); + facelet_t *facelet_c = facelet_create(); + facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); + facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); + facelet_set_attr_clean(facelet_w); + facelet_set_attr_clean(facelet_c); + switch (buf[0]) { + case '\0': + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 10); + INFO("Priority controller configuring Cellular preferred"); + break; + case '\1': + facelet_set_priority(facelet_w, 10); + facelet_set_priority(facelet_c, 0); + INFO("Priority controller configuring Wi-Fi preferred"); + break; + case '\2': + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 0); + INFO("Priority controller configuring both Cellular and Wi-Fi preferred"); + break; + default: + INFO( + "Priority controller invalid data received from updown server. " + "Ignoring..."); + facelet_free(facelet_w); + facelet_free(facelet_c); + return 0; + } + + facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); + + interface_raise_event(interface, facelet_w); + interface_raise_event(interface, facelet_c); + + return 0; } #endif /* ! PRIORITY_CONTROLLER_INTERNAL */ diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h index 247fc3c57..7f257ffcf 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h +++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,7 +21,8 @@ #ifndef FACEMGR_INTERFACE_PRIORITY_CONTROLLER #define FACEMGR_INTERFACE_PRIORITY_CONTROLLER -#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" +#define FACEMGR_UTILITY_CLASS \ + "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" /* * Uncomment this line to use a Priority controller interface internal to the @@ -36,10 +37,9 @@ typedef struct { #ifdef __ANDROID__ #ifdef PRIORITY_CONTROLLER_INTERNAL - JavaVM * jvm; + JavaVM* jvm; #endif /* PRIORITY_CONTROLLER_INTERNAL */ #endif /* __ANDROID__ */ } priority_controller_cfg_t; - #endif /* FACEMGR_INTERFACE_PRIORITY_CONTROLLER */ diff --git a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt index e5fd2167e..4c6c0ea6c 100644 --- a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c index 7d305a5cd..8d31f6cd4 100644 --- a/ctrl/facemgr/src/interfaces/updown/updown.c +++ b/ctrl/facemgr/src/interfaces/updown/updown.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -26,6 +26,7 @@ #include <unistd.h> #include <hicn/facemgr.h> +#include <hicn/util/sstrncpy.h> #include "../../common.h" #include "../../interface.h" @@ -37,107 +38,101 @@ #define UNIX_PATH "\0updownsrv" typedef struct { - int fd; /* Unix client socket */ + int fd; /* Unix client socket */ } updown_data_t; -int updown_initialize(interface_t * interface, void * cfg) -{ - struct sockaddr_un addr; - char * socket_path = UNIX_PATH; - - updown_data_t * data = malloc(sizeof(updown_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; - - data->fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (data->fd == -1) { - perror("socket error"); - goto ERR_SOCKET; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (*socket_path == '\0') { - *addr.sun_path = '\0'; - strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2); - } else { - strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); - } - - if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { - perror("connect error"); - goto ERR_CONNECT; - } - - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[updown_initialize] Error registering fd"); - goto ERR_FD; - } - - return 0; +int updown_initialize(interface_t* interface, void* cfg) { + struct sockaddr_un addr; + char* socket_path = UNIX_PATH; + + updown_data_t* data = malloc(sizeof(updown_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + data->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (data->fd == -1) { + perror("socket error"); + goto ERR_SOCKET; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (*socket_path == '\0') { + *addr.sun_path = '\0'; + strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, socket_path + 1); + } else { + strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, socket_path); + } + + if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + perror("connect error"); + goto ERR_CONNECT; + } + + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[updown_initialize] Error registering fd"); + goto ERR_FD; + } + + return 0; ERR_FD: ERR_CONNECT: - close(data->fd); + close(data->fd); ERR_SOCKET: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int updown_finalize(interface_t * interface) -{ - updown_data_t * data = (updown_data_t*)interface->data; +int updown_finalize(interface_t* interface) { + updown_data_t* data = (updown_data_t*)interface->data; - if (data->fd > 0) - close(data->fd); - free(data); + if (data->fd > 0) close(data->fd); + free(data); - return 0; + return 0; } -int updown_callback(interface_t * interface, int fd, void * unused) -{ - updown_data_t * data = (updown_data_t*)interface->data; - char buf[100]; - int rc; - - rc = read(data->fd, buf, sizeof(buf)); - if (rc < 0) - return -1; - - /* - * If the process is paused (eg. in a debugger, we might have more than one - * read. - * XXX how big is the buffer - * XXX shall we drain the queue if it exceeds buffer size ? - */ - //assert(rc == 1); - - /* Raise facelet update event */ - facelet_t * facelet = facelet_create(); - facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); //CELLULAR); - facelet_set_attr_clean(facelet); - switch(buf[0]) { - case '\0': - facelet_set_admin_state(facelet, FACE_STATE_DOWN); - break; - case '\1': - facelet_set_admin_state(facelet, FACE_STATE_UP); - break; - break; - default: - ERROR("Invalid data received from updown server. Ignoring..."); - facelet_free(facelet); - return -1; - } - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - - interface_raise_event(interface, facelet); - - return 0; +int updown_callback(interface_t* interface, int fd, void* unused) { + updown_data_t* data = (updown_data_t*)interface->data; + char buf[100]; + int rc; + + rc = read(data->fd, buf, sizeof(buf)); + if (rc < 0) return -1; + + /* + * If the process is paused (eg. in a debugger, we might have more than one + * read. + * XXX how big is the buffer + * XXX shall we drain the queue if it exceeds buffer size ? + */ + // assert(rc == 1); + + /* Raise facelet update event */ + facelet_t* facelet = facelet_create(); + facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); // CELLULAR); + facelet_set_attr_clean(facelet); + switch (buf[0]) { + case '\0': + facelet_set_admin_state(facelet, FACE_STATE_DOWN); + break; + case '\1': + facelet_set_admin_state(facelet, FACE_STATE_UP); + break; + break; + default: + ERROR("Invalid data received from updown server. Ignoring..."); + facelet_free(facelet); + return -1; + } + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + + interface_raise_event(interface, facelet); + + return 0; } interface_ops_t updown_ops = { diff --git a/ctrl/facemgr/src/loop_dispatcher.c b/ctrl/facemgr/src/loop_dispatcher.c index 499a1ccac..88e197492 100644 --- a/ctrl/facemgr/src/loop_dispatcher.c +++ b/ctrl/facemgr/src/loop_dispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -28,57 +28,41 @@ #include <stdlib.h> -#include <Dispatch/Dispatch.h> +#include <dispatch/dispatch.h> #include <hicn/facemgr/loop.h> #include <hicn/util/log.h> -struct loop_s { -}; +struct loop_s {}; -loop_t * -loop_create() -{ - loop_t * loop = malloc(sizeof(loop_t)); - if (!loop) { - ERROR("[loop_create] Failed to allocate memory"); - goto ERR_MALLOC; - } - return loop; +loop_t* loop_create() { + loop_t* loop = malloc(sizeof(loop_t)); + if (!loop) { + ERROR("[loop_create] Failed to allocate memory"); + goto ERR_MALLOC; + } + return loop; ERR_MALLOC: - return NULL; + return NULL; } -void -loop_free(loop_t * loop) -{ - /* Nothing to do */ +void loop_free(loop_t* loop) { /* Nothing to do */ } -int -loop_dispatch(loop_t * loop) -{ - dispatch_main(); - return 0; +int loop_dispatch(loop_t* loop) { + dispatch_main(); + return 0; } -int -loop_undispatch(loop_t * loop) -{ - /* Nothing to do */ - return 0; +int loop_undispatch(loop_t* loop) { + /* Nothing to do */ + return 0; } -void -loop_break(loop_t * loop) -{ - exit(0); -} +void loop_break(loop_t* loop) { exit(0); } -int -loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data) -{ - INFO("loop_callback not (yet) implemented"); - return 0; +int loop_callback(loop_t* loop, facemgr_cb_type_t type, void* data) { + INFO("loop_callback not (yet) implemented"); + return 0; } diff --git a/ctrl/facemgr/src/loop_libevent.c b/ctrl/facemgr/src/loop_libevent.c index 674eee905..b619e02e6 100644 --- a/ctrl/facemgr/src/loop_libevent.c +++ b/ctrl/facemgr/src/loop_libevent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,13 +25,13 @@ #include <assert.h> #include <event2/event.h> #include <event2/thread.h> -#include <fcntl.h> // fcntl +#include <fcntl.h> // fcntl #ifdef WITH_THREAD #include <pthread.h> #endif /* WITH_THREAD */ #include <stdlib.h> #include <sys/timerfd.h> -#include <unistd.h> // fcntl +#include <unistd.h> // fcntl #include <hicn/facemgr/api.h> #include <hicn/util/log.h> @@ -43,160 +43,150 @@ * \brief Holds all callback parameters */ typedef struct { - void * owner; - fd_callback_t callback; - void * data; + void *owner; + fd_callback_t callback; + void *data; } cb_wrapper_args_t; TYPEDEF_MAP_H(event_map, int, struct event *); -TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, generic_snprintf); +TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, + generic_snprintf); /* Map that associates timer fds with their associated cb_wrapper_args_t */ TYPEDEF_MAP_H(timer_fd_map, int, cb_wrapper_args_t *); -TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, generic_snprintf); +TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, + generic_snprintf); struct loop_s { - struct event_base * event_base; - event_map_t * event_map; - timer_fd_map_t * timer_fd_map; + struct event_base *event_base; + event_map_t *event_map; + timer_fd_map_t *timer_fd_map; #ifdef WITH_THREAD - pthread_t thread; + pthread_t thread; #endif /* WITH_THREAD */ }; /* Forward declarations */ -int _loop_unregister_fd(loop_t * loop, int fd); -int _loop_unregister_timer(loop_t * loop, int fd); - -loop_t * -loop_create() -{ - loop_t * loop = malloc(sizeof(loop_t)); - if (!loop) { - ERROR("[loop_create] Failed to allocate memory"); - goto ERR_MALLOC; - } +int _loop_unregister_fd(loop_t *loop, int fd); +int _loop_unregister_timer(loop_t *loop, int fd); + +loop_t *loop_create() { + loop_t *loop = malloc(sizeof(loop_t)); + if (!loop) { + ERROR("[loop_create] Failed to allocate memory"); + goto ERR_MALLOC; + } #ifdef WITH_THREAD - evthread_use_pthreads(); + evthread_use_pthreads(); #endif /* WITH_THREAD */ - loop->event_base = event_base_new(); - if (!loop) - goto ERR_EVENT; + loop->event_base = event_base_new(); + if (!loop) goto ERR_EVENT; - loop->event_map = event_map_create(); - if (!loop->event_map) { - ERROR("[loop_create] Failed to create event_map"); - goto ERR_EVENT_MAP; - } + loop->event_map = event_map_create(); + if (!loop->event_map) { + ERROR("[loop_create] Failed to create event_map"); + goto ERR_EVENT_MAP; + } - loop->timer_fd_map = timer_fd_map_create(); - if (!loop->timer_fd_map) { - ERROR("[loop_create] Failed to create timer_fd_map"); - goto ERR_TIMER_FD_MAP; - } + loop->timer_fd_map = timer_fd_map_create(); + if (!loop->timer_fd_map) { + ERROR("[loop_create] Failed to create timer_fd_map"); + goto ERR_TIMER_FD_MAP; + } - event_set_log_callback(NULL); + event_set_log_callback(NULL); - return loop; + return loop; - timer_fd_map_free(loop->timer_fd_map); ERR_TIMER_FD_MAP: - event_map_free(loop->event_map); + event_map_free(loop->event_map); ERR_EVENT_MAP: - event_base_free(loop->event_base); + event_base_free(loop->event_base); ERR_EVENT: - free(loop); + free(loop); ERR_MALLOC: - return NULL; + return NULL; } -void -loop_free(loop_t * loop) -{ - /* - * Release all timer cb_wrapper_args_t - * - * We need to stop all timers, this should release associated fd events at - * the same time... for that reason, this code has to be called before - * releasing events - */ - - int * timer_fd_map_array; - int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array); - if (n < 0) { - ERROR("[loop_free] Could not get event map array"); - } else { - for (unsigned i = 0; i < n; i++) { - int fd = timer_fd_map_array[i]; - if (_loop_unregister_timer(loop, fd) < 0) { - ERROR("[loop_free] Could not unregister timer"); - } - } - free(timer_fd_map_array); +void loop_free(loop_t *loop) { + /* + * Release all timer cb_wrapper_args_t + * + * We need to stop all timers, this should release associated fd events at + * the same time... for that reason, this code has to be called before + * releasing events + */ + + int *timer_fd_map_array; + int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array); + if (n < 0) { + ERROR("[loop_free] Could not get event map array"); + } else { + for (unsigned i = 0; i < n; i++) { + int fd = timer_fd_map_array[i]; + if (_loop_unregister_timer(loop, fd) < 0) { + ERROR("[loop_free] Could not unregister timer"); + } } - timer_fd_map_free(loop->timer_fd_map); - - /* Release all events */ - - int * event_map_array; - n = event_map_get_key_array(loop->event_map, &event_map_array); - if (n < 0) { - ERROR("[loop_free] Could not get event map array"); - } else { - for (unsigned i = 0; i < n; i++) { - int fd = event_map_array[i]; - if (_loop_unregister_fd(loop, fd) < 0) { - ERROR("[loop_free] Could not unregister fd"); - } - } - free(event_map_array); + free(timer_fd_map_array); + } + timer_fd_map_free(loop->timer_fd_map); + + /* Release all events */ + + int *event_map_array; + n = event_map_get_key_array(loop->event_map, &event_map_array); + if (n < 0) { + ERROR("[loop_free] Could not get event map array"); + } else { + for (unsigned i = 0; i < n; i++) { + int fd = event_map_array[i]; + if (_loop_unregister_fd(loop, fd) < 0) { + ERROR("[loop_free] Could not unregister fd"); + } } - event_map_free(loop->event_map); + free(event_map_array); + } + event_map_free(loop->event_map); - event_base_free(loop->event_base); + event_base_free(loop->event_base); - free(loop); + free(loop); } -int -loop_dispatch(loop_t * loop) -{ +int loop_dispatch(loop_t *loop) { #ifdef WITH_THREAD - if (pthread_create(&loop->thread, NULL, (void * (*)(void *))event_base_dispatch, loop->event_base)) { - fprintf(stderr, "Error creating thread\n"); - return -1; - } + if (pthread_create(&loop->thread, NULL, + (void *(*)(void *))event_base_dispatch, + loop->event_base)) { + fprintf(stderr, "Error creating thread\n"); + return -1; + } #else - event_base_dispatch(loop->event_base); + event_base_dispatch(loop->event_base); #endif /* WITH_THREAD */ - return 0; + return 0; } -int -loop_undispatch(loop_t * loop) -{ +int loop_undispatch(loop_t *loop) { #ifdef WITH_THREAD - DEBUG("Waiting for loop to terminate..."); - if(pthread_join(loop->thread, NULL)) { - fprintf(stderr, "Error joining thread\n"); - return -1; - } - DEBUG("Loop terminated !"); + DEBUG("Waiting for loop to terminate..."); + if (pthread_join(loop->thread, NULL)) { + ERROR("Error joining thread\n"); + return -1; + } + DEBUG("Loop terminated !"); #endif /* WITH_THREAD */ - return 0; + return 0; } -void -loop_break(loop_t * loop) -{ - event_base_loopbreak(loop->event_base); -} +void loop_break(loop_t *loop) { event_base_loopbreak(loop->event_base); } -void cb_wrapper(evutil_socket_t fd, short what, void * arg) { - cb_wrapper_args_t * cb_wrapper_args = arg; - cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data); +void cb_wrapper(evutil_socket_t fd, short what, void *arg) { + cb_wrapper_args_t *cb_wrapper_args = arg; + cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data); } /** @@ -208,42 +198,41 @@ void cb_wrapper(evutil_socket_t fd, short what, void * arg) { * \param [in] callback_data - User data to pass alongside callback invocation * \return 0 in case of success, -1 otherwise */ -int -_loop_register_fd(loop_t * loop, int fd, void * callback_owner, - fd_callback_t callback, void * callback_data) -{ - /* This will be freed with the event */ - cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t)); - *cb_wrapper_args = (cb_wrapper_args_t) { - .owner = callback_owner, - .callback = callback, - .data = callback_data, - }; - - evutil_make_socket_nonblocking(fd); - struct event * event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args); - if (!event) { - ERROR("[_loop_register_fd] event_new"); - goto ERR_EVENT_NEW; - } - - if (event_add(event, NULL) < 0) { - ERROR("[_loop_register_fd] event_add"); - goto ERR_EVENT_ADD; - } - - if (event_map_add(loop->event_map, fd, event) < 0) { - ERROR("[_loop_register_fd] event_map_add"); - goto ERR_EVENT_MAP; - } - - return 0; +int _loop_register_fd(loop_t *loop, int fd, void *callback_owner, + fd_callback_t callback, void *callback_data) { + /* This will be freed with the event */ + cb_wrapper_args_t *cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t)); + *cb_wrapper_args = (cb_wrapper_args_t){ + .owner = callback_owner, + .callback = callback, + .data = callback_data, + }; + + evutil_make_socket_nonblocking(fd); + struct event *event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST, + cb_wrapper, cb_wrapper_args); + if (!event) { + ERROR("[_loop_register_fd] event_new"); + goto ERR_EVENT_NEW; + } + + if (event_add(event, NULL) < 0) { + ERROR("[_loop_register_fd] event_add"); + goto ERR_EVENT_ADD; + } + + if (event_map_add(loop->event_map, fd, event) < 0) { + ERROR("[_loop_register_fd] event_map_add"); + goto ERR_EVENT_MAP; + } + + return 0; ERR_EVENT_MAP: ERR_EVENT_ADD: - event_free(event); + event_free(event); ERR_EVENT_NEW: - return -1; + return -1; } /** @@ -251,183 +240,169 @@ ERR_EVENT_NEW: * \param [in] fd - File descriptor to unregister * \return 0 in case of success, -1 otherwise */ -int -_loop_unregister_fd(loop_t * loop, int fd) -{ - struct event * event = NULL; +int _loop_unregister_fd(loop_t *loop, int fd) { + struct event *event = NULL; - if (event_map_remove(loop->event_map, fd, &event) < 0) { - ERROR("[_loop_unregister_fd] Error removing event associated to fd"); - return -1; - } + if (event_map_remove(loop->event_map, fd, &event) < 0) { + ERROR("[_loop_unregister_fd] Error removing event associated to fd"); + return -1; + } - assert(event); + assert(event); - cb_wrapper_args_t * cb_wrapper_args = event_get_callback_arg(event); - free(cb_wrapper_args); + cb_wrapper_args_t *cb_wrapper_args = event_get_callback_arg(event); + free(cb_wrapper_args); - event_del(event); - event_free(event); + event_del(event); + event_free(event); - return 0; + return 0; } -int -loop_timer_callback(loop_t * loop, int fd, void * data) -{ - char buf[1024]; /* size is not important */ - cb_wrapper_args_t * cb_wrapper_args = data; - while (read(fd, &buf, sizeof(buf)) > 0) - ; +int loop_timer_callback(loop_t *loop, int fd, void *data) { + char buf[1024]; /* size is not important */ + cb_wrapper_args_t *cb_wrapper_args = data; + while (read(fd, &buf, sizeof(buf)) > 0) + ; - int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd, - cb_wrapper_args->data); + int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd, + cb_wrapper_args->data); - return rc; + return rc; } -int -_loop_register_timer(loop_t * loop, timer_callback_data_t * timer_callback_data) -{ - int fd = timerfd_create(CLOCK_MONOTONIC, 0); - if (fd == -1) { - perror("timerfd_create"); - return -1; - } +int _loop_register_timer(loop_t *loop, + timer_callback_data_t *timer_callback_data) { + int fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (fd == -1) { + perror("timerfd_create"); + return -1; + } - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl"); - return -1; - } + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + perror("fcntl"); + return -1; + } + + struct itimerspec ts = { + .it_interval = + { + .tv_sec = timer_callback_data->delay_ms / 1000, + .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000, + }, + .it_value = { + .tv_sec = timer_callback_data->delay_ms / 1000, + .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000, + }}; + + if (timerfd_settime(fd, 0, &ts, NULL) == -1) { + perror("timerfd_settime"); + return -1; + } + + /* This should be freed together with the timer release */ + cb_wrapper_args_t *cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t)); + *cb_wrapper_args = (cb_wrapper_args_t){ + .owner = timer_callback_data->owner, + .callback = timer_callback_data->callback, + .data = timer_callback_data->data, + }; + + if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) { + ERROR("[_loop_register_timer] Could not add cb_wrapper to timer map"); + return -1; + } - struct itimerspec ts = { - .it_interval = { - .tv_sec = timer_callback_data->delay_ms / 1000, - .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000, - }, - .it_value = { - .tv_sec = timer_callback_data->delay_ms / 1000, - .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000, - } - }; - - if (timerfd_settime(fd, 0, &ts, NULL) == -1) { - perror("timerfd_settime"); - return -1; - } + if (_loop_register_fd(loop, fd, loop, (fd_callback_t)loop_timer_callback, + cb_wrapper_args) < 0) { + ERROR("[_loop_register_timer] Error registering fd to event loop"); + return -1; + } - /* This should be freed together with the timer release */ - cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t)); - *cb_wrapper_args = (cb_wrapper_args_t) { - .owner = timer_callback_data->owner, - .callback = timer_callback_data->callback, - .data = timer_callback_data->data, - }; + return fd; +} - if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) { - ERROR("[_loop_register_timer] Could not add cb_wrapper to timer map"); - return -1; - } +int _loop_unregister_timer(loop_t *loop, int fd) { + struct itimerspec ts = {.it_interval = + { + .tv_sec = 0, + .tv_nsec = 0, + }, + .it_value = { + /* This value disables the timer */ + .tv_sec = 0, + .tv_nsec = 0, + }}; + ts.it_value.tv_sec = 0; + + if (timerfd_settime(fd, 0, &ts, NULL) == -1) { + perror("timerfd_settime"); + return -1; + } - if (_loop_register_fd(loop, fd, loop, - (fd_callback_t) loop_timer_callback, cb_wrapper_args) < 0) { - ERROR("[_loop_register_timer] Error registering fd to event loop"); - return -1; - } + cb_wrapper_args_t *cb_wrapper_args; + if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) { + ERROR( + "[_loop_unregister_timer] Could not remove cb_wrapper from timer map"); + return -1; + } + assert(cb_wrapper_args); + free(cb_wrapper_args); + + if (_loop_unregister_fd(loop, fd) < 0) { + ERROR("[_loop_unregister_timer] Error unregistering fd from event loop"); + return -1; + } - return fd; + close(fd); + + return 0; } -int -_loop_unregister_timer(loop_t * loop, int fd) -{ - struct itimerspec ts = { - .it_interval = { - .tv_sec = 0, - .tv_nsec = 0, - }, - .it_value = { /* This value disables the timer */ - .tv_sec = 0, - .tv_nsec = 0, - } - }; - ts.it_value.tv_sec = 0; - - if (timerfd_settime(fd, 0, &ts, NULL) == -1) { - perror("timerfd_settime"); +int loop_callback(loop_t *loop, facemgr_cb_type_t type, void *data) { + switch (type) { + case FACEMGR_CB_TYPE_REGISTER_FD: { + fd_callback_data_t *fd_callback_data = (fd_callback_data_t *)data; + if (_loop_register_fd(loop, fd_callback_data->fd, fd_callback_data->owner, + fd_callback_data->callback, + fd_callback_data->data) < 0) { + ERROR("[loop_callback] Error registering fd to event loop"); return -1; + } + break; } - cb_wrapper_args_t * cb_wrapper_args; - if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) { - ERROR("[_loop_unregister_timer] Could not remove cb_wrapper from timer map"); + case FACEMGR_CB_TYPE_UNREGISTER_FD: { + fd_callback_data_t *fd_callback_data = (fd_callback_data_t *)data; + /* We need a map to associate fd and events */ + if (_loop_unregister_fd(loop, fd_callback_data->fd) < 0) { + ERROR("[loop_callback] Error unregistering fd from event loop"); return -1; + } + break; } - assert(cb_wrapper_args); - free(cb_wrapper_args); - if (_loop_unregister_fd(loop, fd) < 0) { - ERROR("[_loop_unregister_timer] Error unregistering fd from event loop"); + case FACEMGR_CB_TYPE_REGISTER_TIMER: { + timer_callback_data_t *timer_callback_data = + (timer_callback_data_t *)data; + + int fd = _loop_register_timer(loop, timer_callback_data); + if (fd < 0) { + ERROR("[loop_callback] Error registering timer to event loop"); return -1; + } + return fd; } - return 0; -} + case FACEMGR_CB_TYPE_UNREGISTER_TIMER: { + int fd = *(int *)data; -int -loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data) -{ - switch(type) { - case FACEMGR_CB_TYPE_REGISTER_FD: - { - fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)data; - if (_loop_register_fd(loop, fd_callback_data->fd, - fd_callback_data->owner, - fd_callback_data->callback, - fd_callback_data->data) < 0) { - - ERROR("[loop_callback] Error registering fd to event loop"); - return -1; - } - break; - } - - case FACEMGR_CB_TYPE_UNREGISTER_FD: - { - fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)data; - /* We need a map to associate fd and events */ - if (_loop_unregister_fd(loop, fd_callback_data->fd) < 0) { - ERROR("[loop_callback] Error unregistering fd from event loop"); - return -1; - } - break; - } - - case FACEMGR_CB_TYPE_REGISTER_TIMER: - { - timer_callback_data_t * timer_callback_data = (timer_callback_data_t *)data; - - int fd = _loop_register_timer(loop, timer_callback_data); - if (fd < 0) { - ERROR("[loop_callback] Error registering timer to event loop"); - return -1; - } - return fd; - - } - - case FACEMGR_CB_TYPE_UNREGISTER_TIMER: - { - int fd = *(int*)data; - - if (_loop_unregister_timer(loop, fd) < 0) { - ERROR("[loop_callback] Error unregistering timer from event loop"); - return -1; - } - return 0; - - } + if (_loop_unregister_timer(loop, fd) < 0) { + ERROR("[loop_callback] Error unregistering timer from event loop"); + return -1; + } + return 0; } - return 0; + } + return 0; } - diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c index 344b034ae..18d2f8f7c 100644 --- a/ctrl/facemgr/src/main.c +++ b/ctrl/facemgr/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -24,7 +24,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <unistd.h> // sleep +#include <unistd.h> // sleep #include <hicn/facemgr.h> #include <hicn/facemgr/cfg.h> @@ -41,7 +41,7 @@ #if 0 static struct event_base * loop; #endif -static loop_t * loop = NULL; +static loop_t* loop = NULL; #ifdef __linux__ #ifdef WITH_THREAD @@ -49,210 +49,193 @@ static bool stop = false; #endif /* WITH_THREAD */ #endif /* __linux__ */ -static struct option long_options[] = -{ - {"config", required_argument, 0, 'c'}, - {0, 0, 0, 0} -}; +static struct option long_options[] = {{"config", required_argument, 0, 'c'}, + {0, 0, 0, 0}}; typedef struct { - char * cfgfile; + char* cfgfile; } facemgr_options_t; -void usage(const char * progname) -{ - printf("%s: Face manager daemon\n", progname); - printf("\n"); - printf("Usage: %s [OPTIONS]\n", progname); - printf("\n"); - printf("OPTIONS:\n"); - printf(" -c --config [FILE|none] Sets the configuration file (unless none, default: /etc/facemgr.conf, ~/facemgr.conf)\n"); - printf("\n"); +void usage(const char* progname) { + printf("%s: Face manager daemon\n", progname); + printf("\n"); + printf("Usage: %s [OPTIONS]\n", progname); + printf("\n"); + printf("OPTIONS:\n"); + printf( + " -c --config [FILE|none] Sets the configuration file (unless none, " + "default: /etc/facemgr.conf, ~/facemgr.conf)\n"); + printf("\n"); } void facemgr_signal_handler(int signal) { - fprintf(stderr, "Received ^C... quitting !\n"); - if (loop) { - loop_break(loop); + fprintf(stderr, "Received ^C... quitting !\n"); + if (loop) { + loop_break(loop); #ifdef __linux__ #ifdef WITH_THREAD stop = true; #endif /* WITH_THREAD */ #endif /* __linux__ */ - } + } } -int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts) -{ - int c; - while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) { - switch(c) { - case 'c': - opts->cfgfile = optarg; - break; - case ':': - case '?': - default: - usage(argv[0]); - exit(EXIT_FAILURE); - } - +int parse_cmdline(int argc, char** argv, facemgr_options_t* opts) { + int c; + while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) { + switch (c) { + case 'c': + opts->cfgfile = optarg; + break; + case ':': + case '?': + default: + usage(argv[0]); + exit(EXIT_FAILURE); } - return 0; + } + return 0; } -#ifdef __linux__ - -#endif /* __linux__ */ - -int -dump_facelet(const facemgr_t * facemgr, const facelet_t * facelet, - void * user_data) -{ - char facelet_s[MAXSZ_FACELET]; - facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); - DEBUG("%s", facelet_s); - return 0; +int dump_facelet(const facemgr_t* facemgr, const facelet_t* facelet, + void* user_data) { + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + DEBUG("%s", facelet_s); + return 0; } -int main(int argc, char ** argv) -{ - facemgr_cfg_t * cfg = NULL; - facemgr_t * facemgr; +int main(int argc, char** argv) { + facemgr_cfg_t* cfg = NULL; + facemgr_t* facemgr; - struct sigaction sigIntHandler; - sigIntHandler.sa_handler = facemgr_signal_handler; - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, NULL); + struct sigaction sigIntHandler; + sigIntHandler.sa_handler = facemgr_signal_handler; + sigemptyset(&sigIntHandler.sa_mask); + sigIntHandler.sa_flags = 0; + sigaction(SIGINT, &sigIntHandler, NULL); - char cfgfile[PATH_MAX]; + char cfgfile[PATH_MAX]; - // TODO: default < config < commandline on a per option basis + // TODO: default < config < commandline on a per option basis - /* Commandline */ - facemgr_options_t cmdline_opts = {0}; - if (parse_cmdline(argc, argv, &cmdline_opts) < 0) { - ERROR("Error parsing commandline"); - goto ERR_CMDLINE; - } + /* Commandline */ + facemgr_options_t cmdline_opts = {0}; + if (parse_cmdline(argc, argv, &cmdline_opts) < 0) { + ERROR("Error parsing commandline"); + goto ERR_CMDLINE; + } - /* Configuration file */ - //facemgr_options_t cfgfile_opts; + /* Configuration file */ + // facemgr_options_t cfgfile_opts; - if (cmdline_opts.cfgfile) { - if (strcasecmp(cmdline_opts.cfgfile, "none") == 0) - goto NO_CFGFILE; + if (cmdline_opts.cfgfile) { + if (strcasecmp(cmdline_opts.cfgfile, "none") == 0) goto NO_CFGFILE; - if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile)) - goto ERR_PATH; + if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile)) goto ERR_PATH; - goto PARSE_CFGFILE; - } + goto PARSE_CFGFILE; + } - /* No commandline path specifed, probe default locations... */ + /* No commandline path specifed, probe default locations... */ - if (probe_cfgfile(cfgfile) < 0) - goto NO_CFGFILE; + if (probe_cfgfile(cfgfile) < 0) goto NO_CFGFILE; PARSE_CFGFILE: - DEBUG("Using configuration file %s", cfgfile); - cfg = facemgr_cfg_create(); - if (!cfg) - goto ERR_FACEMGR_CFG; + DEBUG("Using configuration file %s", cfgfile); + cfg = facemgr_cfg_create(); + if (!cfg) goto ERR_FACEMGR_CFG; - if (parse_config_file(cfgfile, cfg) < 0) { - ERROR("Error parsing configuration file %s", cfgfile); - goto ERR_PARSE; - } + if (parse_config_file(cfgfile, cfg) < 0) { + ERROR("Error parsing configuration file %s", cfgfile); + goto ERR_PARSE; + } - facemgr = facemgr_create_with_config(cfg); - if (!facemgr) - goto ERR_FACEMGR_CONFIG; + facemgr = facemgr_create_with_config(cfg); + if (!facemgr) goto ERR_FACEMGR_CONFIG; - goto MAIN_LOOP; + goto MAIN_LOOP; NO_CFGFILE: - facemgr = facemgr_create(); - if (!facemgr) - goto ERR_FACEMGR; + facemgr = facemgr_create(); + if (!facemgr) goto ERR_FACEMGR; MAIN_LOOP: - /* Main loop */ - loop = loop_create(); - facemgr_set_callback(facemgr, loop, (void*)loop_callback); + /* Main loop */ + loop = loop_create(); + if (!loop) { + ERROR("Failed to create main loop"); + goto ERR_LOOP; + } + facemgr_set_callback(facemgr, loop, (void*)loop_callback); #ifdef __ANDROID__ - facemgr_set_jvm(facemgr, NULL); + facemgr_set_jvm(facemgr, NULL); #endif /* __ ANDROID__ */ - DEBUG("Bootstrap..."); + DEBUG("Bootstrap..."); - if (facemgr_bootstrap(facemgr) < 0 ) - goto ERR_BOOTSTRAP; + if (facemgr_bootstrap(facemgr) < 0) goto ERR_BOOTSTRAP; - if (loop_dispatch(loop) < 0) { - ERROR("Failed to run main loop"); - return EXIT_FAILURE; - } + if (loop_dispatch(loop) < 0) { + ERROR("Failed to run main loop"); + goto ERR_DISPATCH; + } #ifdef __linux__ #ifdef WITH_THREAD - unsigned cpt = 0; - while(!stop) { - if (cpt == 10) { - DEBUG("<facelets>"); + unsigned cpt = 0; + while (!stop) { + if (cpt == 10) { + DEBUG("<facelets>"); #if 1 - facemgr_list_facelets(facemgr, dump_facelet, NULL); + facemgr_list_facelets(facemgr, dump_facelet, NULL); #else - char * buffer; - int n = facemgr_list_facelets_json(facemgr, &buffer); - printf("%s\n", buffer); - free(buffer); + char* buffer; + int n = facemgr_list_facelets_json(facemgr, &buffer); + printf("%s\n", buffer); + free(buffer); #endif - DEBUG("</facelets>"); - cpt = 0; - } - usleep(500000); - cpt++; + DEBUG("</facelets>"); + cpt = 0; } + usleep(500000); + cpt++; + } #endif /* WITH_THREAD */ #endif /* __linux__ */ - facemgr_stop(facemgr); + facemgr_stop(facemgr); - if (loop_undispatch(loop) < 0) { - ERROR("Failed to terminate main loop"); - return EXIT_FAILURE; - } + if (loop_undispatch(loop) < 0) { + ERROR("Failed to terminate main loop"); + } - facemgr_free(facemgr); + facemgr_free(facemgr); - if (cfg) - facemgr_cfg_free(cfg); + if (cfg) facemgr_cfg_free(cfg); - loop_free(loop); + loop_free(loop); - return EXIT_SUCCESS; + return EXIT_SUCCESS; ERR_BOOTSTRAP: + facemgr_free(facemgr); +ERR_DISPATCH: + loop_free(loop); +ERR_LOOP: - facemgr_free(facemgr); - loop_free(loop); ERR_FACEMGR_CONFIG: ERR_FACEMGR: ERR_PARSE: - if (cfg) - facemgr_cfg_free(cfg); + if (cfg) facemgr_cfg_free(cfg); ERR_FACEMGR_CFG: ERR_PATH: ERR_CMDLINE: - return EXIT_FAILURE; - - + return EXIT_FAILURE; } diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt index 22f81401f..bf5ffd699 100644 --- a/ctrl/libhicnctrl/CMakeLists.txt +++ b/ctrl/libhicnctrl/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,50 +11,65 @@ # See the License for the specific language governing permissions and # limitations under the License. +############################################################## +# Project and cmake version +############################################################## cmake_minimum_required(VERSION 3.10 FATAL_ERROR) - project(libhicnctrl) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif() +############################################################## +# Cmake modules +############################################################## set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" ) -include(BuildMacros) - -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) - -set(CMAKE_MACOSX_RPATH ON) - +############################################################## +# Libs and Bins names +############################################################## set(LIBHICNCTRL hicnctrl) - set(LIBHICNCTRL ${LIBHICNCTRL} CACHE INTERNAL "" FORCE) set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared CACHE INTERNAL "" FORCE) set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static CACHE INTERNAL "" FORCE) set(HICNCTRL hicnctrl CACHE INTERNAL "" FORCE) -set(LIBHICNCTRL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE) +set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL}) +set(LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules) + + +############################################################## +# Packaging and versioning +############################################################## +include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake) + +############################################################## +# C Standard +############################################################## +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(CMAKE_MACOSX_RPATH ON) + + +############################################################## +# Check if building as subproject or as root project +############################################################## if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") - find_package_wrapper(HicnPlugin REQUIRED) - endif() + include(CommonSetup) - find_package_wrapper(Libhicn REQUIRED) - list(APPEND HICN_LIBRARIES ${LIBHICN_SHARED}) + find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE) - set(HICN_INCLUDE_DIRS - ${HICN_INCLUDE_DIRS} - ${HICNPLUGIN_INCLUDE_DIRS} - ${SAFE_VAPI_INCLUDE_DIRS}) + if (DISABLE_SHARED_LIBRARIES) + set(LIBTYPE static) + else() + set(LIBTYPE shared) + endif() + list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE}) else() if (DISABLE_SHARED_LIBRARIES) if (WIN32) @@ -65,36 +80,21 @@ else() list(APPEND DEPENDENCIES ${LIBHICN_STATIC} ) - elseif (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") - set( - HICN_INCLUDE_DIRS - ${HICN_INCLUDE_DIRS} - ${HICNPLUGIN_INCLUDE_DIRS} - ${SAFE_VAPI_INCLUDE_DIRS} - ) - - list(APPEND DEPENDENCIES - hicn_plugin - ${SAFE_VAPI_SHARED} - ) else () set(HICN_LIBRARIES ${LIBHICN_SHARED}) list(APPEND DEPENDENCIES ${LIBHICN_SHARED} ) endif () - endif() -set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL}) -set (LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules) +############################################################## +# Include directories +############################################################## add_subdirectory(includes) add_subdirectory(src) -include(Packaging) - if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - include(Packager) - make_packages() + make_packages() endif() diff --git a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake b/ctrl/libhicnctrl/cmake/packaging.cmake index 2851375be..74905d6c4 100644 --- a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake +++ b/ctrl/libhicnctrl/cmake/packaging.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -31,7 +31,7 @@ set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES ) set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES - "${LIBHICNCTRL_COMPONENT} (>= stable_version)" + "${LIBHICNCTRL_COMPONENT} (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) @@ -41,16 +41,16 @@ set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES ) set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES - "${LIBHICNCTRL_COMPONENT} >= stable_version" + "${LIBHICNCTRL_COMPONENT} = stable_version" CACHE STRING "Dependencies for deb/rpm package." ) set(${LIBHICNCTRL_COMPONENT_MODULES}_DEB_DEPENDENCIES - "hicn-plugin (>= stable_version)" + "hicn-plugin (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) set(${LIBHICNCTRL_COMPONENT_MODULES}_RPM_DEPENDENCIES - "hicn-plugin >= stable_version" + "hicn-plugin = stable_version" CACHE STRING "Dependencies for deb/rpm package." ) diff --git a/ctrl/libhicnctrl/examples/Makefile b/ctrl/libhicnctrl/examples/Makefile index ad0e46a1e..a3aae11b0 100644 --- a/ctrl/libhicnctrl/examples/Makefile +++ b/ctrl/libhicnctrl/examples/Makefile @@ -1,7 +1,7 @@ EXEC = $(shell basename $$(pwd)) CC = gcc -CFLAGS = -std=gnu11 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing -DWITH_POLICY=1 +CFLAGS = -std=gnu11 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing -DWITH_POLICY LDFLAGS = -lhicn -lhicnctrl SRC = $(wildcard *.c) diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c index 5f92f5906..a2ef3e9db 100644 --- a/ctrl/libhicnctrl/examples/create_face.c +++ b/ctrl/libhicnctrl/examples/create_face.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,125 +22,117 @@ */ #include <stdlib.h> -#include <sys/types.h> // getifaddrs -#include <ifaddrs.h> // getifaddrs +#include <sys/types.h> // getifaddrs +#include <ifaddrs.h> // getifaddrs #include <stdio.h> -#include <string.h> /* for strncpy */ -#include <sys/socket.h> // socket -#include <sys/ioctl.h> // ioctl +#include <sys/socket.h> // socket +#include <sys/ioctl.h> // ioctl #include <unistd.h> #include <hicn/ctrl.h> #include <hicn/util/log.h> -int get_local_info(char * if_name, ip_address_t * local_ip) { - struct ifaddrs *addrs; - struct ifreq ifr = { - .ifr_addr.sa_family = AF_INET, - }; - int ret = -1; - - int fd = socket(AF_INET, SOCK_DGRAM, 0); - - getifaddrs(&addrs); - - for (struct ifaddrs * tmp = addrs; tmp; tmp = tmp->ifa_next) { - if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET) - continue; - if (strcmp(tmp->ifa_name, "lo") == 0) - continue; - snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name); - - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name); - if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { - //perror("ioctl"); - continue; - } - - *local_ip = IP_ADDRESS_EMPTY; - local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; - if (ip_address_empty(local_ip)) - continue; - - ret = 0; - break; - } - - freeifaddrs(addrs); - close(fd); - return ret; -} - -int main() { - char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1"; - - ip_address_t local_ip; - ip_address_t remote_ip; - char if_name[IFNAMSIZ]; +int get_local_info(char *if_name, hicn_ip_address_t *local_ip) { + struct ifaddrs *addrs; + struct ifreq ifr = { + .ifr_addr.sa_family = AF_INET, + }; + int ret = -1; - /* Retrieving local info */ + int fd = socket(AF_INET, SOCK_DGRAM, 0); - if (get_local_info(if_name, &local_ip) < 0) { - DEBUG("Error getting local information"); - goto ERR_INIT; - } + getifaddrs(&addrs); - char local_ip_str[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip, AF_INET); - DEBUG("Local information :"); - DEBUG(" - Interface name : %s", if_name); - DEBUG(" - IP address : %s", local_ip_str); + for (struct ifaddrs *tmp = addrs; tmp; tmp = tmp->ifa_next) { + if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET) continue; + if (strcmp(tmp->ifa_name, "lo") == 0) continue; + snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name); - if (ip_address_pton (remote_ip_str, &remote_ip) < 0){ - DEBUG("Error parsing remote IP address"); - goto ERR_INIT; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name); + if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { + // perror("ioctl"); + continue; } - /* Filling face information */ - hc_face_t face = { - .face = { - .type = FACE_TYPE_UDP, - .family = AF_INET, - .local_addr = local_ip, - .remote_addr = remote_ip, - .local_port = 6000, - .remote_port = 6000, - .admin_state = FACE_STATE_UNDEFINED, - .state = FACE_STATE_UNDEFINED, -#ifdef WITH_POLICY - .priority = 0, - .tags = POLICY_TAGS_EMPTY, -#endif /* WITH_POLICY */ - }, - }; - if (netdevice_set_name(&face.face.netdevice, if_name) < 0) { - DEBUG("Error setting face netdevice name"); - goto ERR_INIT; - } + *local_ip = IP_ADDRESS_EMPTY; + local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; + if (hicn_ip_address_empty(local_ip)) continue; - /* Connecting to socket and creating face */ + ret = 0; + break; + } - hc_sock_t * socket = hc_sock_create(); - if (!socket){ - DEBUG("Error creating libhicnctrl socket"); - goto ERR_SOCK; - } - - if (hc_sock_connect(socket) < 0){ - DEBUG("Error connecting to forwarder"); - goto ERR; - } - - if (hc_face_create(socket, &face) < 0){ - DEBUG("Error creating face"); - goto ERR; - } + freeifaddrs(addrs); + close(fd); + return ret; +} - DEBUG("Face created successfully"); +int main() { + char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1"; + + hicn_ip_address_t local_ip; + hicn_ip_address_t remote_ip; + char if_name[IFNAMSIZ]; + + /* Retrieving local info */ + + if (get_local_info(if_name, &local_ip) < 0) { + DEBUG("Error getting local information"); + goto ERR_INIT; + } + + char local_ip_str[MAXSZ_IP_ADDRESS]; + hicn_ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip); + DEBUG("Local information :"); + DEBUG(" - Interface name : %s", if_name); + DEBUG(" - IP address : %s", local_ip_str); + + if (hicn_ip_address_pton(remote_ip_str, &remote_ip) < 0) { + DEBUG("Error parsing remote IP address"); + goto ERR_INIT; + } + + /* Filling face information */ + hc_face_t face = { + .type = FACE_TYPE_UDP, + .family = AF_INET, + .local_addr = local_ip, + .remote_addr = remote_ip, + .local_port = 6000, + .remote_port = 6000, + .admin_state = FACE_STATE_UNDEFINED, + .state = FACE_STATE_UNDEFINED, + .priority = 0, + .tags = POLICY_TAGS_EMPTY, + }; + if (netdevice_set_name(&face.netdevice, if_name) < 0) { + DEBUG("Error setting face netdevice name"); + goto ERR_INIT; + } + + /* Connecting to socket and creating face */ + + hc_sock_t *socket = hc_sock_create_forwarder(FORWARDER_TYPE_HICNLIGHT); + if (!socket) { + DEBUG("Error creating libhicnctrl socket"); + goto ERR_SOCK; + } + + if (hc_sock_connect(socket) < 0) { + DEBUG("Error connecting to forwarder"); + goto ERR; + } + + if (hc_face_create(socket, &face) < 0) { + DEBUG("Error creating face"); + goto ERR; + } + + INFO("Face created successfully"); ERR: - hc_sock_free(socket); + hc_sock_free(socket); ERR_SOCK: ERR_INIT: - return 0; + return 0; } diff --git a/ctrl/libhicnctrl/examples/update_priority.c b/ctrl/libhicnctrl/examples/update_priority.c index d350f71c9..6dd974067 100644 --- a/ctrl/libhicnctrl/examples/update_priority.c +++ b/ctrl/libhicnctrl/examples/update_priority.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -24,37 +24,36 @@ #include <hicn/ctrl.h> #include <hicn/util/log.h> -int main(int argc, char **argv) -{ - if (argc != 3) { - fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]); - exit(EXIT_FAILURE); - } - unsigned face_id = atoi(argv[1]); - unsigned priority = atoi(argv[2]); - char face_id_s[SYMBOLIC_NAME_LEN]; - - hc_sock_t * socket = hc_sock_create(); - if (!socket){ - DEBUG("Error creating libhicnctrl socket"); - goto ERR_SOCK; - } - - if (hc_sock_connect(socket) < 0){ - DEBUG("Error connecting to forwarder"); - goto ERR; - } - - snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id); - if (hc_face_set_priority(socket, face_id_s, priority) < 0) { - DEBUG("Error setting face priority"); - goto ERR; - } - - DEBUG("Face priority updated successfully"); +int main(int argc, char **argv) { + if (argc != 3) { + fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]); + exit(EXIT_FAILURE); + } + unsigned face_id = atoi(argv[1]); + unsigned priority = atoi(argv[2]); + char face_id_s[SYMBOLIC_NAME_LEN]; + + hc_sock_t *socket = hc_sock_create_forwarder(FORWARDER_TYPE_HICNLIGHT); + if (!socket) { + DEBUG("Error creating libhicnctrl socket"); + goto ERR_SOCK; + } + + if (hc_sock_connect(socket) < 0) { + DEBUG("Error connecting to forwarder"); + goto ERR; + } + + snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id); + if (hc_face_set_priority(socket, face_id_s, priority) < 0) { + DEBUG("Error setting face priority"); + goto ERR; + } + + DEBUG("Face priority updated successfully"); ERR: - hc_sock_free(socket); + hc_sock_free(socket); ERR_SOCK: - return 0; + return 0; } diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt index 50cfa4ad5..63b8aa9a7 100644 --- a/ctrl/libhicnctrl/includes/CMakeLists.txt +++ b/ctrl/libhicnctrl/includes/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,17 +11,46 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(LIBHICNCTRL_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR} "" +############################################################## +# Public headers directory +############################################################## +set(Libhicnctrl_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" FORCE ) + +############################################################## +# To install header files +############################################################## set(TO_INSTALL_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/action.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/callback.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/command.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/data.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/fw_interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/object.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/object_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/active_interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/cache.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/policy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/punting.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/stats.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/subscription.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/parse.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/socket.h PARENT_SCOPE ) diff --git a/ctrl/libhicnctrl/includes/ctrl.h b/ctrl/libhicnctrl/includes/ctrl.h index e61b7a482..477afd152 100644 --- a/ctrl/libhicnctrl/includes/ctrl.h +++ b/ctrl/libhicnctrl/includes/ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl.h b/ctrl/libhicnctrl/includes/hicn/ctrl.h index e61b7a482..4decdf10f 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,5 +21,6 @@ #define HICNCTRL_H #include <hicn/ctrl/api.h> +#include <hicn/ctrl/socket.h> #endif /* HICNCTRL_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/action.h b/ctrl/libhicnctrl/includes/hicn/ctrl/action.h new file mode 100644 index 000000000..55c4ebf77 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/action.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-2022 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 action.h + * \brief Actions. + */ + +#ifndef HICNCTRL_ACTION_H +#define HICNCTRL_ACTION_H + +#define foreach_action \ + _(UNDEFINED) \ + _(CREATE) \ + _(UPDATE) \ + _(DELETE) \ + _(LIST) \ + _(GET) \ + _(SET) \ + _(SERVE) \ + _(STORE) \ + _(CLEAR) \ + _(SUBSCRIBE) \ + _(N) + +typedef enum { +#define _(x) ACTION_##x, + foreach_action +#undef _ +} hc_action_t; + +extern const char *action_str[]; + +#define action_str(x) action_str[x] + +hc_action_t action_from_str(const char *action_str); + +#endif /* HICNCTRL_ACTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h index b5a968800..87f0e955d 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021-2023 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,8 +58,6 @@ * provide a set of defines to preserve backwards compatibility. At the * moment, those defines are : * - * WITH_POLICY: - * */ #ifndef HICNTRL_API @@ -67,10 +65,27 @@ #include <stdbool.h> #include <stdint.h> - +#include <stddef.h> // object_offset_t + +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/callback.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/objects.h> +#include <hicn/ctrl/socket.h> #include <hicn/util/ip_address.h> -#include <hicn/ctrl/commands.h> -#include "face.h" +#include <hicn/face.h> +#include <hicn/strategy.h> + +#include <hicn/base.h> +/* + * This has to be common between hicn-light and hicn-plugin. We now we keep the + * minimum of the two + */ +#define SYMBOLIC_NAME_LEN 16 + +#include <hicn/ctrl/objects.h> #define HICN_DEFAULT_PORT 9695 @@ -95,266 +110,21 @@ })x) \ .b) #endif + +#define MAX2(x1, x2) (x1 > x2 ? x1 : x2) +#define MAX4(x1, x2, x3, x4) (MAX2(MAX2(x1, x2), MAX2(x3, x4))) +#define MAX8(x1, x2, x3, x4, x5, x6, x7, x8) \ + (MAX2(MAX4(x1, x2, x3, x4), MAX4(x5, x6, x7, x8))) + /****************************************************************************** * Message helper types and aliases ******************************************************************************/ -#define foreach_command \ - _(UNDEFINED) \ - _(CREATE) \ - _(UPDATE) \ - _(DELETE) \ - _(LIST) \ - _(SET) \ - _(N) - -typedef enum { -#define _(x) ACTION_##x, - foreach_command -#undef _ -} hc_action_t; - /** * \brief hICN control message header */ typedef struct hc_msg_s hc_msg_t; - -/****************************************************************************** - * Control Data - ******************************************************************************/ - -struct hc_data_s; -typedef int (*data_callback_t)(struct hc_data_s *, void *); - -/** - * \brief Holds the results of an hICN control request - */ -typedef struct hc_data_s { - size_t size; - size_t current; - size_t max_size_log; - size_t in_element_size; - size_t out_element_size; - u8 command_id; /**< Expected message type (should give element size) */ - u8 *buffer; - bool complete; - - /* Callbacks */ - data_callback_t complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data); - void *complete_cb_data; - int ret; -} hc_data_t; - -/** - * Create a structure holding the results of an hICN control request. - * \result The newly create data structure. - */ -hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb); - -/** - * Free a structure holding the results of an hICN control request. - * \param [in] data - The data structure to free. - */ -void hc_data_free(hc_data_t *data); - -/** - * \brief Adds many new results at the end of the data structure, eventually - * allocating buffer space for it. - * \param [in] data - The data structure to which to add elements. - * \param [in] elements - The array of elements to add. - * \param [in] count - The number of elements to add. - * \return Error code - * - * NOTE: The size of the element should match the one declared at structure - * initialization. - */ -int hc_data_push_many(hc_data_t *data, const void *elements, size_t count); - -/** - * \brief Adds a new result at the end of the data structure, eventually - * allocating buffer space for it. - * \param [in] data - The data structure to which to add an element. - * \param [in] element - The element to add - * \return Error code - * - * NOTE: The size of the element should match the one declared at structure - * initialization. - */ -int hc_data_push(hc_data_t *data, const void *element); - -/** - * \brief Configure a callback (along with private data) to be called upon - * completion of a request - * \param [in] data - hICN control data - * \param [in] cb - Callback function - * \param [in] cb_data - Callback private data - */ -int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data); - -/** - * \brief Mark the data structure as complete. - * \param [in] data - The data structure to which to add an element. - * \return The error code resulting from callback execution if any. 0 is - * returned if the callback executed successfully, or if no callback were - * defined. - */ -int hc_data_set_complete(hc_data_t *data); - -/** - * \brief Reset the data structure holding control data - * \param [in] data - hICN control data - * \return Error code - */ -int hc_data_reset(hc_data_t *data); - -/** - * \brief Find en element in the data structure - * \param [in] data - The data structure in which to find - * \param [in] element - The element to find - * \param [out] found - A pointer to the element, or NULL if not found. - * \return Error code - */ -#define GENERATE_FIND_HEADER(TYPE) \ -int \ -hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \ - hc_ ## TYPE ## _t **found) - -#define GENERATE_FIND(TYPE) \ -int \ -hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \ - hc_ ## TYPE ## _t **found) \ -{ \ - foreach_type(hc_ ## TYPE ## _t, x, data) { \ - if (hc_ ## TYPE ## _cmp(x, element) == 0) { \ - *found = x; \ - return 0; \ - } \ - }; \ - *found = NULL; /* this is optional */ \ - return 0; \ -} - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -/* This should be at least equal to the maximum packet size */ -#define RECV_BUFLEN 8192 - -typedef enum { - HICNLIGHT, - VPP, - UNDEFINED -} forwarder_t; - -/** - * \brief Holds the state of an hICN control socket - */ -typedef struct hc_sock_s hc_sock_t; - -/** - * \brief Create an hICN control socket using the specified URL. - * \param [in] url - The URL to connect to. - * \return an hICN control socket - */ -hc_sock_t * -hc_sock_create_url(const char * url); - -/** - * \brief Create an hICN control socket using the provided forwarder. - * \return an hICN control socket - */ -hc_sock_t * -hc_sock_create_forwarder(forwarder_t forwarder); - -/** - * \brief Create an hICN control socket using the default connection type. - * \return an hICN control socket - */ -hc_sock_t * -hc_sock_create(void); - -/** - * \brief Frees an hICN control socket - * \param [in] s - hICN control socket - */ -void hc_sock_free(hc_sock_t *s); - -/** - * \brief Returns the next available sequence number to use for requests to the - * API. - * \param [in] s - hICN control socket - */ -int hc_sock_get_next_seq(hc_sock_t *s); - -/** - * \brief Sets the socket as non-blocking - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_set_nonblocking(hc_sock_t *s); - -/** - * \brief Return the file descriptor associated to the hICN contorl sock - * \param [in] s - hICN control socket - * \return The file descriptor (positive value), or a negative integer in case - * of error - */ -int hc_sock_get_fd(hc_sock_t *s); - -/** - * \brief Connect the socket - * \return Error code - */ -int hc_sock_connect(hc_sock_t *s); - -/** - * \brief Return the offset and size of available buffer space - * \param [in] s - hICN control socket - * \param [out] buffer - Offset in buffer - * \param [out] size - Remaining size - * \return Error code - */ -int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size); - -/** - * \brief Write/read iexchance on the control socket (internal helper function) - * \param [in] s - hICN control socket - * \param [in] msg - Message to send - * \param [in] msglen - Length of the message to send - * \return Error code - */ -int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq); - -/** - * \brief Helper for reading socket contents - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_recv(hc_sock_t *s); - -/** - * \brief Processing data received by socket - * \param [in] s - hICN control socket - * \param [in] parse - Parse function to convert remote types into lib native - * types, or NULL not to perform any translation. - * \return Error code - */ -int hc_sock_process(hc_sock_t *s, hc_data_t **data); - -/** - * \brief Callback used in async mode when data is available on the socket - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_callback(hc_sock_t *s, hc_data_t **data); - -/** - * \brief Reset the state of the sock (eg. to handle a reconnecton) - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_reset(hc_sock_t *s); +typedef struct hc_result_s hc_result_t; /****************************************************************************** * Command-specific structures and functions @@ -368,7 +138,8 @@ int hc_sock_reset(hc_sock_t *s); * * We redefine command struct: * - for uniformization - * - to use enum instead of type specifiers more appropriate for packet format + * - to use enum instead of type specifiers more appropriate for packet + * format * - to use more flexible types such as for manipulating IP addresses * - host endianness * - more intuitive field name, ordering, consistency, and hierarchy removal @@ -380,9 +151,9 @@ int hc_sock_reset(hc_sock_t *s); * * RETURN DATA FIXME * - * \param [out] pdata - Pointer to the structure storing the results of the call - * (NULL if no data has been received). If the pointer is NULL, no result will - * be stored and only the error code will be exposed to the caller. It is + * \param [out] pdata - Pointer to the structure storing the results of the + * call (NULL if no data has been received). If the pointer is NULL, no result + * will be stored and only the error code will be exposed to the caller. It is * expected that the caller frees this structure using hc_data_free() after * usage. * \see hc_data_free. @@ -407,179 +178,95 @@ int hc_sock_reset(hc_sock_t *s); #define NULLTERM 1 #endif -#define INTERFACE_LEN 16 - #define MAXSZ_HC_NAME_ SYMBOLIC_NAME_LEN #define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM #define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */ #define MAXSZ_HC_ID MAXSZ_HC_ID_ + NULLTERM -#define foreach_type(TYPE, VAR, data) \ - for (TYPE *VAR = (TYPE *)data->buffer; \ - VAR < (TYPE *)(data->buffer + data->size * data->out_element_size); \ - VAR++) - -/** - * New type is defined to reconciliate different enum for add and list. - * Also, values not implemented have been removed for clarity. - */ -#define foreach_connection_type \ - _(UNDEFINED) \ - _(TCP) \ - _(UDP) \ - _(HICN) \ - _(N) - -typedef enum { -#define _(x) CONNECTION_TYPE_##x, - foreach_connection_type -#undef _ -} hc_connection_type_t; - -#define MAXSZ_HC_CONNECTION_TYPE_ 9 -#define MAXSZ_HC_CONNECTION_TYPE MAXSZ_HC_CONNECTION_TYPE_ + NULLTERM + HOTFIXMARGIN - -extern const char *connection_type_str[]; - -hc_connection_type_t connection_type_from_str(const char *str); - -/* Same order as connection_state_t in hicn/core/connectionState.h */ -#define foreach_connection_state \ - _(UNDEFINED) \ - _(DOWN) \ - _(UP) \ - _(N) +#if 0 +#define foreach_type(TYPE, VAR, data) \ + for (TYPE *VAR = (TYPE *)data->buffer; \ + VAR < (TYPE *)((data)->buffer + (data)->size * sizeof(TYPE)); VAR++) +#endif -typedef enum { -#define _(x) HC_CONNECTION_STATE_##x, - foreach_connection_state -#undef _ -} hc_connection_state_t; +#define INPUT_ERROR -2 +#define UNSUPPORTED_CMD_ERROR -3 -#define MAXSZ_HC_CONNECTION_STATE_ 9 -#define MAXSZ_HC_CONNECTION_STATE MAXSZ_HC_CONNECTION_STATE_ + NULLTERM +/*----------------------------------------------------------------------------* + * WLDR + *----------------------------------------------------------------------------*/ -extern const char *connection_state_str[]; +// per connection +int hc_wldr_set(hc_sock_t *s /* XXX */); -typedef int (*HC_PARSE)(const u8 *, u8 *); +/* Object */ -/*----------------------------------------------------------------------------* - * Listeners - *----------------------------------------------------------------------------*/ +#define MAXSZ_HC_OBJECT \ + MAX8(MAXSZ_HC_CONNECTION, MAXSZ_HC_LISTENER, MAXSZ_HC_ROUTE, MAXSZ_HC_FACE, \ + MAXSZ_HC_PUNTING, MAXSZ_HC_STRATEGY, MAXSZ_HC_POLICY, MAXSZ_HC_STATS) -// FIXME the listener should not require any port for hICN... typedef struct { - char name[SYMBOLIC_NAME_LEN]; /* K.w */ // XXX clarify what used for - char interface_name[INTERFACE_LEN]; /* Kr. */ - u32 id; - hc_connection_type_t type; /* .rw */ - int family; /* .rw */ - ip_address_t local_addr; /* .rw */ - u16 local_port; /* .rw */ -} hc_listener_t; + hc_action_t action; + hc_object_type_t object_type; + hc_object_t object; +} hc_command_t; + +// NEW API CALLS + +int hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_data_t **pdata); +int hc_execute_async(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_result_callback_t callback, void *callback_data); + +int hc_object_create(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object); +int hc_object_get(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object, hc_object_t **found); +int hc_object_delete(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object); +int hc_object_list(hc_sock_t *s, hc_object_type_t object_type, + hc_data_t **pdata); + +/* Former API */ int hc_listener_create(hc_sock_t *s, hc_listener_t *listener); /* listener_found might eventually be allocated, and needs to be freed */ -int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found); +int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_data_t **pdata); int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener); int hc_listener_list(hc_sock_t *s, hc_data_t **pdata); -int hc_listener_validate(const hc_listener_t *listener); -int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2); -int hc_listener_parse(void *in, hc_listener_t *listener); - -#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data) - -#define MAXSZ_HC_LISTENER_ \ - INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_ -#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM - -GENERATE_FIND_HEADER(listener); - -int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener); - -/*----------------------------------------------------------------------------* - * Connections - *----------------------------------------------------------------------------*/ - -/* - * NOTE : - * - interface_name is mainly used to derive listeners from connections, but is - * not itself used to create connections. - */ -typedef struct { - u32 id; /* Kr. */ - char name[SYMBOLIC_NAME_LEN]; /* K.w */ - char interface_name[INTERFACE_LEN]; /* Kr. */ - hc_connection_type_t type; /* .rw */ - int family; /* .rw */ - ip_address_t local_addr; /* .rw */ - u16 local_port; /* .rw */ - ip_address_t remote_addr; /* .rw */ - u16 remote_port; /* .rw */ - hc_connection_state_t admin_state; /* .rw */ -#ifdef WITH_POLICY - uint32_t priority; /* .rw */ - policy_tags_t tags; /* .rw */ -#endif /* WITH_POLICY */ - hc_connection_state_t state; /* .r. */ -} hc_connection_t; - int hc_connection_create(hc_sock_t *s, hc_connection_t *connection); -/* connection_found will be allocated, and must be freed */ +/* connection_found might eventually be allocated, and needs to be freed */ int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found); + hc_data_t **pdata); +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection); int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection); int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated); -int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection); -/* -int hc_connection_remove_by_id(hc_sock_t * s, char * name); -int hc_connection_remove_by_name(hc_sock_t * s, char * name); -*/ int hc_connection_list(hc_sock_t *s, hc_data_t **pdata); -int hc_connection_validate(const hc_connection_t *connection); -int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2); -int hc_connection_parse(void *in, hc_connection_t *connection); - -int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); -#ifdef WITH_POLICY -int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); -int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); -#endif /* WITH_POLICY */ - -#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) - -#define MAXSZ_HC_CONNECTION_ \ - MAXSZ_HC_CONNECTION_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \ - MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3) -#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM - -GENERATE_FIND_HEADER(connection); - -int hc_connection_snprintf(char *s, size_t size, - const hc_connection_t *connection); - -/*----------------------------------------------------------------------------* - * Faces - * - * A face is an abstraction introduced by the control library to abstract the - * forwarder implementation details. It encompasses connections and listeners - * and ensures the right dependencies are enforced, eg that we always have a - * listener when a connection is created. - * - *----------------------------------------------------------------------------*/ - -typedef struct { - face_id_t id; - char name[SYMBOLIC_NAME_LEN]; - face_t face; // or embed ? - // face_id_t parent; /* Pointer from connection to listener */ -} hc_face_t; +int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state); +int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority); +int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags); + +int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state); +int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority); +int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags); + +int hc_route_create(hc_sock_t *s, hc_route_t *route); +// hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route); +int hc_route_delete(hc_sock_t *s, hc_route_t *route); +int hc_route_list(hc_sock_t *s, hc_data_t **pdata); +int hc_route_list_async(hc_sock_t *s); /** * \brief Create a face @@ -590,73 +277,37 @@ typedef struct { * The face parameters will be updated with the face ID. */ int hc_face_create(hc_sock_t *s, hc_face_t *face); -int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found); -int hc_face_delete(hc_sock_t *s, hc_face_t *face); +int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_data_t **pdata); +int hc_face_delete(hc_sock_t *s, + hc_face_t *face); //, uint8_t delete_listener); int hc_face_list(hc_sock_t *s, hc_data_t **pdata); -int hc_face_list_async(hc_sock_t *s); //, hc_data_t ** pdata); - -int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); -#ifdef WITH_POLICY -int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); -int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); -#endif /* WITH_POLICY */ - -#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data) - -#define MAX_FACE_ID 255 -#define MAXSZ_FACE_ID_ 3 -#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM -#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN -#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM - -#define MAXSZ_HC_FACE_ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN -#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM - -int hc_face_snprintf(char *s, size_t size, hc_face_t *face); - -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -typedef struct { - face_id_t face_id; /* Kr. */ - int family; /* Krw */ - ip_address_t remote_addr; /* krw */ - u8 len; /* krw */ - u16 cost; /* .rw */ - hc_face_t face; -} hc_route_t; - -int hc_route_parse(void *in, hc_route_t *route); - -int hc_route_create(hc_sock_t * s, hc_route_t * route); -int hc_route_delete(hc_sock_t * s, hc_route_t * route); -int hc_route_list(hc_sock_t * s, hc_data_t ** pdata); -int hc_route_list_async(hc_sock_t * s); +int hc_face_list_async(hc_sock_t *s); -#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data) +int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state); +int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority); +int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags); -#define MAX_COST 65535 -#define MAXSZ_COST 5 -#define MAX_LEN 255 -#define MAXSZ_LEN 3 - -#define MAXSZ_HC_ROUTE_ \ - MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN -#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM +int hc_strategy_list(hc_sock_t *s, hc_data_t **data); +int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy); +int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy); -int hc_route_snprintf(char *s, size_t size, hc_route_t *route); +int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache); +int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache); +int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache); +int hc_cache_list(hc_sock_t *s, hc_data_t **pdata); -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ +int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme); +int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme); +int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme); +int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme); +int hc_mapme_create(hc_sock_t *s, hc_mapme_t *mapme); -typedef struct { - face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ? - int family; /* Krw */ - ip_address_t prefix; /* krw */ - u8 prefix_len; /* krw */ -} hc_punting_t; +int hc_policy_create(hc_sock_t *s, hc_policy_t *policy); +int hc_policy_delete(hc_sock_t *s, hc_policy_t *policy); +int hc_policy_list(hc_sock_t *s, hc_data_t **pdata); int hc_punting_create(hc_sock_t *s, hc_punting_t *punting); int hc_punting_get(hc_sock_t *s, hc_punting_t *punting, @@ -664,91 +315,12 @@ int hc_punting_get(hc_sock_t *s, hc_punting_t *punting, int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting); int hc_punting_list(hc_sock_t *s, hc_data_t **pdata); -int hc_punting_validate(const hc_punting_t *punting); -int hc_punting_cmp(const hc_punting_t *c1, const hc_punting_t *c2); -int hc_punting_parse(void *in, hc_punting_t *punting); - -#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data) - -#define MAXSZ_HC_PUNTING_ 0 -#define MAXSZ_HC_PUNTING MAXSZ_HC_PUNTING_ + NULLTERM - -GENERATE_FIND_HEADER(punting); - -int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting); - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -int hc_cache_set_store(hc_sock_t *s, int enabled); -int hc_cache_set_serve(hc_sock_t *s, int enabled); - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -#define MAXSZ_STRATEGY_NAME 255 - -typedef struct { - char name[MAXSZ_STRATEGY_NAME]; -} hc_strategy_t; - -int hc_strategy_list(hc_sock_t *s, hc_data_t **data); - -#define foreach_strategy(VAR, data) foreach_type(hc_strategy_t, VAR, data) - -#define MAXSZ_HC_STRATEGY_ MAXSZ_STRATEGY_NAME -#define MAXSZ_HC_STRATEGY MAXSZ_HC_STRATEGY_ + NULLTERM - -int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy); - -// per prefix -int hc_strategy_set(hc_sock_t *s /* XXX */); - -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -int hc_wldr_set(hc_sock_t *s /* XXX */); - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -int hc_mapme_set(hc_sock_t *s, int enabled); -int hc_mapme_set_discovery(hc_sock_t *s, int enabled); -int hc_mapme_set_timescale(hc_sock_t *s, double timescale); -int hc_mapme_set_retx(hc_sock_t *s, double timescale); - -/*----------------------------------------------------------------------------* - * Policies - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -typedef struct { - int family; /* Krw */ - ip_address_t remote_addr; /* krw */ - u8 len; /* krw */ - hicn_policy_t policy; /* .rw */ -} hc_policy_t; - -int hc_policy_parse(void *in, hc_policy_t *policy); - -int hc_policy_create(hc_sock_t *s, hc_policy_t *policy); -int hc_policy_delete(hc_sock_t *s, hc_policy_t *policy); -int hc_policy_list(hc_sock_t *s, hc_data_t **pdata); - -#define foreach_policy(VAR, data) foreach_type(hc_policy_t, VAR, data) - -/* TODO */ -#define MAXSZ_HC_POLICY_ 0 -#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM - -int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy); +int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription); +int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription); -#endif /* WITH_POLICY */ +int hc_stats_list(hc_sock_t *s, hc_data_t **pdata); +int hc_stats_snprintf(char *s, size_t size, const hc_stats_t *stats); +int hc_face_stats_list(hc_sock_t *s, hc_data_t **pdata); +int hc_face_stats_snprintf(char *s, size_t size, const hc_face_stats_t *stats); #endif /* HICNTRL_API */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h b/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h new file mode 100644 index 000000000..5b7f424d6 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h @@ -0,0 +1,13 @@ +#ifndef HICNCTRL_CALLBACK_H +#define HICNCTRL_CALLBACK_H + +#include <stdbool.h> + +#include <hicn/ctrl/data.h> + +typedef int (*hc_enable_callback_t)(bool enable); +typedef void (*hc_state_callback_t)(bool enable, void *user_data); +typedef void (*hc_result_callback_t)(hc_data_t *data, void *user_data); +typedef void (*hc_notification_callback_t)(hc_data_t *data, void *user_data); + +#endif /* HICNCTRL_CALLBACK_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/command.h b/ctrl/libhicnctrl/includes/hicn/ctrl/command.h new file mode 100644 index 000000000..1824d14c2 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/command.h @@ -0,0 +1,191 @@ +#ifndef HICNLIGHT_CONFIG_COMMAND +#define HICNLIGHT_CONFIG_COMMAND + +/** + * @file command.h + * @brief Commands. + */ + +#include <stddef.h> // offsetof +#include <hicn/util/ip_address.h> + +#include <hicn/ctrl/api.h> + +/* Update sscanf accordingly in parse_cmd.c */ +#define MAX_PARAMETERS 10 +#define MAX_SCANF_PARAM_LEN 100 + +typedef int (*parser_hook_t)(void *arg); + +typedef enum { + TYPENAME_UNDEFINED, + TYPENAME_INT, + TYPENAME_UINT, + TYPENAME_INT16, + TYPENAME_UINT16, + TYPENAME_STR, + TYPENAME_SYMBOLIC_OR_ID, + TYPENAME_INTERFACE_NAME, + TYPENAME_IP_ADDRESS, + TYPENAME_IP_PREFIX, + TYPENAME_ON_OFF, + TYPENAME_ENUM, + TYPENAME_POLICY_STATE, +} parser_typename_t; + +typedef struct { + parser_typename_t name; + union { + struct { + size_t max_size; + } str; + struct { + int min; + int max; + } integer; + struct { + int (*from_str)(const char *str); + } enum_; + struct { + policy_tag_t tag; + } policy_state; + }; +} parser_type_t; + +typedef struct { + const char *name; + const char *help; + parser_type_t type; + size_t offset; + /* + * quick hack to let the functions update two or more parameters, like for + * IP_ADDRESS or IP_PREFIX types + */ + size_t offset2; + size_t offset3; +} command_parameter_t; + +typedef struct { + hc_action_t action; + hc_object_type_t object_type; + unsigned nparams; + command_parameter_t parameters[MAX_PARAMETERS]; + parser_hook_t post_hook; +} command_parser_t; + +/* + * NOTE: we now use strings everywhere to parse in the same way parameters + * coming from the commandline through getopt (strings), and those coming from + * sscanf (used to be variables, now all strings also. + */ + +#define TYPE_STRN(N) \ + (parser_type_t) { \ + .name = TYPENAME_STR, \ + .str = { \ + .max_size = N, \ + }, \ + } + +#define TYPE_INT(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_INT, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } + +#define TYPE_UINT(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_UINT, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } + +#define TYPE_INT16(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_INT16, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } + +#define TYPE_UINT16(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_UINT16, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } + +#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) + +#define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) + +#define TYPE_IP_ADDRESS \ + (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } + +#define TYPE_IP_PREFIX \ + (parser_type_t) { .name = TYPENAME_IP_PREFIX, } + +#define TYPE_ON_OFF \ + (parser_type_t) { .name = TYPENAME_ON_OFF, } + +#define TYPE_ENUM(x) \ + (parser_type_t) { \ + .name = TYPENAME_ENUM, \ + .enum_ = { \ + .from_str = (int (*)(const char *))x##_from_str, \ + }, \ + } +/* We need to allocate room for the intermediate string */ + +#define TYPE_POLICY_STATE(TAG) \ + (parser_type_t) { \ + .name = TYPENAME_POLICY_STATE, \ + .policy_state = { \ + .tag = TAG, \ + }, \ + } +/* We need to allocate room for the intermediate string */ + +/** + * \brief Register a protocol + * \param protocol Pointer to a protocol_t structure describing the protocol to + * register \return None + */ + +void command_register(const command_parser_t *command); + +/** + * \brief Search a registered protocol in the library according to its name + * \param[in] action The action of the command. + * \param[in] object The object of the command. + * \param[in] nparams The number of parameters expected in the command. + * \return A pointer to the corresponding command if any, NULL othewise + */ +const command_parser_t *command_search(hc_action_t action, + hc_object_type_t object, + unsigned nparams); + +/** + * @brief List the commands associated with the specified object and/or action. + * Use OBJECT_UNDEFINED and ACTION_UNDEFINED to list all the available objects. + * Use ACTION_UNDEFINED to list all the actions associated to the specified + * object. + * + * @param object The action of the command + * @param action The object of the command + */ +void command_list(hc_object_type_t object, hc_action_t action); + +#define COMMAND_REGISTER(MOD) \ + static void __init_##MOD(void) __attribute__((constructor)); \ + static void __init_##MOD(void) { command_register(&MOD); } + +#endif /* HICNLIGHT_CONFIG_COMMAND */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h deleted file mode 100644 index 3758f0f41..000000000 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h +++ /dev/null @@ -1,434 +0,0 @@ -/* - * 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 commands.h - * @brief All hicn-light commands: 14 in total. - * - * Header and payload in binary format. - */ - -#ifndef commands_h -#define commands_h - -#ifndef _WIN32 -#include <netinet/in.h> -#include <sys/socket.h> -#endif - -#include <stdint.h> -#include <stdlib.h> - -#include <hicn/util/ip_address.h> -#ifdef WITH_POLICY -#include <hicn/policy.h> -#endif /* WITH_POLICY */ - -#define SYMBOLIC_NAME_LEN 16 -#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10 - -typedef struct in6_addr ipv6_addr_t; -typedef uint32_t ipv4_addr_t; - -typedef enum { - REQUEST_LIGHT = 0xc0, // this is a command - RESPONSE_LIGHT, - ACK_LIGHT, - NACK_LIGHT, - LAST_MSG_TYPE_VALUE -} message_type; - -typedef enum { - ADD_LISTENER = 0, - ADD_CONNECTION, - LIST_CONNECTIONS, - ADD_ROUTE, - LIST_ROUTES, - REMOVE_CONNECTION, - REMOVE_LISTENER, - REMOVE_ROUTE, - CACHE_STORE, - CACHE_SERVE, - CACHE_CLEAR, - SET_STRATEGY, - SET_WLDR, - ADD_PUNTING, - LIST_LISTENERS, - MAPME_ENABLE, - MAPME_DISCOVERY, - MAPME_TIMESCALE, - MAPME_RETX, - MAPME_SEND_UPDATE, - CONNECTION_SET_ADMIN_STATE, -#ifdef WITH_POLICY - ADD_POLICY, - LIST_POLICIES, - REMOVE_POLICY, - UPDATE_CONNECTION, - CONNECTION_SET_PRIORITY, - CONNECTION_SET_TAGS, -#endif /* WITH_POLICY */ - LAST_COMMAND_VALUE -} command_id; - -typedef enum { - ADDR_INET = 1, - ADDR_INET6, - ADDR_LINK, - ADDR_IFACE, - ADDR_UNIX /* PF_UNIX */ -} address_type; - -typedef enum { - UDP_CONN, - TCP_CONN, - GRE_CONN, // not implemented - HICN_CONN -} connection_type; - -typedef enum { ACTIVATE_ON, ACTIVATE_OFF } activate_type; - -//========== HEADER ========== - -typedef struct { - uint8_t messageType; - uint8_t commandID; - uint16_t length; // tells the number of structures in the payload - uint32_t seqNum; -} header_control_message; -// for the moment has to be at least 8 bytes - -// SIZE=8 - -//========== [00] ADD LISTENER ========== - -typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode; - -typedef struct { - char symbolic[SYMBOLIC_NAME_LEN]; - char interfaceName[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint16_t port; - // uint16_t etherType; - uint8_t addressType; - uint8_t listenerMode; - uint8_t connectionType; -} add_listener_command; - -// SIZE=56 - -//========== [01] ADD CONNECTION ========== - -typedef struct { - char symbolic[SYMBOLIC_NAME_LEN]; - //char interfaceName[SYMBOLIC_NAME_LEN]; - ip_address_t remoteIp; - ip_address_t localIp; - uint16_t remotePort; - uint16_t localPort; - uint8_t ipType; - uint8_t connectionType; - uint8_t admin_state; -#ifdef WITH_POLICY - uint32_t priority; - policy_tags_t tags; -#endif /* WITH_POLICY */ -} add_connection_command; - -// SIZE=56 - -//========== [02] LIST CONNECTIONS ========== - -typedef enum { - CONN_GRE, - CONN_TCP, - CONN_UDP, - CONN_MULTICAST, - CONN_L2, - CONN_HICN -} list_connections_type; - -typedef enum { - IFACE_UP = 0, - IFACE_DOWN = 1, - IFACE_UNKNOWN = 2 // not used actually -} connection_state; - -typedef struct { - add_connection_command connectionData; - uint32_t connid; - uint8_t state; - char interfaceName[SYMBOLIC_NAME_LEN]; - char connectionName[SYMBOLIC_NAME_LEN]; -} list_connections_command; - -// SIZE=80 - -//========== [03] ADD ROUTE ========== - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint16_t cost; - uint8_t addressType; - uint8_t len; -} add_route_command; - -// SIZE=36 - -//========== [04] LIST ROUTE ========== - -typedef struct { - ip_address_t address; - uint32_t connid; - uint16_t cost; - uint8_t addressType; - uint8_t len; -} list_routes_command; - -// SIZE=24 - -//========== [05] REMOVE CONNECTION ========== -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; -} remove_connection_command; - -//========== [06] REMOVE LISTENER ========== -typedef struct { - char symbolicOrListenerid[SYMBOLIC_NAME_LEN]; -} remove_listener_command; - -// SIZE=16 - -//========== [07] REMOVE ROUTE ========== - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t addressType; - uint8_t len; -} remove_route_command; - -// SIZE=36 - -//========== [08] CACHE STORE ========== - -typedef struct { - uint8_t activate; -} cache_store_command; - -// SIZE=1 - -//========== [09] CACHE SERVE ========== - -typedef struct { - uint8_t activate; -} cache_serve_command; - -// SIZE=1 - -//========== [10] SET STRATEGY ========== - -typedef enum { - SET_STRATEGY_LOADBALANCER, - SET_STRATEGY_RANDOM, - SET_STRATEGY_LOW_LATENCY, - LAST_STRATEGY_VALUE -} strategy_type; - -typedef struct { - ip_address_t address; - uint8_t strategyType; - uint8_t addressType; - uint8_t len; - uint8_t related_prefixes; - ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t addresses_type[MAX_FWD_STRATEGY_RELATED_PREFIXES]; -} set_strategy_command; - -// SIZE=208 - -//========== [11] SET WLDR ========== - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint8_t activate; -} set_wldr_command; - -// SIZE=17 - -//========== [12] ADD PUNTING ========== - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t addressType; - uint8_t len; -} add_punting_command; - -// SIZE=36 - -//========== [13] LIST LISTENER ========== - -typedef struct { - ip_address_t address; - char listenerName[SYMBOLIC_NAME_LEN]; - char interfaceName[SYMBOLIC_NAME_LEN]; - uint32_t connid; - uint16_t port; - uint8_t addressType; - uint8_t encapType; -} list_listeners_command; - -// SIZE=56 - -//========== [14] MAPME ========== - -// (enable/discovery/timescale/retx) - -typedef struct { - uint8_t activate; -} mapme_activator_command; - -// SIZE=1 - -typedef struct { - uint32_t timePeriod; -} mapme_timing_command; - -typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; -} mapme_send_update_command; - -// SIZE=1 - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint8_t admin_state; - uint8_t pad8[3]; -} connection_set_admin_state_command; - -#ifdef WITH_POLICY - -typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; - hicn_policy_t policy; -} add_policy_command; - -typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; - hicn_policy_t policy; -} list_policies_command; - -typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; -} remove_policy_command; - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint8_t admin_state; - uint32_t priority; - policy_tags_t tags; -} update_connection_command; - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint32_t priority; -} connection_set_priority_command; - -typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - policy_tags_t tags; -} connection_set_tags_command; - -#endif /* WITH_POLICY */ - -//===== size of commands ====== -// REMINDER: when a new_command is added, the following switch has to be -// updated. -static inline int payloadLengthDaemon(command_id id) { - switch (id) { - case ADD_LISTENER: - return sizeof(add_listener_command); - case ADD_CONNECTION: - return sizeof(add_connection_command); - case LIST_CONNECTIONS: - return 0; // list connections: payload always 0 - case ADD_ROUTE: - return sizeof(add_route_command); - case LIST_ROUTES: - return 0; // list routes: 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: - return sizeof(cache_store_command); - case CACHE_SERVE: - return sizeof(cache_serve_command); - case CACHE_CLEAR: - return 0; // cache clear - case SET_STRATEGY: - return sizeof(set_strategy_command); - case SET_WLDR: - return sizeof(set_wldr_command); - case ADD_PUNTING: - return sizeof(add_punting_command); - case LIST_LISTENERS: - return 0; // list listeners: payload always 0 - case MAPME_ENABLE: - return sizeof(mapme_activator_command); - case MAPME_DISCOVERY: - return sizeof(mapme_activator_command); - case MAPME_TIMESCALE: - return sizeof(mapme_timing_command); - case MAPME_RETX: - return sizeof(mapme_timing_command); - case MAPME_SEND_UPDATE: - return sizeof(mapme_send_update_command); - case CONNECTION_SET_ADMIN_STATE: - return sizeof(connection_set_admin_state_command); -#ifdef WITH_POLICY - case ADD_POLICY: - return sizeof(add_policy_command); - case LIST_POLICIES: - return 0; // list policies: payload always 0 - case REMOVE_POLICY: - return sizeof(remove_policy_command); - case UPDATE_CONNECTION: - return sizeof(update_connection_command); - case CONNECTION_SET_PRIORITY: - return sizeof(connection_set_priority_command); - case CONNECTION_SET_TAGS: - return sizeof(connection_set_tags_command); -#endif /* WITH_POLICY */ - case LAST_COMMAND_VALUE: - return 0; - default: - return 0; - } -} -#endif diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/data.h b/ctrl/libhicnctrl/includes/hicn/ctrl/data.h new file mode 100644 index 000000000..d2696db1c --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/data.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021-2022 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 data.h + * \brief Request result data. + */ + +#ifndef HICNCTRL_DATA_H +#define HICNCTRL_DATA_H + +#include <stdbool.h> +#include <stddef.h> // size_t +#include <stdint.h> // uint*_t +#include <sys/types.h> +#include <unistd.h> + +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/object.h> + +/** + * \brief Holds the results of an hICN control request + */ +typedef struct hc_data_s hc_data_t; + +/** + * Create a structure holding the results of an hICN control request. + * \result The newly create data structure. + */ +hc_data_t *hc_data_create(hc_object_type_t object_type); + +/** + * Free a structure holding the results of an hICN control request. + * \param [in] data - The data structure to free. + */ +void hc_data_free(hc_data_t *data); + +/* + * This function can fail if the current data size is bigger than the requested + * maximum size + */ +int hc_data_set_max_size(hc_data_t *data, size_t max_size); + +const uint8_t *hc_data_get_buffer(hc_data_t *data); +const uint8_t *hc_data_get_free(hc_data_t *data); +void hc_data_inc_size(hc_data_t *data); + +hc_object_type_t hc_data_get_object_type(const hc_data_t *data); + +void hc_data_set_object_type(hc_data_t *data, hc_object_type_t object_type); + +ssize_t hc_data_get_size(const hc_data_t *data); + +/* + * This is used to perform manual allocation once after initialization is the + * size of the data to store is known in advance. This does not prevent future + * reallocations (in the limit though of the value in max_size, if applicable). + */ +int hc_data_allocate(hc_data_t *data, size_t size); + +int hc_data_clear(hc_data_t *data); + +#if 0 +int hc_data_ensure_available(hc_data_t *data, size_t count); +#endif + +/** + * \brief Adds many new results at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add elements. + * \param [in] elements - The array of elements to add. + * \param [in] count - The number of elements to add. + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count); + +/** + * \brief Adds a new result at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add an element. + * \param [in] element - The element to add + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push(hc_data_t *data, const void *element); + +#if 0 +uint8_t *hc_data_get_next(hc_data_t *data); + +/** + * \brief Configure a callback (along with private data) to be called upon + * completion of a request + * \param [in] data - hICN control data + * \param [in] cb - Callback function + * \param [in] cb_data - Callback private data + */ +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data); + +void hc_data_set_size(hc_data_t *data, int size); +#endif + +void hc_data_set_complete(hc_data_t *data); +bool hc_data_is_complete(const hc_data_t *data); + +void hc_data_set_error(hc_data_t *data); + +bool hc_data_get_result(hc_data_t *data); + +#if 0 +/** + * \brief Reset the data structure holding control data + * \param [in] data - hICN control data + * \return Error code + */ +int hc_data_reset(hc_data_t *data); +#endif + +#define VAR(x) __##x +#define hc_data_foreach(DATA, OBJECT, BODY) \ + do { \ + hc_object_t *OBJECT; \ + size_t VAR(size) = hc_object_size(hc_data_get_object_type(DATA)); \ + for (unsigned VAR(i) = 0; VAR(i) < hc_data_get_size(DATA); VAR(i)++) { \ + OBJECT = (hc_object_t *)(hc_data_get_buffer(DATA) + VAR(i) * VAR(size)); \ + BODY \ + } \ + } while (0) + +hc_object_t *hc_data_find(hc_data_t *data, hc_object_t *object); + +const hc_object_t *hc_data_get_object(const hc_data_t *data, off_t pos); + +#endif /* HICNCTRL_DATA_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h deleted file mode 100644 index 49a6a783c..000000000 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 face.h - * \brief Face abstraction - */ -#ifndef HICN_FACE_H -#define HICN_FACE_H - -#ifndef SPACES -#define SPACES(x) x -#endif -#ifndef SPACE -#define SPACE 1 -#endif -#ifndef NULLTERM -#define NULLTERM 1 -#endif - -#include <hicn/policy.h> - -#include <hicn/util/ip_address.h> - -//typedef unsigned int hash_t; //incompatible with vpp - -/* Netdevice type */ - -#include <net/if.h> // IFNAMSIZ - -#define foreach_netdevice_type \ - _(UNDEFINED) \ - _(LOOPBACK) \ - _(WIRED) \ - _(WIFI) \ - _(CELLULAR) \ - _(VPN) \ - _(N) - -#define MAXSZ_NETDEVICE_TYPE_ 9 -#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM - -typedef enum { -#define _(x) NETDEVICE_TYPE_ ## x, -foreach_netdevice_type -#undef _ -} netdevice_type_t; - -extern const char * netdevice_type_str[]; - - -/* Netdevice */ - -/** - * \brief Netdevice type - * - * NOTE - * - This struct cannot be made opaque as it is currently part of face_t - * - We recommand using the API as to keep redundant attributes consistent - */ -typedef struct { - u32 index; - char name[IFNAMSIZ]; -} netdevice_t; - -#define NETDEVICE_EMPTY (netdevice_t) { \ - .index = 0, \ - .name = {0}, \ -} - -netdevice_t * netdevice_create_from_index(u32 index); -netdevice_t * netdevice_create_from_name(const char * name); -#define netdevice_initialize_from_index netdevice_set_index -#define netdevice_initialize_from_name netdevice_set_name -void netdevice_free(netdevice_t * netdevice); -int netdevice_get_index(const netdevice_t * netdevice, u32 * index); -int netdevice_set_index(netdevice_t * netdevice, u32 index); -int netdevice_get_name(const netdevice_t * netdevice, const char ** name); -int netdevice_set_name(netdevice_t * netdevice, const char * name); -int netdevice_update_index(netdevice_t * netdevice); -int netdevice_update_name(netdevice_t * netdevice); -int netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2); - -#define NETDEVICE_UNDEFINED_INDEX 0 - -/* Face state */ - -#define foreach_face_state \ - _(UNDEFINED) \ - _(DOWN) \ - _(UP) \ - _(N) - - -#define MAXSZ_FACE_STATE_ 9 -#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1 - -typedef enum { -#define _(x) FACE_STATE_ ## x, -foreach_face_state -#undef _ -} face_state_t; - -extern const char * face_state_str[]; - - -/* Face type */ - -#define foreach_face_type \ - _(UNDEFINED) \ - _(HICN) \ - _(HICN_LISTENER) \ - _(TCP) \ - _(TCP_LISTENER) \ - _(UDP) \ - _(UDP_LISTENER) \ - _(N) - -#define MAXSZ_FACE_TYPE_ 13 -#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1 - -typedef enum { -#define _(x) FACE_TYPE_ ## x, -foreach_face_type -#undef _ -} face_type_t; - -extern const char * face_type_str[]; - -#ifdef WITH_POLICY -#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + MAXSZ_POLICY_TAGS_ + 7 -#else -#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + 4 -#endif /* WITH_POLICY */ -#define MAXSZ_FACE MAXSZ_FACE_ + 1 - -/* Face */ - -typedef u32 face_id_t; - -typedef struct { - face_type_t type; - face_state_t admin_state; - face_state_t state; -#ifdef WITH_POLICY - uint32_t priority; - policy_tags_t tags; /**< \see policy_tag_t */ -#endif /* WITH_POLICY */ - - /* - * Depending on the face type, some of the following fields will be unused - */ - netdevice_t netdevice; - int family; /* To access family independently of face type */ - ip_address_t local_addr; - ip_address_t remote_addr; - u16 local_port; - u16 remote_port; -} face_t; - -int face_initialize(face_t * face); -int face_initialize_udp(face_t * face, const char * interface_name, - const ip_address_t * local_addr, u16 local_port, - const ip_address_t * remote_addr, u16 remote_port, - int family); -int face_initialize_udp_sa(face_t * face, - const char * interface_name, - const struct sockaddr * local_addr, const struct sockaddr * remote_addr); - -face_t * face_create(); -face_t * face_create_udp(const char * interface_name, - const ip_address_t * local_addr, u16 local_port, - const ip_address_t * remote_addr, u16 remote_port, int family); -face_t * face_create_udp_sa(const char * interface_name, - const struct sockaddr * local_addr, - const struct sockaddr * remote_addr); - -int face_finalize(face_t * face); - -void face_free(face_t * face); - -typedef int (*face_cmp_t)(const face_t * f1, const face_t * f2); - -int face_cmp(const face_t * f1, const face_t * f2); -unsigned int face_hash(const face_t * face); - -size_t -face_snprintf(char * s, size_t size, const face_t * face); - -policy_tags_t face_get_tags(const face_t * face); -int face_set_tags(face_t * face, policy_tags_t tags); - -#endif /* HICN_FACE_H */ - diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h b/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h new file mode 100644 index 000000000..0656de080 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +#ifndef HICNCTRL_FW_INTERFACE_H +#define HICNCTRL_FW_INTERFACE_H + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/callback.h> + +/** + * \file fw_interface.h + * \brief Forwarder interface + * + * Forwarder interface is designed to be a reusable module (that might be + * wrapped in a C++ class), providing a fw-agnostic interface with the + * following goals: + * - maintaining a permanent connection to the fw (and keep track of the + * fw state, eventually caching some aspects) + * - allowing the tracking of multiplexed requests + * - supporting a stream of concurrent notifications that might be needed to + * synchronize states. + * + * It is design to be easily integrated with the different event loops used + * across the projects (libevent for C, asio for C++). + */ + +#define foreach_fw_state \ + _(UNDEFINED) \ + _(DISABLED) /* stack is stopped */ \ + _(REQUESTED) /* stack is starting */ \ + _(AVAILABLE) /* forwarder is running */ \ + _(CONNECTING) /* XXX NEW */ \ + _(CONNECTED) /* control socket connected */ \ + _(READY) /* listener is present */ \ + _(N) + +typedef enum { +#define _(x) FW_STATE_##x, + foreach_fw_state +#undef _ +} fw_state_t; + +extern const char *fw_state_str[]; + +#define fw_state_str(x) fw_state_str[x] + +typedef struct fw_interface_s fw_interface_t; + +fw_interface_t *fw_interface_create_url(forwarder_type_t type, const char *url); +fw_interface_t *fw_interface_create(forwarder_type_t type); + +void fw_interface_free(fw_interface_t *fi); + +int fw_interface_get_fd(const fw_interface_t *fi); + +/* + * Enable the stack + */ +int fw_interface_enable(fw_interface_t *fi); + +/* + * Disable the stack + */ +int fw_interface_disable(fw_interface_t *fi); + +/* + * Request a permanent connection to the forwarder, starting it if needed. + */ +int fw_interface_connect(fw_interface_t *fi); + +/* + * Disconnect from the forwarder + */ +int fw_interface_disconnect(fw_interface_t *fi); + +fw_state_t fw_interface_get_state(const fw_interface_t *fi); + +int fw_interface_subscribe_all(fw_interface_t *fi); + +int fw_interface_unsubscribe_all(fw_interface_t *fi); + +int fw_interface_execute(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_data_t **pdata); + +int fw_interface_execute_async(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +int fw_interface_set_enable_callback(fw_interface_t *fi, + hc_enable_callback_t callback); + +int fw_interface_set_state_callback(fw_interface_t *fi, + hc_state_callback_t callback, + void *callback_data); + +int fw_interface_set_result_callback(fw_interface_t *fi, + hc_result_callback_t callback, + void *callback_data); + +int fw_interface_set_notification_callback(fw_interface_t *fi, + hc_notification_callback_t callback, + void *callback_data); + +// manage stack [android] +// - not needed for face mgr +// operations +// - create face/route : facemgr, hproxy +// - set fw strategy +// - get listeners, hicn listener port +// subscribe all +// callbacks: +// - forwarder available/unavailable +// timers & reattempts : clarify +// XXX remove_self on sock disconnect... should be in libhicnctrl + +int fw_interface_on_receive(fw_interface_t *fi, size_t count); +int fw_interface_get_recv_buffer(fw_interface_t *fi, uint8_t **buffer, + size_t *size); + +#endif /* HICNCTRL_FW_INTERFACE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h new file mode 100644 index 000000000..3e3e98c35 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 hicn-light.h + * @brief hicn-light specifics. + * + * Header and payload in binary format. + */ + +#ifndef HICN_CTRL_HICNLIGHT_H +#define HICN_CTRL_HICNLIGHT_H + +#ifndef _WIN32 +#include <netinet/in.h> +#include <sys/socket.h> +#endif + +#include <stdint.h> +#include <stdlib.h> + +#include <hicn/policy.h> +#include <hicn/strategy.h> +#include <hicn/util/ip_address.h> + +#include "api.h" + +#define SYMBOLIC_NAME_LEN 16 + +typedef struct in6_addr ipv6_addr_t; +typedef uint32_t ipv4_addr_t; + +typedef enum { + MESSAGE_COMMAND_SUBTYPE_UNDEFINED, + REQUEST_LIGHT = 0xc0, // this is a command + RESPONSE_LIGHT, + ACK_LIGHT, + NACK_LIGHT, + NOTIFICATION_LIGHT, + MESSAGE_COMMAND_SUBTYPE_N +} message_command_subtype_t; + +#define message_type_is_valid(message_type) \ + ((message_type != MESSAGE_TYPE_UNDEFINED) && \ + (message_type != MESSAGE_COMMAND_SUBTYPE_N)) + +#define message_type_from_uchar(x) \ + (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) \ + ? MESSAGE_COMMAND_SUBTYPE_N \ + : (message_command_subtype_t)(x)) + +#define foreach_command_type \ + _(listener_add, LISTENER_ADD) \ + _(listener_remove, LISTENER_REMOVE) \ + _(listener_list, LISTENER_LIST) \ + _(connection_add, CONNECTION_ADD) \ + _(connection_remove, CONNECTION_REMOVE) \ + _(connection_list, CONNECTION_LIST) \ + _(connection_update, CONNECTION_UPDATE) \ + _(route_add, ROUTE_ADD) \ + _(route_remove, ROUTE_REMOVE) \ + _(route_list, ROUTE_LIST) \ + _(cache_set_store, CACHE_SET_STORE) \ + _(cache_set_serve, CACHE_SET_SERVE) \ + _(cache_clear, CACHE_CLEAR) \ + _(cache_list, CACHE_LIST) \ + _(strategy_set, STRATEGY_SET) \ + _(strategy_add_local_prefix, STRATEGY_ADD_LOCAL_PREFIX) \ + _(wldr_set, WLDR_SET) \ + _(punting_add, PUNTING_ADD) \ + _(mapme_enable, MAPME_ENABLE) \ + _(mapme_set_discovery, MAPME_SET_DISCOVERY) \ + _(mapme_set_timescale, MAPME_SET_TIMESCALE) \ + _(mapme_set_retx, MAPME_SET_RETX) \ + _(mapme_add, MAPME_ADD) \ + _(policy_add, POLICY_ADD) \ + _(policy_remove, POLICY_REMOVE) \ + _(policy_list, POLICY_LIST) \ + _(active_interface_update, ACTIVE_INTERFACE_UPDATE) \ + _(subscription_add, SUBSCRIPTION_ADD) \ + _(subscription_remove, SUBSCRIPTION_REMOVE) \ + _(stats_list, STATS_LIST) \ + _(face_stats_list, FACE_STATS_LIST) + +typedef enum { + COMMAND_TYPE_UNDEFINED, +#define _(l, u) COMMAND_TYPE_##u, + foreach_command_type +#undef _ + COMMAND_TYPE_N, +} command_type_t; + +extern const char *command_type_str[]; + +#define command_type_str(x) command_type_str[x] + +#define command_type_is_valid(command_type) \ + ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N)) + +#define command_type_from_uchar(x) \ + (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x)) + +/* Should be at least 8 bytes */ +typedef struct { + uint8_t message_type; + uint8_t command_id; + uint16_t length; /* Number of structures in the payload */ + uint32_t seq_num; +} cmd_header_t; + +typedef struct { + cmd_header_t header; +} msg_header_t; + +/* Listener */ + +typedef struct { + char symbolic[SYMBOLIC_NAME_LEN]; + char interface_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint16_t port; + uint8_t family; + uint8_t type; +} cmd_listener_add_t; + +typedef struct { + char symbolicOrListenerid[SYMBOLIC_NAME_LEN]; +} cmd_listener_remove_t; + +typedef struct { + void *_; // Otherwise empty structs result in clang build error +} cmd_listener_list_t; + +/* Connection */ + +typedef struct { + char symbolic[SYMBOLIC_NAME_LEN]; + // char interface_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t remote_ip; + hicn_ip_address_t local_ip; + uint16_t remote_port; + uint16_t local_port; + uint8_t family; + uint8_t type; + uint8_t admin_state; + uint8_t __pad; + uint32_t priority; + policy_tags_t tags; +} cmd_connection_add_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; +} cmd_connection_remove_t; + +typedef struct { + void *_; +} cmd_connection_list_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint8_t admin_state; + uint8_t pad8[3]; +} cmd_connection_set_admin_state_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint8_t admin_state; + uint32_t priority; + policy_tags_t tags; +} cmd_connection_update_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint32_t priority; +} cmd_connection_set_priority_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + policy_tags_t tags; +} cmd_connection_set_tags_t; + +/* Route */ + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint16_t cost; + uint8_t family; + uint8_t len; +} cmd_route_add_t; + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint8_t family; + uint8_t len; +} cmd_route_remove_t; + +typedef struct { + void *_; +} cmd_route_list_t; + +/* Cache */ + +typedef struct { + uint8_t activate; +} cmd_cache_set_store_t; + +typedef struct { + uint8_t activate; +} cmd_cache_set_serve_t; + +typedef struct { + void *_; +} cmd_cache_clear_t; + +typedef struct { + void *_; +} cmd_cache_list_t; + +typedef struct { + uint8_t store_in_cs; + uint8_t serve_from_cs; + uint32_t cs_size; + uint32_t num_stale_entries; +} cmd_cache_list_reply_t; + +typedef struct { + cmd_header_t header; + cmd_cache_list_reply_t payload; +} msg_cache_list_reply_t; + +/* WLDR */ + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint8_t activate; +} cmd_wldr_set_t; + +/* Strategy */ + +typedef struct { + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + uint8_t type; + uint8_t related_prefixes; + union { + struct { + hicn_ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + } low_latency; + }; +} cmd_strategy_set_t; + +typedef struct { + uint8_t type; + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + hicn_ip_address_t local_address; + uint8_t local_family; + uint8_t local_len; +} cmd_strategy_add_local_prefix_t; + +/* Punting */ + +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint8_t family; + uint8_t len; +} cmd_punting_add_t; + +/* MAP-Me */ + +typedef struct { + uint8_t activate; +} cmd_mapme_activator_t; + +typedef cmd_mapme_activator_t cmd_mapme_enable_t; +typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t; + +typedef struct { + uint32_t timePeriod; +} cmd_mapme_timing_t; + +typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t; +typedef cmd_mapme_timing_t cmd_mapme_set_retx_t; + +typedef struct { + hicn_ip_address_t address; + uint32_t face_id; + uint8_t family; + uint8_t len; +} cmd_mapme_add_t; + +/* dummy */ +typedef struct { + void *_; +} cmd_mapme_list_item_t; + +/* Policy */ + +typedef struct { + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + hicn_policy_t policy; +} cmd_policy_add_t; + +typedef struct { + hicn_ip_address_t address; + uint8_t family; + uint8_t len; +} cmd_policy_remove_t; + +typedef struct { + void *_; +} cmd_policy_list_t; + +/* Subscription */ + +typedef struct { + uint32_t topics; +} cmd_subscription_add_t; + +typedef struct { + uint32_t topics; +} cmd_subscription_remove_t; + +/* Statistics */ + +// General stats +typedef struct { + void *_; +} cmd_stats_list_t; + +// Per-face stats +typedef struct { + void *_; +} cmd_face_stats_list_t; + +typedef void *cmd_active_interface_update_t; + +/* Full messages */ + +#define _(l, u) \ + typedef struct { \ + cmd_header_t header; \ + cmd_##l##_t payload; \ + } msg_##l##_t; +foreach_command_type +#undef _ + + /* Serialized version of hc_listener_t */ + typedef struct { + char name[SYMBOLIC_NAME_LEN]; + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + uint32_t id; + uint16_t local_port; + uint8_t type; + uint8_t family; +} cmd_listener_list_item_t; + +static_assert(sizeof(cmd_listener_list_item_t) == 56, ""); + +typedef struct { + cmd_header_t header; + cmd_listener_list_item_t payload; +} msg_listener_list_reply_t; + +/* Serialized version of hc_connection_t */ +typedef struct { + char name[SYMBOLIC_NAME_LEN]; + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + hicn_ip_address_t remote_addr; + uint32_t id; + uint32_t priority; + uint16_t local_port; + uint16_t remote_port; + uint8_t netdevice_type; + uint8_t type; + uint8_t family; + uint8_t admin_state; + uint8_t tags; + uint8_t state; + uint8_t __pad[6]; +} cmd_connection_list_item_t; + +static_assert(POLICY_TAG_N <= 8, ""); +static_assert(sizeof(cmd_connection_list_item_t) == 88, ""); + +typedef struct { + cmd_header_t header; + cmd_connection_list_item_t payload; +} msg_connection_list_reply_t; + +typedef msg_connection_list_reply_t msg_connection_notify_t; + +typedef struct { + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + hicn_ip_address_t remote_addr; + uint32_t id; + uint32_t priority; + uint16_t local_port; + uint16_t remote_port; + uint8_t netdevice_type; + uint8_t type; + uint8_t family; + uint8_t admin_state; + uint8_t tags; + uint8_t state; + uint8_t __pad[6]; +} cmd_face_list_item_t; + +static_assert(sizeof(cmd_face_list_item_t) == 72, ""); + +typedef struct { + char face_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t remote_addr; + uint32_t face_id; + uint16_t cost; + uint8_t family; + uint8_t len; + cmd_face_list_item_t face; +} cmd_route_list_item_t; + +static_assert(sizeof(cmd_route_list_item_t) == 112, ""); + +typedef struct { + cmd_header_t header; + cmd_route_list_item_t payload; +} msg_route_list_reply_t; + +typedef msg_route_list_reply_t msg_route_notify_t; + +typedef struct { + uint8_t state; + uint8_t disabled; + uint16_t __pad; +} _policy_tag_state_t; + +typedef struct { + uint32_t throughput; + uint32_t latency; + uint32_t loss_rate; +} _interface_stats_t; + +typedef struct { + _interface_stats_t wired; + _interface_stats_t wifi; + _interface_stats_t cellular; + _interface_stats_t all; +} _policy_stats_t; + +typedef struct { + char app_name[APP_NAME_LEN]; + _policy_tag_state_t tags[POLICY_TAG_N]; + _policy_stats_t stats; + uint8_t __pad[4]; +} _hicn_policy_t; + +static_assert(sizeof(_hicn_policy_t) == 208, ""); + +typedef struct { + uint8_t policy[208]; + hicn_ip_address_t remote_addr; + uint8_t family; + uint8_t len; + uint8_t __pad[6]; +} cmd_policy_list_item_t; + +static_assert(sizeof(cmd_policy_list_item_t) == 232, ""); + +typedef struct { + cmd_header_t header; + cmd_policy_list_item_t payload; +} msg_policy_list_reply_t; + +typedef msg_policy_list_reply_t msg_policy_notify_t; + +/* Those are needed to build but not used */ +typedef struct { + uint8_t _; +} cmd_strategy_list_item_t; +typedef struct { + uint8_t _; +} cmd_subscription_list_item_t; + +/* Statistics */ + +// General stats +typedef struct { + hc_stats_t stats; +} cmd_stats_list_item_t; + +typedef struct { + cmd_header_t header; + cmd_stats_list_item_t payload; +} msg_stats_list_reply_t; + +// Per-face stats +typedef struct { + hc_face_stats_t stats; +} cmd_face_stats_list_item_t; + +typedef struct { + cmd_header_t header; + cmd_face_stats_list_item_t payload; +} msg_face_stats_list_reply_t; + +//===== size of commands ====== +// REMINDER: when a new_command is added, the following switch has to be +// updated. +static inline int command_get_payload_len(command_type_t command_type) { + switch (command_type) { +#define _(l, u) \ + case COMMAND_TYPE_##u: \ + return sizeof(cmd_##l##_t); + foreach_command_type +#undef _ + case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N : return 0; + } +} + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +int hc_sock_initialize_module(hc_sock_t *s); + +#endif /* HICN_CTRL_HICNLIGHT_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/object.h b/ctrl/libhicnctrl/includes/hicn/ctrl/object.h new file mode 100644 index 000000000..74b88c515 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/object.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 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 object.h + * \brief API object representation. + */ + +#ifndef HICNCTRL_OBJECT_H +#define HICNCTRL_OBJECT_H + +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/objects.h> + +typedef union { + hc_connection_t connection; + hc_listener_t listener; + hc_route_t route; + hc_face_t face; + // hc_data_t *data; + hc_punting_t punting; + hc_stats_t stats; + hc_face_stats_t face_stats; + hc_strategy_t strategy; + hc_policy_t policy; + hc_subscription_t subscription; + hc_cache_t cache; + hc_mapme_t mapme; + hc_active_interface_t active_interface; + uint8_t as_uint8; +} hc_object_t; + +#define MAXSZ_OBJECT_T MAX + +#define IS_VALID_ACTION(x) IS_VALID_ENUM_TYPE(ACTION, x) + +bool hc_object_is_empty(const hc_object_t *object); + +size_t hc_object_size(hc_object_type_t object_type); + +int hc_object_validate(hc_object_type_t object_type, hc_object_t *object, + bool allow_partial); +int hc_object_cmp(hc_object_type_t object_type, hc_object_t *object1, + hc_object_t *object2); +int hc_object_snprintf(char *s, size_t size, hc_object_type_t object_type, + hc_object_t *object); + +#define foreach_object(VAR, data) foreach_type(hc_object_t, VAR, data) + +#define foreach_type(TYPE, VAR, DATA) \ + for (TYPE *VAR = (TYPE *)hc_data_get_buffer(DATA); \ + VAR < (TYPE *)(hc_data_get_buffer(DATA) + \ + hc_data_get_size(DATA) * sizeof(TYPE)); \ + VAR++) + +#endif /* HICNCTRL_OBJECT_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h b/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h new file mode 100644 index 000000000..4c5a8c425 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2022 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 object_type.h + * \brief Object type. + */ + +#ifndef HICNCTRL_OBJECT_TYPE_H +#define HICNCTRL_OBJECT_TYPE_H + +#define foreach_object_type \ + _(UNDEFINED) \ + _(CONNECTION) \ + _(LISTENER) \ + _(ROUTE) \ + _(FACE) \ + _(STRATEGY) \ + _(PUNTING) \ + _(POLICY) \ + _(CACHE) \ + _(MAPME) \ + _(WLDR) \ + _(LOCAL_PREFIX) \ + _(PROBE) \ + _(SUBSCRIPTION) \ + _(ACTIVE_INTERFACE) \ + _(STATS) \ + _(FACE_STATS) \ + _(N) + +typedef enum { +#define _(x) OBJECT_TYPE_##x, + foreach_object_type +#undef _ +} hc_object_type_t; + +extern const char *object_type_str[]; + +#define object_type_str(x) object_type_str[x] + +hc_object_type_t object_type_from_str(const char *object_str); + +#define IS_VALID_OBJECT_TYPE(x) IS_VALID_ENUM_TYPE(OBJECT_TYPE, x) + +#endif /* HICNCTRL_OBJECT_TYPE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h new file mode 100644 index 000000000..5509f99a8 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h @@ -0,0 +1,17 @@ +#ifndef HICNCTRL_OBJECTS_H +#define HICNCTRL_OBJECTS_H + +#include <hicn/ctrl/objects/connection.h> +#include <hicn/ctrl/objects/face.h> +#include <hicn/ctrl/objects/listener.h> +#include <hicn/ctrl/objects/route.h> +#include <hicn/ctrl/objects/punting.h> +#include <hicn/ctrl/objects/stats.h> +#include <hicn/ctrl/objects/strategy.h> +#include <hicn/ctrl/objects/policy.h> +#include <hicn/ctrl/objects/subscription.h> +#include <hicn/ctrl/objects/cache.h> +#include <hicn/ctrl/objects/mapme.h> +#include <hicn/ctrl/objects/active_interface.h> + +#endif /* HICNCTRL_OBJECTS_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h new file mode 100644 index 000000000..56a1d8cd5 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2022 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 objects/active_interface.h + * \brief Route. + */ + +#ifndef HICNCTRL_OBJECTS_ACTIVE_INTERFACE_H +#define HICNCTRL_OBJECTS_ACTIVE_INTERFACE_H + +#include <hicn/ctrl/objects/face.h> + +typedef struct { + hicn_ip_prefix_t prefix; + netdevice_flags_t interface_types; +} hc_active_interface_t; + +#define foreach_active_interface(VAR, data) \ + foreach_type(hc_active_interface_t, VAR, data) + +// XXX WRONG +#define MAXSZ_HC_ACTIVE_INTERFACE_ \ + MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN +#define MAXSZ_HC_ACTIVE_INTERFACE MAXSZ_HC_ACTIVE_INTERFACE_ + NULLTERM + +int hc_active_interface_snprintf(char *s, size_t size, + const hc_active_interface_t *active_interface); +int hc_active_interface_validate(const hc_active_interface_t *active_interface, + bool allow_partial); + +#endif diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/base.h index 0f6c7f8b4..fc40f680e 100644 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 HUACHENTEL and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -13,11 +13,13 @@ * limitations under the License. */ -#ifndef __IETF_INTERFACE_H__ -#define __IETF_INTERFACE_H__ - -int ietf_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription); +/** + * \file base.h + * \brief Base definitions for objects. + */ +#ifndef HICNCTRL_OBJECTS_BASE +#define HICNCTRL_OBJECTS_BASE +#define INTERFACE_LEN 16 -#endif /* __IETF_INTERFACE_H__ */ +#endif /* HICNCTRL_OBJECTS_BASE */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h new file mode 100644 index 000000000..1f8691be6 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-2022 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 objects/cache.h + * \brief Cache. + */ + +#ifndef HICNCTRL_OBJECTS_CACHE_H +#define HICNCTRL_OBJECTS_CACHE_H + +typedef struct { + uint8_t serve; // 1 = on, 0 = off + uint8_t store; // 1 = on, 0 = off +} hc_cache_t; + +typedef struct { + bool store; + bool serve; + size_t cs_size; + size_t num_stale_entries; +} hc_cache_info_t; + +int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info); + +#endif /* HICNCTRL_OBJECTS_CACHE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h new file mode 100644 index 000000000..771b48c20 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-2022 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 objects/connection.h + * \brief Connection. + */ + +#ifndef HICNCTRL_OBJECTS_CONNECTION_H +#define HICNCTRL_OBJECTS_CONNECTION_H + +#include <stdint.h> +#include <hicn/face.h> + +#include "base.h" + +/* + * NOTE : + * - interface_name is mainly used to derive listeners from connections, + * but is not itself used to create connections. + */ +typedef struct { + uint32_t id; /* Kr. */ + char name[SYMBOLIC_NAME_LEN]; /* K.w */ + char interface_name[INTERFACE_LEN]; /* Kr. */ + netdevice_type_t netdevice_type; /* .r. */ + face_type_t type; /* .rw */ + int family; /* .rw */ + hicn_ip_address_t local_addr; /* .rw */ + uint16_t local_port; /* .rw */ + hicn_ip_address_t remote_addr; /* .rw */ + uint16_t remote_port; /* .rw */ + face_state_t admin_state; /* .rw */ + uint32_t priority; /* .rw */ + policy_tags_t tags; /* .rw */ + face_state_t state; /* .r. */ +} hc_connection_t; + +#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) + +#define MAXSZ_HC_CONNECTION_ \ + MAXSZ_FACE_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \ + MAXSZ_FACE_TYPE_ + SPACES(3) +#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM + +int hc_connection_validate(const hc_connection_t *connection, + bool allow_partial); +int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2); +int hc_connection_snprintf(char *s, size_t size, + const hc_connection_t *connection); + +#endif /* HICNCTRL_OBJECTS_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h new file mode 100644 index 000000000..1aa122f37 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 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 objects/face.h + * \brief Face. + * + * A face is an abstraction introduced by the control library to abstract the + * forwarder implementation details. It encompasses connections and listeners + * and ensures the right dependencies are enforced, eg that we always have a + * listener when a connection is created. + */ + +#ifndef HICNCTRL_OBJECTS_FACE_H +#define HICNCTRL_OBJECTS_FACE_H + +#include <hicn/face.h> + +#include "base.h" + +typedef face_t hc_face_t; + +#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data) + +#define MAX_FACE_ID 255 +#define MAXSZ_FACE_ID_ 3 +#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM +#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN +#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM + +#define MAXSZ_HC_FACE_ \ + MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN +#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM + +int hc_face_snprintf(char *s, size_t size, const hc_face_t *face); + +#endif /* HICNCTRL_OBJECTS_FACE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h new file mode 100644 index 000000000..0fb74f558 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2022 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 objects/listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_OBJECTS_LISTENER_H +#define HICNCTRL_OBJECTS_LISTENER_H + +#include <stddef.h> // offsetof +#include <stdint.h> +#include <hicn/face.h> + +#include "base.h" + +// FIXME the listener should not require any port for hICN... +typedef struct { + char name[SYMBOLIC_NAME_LEN]; /* K.w */ + char interface_name[INTERFACE_LEN]; /* Kr. */ + uint32_t id; /* Kr. */ + face_type_t type; /* .rw */ + int family; /* .rw */ + hicn_ip_address_t local_addr; /* .rw */ + uint16_t local_port; /* .rw */ +} hc_listener_t; + +int hc_listener_validate(const hc_listener_t *listener, bool allow_partial); +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2); + +#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data) + +#define MAXSZ_HC_LISTENER_ \ + INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_FACE_TYPE_ +#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM + +int hc_listener_snprintf(char *s, size_t size, const hc_listener_t *listener); + +#endif /* HICNCTRL_OBJECTS_LISTENER_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h new file mode 100644 index 000000000..3eda1bfaa --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 objects/mapme.h + * \brief MAP-Me. + */ + +#ifndef HICNCTRL_OBJECTS_MAPME_H +#define HICNCTRL_OBJECTS_MAPME_H + +typedef enum { + MAPME_TARGET_ENABLE, + MAPME_TARGET_DISCOVERY, + MAPME_TARGET_TIMESCALE, + MAPME_TARGET_RETX, +} mapme_target_t; + +static inline mapme_target_t mapme_target_from_str(char *mapme_target_str) { + if (strcasecmp(mapme_target_str, "enable") == 0) + return MAPME_TARGET_ENABLE; + else if (strcasecmp(mapme_target_str, "discovery") == 0) + return MAPME_TARGET_DISCOVERY; + else if (strcasecmp(mapme_target_str, "timescale") == 0) + return MAPME_TARGET_TIMESCALE; + else + return MAPME_TARGET_RETX; +} + +#define MAX_MAPME_ARG_LEN 30 + +typedef struct { + mapme_target_t target; + // Command argument stored as a string + // before being parsed into 'enabled' or 'timescale' + char unparsed_arg[MAX_MAPME_ARG_LEN]; + + uint8_t enabled; // 1 = on, 0 = off + uint32_t timescale; // Milliseconds + + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + uint32_t face_id; +} hc_mapme_t; + +#endif /* HICNCTRL_OBJECTS_MAPME_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h new file mode 100644 index 000000000..437387e4a --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-2022 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 objects/policy.h + * \brief Policy. + */ + +#ifndef HICNCTRL_OBJECTS_POLICY_H +#define HICNCTRL_OBJECTS_POLICY_H + +typedef struct { + int family; /* Krw */ + hicn_ip_address_t remote_addr; /* krw */ + uint8_t len; /* krw */ + hicn_policy_t policy; /* .rw */ +} hc_policy_t; + +#define foreach_policy(VAR, data) foreach_type(hc_policy_t, VAR, data) + +/* TODO */ +#define MAXSZ_HC_POLICY_ 0 +#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM + +int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy); +int hc_policy_validate(const hc_policy_t *policy); + +#endif /* HICNCTRL_OBJECTS_POLICY_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h new file mode 100644 index 000000000..d18e596b1 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 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 objects/punting.h + * \brief Punting + */ + +#ifndef HICNCTRL_OBJECTS_PUNTING_H +#define HICNCTRL_OBJECTS_PUNTING_H + +typedef struct { + face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ? + int family; /* Krw */ + hicn_ip_address_t prefix; /* krw */ + u8 prefix_len; /* krw */ +} hc_punting_t; + +int hc_punting_validate(const hc_punting_t *punting); +int hc_punting_cmp(const hc_punting_t *c1, const hc_punting_t *c2); + +#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data) + +#define MAXSZ_HC_PUNTING_ 0 +#define MAXSZ_HC_PUNTING MAXSZ_HC_PUNTING_ + NULLTERM + +int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting); + +#endif /* HICNCTRL_OBJECTS_PUNTING_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h new file mode 100644 index 000000000..fb68e9430 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2022 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 objects/route.h + * \brief Route. + */ + +#ifndef HICNCTRL_OBJECTS_ROUTE_H +#define HICNCTRL_OBJECTS_ROUTE_H + +#include <hicn/ctrl/objects/face.h> + +typedef struct { + face_id_t face_id; /* Kr. ID (used when face and face_name == NULL) */ + char face_name[SYMBOLIC_NAME_LEN]; /* Kr. a name or an ID (if integer), used + if face is NULL */ + int family; /* Krw */ + hicn_ip_address_t remote_addr; /* krw */ + uint8_t len; /* krw */ + uint16_t cost; /* .rw */ + hc_face_t face; /* use by default if not NULL, otherwise look at face_name, + then face_id */ +} hc_route_t; + +#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data) + +#define MAX_COST 65535 +#define MAXSZ_COST 5 +#define MAX_LEN 255 +#define MAXSZ_LEN 3 + +#define MAXSZ_HC_ROUTE_ \ + MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN +#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM + +int hc_route_snprintf(char *s, size_t size, const hc_route_t *route); +int hc_route_validate(const hc_route_t *route, bool allow_partial); + +#endif /* HICNCTRL_OBJECTS_ROUTE_H */ diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/stats.h index 16f65e5c4..31c590dee 100644 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -13,13 +13,17 @@ * limitations under the License. */ -#ifndef __HICN_LIGHT_H__ -#define __HICN_LIGHT_H__ +/** + * \file objects/stats.h + * \brief Stats. + */ + +#ifndef HICNCTRL_OBJECTS_STATS_H +#define HICNCTRL_OBJECTS_STATS_H -#include "hicn_light_comm.h" +#define MAXSZ_HC_STATS 600 -// functions that sysrepo-plugin need -int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx); -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx); +typedef hicn_light_stats_t hc_stats_t; +typedef connection_stats_t hc_face_stats_t; -#endif //__HICN_LIGHT_H__
\ No newline at end of file +#endif /* HICNCTRL_OBJECTS_STATS_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h new file mode 100644 index 000000000..208f4620b --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h @@ -0,0 +1,46 @@ + +/* + * Copyright (c) 2021-2022 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 objects/strategy.h + * \brief Strategy. + */ + +#ifndef HICNCTRL_OBJECTS_STRATEGY_H +#define HICNCTRL_OBJECTS_STRATEGY_H + +#include <hicn/strategy.h> + +#define MAXSZ_STRATEGY_NAME 255 + +typedef struct { + // The name is not set by the controller + // but populated by the daemon + char name[MAXSZ_STRATEGY_NAME]; + strategy_type_t type; + hicn_ip_address_t address, local_address; + int family, local_family; + u8 len, local_len; +} hc_strategy_t; + +#define foreach_strategy(VAR, data) foreach_type(hc_strategy_t, VAR, data) + +#define MAXSZ_HC_STRATEGY_ MAXSZ_STRATEGY_NAME +#define MAXSZ_HC_STRATEGY MAXSZ_HC_STRATEGY_ + NULLTERM + +int hc_strategy_snprintf(char *s, size_t size, const hc_strategy_t *strategy); + +#endif /* HICNCTRL_OBJECTS_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h new file mode 100644 index 000000000..861341160 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021-2022 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 objects/subscription.h + * \brief Subscription. + */ + +#ifndef HICNCTRL_OBJECTS_SUBSCRIPTION_H +#define HICNCTRL_OBJECTS_SUBSCRIPTION_H + +#include <limits.h> +#include <stddef.h> +#include <hicn/ctrl/object_type.h> + +#undef PUNTING // TODO(eloparco): Undefined to avoid collisions + // Fix the collision + +// Used only to create 'hc_topic_t' +typedef struct { +#define _(x) char x; + foreach_object_type +#undef _ +} object_offset_t; + +// Flags for topic subscriptions +typedef enum { +#define _(x) TOPIC_##x = (1 << offsetof(object_offset_t, x)), + foreach_object_type +#undef _ + TOPIC_ALL = INT_MAX, +} hc_topic_t; + +static inline hc_object_type_t object_from_topic(hc_topic_t topic) { +#define _(x) \ + if (topic == TOPIC_##x) return OBJECT_TYPE_##x; + foreach_object_type +#undef _ + return OBJECT_TYPE_UNDEFINED; +} + +static inline hc_topic_t topic_from_object_type(hc_object_type_t object_type) { + if (object_type == OBJECT_TYPE_UNDEFINED) return TOPIC_ALL; +#define _(x) \ + if (object_type == OBJECT_TYPE_##x) return TOPIC_##x; + foreach_object_type +#undef _ + return TOPIC_UNDEFINED; +} + +#define NUM_TOPICS OBJECT_TYPE_N // Because a topic is created for each object +#define ALL_TOPICS ~0 + +// Subscriptions +typedef uint32_t hc_topics_t; +typedef struct { + hc_topics_t topics; +} hc_subscription_t; + +#if 0 +typedef struct { + netdevice_type_t interface_type; +} hc_event_interface_update_t; + +typedef struct { + ip_prefix_t prefix; + netdevice_type_t interface_type; +} hc_event_active_interface_update_t; +#endif + +#endif /* HICNCTRL_OBJECTS_SUBSCRIPTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h b/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h new file mode 100644 index 000000000..8921d25ed --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h @@ -0,0 +1,116 @@ +#ifndef HICNLIGHT_PARSE_CMD +#define HICNLIGHT_PARSE_CMD + +#include <hicn/ctrl/api.h> + +#include "command.h" + +/* Update sscanf accordingly in parse_cmd.c */ +#define MAX_PARAMETERS 10 +#define MAX_SCANF_PARAM_LEN 100 + +typedef int (*parser_hook_t)(void* arg); + +#if 0 +typedef struct { + const char* name; + const char* help; + parser_type_t type; + size_t offset; + /* + * quick hack to let the functions update two or more parameters, like for + * IP_ADDRESS or IP_PREFIX types + */ + size_t offset2; + size_t offset3; +} command_parameter_t; + +typedef struct { + hc_action_t action; + hc_object_type_t object; + unsigned nparams; + command_parameter_t parameters[MAX_PARAMETERS]; + parser_hook_t post_hook; +} command_parser_t; + +#define TYPE_STRN(N) \ + (parser_type_t) { \ + .name = TYPENAME_STR, \ + .str = { \ + .max_size = N, \ + }, \ + } +#define TYPE_FMT_STRN(N) "%s" + +#define TYPE_INT(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_INT, \ + .sint = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } +#define TYPE_FMT_INT "%d" + +#define TYPE_UINT(min, max) \ + (parser_type_t) { \ + .name = TYPENAME_UINT, \ + .uint = { \ + .min = min, \ + .max = max, \ + }, \ + } +#define TYPE_FMT_UINT "%u" + +#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) +#define TYPE_FMT_SYMBOLIC_OR_ID "%s" + +#define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) +#define TYPE_FMT_INTERFACE_NAME "%s" + +#define TYPE_IP_ADDRESS \ + (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } +#define TYPE_FMT_IP_ADDRESS "%s" + +#define TYPE_IP_PREFIX \ + (parser_type_t) { .name = TYPENAME_IP_PREFIX, } +#define TYPE_FMT_IP_PREFIX "%s" + +#define TYPE_ON_OFF \ + (parser_type_t) { .name = TYPENAME_ON_OFF, } +#define TYPE_FMT_ON_OFF "%s" + +#define TYPE_ENUM(x) \ + (parser_type_t) { \ + .name = TYPENAME_ENUM, \ + .enum_ = { \ + .from_str = (int (*)(const char*))x##_from_str, \ + }, \ + } +/* We need to allocate room for the intermediate string */ +#define TYPE_FMT_ENUM "%s" + +#define TYPE_POLICY_STATE(TAG) \ + (parser_type_t) { \ + .name = TYPENAME_POLICY_STATE, \ + .policy_state = { \ + .tag = TAG, \ + }, \ + } +/* We need to allocate room for the intermediate string */ +#define TYPE_FMT_POLICY_STATE "%s" +#endif + +int parse_getopt_args(const command_parser_t* parser, int argc, char* argv[], + hc_command_t* command); + +int parse(const char* cmd, hc_command_t* command); +int help(const char* cmd); + +/** + * @brief Convert the action enum to the action name used in the commands (e.g. + * from ACTION_CREATE to "add"). + */ +const char* action_to_cmd_action(hc_action_t action); + +#endif /* HICNLIGHT_PARSE_CMD */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h index d7ef6a26f..f1801d772 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,7 +21,7 @@ #define HICN_ROUTE_H #include <hicn/util/ip_address.h> -#include <hicn/ctrl/face.h> +#include <hicn/face.h> typedef u16 route_cost_t; @@ -30,18 +30,23 @@ typedef struct hicn_route_s hicn_route_t; #define MAXSZ_ROUTE_ MAXSZ_PREFIX + 3 + MAXSZ_COST #define MAXSZ_ROUTE MAXSZ_ROUTE_ + NULLTERM -hicn_route_t * hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost); -hicn_route_t * hicn_route_dup(const hicn_route_t * route); -void hicn_route_free(hicn_route_t * route); +#define MIN_ROUTE_COST 1 +#define MAX_ROUTE_COST 255 +#define IS_VALID_ROUTE_COST(x) ((x >= MIN_ROUTE_COST) && (x <= MAX_ROUTE_COST)) -int hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2); +hicn_route_t* hicn_route_create(hicn_ip_prefix_t* prefix, face_id_t face_id, + route_cost_t cost); +hicn_route_t* hicn_route_dup(const hicn_route_t* route); +void hicn_route_free(hicn_route_t* route); -int hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix); -int hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix); +int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2); -int hicn_route_get_cost(const hicn_route_t * route, int * cost); -int hicn_route_set_cost(hicn_route_t * route, const int cost); +int hicn_route_get_prefix(const hicn_route_t* route, hicn_ip_prefix_t* prefix); +int hicn_route_set_prefix(hicn_route_t* route, const hicn_ip_prefix_t prefix); -size_t hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route); +int hicn_route_get_cost(const hicn_route_t* route, int* cost); +int hicn_route_set_cost(hicn_route_t* route, const int cost); + +size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route); #endif diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h b/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h new file mode 100644 index 000000000..e53032955 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021-2022 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 socket.h + * \brief Control socket + */ + +#ifndef HICNCTRL_SOCKET_H +#define HICNCTRL_SOCKET_H + +#include <hicn/ctrl/data.h> + +/* With UDP, the buffer should be able to receieve a full packet, and thus MTU + * (max 9000) is sufficient. Messages will be received fully one by one. + * With TCP, the buffer should be at least able to receive a message header and + * the maximum size of a data element, so any reasonable size will be correct, + * it might just optimize performance. Messages might arrive in chunks that the + * library is able to parse. + */ +#define JUMBO_MTU 9000 +#define RECV_BUFLEN 65535 + +#define foreach_forwarder_type \ + _(UNDEFINED) \ + _(HICNLIGHT) \ + _(VPP) \ + _(N) + +typedef enum { +#define _(x) FORWARDER_TYPE_##x, + foreach_forwarder_type +#undef _ +} forwarder_type_t; + +extern const char *forwarder_type_str[]; + +#define forwarder_type_str(x) forwarder_type_str[x] + +forwarder_type_t forwarder_type_from_str(const char *str); + +/** + * \brief Holds the state of an hICN control socket + */ +typedef struct hc_sock_s hc_sock_t; + +/** + * \brief Create an hICN control socket using the provided forwarder. + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder); + +/** + * \brief Create an hICN control socket using the provided forwarder and a + * URL. \return an hICN control socket + */ +hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder, + const char *url); + +/** + * \brief Create an hICN control socket using the default connection type. + * XXX doc + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create(forwarder_type_t forwarder, const char *url); + +/** + * \brief Frees an hICN control socket + * \param [in] s - hICN control socket + */ +void hc_sock_free(hc_sock_t *s); + +/** + * \brief Returns the next available sequence number to use for requests to + * the API. \param [in] s - hICN control socket + */ +int hc_sock_get_next_seq(hc_sock_t *s); + +/** + * \brief Sets the socket as non-blocking + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_set_nonblocking(hc_sock_t *s); + +/** + * \brief Return the file descriptor associated to the hICN contorl sock + * \param [in] s - hICN control socket + * \return The file descriptor (positive value), or a negative integer in case + * of error + */ +int hc_sock_get_fd(hc_sock_t *s); + +/** + * \brief Connect the socket + * \return Error code + */ +int hc_sock_connect(hc_sock_t *s); + +/** + * \brief Return the offset and size of available buffer space + * \param [in] s - hICN control socket + * \param [out] buffer - Offset in buffer + * \param [out] size - Remaining size + * \return Error code + */ +int hc_sock_get_recv_buffer(hc_sock_t *s, uint8_t **buffer, size_t *size); + +#if 0 +/** + * \brief Write/read iexchance on the control socket (internal helper + * function) \param [in] s - hICN control socket \param [in] msg - Message to + * send \param [in] msglen - Length of the message to send \return Error code + */ +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq); +#endif + +/** + * \brief Processing data received by socket + * \param [in] s - hICN control socket + * \param [in] parse - Parse function to convert remote types into lib native + * types, or NULL not to perform any translation. + * \return Error code + */ +int hc_sock_process(hc_sock_t *s, hc_data_t **data); + +int hc_sock_receive(hc_sock_t *s, hc_data_t **data); +int hc_sock_receive_all(hc_sock_t *s, hc_data_t **data); + +#if 0 +/** + * \brief Callback used in async mode when data is available on the socket + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_callback(hc_sock_t *s, hc_data_t **data); +#endif + +/** + * \brief Reset the state of the sock (eg. to handle a reconnecton) + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_reset(hc_sock_t *s); + +void hc_sock_increment_woff(hc_sock_t *s, size_t bytes); + +#if 0 +int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, + data_callback_t complete_cb, void *complete_cb_data); + +#endif + +int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); + +int hc_sock_set_async(hc_sock_t *s); + +int hc_sock_is_async(hc_sock_t *s); + +int hc_sock_on_receive(hc_sock_t *s, size_t count); + +#endif /* HICNCTRL_SOCKET_H */ diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt index f9934d70e..3ea5c5db9 100644 --- a/ctrl/libhicnctrl/src/CMakeLists.txt +++ b/ctrl/libhicnctrl/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2023 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,80 +11,193 @@ # See the License for the specific language governing permissions and # limitations under the License. -list(APPEND COMPILER_DEFINITIONS - "-DWITH_POLICY" -) - +############################################################## +# Source files +############################################################## set(SOURCE_FILES - face.c - route.c - api.c + action.c + api.c + command.c + commands/command_cache.c + commands/command_connection.c + commands/command_face.c + commands/command_listener.c + commands/command_mapme.c + commands/command_policy.c + commands/command_punting.c + commands/command_route.c + commands/command_stats.c + commands/command_strategy.c + commands/command_subscription.c + data.c + fw_interface.c + object.c + object_type.c + object_vft.c + objects/active_interface.c + objects/base.c + objects/connection.c + objects/face.c + objects/listener.c + objects/mapme.c + objects/route.c + objects/strategy.c + objects/stats.c + objects/subscription.c + parse.c + request.c + route.c + socket.c ) set(HEADER_FILES - api_private.h + object_vft.h + objects/active_interface.h + objects/base.h + objects/connection.h + objects/face.h + objects/listener.h + objects/mapme.h + objects/route.h + objects/stats.h + objects/strategy.h + objects/subscription.h + request.h + api_private.h ) + +############################################################## +# Libraries to link +############################################################## set(LIBRARIES - m - dl - ${HICN_LIBRARIES} + m + dl + ${HICN_LIBRARIES} ) + +############################################################## +# Include directories +############################################################## set(INCLUDE_DIRS + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/../includes/ - ${HICN_INCLUDE_DIRS} + PUBLIC + $<BUILD_INTERFACE:${Libhicnctrl_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) -# Android requires static libraries + +############################################################## +# Library type +############################################################## if (DISABLE_SHARED_LIBRARIES) - set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC}) - set(LINK_TYPE STATIC) + set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC}) + set(LINK_TYPE STATIC) else () - set(LINK_TYPE SHARED STATIC) + set(LINK_TYPE SHARED STATIC) endif () -if (${CMAKE_SYSTEM_NAME} MATCHES Android) - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_api.c - ) + +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + +############################################################## +# Do not use modules if Android +############################################################## + +if (${CMAKE_SYSTEM_NAME} MATCHES Android OR ${CMAKE_SYSTEM_NAME} MATCHES iOS) + list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/mapme.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/stats.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/subscription.c + ) + list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/stats.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/subscription.h + ) else() - add_subdirectory(modules) + add_subdirectory(modules) endif() + +############################################################## +# Build main hicnctrl library +############################################################## build_library(${LIBHICNCTRL} - ${LINK_TYPE} - SOURCES ${SOURCE_FILES} ${HEADER_FILES} - INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} + ${LINK_TYPE} + SOURCES ${SOURCE_FILES} ${HEADER_FILES} + INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} + LINK_LIBRARIES ${LIBRARIES} + DEPENDS ${DEPENDENCIES} + COMPONENT ${LIBHICNCTRL_COMPONENT} + INCLUDE_DIRS ${INCLUDE_DIRS} + DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS} + VERSION ${CURRENT_VERSION} + EXPORT_NAME "${LIBHICNCTRL_COMPONENT}" + COMPILE_OPTIONS ${COMPILER_OPTIONS} +) + +############################################################## +# Unit tests +############################################################## +if (${BUILD_TESTS}) + add_subdirectory(test) +endif() + +############################################################## +# Cmake config files +############################################################## +create_cmake_config ( + ${LIBHICNCTRL_COMPONENT} + INCLUDE_DIRS ${Libhicnctrl_INCLUDE_DIRS} + VERSION ${CURRENT_VERSION} + COMPONENT ${LIBHICNCTRL_COMPONENT} + NAMESPACE hicn +) + + +############################################################## +# Build executables +############################################################## +if (NOT DISABLE_EXECUTABLES) + if (DISABLE_SHARED_LIBRARIES) + set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC}) + set(DEPENDENCIES ${LIBHICNCTRL_STATIC}) + else () + set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED}) + set(DEPENDENCIES ${LIBHICNCTRL_SHARED}) + endif () + + list(APPEND DAEMON_SRC + hicnctrl.c + ) + + build_executable(${HICNCTRL} + SOURCES ${DAEMON_SRC} LINK_LIBRARIES ${LIBRARIES} DEPENDS ${DEPENDENCIES} COMPONENT ${LIBHICNCTRL_COMPONENT} INCLUDE_DIRS ${INCLUDE_DIRS} - HEADER_ROOT_DIR hicn DEFINITIONS ${COMPILER_DEFINITIONS} -) - -if (NOT DISABLE_EXECUTABLES) - if (DISABLE_SHARED_LIBRARIES) - set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC}) - set(DEPENDENCIES ${LIBHICNCTRL_STATIC}) - else () - set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED}) - set(DEPENDENCIES ${LIBHICNCTRL_SHARED}) - endif () - - list(APPEND DAEMON_SRC - cli.c - ) - - build_executable(${HICNCTRL} - SOURCES ${DAEMON_SRC} - LINK_LIBRARIES ${LIBRARIES} - DEPENDS ${DEPENDENCIES} - COMPONENT ${LIBHICNCTRL_COMPONENT} - INCLUDE_DIRS ${INCLUDE_DIRS} - DEFINITIONS ${COMPILER_DEFINITIONS} - LINK_FLAGS ${LINK_FLAGS} - ) + LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} + ) endif () diff --git a/ctrl/libhicnctrl/src/action.c b/ctrl/libhicnctrl/src/action.c new file mode 100644 index 000000000..c8834d90c --- /dev/null +++ b/ctrl/libhicnctrl/src/action.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 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 action.c + * \brief Implementation of actions. + */ + +#include <strings.h> + +#include <hicn/ctrl/action.h> + +const char *action_str[] = { +#define _(x) [ACTION_##x] = #x, + foreach_action +#undef _ +}; + +hc_action_t action_from_str(const char *action_str) { +#define _(x) \ + if (strcasecmp(action_str, #x) == 0) \ + return ACTION_##x; \ + else + foreach_action +#undef _ + if (strcasecmp(action_str, "add") == 0) return ACTION_CREATE; + else if (strcasecmp(action_str, "remove") == 0) return ACTION_DELETE; + else return ACTION_UNDEFINED; +} diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c index 4bb66c784..c133b9123 100644 --- a/ctrl/libhicnctrl/src/api.c +++ b/ctrl/libhicnctrl/src/api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -18,1274 +18,275 @@ * \brief Implementation of hICN control library API */ -#include <hicn/util/log.h> -#include "api_private.h" - -#include <math.h> // log2 +#include <assert.h> #include <dlfcn.h> // dlopen +#include <hicn/strategy.h> +#include <hicn/util/log.h> +#include <hicn/ctrl/route.h> +#include <math.h> // log2 -/* /!\ Please update constants in public header file upon changes */ -const char * connection_state_str[] = { -#define _(x) [HC_CONNECTION_STATE_ ## x] = STRINGIZE(x), -foreach_connection_state -#undef _ -}; - -/* /!\ Please update constants in public header file upon changes */ -const char * connection_type_str[] = { -#define _(x) [CONNECTION_TYPE_ ## x] = STRINGIZE(x), -foreach_connection_type -#undef _ -}; - -hc_connection_type_t -connection_type_from_str(const char * str) -{ - if (strcasecmp(str, "TCP") == 0) - return CONNECTION_TYPE_TCP; - else if (strcasecmp(str, "UDP") == 0) - return CONNECTION_TYPE_UDP; - else if (strcasecmp(str, "HICN") == 0) - return CONNECTION_TYPE_HICN; - else - return CONNECTION_TYPE_UNDEFINED; -} - -/* Conversions to shield lib user from heterogeneity */ - -#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN)) - -const hc_connection_type_t map_from_list_connections_type[] = { - [CONN_GRE] = CONNECTION_TYPE_UNDEFINED, - [CONN_TCP] = CONNECTION_TYPE_TCP, - [CONN_UDP] = CONNECTION_TYPE_UDP, - [CONN_MULTICAST] = CONNECTION_TYPE_UNDEFINED, - [CONN_L2] = CONNECTION_TYPE_UNDEFINED, - [CONN_HICN] = CONNECTION_TYPE_HICN, -}; - -#define IS_VALID_LIST_LISTENERS_TYPE(x) ((x >= ENCAP_TCP) && (x <= ENCAP_HICN)) - -const hc_connection_type_t map_from_encap_type[] = { - [ENCAP_TCP] = CONNECTION_TYPE_TCP, - [ENCAP_UDP] = CONNECTION_TYPE_UDP, - [ENCAP_ETHER] = CONNECTION_TYPE_UNDEFINED, - [ENCAP_LOCAL] = CONNECTION_TYPE_UNDEFINED, - [ENCAP_HICN] = CONNECTION_TYPE_HICN, -}; - -const connection_type map_to_connection_type[] = { - [CONNECTION_TYPE_TCP] = TCP_CONN, - [CONNECTION_TYPE_UDP] = UDP_CONN, - [CONNECTION_TYPE_HICN] = HICN_CONN, -}; - -const listener_mode map_to_listener_mode[] = { - [CONNECTION_TYPE_TCP] = IP_MODE, - [CONNECTION_TYPE_UDP] = IP_MODE, - [CONNECTION_TYPE_HICN] = HICN_MODE, -}; - -#define IS_VALID_LIST_CONNECTIONS_STATE(x) ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN)) - -/* -#define IS_VALID_CONNECTION_STATE(x) IS_VALID_ENUM_TYPE(CONNECTION_STATE, x) - -static const connection_state map_to_connection_state[] = { - [HC_CONNECTION_STATE_UP] = IFACE_UP, - [HC_CONNECTION_STATE_DOWN] = IFACE_DOWN, -}; - -*/ - -const hc_connection_state_t map_from_list_connections_state[] = { - [IFACE_UP] = HC_CONNECTION_STATE_UP, - [IFACE_DOWN] = HC_CONNECTION_STATE_DOWN, - [IFACE_UNKNOWN] = HC_CONNECTION_STATE_UNDEFINED, -}; - - -const int map_from_addr_type[] = { - [ADDR_INET] = AF_INET, - [ADDR_INET6] = AF_INET6, - [ADDR_LINK] = AF_UNSPEC, - [ADDR_IFACE] = AF_UNSPEC, - [ADDR_UNIX] = AF_UNSPEC, -}; - -const address_type map_to_addr_type[] = { - [AF_INET] = ADDR_INET, - [AF_INET6] = ADDR_INET6, -}; - -/****************************************************************************** - * Control Data - ******************************************************************************/ - -hc_data_t * -hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb) -{ - hc_data_t * data = malloc(sizeof(hc_data_t)); - if (!data) - goto ERR_MALLOC; - - /* FIXME Could be NULL thanks to realloc provided size is 0 */ - data->max_size_log = DEFAULT_SIZE_LOG; - data->in_element_size = in_element_size; - data->out_element_size = out_element_size; - data->size = 0; - data->complete = false; - data->command_id = 0; // TODO this could also be a busy mark in the socket - /* No callback needed in blocking code for instance */ - data->complete_cb = complete_cb; - - data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); - if (!data->buffer) - goto ERR_BUFFER; - data->ret = 0; - - return data; - -ERR_BUFFER: - hc_data_free(data); -ERR_MALLOC: - return NULL; -} - -void -hc_data_free(hc_data_t * data) -{ - if (data->buffer) - free(data->buffer); - free(data); -} - -int -hc_data_ensure_available(hc_data_t * data, size_t count) -{ - size_t new_size_log = (data->size + count - 1 > 0) - ? log2(data->size + count - 1) + 1 - : 0; - if (new_size_log > data->max_size_log) { - data->max_size_log = new_size_log; - data->buffer = realloc(data->buffer, (1 << new_size_log) * data->out_element_size); - if (!data->buffer) - return -1; - } - - return 0; -} +#include "api_private.h" +#include "object_vft.h" +#include "request.h" -int -hc_data_push_many(hc_data_t * data, const void * elements, size_t count) -{ - if (hc_data_ensure_available(data, count) < 0) - return -1; +#include <hicn/ctrl/socket.h> +#include "socket_private.h" - memcpy(data->buffer + data->size * data->out_element_size, elements, - count * data->out_element_size); - data->size += count; +#define ENOIMPL 42 - return 0; -} +int hc_sock_on_init(hc_sock_t *s, hc_request_t *request) { + int rc; + ssize_t size; -int -hc_data_push(hc_data_t * data, const void * element) -{ - return hc_data_push_many(data, element, 1); -} + uint8_t *buffer; -/** - * - * NOTE: This function make sure there is enough room available in the data - * structure. - */ -u8 * -hc_data_get_next(hc_data_t * data) -{ - if (hc_data_ensure_available(data, 1) < 0) - return NULL; + size = s->ops.prepare(s, request, &buffer); + if (size < 0) goto ERR_PREPARE; - return data->buffer + data->size * data->out_element_size; -} + if (size == 0) return 1; /* Done */ -int -hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data) -{ - data->complete_cb = cb; - data->complete_cb_data = cb_data; - return 0; -} + assert(hc_request_get_data(hc_request_get_current(request))); -int -hc_data_set_complete(hc_data_t * data) -{ - data->complete = true; - data->ret = 0; - if (data->complete_cb) - return data->complete_cb(data, data->complete_cb_data); - return 0; -} + rc = s->ops.send(s, buffer, size); + if (rc < 0) goto ERR_SEND; -int -hc_data_set_error(hc_data_t * data) -{ - data->ret = -1; - return 0; -} + return 0; -int -hc_data_reset(hc_data_t * data) -{ - data->size = 0; - return 0; +ERR_PREPARE: +ERR_SEND: + return -1; } -static hc_sock_t * _open_module(const char *name) -{ - char complete_name[128]; -#ifdef __APPLE__ - sprintf(complete_name, "%s.dylib", name); -#elif defined(__linux__) - sprintf(complete_name, "%s.so", name); -#else - #error "System not supported for dynamic lynking" -#endif +int hc_sock_on_receive(hc_sock_t *s, size_t count) { + int rc; - void *handle = 0; - const char *error = 0; - hc_sock_t *(*creator)(void) = 0; - hc_sock_t *ret = 0; + DEBUG("hc_sock_on_receive: calling process with count=%ld", count); + rc = s->ops.process(s, count); + if (rc < 0) goto ERR_PROCESS; - // open module - handle = dlopen(complete_name, RTLD_LAZY); - if (!handle) { - if ((error = dlerror()) != 0) { - ERROR("%s", error); + hc_request_t *request = hc_sock_get_request(s); + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + if (hc_data_is_complete(data)) { + /* + * We only notice a request is complete when trying to send the second + * time... either the state machine reaches the end, or in case of generic + * requests, we mark it as such. + */ + ON_INIT: + rc = hc_sock_on_init(s, request); + if (rc < 0) goto ERR_INIT; + if (rc == 1) { + if (!hc_request_pop(request)) { + /* Free request context */ + /* In case of error, data is NULL */ + // hc_sock_free_request(s, request); + if (!hc_request_is_subscription(request)) + hc_request_set_complete(request); + return 1; /* Done */ + } + goto ON_INIT; } - - return 0; - } - - // get factory method - creator = (hc_sock_t * (*)(void)) dlsym(handle, "_hc_sock_create"); - if (!creator) { - if ((error = dlerror()) != 0) { - ERROR("%s", error); - return 0; +#if 0 } +#endif } - - ret = (*creator)(); - ret->handle = handle; - - return ret; -} - -hc_sock_t *hc_sock_create_forwarder(forwarder_t forwarder) -{ - switch (forwarder) - { - case HICNLIGHT: - return _open_module("hicnlightctrl_module"); - case VPP: - return _open_module("vppctrl_module"); - default: - return NULL; + return 0; /* Continue processing */ + +ERR_INIT: +ERR_PROCESS: + return -1; +} + +// -1 error +// 0 = request is not yet complete +// 1 request is complete +int hc_sock_receive(hc_sock_t *s, hc_data_t **pdata) { + int rc; + DEBUG("Waiting for data..."); + rc = s->ops.recv(s); + if (rc < 0) return -1; + + rc = hc_sock_on_receive(s, 0); + if (rc < 0) return -1; + + hc_request_t *request = hc_sock_get_request(s); + /* + * If notification, display it, ideally callback. What to do with + * allocated data ? + */ + // XXX problem we display object on ACK... but not subsequent + // notifications + // XXX we should rely on callback here in addition, even for a synchronous + // request + if (hc_request_is_subscription(request)) { + hc_data_t *data = hc_request_get_data(request); + assert(data); + hc_object_t *obj = (hc_object_t *)hc_data_get_buffer(data); + char buf[MAXSZ_HC_OBJECT]; + hc_object_type_t object_type = hc_data_get_object_type(data); + if (hc_object_snprintf(buf, sizeof(buf), object_type, obj) > 0) { + ; + INFO("%s %s", object_type_str(object_type), buf); } -} - -#ifdef ANDROID -// In android we do not load a module at runtime -// but we link the hicnlight implmentation directly -// to the main library -extern hc_sock_t *_hc_sock_create(); -#endif - -hc_sock_t *hc_sock_create(void) -{ -#ifdef ANDROID - hc_sock_t *ret = _hc_sock_create(); - ret->handle = NULL; - return ret; -#else - return hc_sock_create_forwarder(HICNLIGHT); -#endif -} + } -void hc_sock_free(hc_sock_t *s) -{ - void *handle = s->handle; - s->hc_sock_free(s); + // XXX need same for async + if (rc != 1) return 0; - if (handle) { - dlclose(handle); + hc_request_t *current_request = hc_request_get_current(request); + if (hc_request_is_complete(current_request)) { + /* We either return the (last) allocated data, or free it */ + if (pdata) { + *pdata = hc_request_get_data(request); + } else { + hc_request_reset_data(request); } + hc_request_on_complete(request); + // hc_sock_free_request(s, request); + } + return 1; } -int hc_sock_get_next_seq(hc_sock_t *s) -{ - return s->hc_sock_get_next_seq(s); -} - -int hc_sock_set_nonblocking(hc_sock_t *s) -{ - return s->hc_sock_get_next_seq(s); -} - -int hc_sock_get_fd(hc_sock_t *s) -{ - return s->hc_sock_get_fd(s); -} - -int hc_sock_connect(hc_sock_t *s) -{ - return s->hc_sock_connect(s); -} - -int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) -{ - return s->hc_sock_get_available(s, buffer, size); -} - -int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) -{ - return s->hc_sock_send(s, msg, msglen, seq); -} - -int hc_sock_recv(hc_sock_t *s) -{ - return s->hc_sock_recv(s); -} - -int hc_sock_process(hc_sock_t *s, hc_data_t **data) -{ - return s->hc_sock_process(s, data); -} - -int hc_sock_callback(hc_sock_t *s, hc_data_t **data) -{ - return s->hc_sock_callback(s, data); -} - -int hc_sock_reset(hc_sock_t *s) -{ - return s->hc_sock_reset(s); -} - -int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) -{ - return s->hc_listener_create(s, listener); -} - -int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found) -{ - return s->hc_listener_get(s, listener, listener_found); -} - -int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) -{ - return s->hc_listener_delete(s, listener); -} - -int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) -{ - return s->hc_listener_list(s, pdata); -} - -GENERATE_FIND(listener); - -/* LISTENER VALIDATE */ - -int -hc_listener_validate(const hc_listener_t * listener) -{ - if (!IS_VALID_FAMILY(listener->family)) - return -1; - - if (!IS_VALID_CONNECTION_TYPE(listener->type)) - return -1; - - return 0; -} - -/* LISTENER CMP */ - -int -hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2) -{ - int rc; - - rc = INT_CMP(l1->type, l2->type); - if (rc != 0) - return rc; - - rc = INT_CMP(l1->family, l2->family); - if (rc != 0) - return rc; - - rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN); - if (rc != 0) - return rc; - - rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family); - if (rc != 0) - return rc; - - rc = INT_CMP(l1->local_port, l2->local_port); - if (rc != 0) - return rc; - - return rc; -} - -/* LISTENER PARSE */ - -int -hc_listener_parse(void * in, hc_listener_t * listener) -{ - int rc; - - list_listeners_command * cmd = (list_listeners_command *)in; - - if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType)) - return -1; - - hc_connection_type_t type = map_from_encap_type[cmd->encapType]; - if (type == CONNECTION_TYPE_UNDEFINED) - return -1; - - if (!IS_VALID_ADDR_TYPE(cmd->addressType)) - return -1; - - int family = map_from_addr_type[cmd->addressType]; - if (!IS_VALID_FAMILY(family)) - return -1; - - *listener = (hc_listener_t) { - .id = cmd->connid, - .type = type, - .family = family, - .local_addr = UNION_CAST(cmd->address, ip_address_t), - .local_port = ntohs(cmd->port), - }; - rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", cmd->listenerName); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_listener_parse] Unexpected truncation of symbolic name string"); - rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName); - if (rc >= INTERFACE_LEN) - WARN("[hc_listener_parse] Unexpected truncation of interface name string"); - return 0; -} - -/* LISTENER SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int -hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener) -{ - char local[MAXSZ_URL]; - int rc; - rc = url_snprintf(local, MAXSZ_URL, - listener->family, &listener->local_addr, listener->local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_listener_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - - return snprintf(s, size, "%s %s %s", listener->interface_name, local, - connection_type_str[listener->type]); -} - -int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) -{ - return s->hc_connection_create(s, connection); -} - -int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found) -{ - return s->hc_connection_get(s, connection, connection_found); -} - -int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection) -{ - return s->hc_connection_update_by_id(s, hc_connection_id, connection); -} - -int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, - hc_connection_t *connection_updated) -{ - return s->hc_connection_update(s, connection_current, connection_updated); -} - -int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) -{ - return s->hc_connection_delete(s, connection); -} - -int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) -{ - return s->hc_connection_list(s, pdata); -} - -int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state) -{ - return s->hc_connection_set_admin_state(s, conn_id_or_name, state); -} - -#ifdef WITH_POLICY -int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) -{ - return s->hc_connection_set_priority(s, conn_id_or_name, priority); -} - -int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) -{ - return s->hc_connection_set_tags(s, conn_id_or_name, tags); -} -#endif // WITH_POLICY - -GENERATE_FIND(connection); - -/* CONNECTION VALIDATE */ - -int -hc_connection_validate(const hc_connection_t * connection) -{ - if (!IS_VALID_FAMILY(connection->family)) - return -1; - - if (!IS_VALID_CONNECTION_TYPE(connection->type)) - return -1; +int hc_sock_receive_all(hc_sock_t *s, hc_data_t **pdata) { + for (;;) { + int rc = hc_sock_receive(s, pdata); + if (rc < 0) return -1; - /* TODO assert both local and remote have the right family */ - - return 0; + /* If request is complete, stop */ + if (rc == 1) break; + } + return 0; } -/* CONNECTION CMP */ - -/* - * hICN light uses ports even for hICN connections, but their value is ignored. - * As connections are specific to hicn-light, we can safely use IP and ports for - * comparison independently of the face type. +/** + * @return <0 in case of error + * -1 : validation error + * -2 : error during send + * -3 : error receiving or parsing + * + * If the caller provider a non-NULL hc_data_t pointer to receive results + * back, it is responsible for freeing it. */ -int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2) -{ - int rc; - - rc = INT_CMP(c1->type, c2->type); - if (rc != 0) - return rc; - - rc = INT_CMP(c1->family, c2->family); - if (rc != 0) - return rc; - - rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN); - if (rc != 0) - return rc; - - rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family); - if (rc != 0) - return rc; - - rc = INT_CMP(c1->local_port, c2->local_port); - if (rc != 0) - return rc; - - rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family); - if (rc != 0) - return rc; - - rc = INT_CMP(c1->remote_port, c2->remote_port); - if (rc != 0) - return rc; - - return rc; -} - -/* CONNECTION PARSE */ - -int -hc_connection_parse(void * in, hc_connection_t * connection) -{ - int rc; - list_connections_command * cmd = (list_connections_command *)in; - - if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connectionType)) - return -1; +int _hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_result_callback_t callback, + void *callback_data, hc_data_t **pdata) { + assert(!(hc_sock_is_async(s) && pdata)); - hc_connection_type_t type = map_from_list_connections_type[cmd->connectionData.connectionType]; - if (type == CONNECTION_TYPE_UNDEFINED) - return -1; - - if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state)) - return -1; - - hc_connection_state_t state = map_from_list_connections_state[cmd->state]; - if (state == HC_CONNECTION_STATE_UNDEFINED) - return -1; - - if (!IS_VALID_ADDR_TYPE(cmd->connectionData.ipType)) - return -1; - - int family = map_from_addr_type[cmd->connectionData.ipType]; - if (!IS_VALID_FAMILY(family)) - return -1; - - *connection = (hc_connection_t) { - .id = cmd->connid, - .type = type, - .family = family, - .local_addr = cmd->connectionData.localIp, - //.local_addr = UNION_CAST(cmd->connectionData.localIp, ip_address_t), - .local_port = ntohs(cmd->connectionData.localPort), - .remote_addr = cmd->connectionData.remoteIp, - //.remote_addr = UNION_CAST(cmd->connectionData.remoteIp, ip_address_t), - .remote_port = ntohs(cmd->connectionData.remotePort), - .admin_state = cmd->connectionData.admin_state, -#ifdef WITH_POLICY - .priority = cmd->connectionData.priority, - .tags = cmd->connectionData.tags, -#endif /* WITH_POLICY */ - .state = state, - }; - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", cmd->connectionData.symbolic); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_connection_parse] Unexpected truncation of symbolic name string"); - rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName); - if (rc >= INTERFACE_LEN) - WARN("[hc_connection_parse] Unexpected truncation of interface name string"); - return 0; -} - -/* CONNECTION SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int -hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection) -{ - char local[MAXSZ_URL]; - char remote[MAXSZ_URL]; - int rc; - - // assert(connection->connection_state) - - rc = url_snprintf(local, MAXSZ_URL, connection->family, - &connection->local_addr, connection->local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - rc = url_snprintf(remote, MAXSZ_URL, connection->family, - &connection->remote_addr, connection->remote_port); - if (rc >= MAXSZ_URL) - WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - - return snprintf(s, size, "%s %s %s %s %s", - connection_state_str[connection->state], - connection->interface_name, - local, - remote, - connection_type_str[connection->type]); -} - -int hc_face_create(hc_sock_t *s, hc_face_t *face) -{ - return s->hc_face_create(s, face); -} - -int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found) -{ - return s->hc_face_get(s, face, face_found); -} - -int hc_face_delete(hc_sock_t *s, hc_face_t *face) -{ - return s->hc_face_delete(s, face); -} - -int hc_face_list(hc_sock_t *s, hc_data_t **pdata) -{ - return s->hc_face_list(s, pdata); -} - -int hc_face_list_async(hc_sock_t *s) -{ - return s->hc_face_list_async(s); -} - -int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state) -{ - return s->hc_face_set_admin_state(s, conn_id_or_name, state); -} - -#ifdef WITH_POLICY -int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) -{ - return s->hc_face_set_priority(s, conn_id_or_name, priority); -} - -int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) -{ - return s->hc_face_set_tags(s, conn_id_or_name, tags); -} -#endif /* WITH_POLICY */ - -/* /!\ Please update constants in header file upon changes */ -int -hc_face_snprintf(char * s, size_t size, hc_face_t * face) -{ - /* URLs are also big enough to contain IP addresses in the hICN case */ - char local[MAXSZ_URL]; - char remote[MAXSZ_URL]; -#ifdef WITH_POLICY - char tags[MAXSZ_POLICY_TAGS]; -#endif /* WITH_POLICY */ - int rc; - - switch(face->face.type) { - case FACE_TYPE_HICN: - case FACE_TYPE_HICN_LISTENER: - rc = ip_address_snprintf(local, MAXSZ_URL, - &face->face.local_addr, - face->face.family); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - rc = ip_address_snprintf(remote, MAXSZ_URL, - &face->face.remote_addr, - face->face.family); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - break; - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - rc = url_snprintf(local, MAXSZ_URL, face->face.family, - &face->face.local_addr, - face->face.local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - rc = url_snprintf(remote, MAXSZ_URL, face->face.family, - &face->face.remote_addr, - face->face.remote_port); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) - return rc; - break; - default: - return -1; - } - - // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS) -#ifdef WITH_POLICY - rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags); - if (rc >= MAXSZ_POLICY_TAGS) - WARN("[hc_face_snprintf] Unexpected truncation of policy tags string"); - if (rc < 0) - return rc; - - return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", - face->id, - face->name, - face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*", - face_type_str[face->face.type], - local, - remote, - face_state_str[face->face.state], - face_state_str[face->face.admin_state], - face->face.priority, - tags); -#else - return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s", - face->id, - face->name, - face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*", - face_type_str[face->face.type], - local, - remote, - face_state_str[face->face.state], - face_state_str[face->face.admin_state]); -#endif /* WITH_POLICY */ -} - -int -hc_connection_parse_to_face(void * in, hc_face_t * face) -{ - hc_connection_t connection; - - if (hc_connection_parse(in, &connection) < 0) { - ERROR("[hc_connection_parse_to_face] Could not parse connection"); - return -1; - } - - if (hc_connection_to_face(&connection, face) < 0) { - ERROR("[hc_connection_parse_to_face] Could not convert connection to face."); - return -1; - } - - return 0; -} - -int hc_route_create(hc_sock_t * s, hc_route_t * route) -{ - return s->hc_route_create(s, route); -} - -int hc_route_delete(hc_sock_t * s, hc_route_t * route) -{ - return s->hc_route_delete(s, route); -} - -int hc_route_list(hc_sock_t * s, hc_data_t ** pdata) -{ - return s->hc_route_list(s, pdata); -} - -int hc_route_list_async(hc_sock_t * s) -{ - return s->hc_route_list_async(s); -} - -/* ROUTE PARSE */ - -int -hc_route_parse(void * in, hc_route_t * route) -{ - list_routes_command * cmd = (list_routes_command *) in; + if (hc_sock_is_async(s) && !s->ops.get_fd) { + return -1; /* No async support */ + } - if (!IS_VALID_ADDR_TYPE(cmd->addressType)) { - ERROR("[hc_route_parse] Invalid address type"); - return -1; - } + // XXX no need to pass pdata to the request + // XXX sync socket, no multiplexed requests, no notifications + /* + * The request will contain all state needed to identify and demultiplex + * replies and notifications arriving on the socket. We assume there is at + * most a single request/reply in progress for a given request, and that + * requests involving multiple queries will run them sequentially. The use + * of a sequence number that is transported by the requests and reply is + * thus sufficient to disambiguate them. + */ + hc_request_t *request = hc_sock_create_request(s, action, object_type, object, + callback, callback_data); + if (!request) { + goto ERR_REQUEST; + } - int family = map_from_addr_type[cmd->addressType]; - if (!IS_VALID_FAMILY(family)) { - ERROR("[hc_route_parse] Invalid address family"); - return -1; + if (hc_request_requires_object(request)) { + if (hc_object_is_empty(object) || + hc_object_validate(object_type, object, true) < 0) { + goto ERR_VALIDATE; } - - *route = (hc_route_t) { - .face_id = cmd->connid, - .family = family, - .remote_addr = UNION_CAST(cmd->address, ip_address_t), - .len = cmd->len, - .cost = cmd->cost, - }; - return 0; -} - -/* ROUTE SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int -hc_route_snprintf(char * s, size_t size, hc_route_t * route) -{ - /* interface cost prefix length */ - - char prefix[MAXSZ_IP_ADDRESS]; - int rc; - - rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr, - route->family); - if (rc >= MAXSZ_IP_ADDRESS) - ; - if (rc < 0) - return rc; - - return snprintf(s, size, "%*d %*d %s %*d", MAXSZ_FACE_ID, route->face_id, - MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, route->len); -} - -/* FACE -> LISTENER */ - -int -hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener) -{ - const face_t * f = &face->face; - - switch(f->type) { - case FACE_TYPE_HICN_LISTENER: - break; - case FACE_TYPE_TCP_LISTENER: - break; - case FACE_TYPE_UDP_LISTENER: - break; - default: - return -1; + } else { + if (object && !hc_object_is_empty(object)) { + goto ERR_CHECK; } - return -1; /* XXX Not implemented */ -} - -/* LISTENER -> FACE */ - -int -hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face) -{ - return -1; /* XXX Not implemented */ -} - -/* FACE -> CONNECTION */ - -int -hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name) -{ - int rc; - const face_t * f = &face->face; + } - switch(f->type) { - case FACE_TYPE_HICN: - *connection = (hc_connection_t) { - .type = CONNECTION_TYPE_HICN, - .family = f->family, - .local_addr = f->local_addr, - .local_port = 0, - .remote_addr = f->remote_addr, - .remote_port = 0, - .admin_state = face_state_to_connection_state(f->admin_state), - .state = face_state_to_connection_state(f->state), -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", - f->netdevice.name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string"); - break; - case FACE_TYPE_TCP: - *connection = (hc_connection_t) { - .type = CONNECTION_TYPE_TCP, - .family = f->family, - .local_addr = f->local_addr, - .local_port = f->local_port, - .remote_addr = f->remote_addr, - .remote_port = f->remote_port, - .admin_state = face_state_to_connection_state(f->admin_state), - .state = face_state_to_connection_state(f->state), -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - if (generate_name) { - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE()); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string"); - } else { - memset(connection->name, 0, SYMBOLIC_NAME_LEN); - } - break; - case FACE_TYPE_UDP: - *connection = (hc_connection_t) { - .type = CONNECTION_TYPE_UDP, - .family = AF_INET, - .local_addr = f->local_addr, - .local_port = f->local_port, - .remote_addr = f->remote_addr, - .remote_port = f->remote_port, - .admin_state = face_state_to_connection_state(f->admin_state), - .state = face_state_to_connection_state(f->state), -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - if (generate_name) { - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE()); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string"); - } else { - memset(connection->name, 0, SYMBOLIC_NAME_LEN); - } - snprintf(connection->interface_name, INTERFACE_LEN, "%s", - f->netdevice.name); - break; - default: - return -1; + /* Workaround for non-fd based modules */ + if (s->ops.prepare && s->ops.send && s->ops.recv && s->ops.process) { + if (hc_sock_on_init(s, request) < 0) goto ERR_INIT; + + if (hc_sock_is_async(s)) return 0; + + if (hc_sock_receive_all(s, pdata) < 0) goto ERR_RECV; + } else if (s->ops.prepare) { + // hc_data_t *data = hc_data_create(OBJECT_TYPE_LISTENER); + // hc_data_push(data, NULL); + // No nested requests for now... + ssize_t size = s->ops.prepare(s, request, NULL); + _ASSERT(size == 0); /* Done */ + if (hc_request_is_complete(request)) { + if (pdata) { + *pdata = hc_request_get_data(request); + } else { + hc_request_reset_data(request); + } + hc_request_on_complete(request); } + } - rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", - f->netdevice.name); - if (rc >= INTERFACE_LEN) - WARN("hc_face_to_connection] Unexpected truncation of interface name string"); + return 0; - return 0; +ERR_RECV: + hc_request_reset_data(request); +ERR_INIT: + hc_sock_free_request(s, request, true); +ERR_CHECK: +ERR_REQUEST: +ERR_VALIDATE: + if (pdata) *pdata = NULL; + return -1; } -/* CONNECTION -> FACE */ - -int -hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face) -{ - int rc; - switch (connection->type) { - case CONNECTION_TYPE_TCP: - *face = (hc_face_t) { - .id = connection->id, - .face = { - .type = FACE_TYPE_TCP, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - .remote_addr = connection->remote_addr, - .remote_port = connection->remote_port, - .admin_state = connection_state_to_face_state(connection->admin_state), - .state = connection_state_to_face_state(connection->state), -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - case CONNECTION_TYPE_UDP: - *face = (hc_face_t) { - .id = connection->id, - .face = { - .type = FACE_TYPE_UDP, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - .remote_addr = connection->remote_addr, - .remote_port = connection->remote_port, - .admin_state = connection_state_to_face_state(connection->admin_state), - .state = connection_state_to_face_state(connection->state), -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - case CONNECTION_TYPE_HICN: - *face = (hc_face_t) { - .id = connection->id, - .face = { - .type = FACE_TYPE_HICN, - .family = connection->family, - .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX - .local_addr = connection->local_addr, - .remote_addr = connection->remote_addr, - .admin_state = connection_state_to_face_state(connection->admin_state), - .state = connection_state_to_face_state(connection->state), -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - default: - return -1; - } - face->face.netdevice.name[0] = '\0'; - face->face.netdevice.index = 0; - rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_connection_to_face] Unexpected truncation of symbolic name string"); - rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", connection->interface_name); - if (rc >= INTERFACE_LEN) - WARN("[hc_connection_to_face] Unexpected truncation of interface name string"); - netdevice_update_index(&face->face.netdevice); - return 0; +int hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_data_t **pdata) { + return _hc_execute(s, action, object_type, object, NULL, NULL, pdata); } -/* CONNECTION -> LISTENER */ - -int -hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener) -{ - int rc; - *listener = (hc_listener_t) { - .id = ~0, - .type = connection->type, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - }; - rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", RANDBYTE()); // generate name - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_connection_to_local_listener] Unexpected truncation of symbolic name string"); - rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", connection->interface_name); - if (rc >= INTERFACE_LEN) - WARN("[hc_connection_to_local_listener] Unexpected truncation of interface name string"); - - return 0; -} - -int hc_punting_create(hc_sock_t *s, hc_punting_t *punting) -{ - return s->hc_punting_create(s, punting); +int hc_execute_async(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_result_callback_t callback, void *callback_data) { + return _hc_execute(s, action, object_type, object, callback, callback_data, + NULL); } -int hc_punting_get(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found) -{ - return s->hc_punting_get(s, punting, punting_found); -} +/*----------------------------------------------------------------------------* + * VFT + *----------------------------------------------------------------------------*/ -int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) -{ - return s->hc_punting_delete(s, punting); +int hc_object_create(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object) { + return hc_execute(s, ACTION_CREATE, object_type, object, NULL); } -int hc_punting_list(hc_sock_t *s, hc_data_t **pdata) -{ - return s->hc_punting_list(s, pdata); +int hc_object_get(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object, hc_object_t **found) { + return hc_execute(s, ACTION_GET, object_type, object, NULL); } -int hc_punting_validate(const hc_punting_t * punting) -{ - if (!IS_VALID_FAMILY(punting->family)) - return -1; - - /* - * We might use the zero value to add punting on all faces but this is not - * (yet) implemented - */ - if (punting->face_id == 0) { - ERROR("Punting on all faces is not (yet) implemented."); - return -1; +int hc_object_find(hc_sock_t *s, hc_object_type_t object_type, hc_data_t *data, + const hc_object_t *element, hc_object_t **found) { +// XXX NOT IMPLEMENTED +#if 0 + foreach_type(hc_object_t, x, data) { + if (hc_object_cmp(x, element) == 0) { + *found = x; + return 0; } - - return 0; -} - -int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2) -{ - int rc; - - rc = INT_CMP(p1->face_id, p2->face_id); - if (rc != 0) - return rc; - - rc = INT_CMP(p1->family, p2->family); - if (rc != 0) - return rc; - - rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family); - if (rc != 0) - return rc; - - rc = INT_CMP(p1->prefix_len, p2->prefix_len); - if (rc != 0) - return rc; - - return rc; -} - -int hc_punting_parse(void * in, hc_punting_t * punting) -{ - ERROR("hc_punting_parse not (yet) implemented."); - return -1; -} - -int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting) -{ - ERROR("hc_punting_snprintf not (yet) implemented."); - return -1; -} - -int hc_cache_set_store(hc_sock_t *s, int enabled) -{ - return s->hc_cache_set_store(s, enabled); -} - -int hc_cache_set_serve(hc_sock_t *s, int enabled) -{ - return s->hc_cache_set_serve(s, enabled); -} - -int hc_strategy_list(hc_sock_t *s, hc_data_t **data) -{ - return s->hc_strategy_list(s, data); -} - -int hc_strategy_set(hc_sock_t *s /* XXX */) -{ - return s->hc_strategy_set(s); -} - -/* /!\ Please update constants in header file upon changes */ -int -hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy) -{ - return snprintf(s, size, "%s", strategy->name); -} - -int hc_wldr_set(hc_sock_t *s /* XXX */) -{ - return s->hc_wldr_set(s); -} - -int hc_mapme_set(hc_sock_t *s, int enabled) -{ - return s->hc_mapme_set(s, enabled); -} - -int hc_mapme_set_discovery(hc_sock_t *s, int enabled) -{ - return s->hc_mapme_set_discovery(s, enabled); -} - -int hc_mapme_set_timescale(hc_sock_t *s, double timescale) -{ - return s->hc_mapme_set_timescale(s, timescale); -} - -int hc_mapme_set_retx(hc_sock_t *s, double timescale) -{ - return s->hc_mapme_set_retx(s, timescale); + }; +#endif + *found = NULL; /* this is optional */ + return 0; } -#ifdef WITH_POLICY - -/* POLICY PARSE */ - -int -hc_policy_parse(void * in, hc_policy_t * policy) -{ - list_policies_command * cmd = (list_policies_command *) in; - - if (!IS_VALID_ADDR_TYPE(cmd->addressType)) - return -1; - - int family = map_from_addr_type[cmd->addressType]; - if (!IS_VALID_FAMILY(family)) - return -1; - - *policy = (hc_policy_t) { - .family = family, - .remote_addr = UNION_CAST(cmd->address, ip_address_t), - .len = cmd->len, - .policy = cmd->policy, - }; - return 0; +int hc_object_delete(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object) { + return hc_execute(s, ACTION_DELETE, object_type, object, NULL); } -/* POLICY SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int -hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy) -{ - return 0; +int hc_object_list(hc_sock_t *s, hc_object_type_t object_type, + hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, object_type, NULL, pdata); } - -#endif /* WITH_POLICY */
\ No newline at end of file diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h index 3922e1f3c..2f483ad2d 100644 --- a/ctrl/libhicnctrl/src/api_private.h +++ b/ctrl/libhicnctrl/src/api_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -17,192 +17,62 @@ #define HICN_API_PRIVATE_H #include <hicn/ctrl/api.h> -#include <hicn/ctrl/commands.h> #include <hicn/util/token.h> #include <hicn/util/log.h> #include <hicn/util/map.h> +#ifndef HICN_VPP_PLUGIN +#include <hicn/util/sstrncpy.h> +#endif +#include <hicn/validation.h> +#include <ctype.h> -#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0) #define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) -#if 0 -#ifdef __APPLE__ -#define RANDBYTE() (u8)(arc4random() & 0xFF) -#else -#define RANDBYTE() (u8)(random() & 0xFF) -#endif -#endif -#define RANDBYTE() (u8)(rand() & 0xFF) - -hc_connection_type_t -connection_type_from_str(const char * str); - -extern const hc_connection_type_t map_from_list_connections_type[]; -extern const hc_connection_type_t map_from_encap_type[]; -extern const connection_type map_to_connection_type[]; -extern const listener_mode map_to_listener_mode[]; -extern const hc_connection_state_t map_from_list_connections_state[]; -extern const int map_from_addr_type[]; -extern const address_type map_to_addr_type[]; -extern const char * connection_state_str[]; -extern const char * connection_type_str[]; - -typedef enum { - ENCAP_TCP, - ENCAP_UDP, - ENCAP_ETHER, - ENCAP_LOCAL, - ENCAP_HICN -} EncapType; - -#define connection_state_to_face_state(x) ((face_state_t)(x)) -#define face_state_to_connection_state(x) ((hc_connection_state_t)(x)) +/* + * Input validation + */ + +static inline bool IS_VALID_ADDRESS(const hicn_ip_address_t *addr, int family) { + char addr_str[INET6_ADDRSTRLEN]; + return !hicn_ip_address_empty(addr) && + hicn_ip_address_ntop(addr, addr_str, INET6_ADDRSTRLEN, family) >= 0; +} + +static inline bool IS_VALID_PREFIX_LEN(u8 len) { + return len <= MAX_IPV6_PREFIX_LEN; +} +// https://github.com/shemminger/iproute2/blob/50b668bdbf0ebc270495eb4b352d0c3982159d0a/lib/utils.c#L825 +static inline bool IS_VALID_INTERFACE_NAME(const char *name) { + size_t len = strnlen_s(name, INTERFACE_LEN); + if (len == 0 || len >= IFNAMSIZ) return true; + + while (*name) { + if (*name == '/' || isspace(*name)) return false; + ++name; + } + + return true; +} + +static inline bool IS_VALID_NAME(const char *name) { + return is_symbolic_name(name, SYMBOLIC_NAME_LEN); +} + +static inline bool IS_VALID_STR_ID(const char *name) { + return is_number(name, SYMBOLIC_NAME_LEN); +} + +#define IS_VALID_TYPE(x) IS_VALID_ENUM_TYPE(FACE_TYPE, x) #define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX)) +#define IS_VALID_FACE_ID(x) ((x) != INVALID_FACE_ID) -#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x) +#define IS_VALID_ID(x) (1) +#define IS_VALID_POLICY(x) (1) typedef struct hc_sock_impl_s hc_sock_impl_t; -int hc_data_ensure_available(hc_data_t * data, size_t count); -u8 *hc_data_get_next(hc_data_t * data); -int hc_data_set_error(hc_data_t * data); - -int -hc_connection_parse_to_face(void * in, hc_face_t * face); - -int -hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face); - -int -hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face); - -int -hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener); - -int -hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener); - -int -hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name); - -struct hc_sock_s { - int (*hc_sock_get_next_seq)(hc_sock_t *s); - int (*hc_sock_set_nonblocking)(hc_sock_t *s); - int (*hc_sock_get_fd)(hc_sock_t *s); - int (*hc_sock_connect)(hc_sock_t *s); - int (*hc_sock_get_available)(hc_sock_t *s, u8 **buffer, size_t *size); - int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq); - int (*hc_sock_recv)(hc_sock_t *s); - int (*hc_sock_process)(hc_sock_t *s, hc_data_t **data); - int (*hc_sock_callback)(hc_sock_t *s, hc_data_t **data); - int (*hc_sock_reset)(hc_sock_t *s); - void (*hc_sock_free)(hc_sock_t *s); - - int (*hc_listener_create)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_create_async)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_get)(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found); - int (*hc_listener_delete)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_delete_async)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_listener_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_listener_validate)(const hc_listener_t *listener); - int (*hc_listener_cmp)(const hc_listener_t *l1, const hc_listener_t *l2); - int (*hc_listener_parse)(void *in, hc_listener_t *listener); - - int (*hc_connection_create)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_create_async)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_get)(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found); - int (*hc_connection_update_by_id)(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection); - int (*hc_connection_update)(hc_sock_t *s, hc_connection_t *connection_current, - hc_connection_t *connection_updated); - int (*hc_connection_delete)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_delete_async)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_connection_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_connection_validate)(const hc_connection_t *connection); - int (*hc_connection_cmp)(const hc_connection_t *c1, const hc_connection_t *c2); - int (*hc_connection_parse)(void *in, hc_connection_t *connection); - int (*hc_connection_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); - int (*hc_connection_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); - -#ifdef WITH_POLICY - int (*hc_connection_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); - int (*hc_connection_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); - int (*hc_connection_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); - int (*hc_connection_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); -#endif // WITH_POLICY - - int (*hc_connection_snprintf)(char *s, size_t size, - const hc_connection_t *connection); - - int (*hc_face_create)(hc_sock_t *s, hc_face_t *face); - int (*hc_face_get)(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found); - int (*hc_face_delete)(hc_sock_t *s, hc_face_t *face); - int (*hc_face_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_face_list_async)(hc_sock_t *s); - int (*hc_face_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); - int (*hc_face_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); - -#ifdef WITH_POLICY - int (*hc_face_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); - int (*hc_face_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); - int (*hc_face_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); - int (*hc_face_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags); -#endif // WITH_POLICY - - int (*hc_face_snprintf)(char *s, size_t size, hc_face_t *face); - - int (*hc_route_parse)(void *in, hc_route_t *route); - int (*hc_route_create)(hc_sock_t * s, hc_route_t * route); - int (*hc_route_create_async)(hc_sock_t * s, hc_route_t * route); - int (*hc_route_delete)(hc_sock_t * s, hc_route_t * route); - int (*hc_route_delete_async)(hc_sock_t * s, hc_route_t * route); - int (*hc_route_list)(hc_sock_t * s, hc_data_t ** pdata); - int (*hc_route_list_async)(hc_sock_t * s); - - int (*hc_punting_create)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_create_async)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_get)(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found); - int (*hc_punting_delete)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_punting_validate)(const hc_punting_t *punting); - int (*hc_punting_cmp)(const hc_punting_t *c1, const hc_punting_t *c2); - int (*hc_punting_parse)(void *in, hc_punting_t *punting); - - int (*hc_cache_set_store)(hc_sock_t *s, int enabled); - int (*hc_cache_set_serve)(hc_sock_t *s, int enabled); - int (*hc_cache_set_store_async)(hc_sock_t *s, int enabled); - int (*hc_cache_set_serve_async)(hc_sock_t *s, int enabled); - - int (*hc_strategy_list)(hc_sock_t *s, hc_data_t **data); - int (*hc_strategy_snprintf)(char *s, size_t size, hc_strategy_t *strategy); - int (*hc_strategy_set)(hc_sock_t *s /* XXX */); - - int (*hc_wldr_set)(hc_sock_t *s /* XXX */); - - int (*hc_mapme_set)(hc_sock_t *s, int enabled); - int (*hc_mapme_set_discovery)(hc_sock_t *s, int enabled); - int (*hc_mapme_set_timescale)(hc_sock_t *s, double timescale); - int (*hc_mapme_set_retx)(hc_sock_t *s, double timescale); - -#ifdef WITH_POLICY - int (*hc_policy_parse)(void *in, hc_policy_t *policy); - int (*hc_policy_create)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_create_async)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_delete)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_delete_async)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_policy_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_policy_snprintf)(char *s, size_t size, hc_policy_t *policy); -#endif // WITH_POLICY - - // Reference to module containing the implementation - void *handle; -}; - -#endif // HICN_API_PRIVATE_H
\ No newline at end of file +int hc_data_ensure_available(hc_data_t *data, size_t count); +u8 *hc_data_get_next(hc_data_t *data); + +#endif // HICN_API_PRIVATE_H diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c deleted file mode 100644 index 064eb77e3..000000000 --- a/ctrl/libhicnctrl/src/cli.c +++ /dev/null @@ -1,883 +0,0 @@ -/* - * 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 cli.c - * \brief Command line interface - */ -#include <ctype.h> // isalpha isalnum -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> // getopt - -#include <hicn/ctrl.h> -#include <hicn/util/ip_address.h> -#include <hicn/util/token.h> - - -#define die(LABEL, MESSAGE) do { \ - printf(MESSAGE "\n"); \ - rc = -1; \ - goto ERR_ ## LABEL; \ -} while(0) - -#define foreach_object \ - _(UNDEFINED) \ - _(FACE) \ - _(ROUTE) \ - _(STRATEGY) \ - _(LISTENER) \ - _(CONNECTION) \ - _(N) - -typedef enum { -#define _(x) OBJECT_ ## x, -foreach_object -#undef _ -} hc_object_t; - -#define HICNLIGHT_PARAM "hicnlight" -#define VPP_PARAM "vpp" - -void -usage_header() -{ - fprintf(stderr, "Usage:\n"); -} - -void -usage_face_create(const char * prog, bool header, bool verbose) -{ - - if (header) - usage_header(); - fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Create a face on specified address and port.\n"); -} - -void -usage_face_delete(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -df ID\n", prog); - //fprintf(stderr, "%s -df NAME\n", prog); - fprintf(stderr, "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Delete a face...\n"); -} - -void -usage_face_list(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -F\n", prog); - if (verbose) - fprintf(stderr, " List all faces.\n"); -} - -void -usage_face(const char * prog, bool header, bool verbose) -{ - usage_face_create(prog, header, verbose); - usage_face_delete(prog, header, verbose); - usage_face_list(prog, header, verbose); -} - -void -usage_route_create(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog); - //fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog); - if (verbose) - fprintf(stderr, " Create a route...\n"); -} - -void -usage_route_delete(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog); - //fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog); - if (verbose) - fprintf(stderr, " Delete a route...\n"); -} - -void -usage_route_list(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -R\n", prog); - if (verbose) - fprintf(stderr, " List all routes.\n"); -} - -void -usage_route(const char * prog, bool header, bool verbose) -{ - usage_route_create(prog, header, verbose); - usage_route_delete(prog, header, verbose); - usage_route_list(prog, header, verbose); -} - -void -usage_forwarding_strategy_create(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); -} -void -usage_forwarding_strategy_delete(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); -} - -void -usage_forwarding_strategy_list(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -S\n", prog); - if (verbose) - fprintf(stderr, " List all availble forwarding strategies.\n"); -} - -void -usage_forwarding_strategy(const char * prog, bool header, bool verbose) -{ - usage_forwarding_strategy_create(prog, header, verbose); - usage_forwarding_strategy_delete(prog, header, verbose); - usage_forwarding_strategy_list(prog, header, verbose); -} - -void -usage_listener_create(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Create a listener on specified address and port.\n"); -} - -void -usage_listener_delete(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -dl ID\n", prog); - fprintf(stderr, "%s -dl NAME\n", prog); - fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Delete a listener...\n"); -} - -void -usage_listener_list(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -L\n", prog); - if (verbose) - fprintf(stderr, " List all listeners.\n"); -} - -void -usage_listener(const char * prog, bool header, bool verbose) -{ - usage_listener_create(prog, header, verbose); - usage_listener_delete(prog, header, verbose); - usage_listener_list(prog, header, verbose); -} -void -usage_connection_create(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Create a connection on specified address and port.\n"); -} - -void -usage_connection_delete(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -dc ID\n", prog); - fprintf(stderr, "%s -dc NAME\n", prog); - fprintf(stderr, "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog); - if (verbose) - fprintf(stderr, " Delete a connection...\n"); -} - -void -usage_connection_list(const char * prog, bool header, bool verbose) -{ - if (header) - usage_header(); - fprintf(stderr, "%s -C\n", prog); - if (verbose) - fprintf(stderr, " List all connections.\n"); -} - -void -usage_connection(const char * prog, bool header, bool verbose) -{ - usage_connection_create(prog, header, verbose); - usage_connection_delete(prog, header, verbose); - usage_connection_list(prog, header, verbose); -} - -void usage(const char * prog) -{ - fprintf(stderr, "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog); - fprintf(stderr, "\n"); - fprintf(stderr, "High-level commands\n"); - fprintf(stderr, "\n"); - usage_face(prog, false, true); - usage_route(prog, false, true); - usage_forwarding_strategy(prog, false, true); - fprintf(stderr, "\n"); - fprintf(stderr, "Low level commands (hicn-light specific)\n"); - fprintf(stderr, "\n"); - usage_listener(prog, false, true); - usage_connection(prog, false, true); -} - -typedef struct { - hc_action_t action; - hc_object_t object; - union { - hc_face_t face; - hc_route_t route; - hc_connection_t connection; - hc_listener_t listener; - }; -} hc_command_t; - -/** - * Return true if string is purely an integer - */ -static inline -bool -is_number(const char *string) { - size_t len = strlen(string); - for (size_t i = 0; i < len; i++) - if (!isdigit(string[i])) - return false; - return true; -} - -/** - * A symbolic name must be at least 1 character and must begin with an alpha. - * The remainder must be an alphanum. - */ -static inline -bool -is_symbolic_name(const char *name) -{ - size_t len = strlen(name); - if (len <= 0) - return false; - if (!isalpha(name[0])) - return false; - for (size_t i = 1; i < len; i++) { - if (!isalnum(name[i])) - return false; - } - return true; -} - -face_type_t -face_type_from_str(const char * str) -{ -#define _(x) \ - if (strcasecmp(str, STRINGIZE(x)) == 0) \ - return FACE_TYPE_ ## x; \ - else -foreach_face_type -#undef _ - return FACE_TYPE_UNDEFINED; -} - - -int -parse_options(int argc, char *argv[], hc_command_t * command, forwarder_t *forwarder) -{ - command->object = OBJECT_UNDEFINED; - command->action = ACTION_CREATE; - int opt; - int family; - - while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) { - switch (opt) { - case 'z' : - if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) { - *forwarder = VPP; - } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) { - *forwarder = HICNLIGHT; - } else { - usage(argv[0]); - exit(EXIT_FAILURE); - } - break; - case 'd': - command->action = ACTION_DELETE; - break; - case 'f': - command->object = OBJECT_FACE; - break; - case 'l': - command->object = OBJECT_LISTENER; - break; - case 'c': - command->object = OBJECT_CONNECTION; - break; - case 'r': - command->object = OBJECT_ROUTE; - break; - case 'F': - command->action = ACTION_LIST; - command->object = OBJECT_FACE; - break; - case 'L': - command->action = ACTION_LIST; - command->object = OBJECT_LISTENER; - break; - case 'C': - command->action = ACTION_LIST; - command->object = OBJECT_CONNECTION; - break; - case 'R': - command->action = ACTION_LIST; - command->object = OBJECT_ROUTE; - break; - case 'S': - command->action = ACTION_LIST; - command->object = OBJECT_STRATEGY; - break; - default: /* "h" */ - usage(argv[0]); - exit(EXIT_SUCCESS); - } - } - - if (command->object == OBJECT_UNDEFINED) { - fprintf(stderr, "Missing object specification: connection | listener | route\n"); - return -1; - } - - /* Parse and validate parameters for add/delete */ - switch(command->object) { - case OBJECT_FACE: - switch(command->action) { - case ACTION_CREATE: - if ((argc - optind != 5) && (argc - optind != 6)) { - usage_face_create(argv[0], true, false); - goto ERR_PARAM; - } - /* NAME will be autogenerated (and currently not used) */ - //snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - command->face.face.type = face_type_from_str(argv[optind++]); - if (command->face.face.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->face.face.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->face.face.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0) - goto ERR_PARAM; - command->face.face.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || (command->face.face.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0) - goto ERR_PARAM; - command->face.face.remote_port = atoi(argv[optind++]); - if (argc != optind) { - //netdevice_set_name(&command->face.face.netdevice, argv[optind++]); - command->face.face.netdevice.index = atoi(argv[optind++]); - } - - break; - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) { - usage_face_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind])) { - command->face.id = atoi(argv[optind++]); - snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - //} else if (is_symbolic_name(argv[optind])) { - // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->face.face.type = face_type_from_str(argv[optind++]); - if (command->face.face.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->face.face.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->face.face.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0) - goto ERR_PARAM; - command->face.face.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || (command->face.face.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0) - goto ERR_PARAM; - command->face.face.remote_port = atoi(argv[optind++]); - if (argc != optind) { - command->face.face.netdevice.index = atoi(argv[optind++]); - //netdevice_set_name(&command->face.face.netdevice, argv[optind++]); - } - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_face_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - break; - } - break; - - case OBJECT_ROUTE: - switch(command->action) { - case ACTION_CREATE: - if ((argc - optind != 2) && (argc - optind != 3)) { - usage_route_create(argv[0], true, false); - goto ERR_PARAM; - } - - command->route.face_id = atoi(argv[optind++]); - - { - ip_prefix_t prefix; - ip_prefix_pton(argv[optind++], &prefix); - command->route.family = prefix.family; - command->route.remote_addr = prefix.address; - command->route.len = prefix.len; - } - - if (argc != optind) { - printf("parse cost\n"); - command->route.cost = atoi(argv[optind++]); - } - break; - - case ACTION_DELETE: - if (argc - optind != 2) { - usage_route_delete(argv[0], true, false); - goto ERR_PARAM; - } - - command->route.face_id = atoi(argv[optind++]); - - { - ip_prefix_t prefix; - ip_prefix_pton(argv[optind++], &prefix); - command->route.family = prefix.family; - command->route.remote_addr = prefix.address; - command->route.len = prefix.len; - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_route_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - break; - } - break; - - case OBJECT_STRATEGY: - switch(command->action) { - case ACTION_LIST: - if (argc - optind != 0) { - usage_forwarding_strategy_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - default: - goto ERR_COMMAND; - break; - } - break; - - case OBJECT_LISTENER: - switch(command->action) { - case ACTION_CREATE: - if ((argc - optind != 4) && (argc - optind != 5)) { - usage_listener_create(argv[0], true, false); - goto ERR_PARAM; - } - snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - command->listener.type = connection_type_from_str(argv[optind++]); - if (command->listener.type == CONNECTION_TYPE_UNDEFINED) - goto ERR_PARAM; - command->listener.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->listener.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0) - goto ERR_PARAM; - command->listener.local_port = atoi(argv[optind++]); - if (argc != optind) { - snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]); - } - break; - - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) { - usage_listener_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind])) { - command->listener.id = atoi(argv[optind++]); - snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - } else if (is_symbolic_name(argv[optind])) { - snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->listener.type = connection_type_from_str(argv[optind++]); - if (command->listener.type == CONNECTION_TYPE_UNDEFINED) - goto ERR_PARAM; - command->listener.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->listener.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0) - goto ERR_PARAM; - command->listener.local_port = atoi(argv[optind++]); - if (argc != optind) { - snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]); - } - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_listener_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - break; - } - break; - - case OBJECT_CONNECTION: - switch(command->action) { - case ACTION_CREATE: - /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */ - if ((argc - optind != 6) && (argc - optind != 7)) { - usage_connection_create(argv[0], true, false); - goto ERR_PARAM; - } - snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - command->connection.type = connection_type_from_str(argv[optind++]); - if (command->connection.type == CONNECTION_TYPE_UNDEFINED) - goto ERR_PARAM; - command->connection.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->connection.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0) - goto ERR_PARAM; - command->connection.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || (command->connection.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0) - goto ERR_PARAM; - command->connection.remote_port = atoi(argv[optind++]); - - break; - - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) { - usage_connection_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind])) { - command->connection.id = atoi(argv[optind++]); - snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - } else if (is_symbolic_name(argv[optind])) { - snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->connection.type = connection_type_from_str(argv[optind++]); - if (command->connection.type == CONNECTION_TYPE_UNDEFINED) - goto ERR_PARAM; - command->connection.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->connection.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0) - goto ERR_PARAM; - command->connection.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || (command->connection.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0) - goto ERR_PARAM; - command->connection.remote_port = atoi(argv[optind++]); - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_connection_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - break; - } - break; - - default: - goto ERR_COMMAND; - break; - } - - return 0; - -ERR_PARAM: -ERR_COMMAND: - return -1; -} - -int main(int argc, char *argv[]) -{ - hc_data_t * data; - int rc = 1; - hc_command_t command = {0}; - char buf_listener[MAXSZ_HC_LISTENER]; - char buf_connection[MAXSZ_HC_CONNECTION]; - char buf_route[MAXSZ_HC_ROUTE]; - char buf_strategy[MAXSZ_HC_STRATEGY]; - - forwarder_t forwarder = HICNLIGHT; - - if (parse_options(argc, argv, &command, &forwarder) < 0) - die(OPTIONS, "Bad arguments"); - - hc_sock_t * s = hc_sock_create_forwarder(forwarder); - if (!s) - die(SOCKET, "Error creating socket."); - - if (hc_sock_connect(s) < 0) - die(CONNECT, "Error connecting to the forwarder."); - - switch(command.object) { - case OBJECT_FACE: - switch(command.action) { - case ACTION_CREATE: - if (hc_face_create(s, &command.face) < 0) - die(COMMAND, "Error creating face"); - printf("OK\n"); - break; - - case ACTION_DELETE: - if (hc_face_delete(s, &command.face) < 0) - die(COMMAND, "Error creating face"); - printf("OK\n"); - break; - - case ACTION_LIST: - if (hc_face_list(s, &data) < 0) - die(COMMAND, "Error getting connections."); - - printf("Faces:\n"); - foreach_face(f, data) { - if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE) - die(COMMAND, "Display error"); - printf("[%s] %s\n", f->name, buf_connection); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for connection"); - break; - } - break; - - case OBJECT_ROUTE: - switch(command.action) { - case ACTION_CREATE: - if (hc_route_create(s, &command.route) < 0) - die(COMMAND, "Error creating route"); - printf("OK\n"); - break; - - case ACTION_DELETE: - if (hc_route_delete(s, &command.route) < 0) - die(COMMAND, "Error creating route"); - printf("OK\n"); - break; - - case ACTION_LIST: - if (hc_route_list(s, &data) < 0) - die(COMMAND, "Error getting routes."); - - printf("Routes:\n"); - foreach_route(r, data) { - if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= MAXSZ_HC_ROUTE) - die(COMMAND, "Display error"); - printf("%s\n", buf_route); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for route"); - break; - } - break; - - case OBJECT_STRATEGY: - switch(command.action) { - case ACTION_LIST: - if (hc_strategy_list(s, &data) < 0) - die(COMMAND, "Error getting routes."); - - printf("Forwarding strategies:\n"); - foreach_strategy(st, data) { - if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= MAXSZ_HC_STRATEGY) - die(COMMAND, "Display error"); - printf("%s\n", buf_strategy); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for strategy"); - break; - } - break; - - case OBJECT_LISTENER: - switch(command.action) { - case ACTION_CREATE: - if (hc_listener_create(s, &command.listener) < 0) - die(COMMAND, "Error creating listener"); - printf("OK\n"); - break; - case ACTION_DELETE: - if (hc_listener_delete(s, &command.listener) < 0) - die(COMMAND, "Error deleting listener"); - printf("OK\n"); - break; - break; - case ACTION_LIST: - if (hc_listener_list(s, &data) < 0) - die(COMMAND, "Error getting listeners."); - - printf("Listeners:\n"); - foreach_listener(l, data) { - if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER) - die(COMMAND, "Display error"); - printf("[%d] %s\n", l->id, buf_listener); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for listener"); - break; - } - break; - - case OBJECT_CONNECTION: - switch(command.action) { - case ACTION_CREATE: - if (hc_connection_create(s, &command.connection) < 0) - die(COMMAND, "Error creating connection"); - printf("OK\n"); - break; - case ACTION_DELETE: - if (hc_connection_delete(s, &command.connection) < 0) - die(COMMAND, "Error creating connection"); - printf("OK\n"); - break; - case ACTION_LIST: - if (hc_connection_list(s, &data) < 0) - die(COMMAND, "Error getting connections."); - - printf("Connections:\n"); - foreach_connection(c, data) { - if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION) - die(COMMAND, "Display error"); - printf("[%s] %s\n", c->name, buf_connection); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for connection"); - break; - } - break; - - default: - die(COMMAND, "Unsupported object"); - break; - } - -ERR_COMMAND: -ERR_CONNECT: - hc_sock_free(s); -ERR_SOCKET: -ERR_OPTIONS: - return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/ctrl/libhicnctrl/src/cli.h b/ctrl/libhicnctrl/src/cli.h new file mode 100644 index 000000000..b04448a6e --- /dev/null +++ b/ctrl/libhicnctrl/src/cli.h @@ -0,0 +1,4 @@ +#include <hicn/ctrl.h> + +typedef int (*command_function)(hc_sock_t *, hc_command_t *); +extern command_function command_vft[][ACTION_N]; diff --git a/ctrl/libhicnctrl/src/command.c b/ctrl/libhicnctrl/src/command.c new file mode 100644 index 000000000..77b6eb7e8 --- /dev/null +++ b/ctrl/libhicnctrl/src/command.c @@ -0,0 +1,127 @@ + +/** + * @file command.c + * @brief Implementation of commands. + */ + +#ifdef __linux__ +#define _GNU_SOURCE +#endif /* __linux__ */ +#include <search.h> /* tfind, tdestroy, twalk */ +#include <stdio.h> +#include <ctype.h> +#include <hicn/ctrl/command.h> + +#include <hicn/util/log.h> + +#include <hicn/ctrl/parse.h> + +/* Commands are registered in the following tree. */ +static void *commands_root = NULL; /**< Tree ordered by name */ + +#ifdef __linux__ +static void nothing_to_free() {} + +__attribute__((destructor)) static void command_clear() { + tdestroy(commands_root, nothing_to_free); +} +#endif /* __linux__ */ + +static int _command_compare(const command_parser_t *c1, + const command_parser_t *c2) { + if (c1->object_type != c2->object_type) + return c2->object_type - c1->object_type; + if (c1->action != c2->action) return c2->action - c1->action; + if (c1->nparams != c2->nparams) return c2->nparams - c1->nparams; + return 0; +} + +#define command_compare (int (*)(const void *, const void *))(_command_compare) + +void command_register(const command_parser_t *command) { + // Insert the command in the tree if the keys does not exist yet + tsearch(command, &commands_root, command_compare); +} + +const command_parser_t *command_search(const hc_action_t action, + hc_object_type_t object_type, + unsigned nparams) { + command_parser_t **command, search; + + search.action = action; + search.object_type = object_type; + search.nparams = nparams; + command = tfind(&search, &commands_root, command_compare); + + return command ? *command : NULL; +} + +static inline void to_lowercase(char *p) { + for (; *p; ++p) *p = tolower(*p); +} + +typedef struct { + hc_object_type_t object_type; + hc_action_t action; +} cmd_search_params_t; + +static hc_object_type_t prev_obj = OBJECT_TYPE_UNDEFINED; +static hc_action_t prev_action = ACTION_UNDEFINED; +static void traversal_action(const void *nodep, VISIT which, + void *cmd_params0) { + cmd_search_params_t *cmd_params = cmd_params0; + + // Execute this function during inorder traversal + if (which != postorder && which != leaf) return; + + command_parser_t *datap; + datap = *(command_parser_t **)nodep; + char *obj_str = strdup(object_type_str(datap->object_type)); + to_lowercase(obj_str); + + // List all objects + if (cmd_params->object_type == OBJECT_TYPE_UNDEFINED && + cmd_params->action == ACTION_UNDEFINED) { + if (datap->object_type == prev_obj) goto FREE_STR; + prev_obj = datap->object_type; + + printf("\thelp %s\n", obj_str); + goto FREE_STR; + } + + // List actions for specific object + if (datap->object_type != cmd_params->object_type) goto FREE_STR; + if (cmd_params->action == ACTION_UNDEFINED) { + if (datap->action == prev_action) goto FREE_STR; + prev_action = datap->action; + + printf("\thelp %s %s\n", obj_str, action_to_cmd_action(datap->action)); + goto FREE_STR; + } + + // List commands for specific object and action + if (datap->action != cmd_params->action) goto FREE_STR; + printf(" %s %s ", action_to_cmd_action(datap->action), obj_str); + for (int i = 0; i < datap->nparams; i++) + printf("<%s> ", datap->parameters[i].name); + printf("\n\n"); + // List options' details + if (datap->nparams == 0) goto FREE_STR; + for (int i = 0; i < datap->nparams; i++) + printf("%16s: %s\n", datap->parameters[i].name, datap->parameters[i].help); + printf("\n"); + +FREE_STR: + free(obj_str); +} + +void command_list(hc_object_type_t object_type, hc_action_t action) { +#if defined(__linux__) && !defined(__ANDROID__) + cmd_search_params_t cmd_params = {.object_type = object_type, + .action = action}; + twalk_r(commands_root, traversal_action, &cmd_params); +#else + fprintf(stderr, "twalk_r() function only available on linux"); + (void)traversal_action; +#endif +} diff --git a/ctrl/libhicnctrl/src/commands/command_cache.c b/ctrl/libhicnctrl/src/commands/command_cache.c new file mode 100644 index 000000000..22cb8baaa --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_cache.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_cache.h + * \brief Implementation of cache command. + */ + +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define serve \ + { \ + .name = "serve", \ + .help = \ + "Enables/disables replies from local content store. Either the " \ + "string 'on' or 'off'", \ + .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, serve), \ + } + +#define store \ + { \ + .name = "store", \ + .help = \ + "enables/disables the storage of incoming data packets in the local " \ + "content store. Either the string 'on' or 'off'", \ + .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, store), \ + } + +/* Commands */ + +static const command_parser_t command_cache_set_serve = { + .action = ACTION_SERVE, + .object_type = OBJECT_TYPE_CACHE, + .nparams = 1, + .parameters = {serve}, +}; +COMMAND_REGISTER(command_cache_set_serve); + +static const command_parser_t command_cache_set_store = { + .action = ACTION_STORE, + .object_type = OBJECT_TYPE_CACHE, + .nparams = 1, + .parameters = {store}, +}; +COMMAND_REGISTER(command_cache_set_store); + +static const command_parser_t command_cache_clear = { + .action = ACTION_CLEAR, + .object_type = OBJECT_TYPE_CACHE, + .nparams = 0, +}; +COMMAND_REGISTER(command_cache_clear); + +static const command_parser_t command_cache_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_CACHE, + .nparams = 0, +}; +COMMAND_REGISTER(command_cache_list); diff --git a/ctrl/libhicnctrl/src/commands/command_connection.c b/ctrl/libhicnctrl/src/commands/command_connection.c new file mode 100644 index 000000000..a43934fdf --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_connection.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_connection.h + * \brief Implementation of connection command. + */ +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define type_hicn \ + { \ + .name = "type", .help = "connection type (hICN)", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \ + } + +#define type_tcp_udp \ + { \ + .name = "type", .help = "connection type [tcp | udp]", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \ + } + +#define symbolic \ + { \ + .name = "symbolic", \ + .help = "symbolic name, e.g. 'conn1' (must be unique, start with alpha)", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \ + } + +#define local_address \ + { \ + .name = "local_addr", .help = "local IP address on which to bind.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, local_addr), \ + .offset2 = offsetof(hc_connection_t, family), \ + } + +#define local_port \ + { \ + .name = "local_port", .help = "Local port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_connection_t, local_port), \ + } + +#define remote_address \ + { \ + .name = "remote_address", \ + .help = "The IPv4 or IPv6 or hostname of the remote system.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, remote_addr), \ + .offset2 = offsetof(hc_connection_t, family), \ + } + +#define remote_port \ + { \ + .name = "remote_port", .help = "Remote port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_connection_t, remote_port), \ + } + +#define interface \ + { \ + .name = "interface", .help = "Interface on which to bind", \ + .type = TYPE_INTERFACE_NAME, \ + .offset = offsetof(hc_connection_t, interface_name), \ + } + +#define symbolic_or_id \ + { \ + .name = "symbolic", .help = "The connection symbolic name or id", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \ + } + +/* Commands */ + +int on_connection_create(hc_connection_t* connection) { + connection->admin_state = FACE_STATE_UP; + return 0; +} + +#if 0 +static command_parser_t command_connection_create4 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 4, + .parameters = {type_hicn, symbolic, local_address, remote_address}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create4); + +static const command_parser_t command_connection_create5 = { + .action = ACTION_CREATE, + .object = OBJECT_TYPE_CONNECTION, + .nparams = 5, + .parameters = {type_hicn, symbolic, local_address, remote_address, + interface}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create5); +#endif + +static const command_parser_t command_connection_create4 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 4, + .parameters = {type_tcp_udp, symbolic, remote_address, remote_port}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create4); + +static const command_parser_t command_connection_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 5, + .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, + interface}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create5); + +static const command_parser_t command_connection_create6 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 6, + .parameters = {type_tcp_udp, symbolic, local_address, local_port, + remote_address, remote_port}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create6); + +static const command_parser_t command_connection_create7 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 7, + .parameters = {type_tcp_udp, symbolic, local_address, local_port, + remote_address, remote_port, interface}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create7); + +static const command_parser_t command_connection_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 0, +}; +COMMAND_REGISTER(command_connection_list); + +static const command_parser_t command_connection_remove = { + .action = ACTION_DELETE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 1, + .parameters = {symbolic_or_id}, +}; +COMMAND_REGISTER(command_connection_remove); diff --git a/ctrl/libhicnctrl/src/commands/command_face.c b/ctrl/libhicnctrl/src/commands/command_face.c new file mode 100644 index 000000000..e383de1b5 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_face.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_face.h + * \brief Implementation of face command. + */ +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define type_hicn \ + { \ + .name = "type", .help = "face type (hICN)", .type = TYPE_ENUM(face_type), \ + .offset = offsetof(hc_face_t, type), \ + } + +#define type_tcp_udp \ + { \ + .name = "type", .help = "face type [tcp | udp]", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_face_t, type), \ + } + +#define local_address \ + { \ + .name = "local_addr", .help = "local IP address on which to bind.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_face_t, local_addr), \ + .offset2 = offsetof(hc_face_t, family), \ + } + +#define local_port \ + { \ + .name = "local_port", .help = "Local port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_face_t, local_port), \ + } + +#define remote_address \ + { \ + .name = "remote_address", \ + .help = "The IPv4 or IPv6 or hostname of the remote system.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_face_t, remote_addr), \ + .offset2 = offsetof(hc_face_t, family), \ + } + +#define remote_port \ + { \ + .name = "remote_port", .help = "Remote port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_face_t, remote_port), \ + } + +#define interface \ + { \ + .name = "interface", .help = "Interface on which to bind", \ + .type = TYPE_INTERFACE_NAME, \ + .offset = offsetof(hc_face_t, netdevice.name), \ + } + +#define symbolic_or_id \ + { \ + .name = "symbolic", .help = "The face symbolic name or id", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_face_t, name), \ + } + +/* Commands */ + +int on_face_create(hc_face_t* face) { + face->admin_state = FACE_STATE_UP; + face->id = INVALID_FACE_ID; + return 0; +} + +#if 0 +static command_parser_t command_face_create3 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 3, + .parameters = {type_hicn, local_address, remote_address}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create3); + +static const command_parser_t command_face_create4 = { + .action = ACTION_CREATE, + .object = OBJECT_TYPE_FACE, + .nparams = 4, + .parameters = {type_hicn, local_address, remote_address, + interface}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create4); +#endif + +static const command_parser_t command_face_create3 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 3, + .parameters = {type_tcp_udp, remote_address, remote_port}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create3); + +static const command_parser_t command_face_create4 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 4, + .parameters = {type_tcp_udp, remote_address, remote_port, interface}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create4); + +static const command_parser_t command_face_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 5, + .parameters = {type_tcp_udp, local_address, local_port, remote_address, + remote_port}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create5); + +static const command_parser_t command_face_create6 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 6, + .parameters = {type_tcp_udp, local_address, local_port, remote_address, + remote_port, interface}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create6); + +static const command_parser_t command_face_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_FACE, + .nparams = 0, +}; +COMMAND_REGISTER(command_face_list); + +static const command_parser_t command_face_remove6 = { + .action = ACTION_DELETE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 6, + .parameters = {type_tcp_udp, local_address, local_port, remote_address, + remote_port, interface}, +}; +COMMAND_REGISTER(command_face_remove6); + +static const command_parser_t command_face_remove1 = { + .action = ACTION_DELETE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 1, + .parameters = {symbolic_or_id}, +}; +COMMAND_REGISTER(command_face_remove1); diff --git a/ctrl/libhicnctrl/src/commands/command_listener.c b/ctrl/libhicnctrl/src/commands/command_listener.c new file mode 100644 index 000000000..604c0a672 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_listener.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_listener.h + * \brief Implementation of listener command. + */ +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define protocol_hicn \ + { \ + .name = "protocol", .help = "Protocol [hicn].", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \ + } + +#define protocol_tcp_udp \ + { \ + .name = "protocol", .help = "Protocol [tcp | udp]", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \ + } + +#define symbolic \ + { \ + .name = "symbolic", \ + .help = \ + "User defined name for listener, must start with alpha and be " \ + "alphanum", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \ + } + +#define local_address \ + { \ + .name = "local_addr", \ + .help = \ + "IPv4 or IPv6 address (or prefix protocol = hicn) assigend to the " \ + "local interface", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_listener_t, local_addr), \ + .offset2 = offsetof(hc_listener_t, family), \ + } + +#define local_port \ + { \ + .name = "local_port", .help = "Local port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_listener_t, local_port), \ + } + +#define interface \ + { \ + .name = "interface", .help = "Interface on which to bind", \ + .type = TYPE_INTERFACE_NAME, \ + .offset = offsetof(hc_listener_t, interface_name), \ + } + +#define symbolic_or_id \ + { \ + .name = "symbolic", .help = "The listener symbolic name or id", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \ + } + +/* Commands */ + +/* The parse sets the wrong face_type_t for listener, we fix that here */ +int on_listener_create(hc_listener_t* listener) { + switch (listener->type) { + case FACE_TYPE_UDP: + listener->type = FACE_TYPE_UDP_LISTENER; + break; + case FACE_TYPE_TCP: + listener->type = FACE_TYPE_TCP_LISTENER; + break; + case FACE_TYPE_HICN: + listener->type = FACE_TYPE_HICN_LISTENER; + break; + case FACE_TYPE_UDP_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_HICN_LISTENER: + break; + case FACE_TYPE_UNDEFINED: + case FACE_TYPE_N: + return -1; + } + return 0; +} + +#if 0 +static const command_parser_t command_listener_create4 = { + .action = ACTION_CREATE, + .object = OBJECT_TYPE_LISTENER, + .nparams = 4, + .parameters = {protocol_hicn, symbolic, local_address, interface}, + .post_hook = (parser_hook_t)on_listener_create, +}; +COMMAND_REGISTER(command_listener_create4); +#endif + +static const command_parser_t command_listener_create4 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_LISTENER, + .nparams = 4, + .parameters = {protocol_tcp_udp, symbolic, local_address, local_port}, + .post_hook = (parser_hook_t)on_listener_create, +}; +COMMAND_REGISTER(command_listener_create4); + +static const command_parser_t command_listener_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_LISTENER, + .nparams = 5, + .parameters = {protocol_tcp_udp, symbolic, local_address, local_port, + interface}, + .post_hook = (parser_hook_t)on_listener_create, +}; +COMMAND_REGISTER(command_listener_create5); + +static const command_parser_t command_listener_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_LISTENER, + .nparams = 0, +}; +COMMAND_REGISTER(command_listener_list); + +static const command_parser_t command_listener_remove = { + .action = ACTION_DELETE, + .object_type = OBJECT_TYPE_LISTENER, + .nparams = 1, + .parameters = {symbolic_or_id}, +}; +COMMAND_REGISTER(command_listener_remove); diff --git a/ctrl/libhicnctrl/src/commands/command_mapme.c b/ctrl/libhicnctrl/src/commands/command_mapme.c new file mode 100644 index 000000000..7dcca038c --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_mapme.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_mapme.h + * \brief Implementation of mapme command. + */ +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define target \ + { \ + .name = "target", \ + .help = \ + "Target for the set action, e.g. enable, discovery, timescale, retx", \ + .type = TYPE_ENUM(mapme_target), .offset = offsetof(hc_mapme_t, target), \ + } + +#define value \ + { \ + .name = "value", \ + .help = "Value to set for the target, e.g. 'on', 'off', milliseconds", \ + .type = TYPE_STRN(4), .offset = offsetof(hc_mapme_t, unparsed_arg), \ + } + +#define prefix \ + { \ + .name = "prefix", \ + .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_mapme_t, address), \ + .offset2 = offsetof(hc_mapme_t, len), \ + .offset3 = offsetof(hc_mapme_t, family), \ + } + +/* Commands */ + +// Parse the raw string argument into 'timescale' or 'enabled', +// necessary since the command dispatch is based on the number +// of arguments and not their type +int parse_args(hc_mapme_t* mapme) { + mapme->timescale = atoi(mapme->unparsed_arg); + + if (strcasecmp(mapme->unparsed_arg, "off") == 0) mapme->enabled = 0; + if (strcasecmp(mapme->unparsed_arg, "on") == 0) mapme->enabled = 1; + + return 0; +} + +static const command_parser_t command_mapme_set = { + .action = ACTION_SET, + .object_type = OBJECT_TYPE_MAPME, + .nparams = 2, + .parameters = {target, value}, + .post_hook = (parser_hook_t)parse_args, +}; +COMMAND_REGISTER(command_mapme_set); + +static const command_parser_t command_mapme_update = { + .action = ACTION_UPDATE, + .object_type = OBJECT_TYPE_MAPME, + .nparams = 1, + .parameters = {prefix}, +}; +COMMAND_REGISTER(command_mapme_update); diff --git a/ctrl/libhicnctrl/src/commands/command_policy.c b/ctrl/libhicnctrl/src/commands/command_policy.c new file mode 100644 index 000000000..eaf949880 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_policy.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_policy.h + * \brief Implementation of policy command. + */ + +#if 0 +#include <hicn/policy.h> + +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define prefix \ + { \ + .name = "prefix", \ + .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_policy_t, remote_addr), \ + .offset2 = offsetof(hc_policy_t, len), \ + .offset3 = offsetof(hc_policy_t, family), \ + } + +#define app_name \ + { \ + .name = "app_name", \ + .help = "The application name associated to this policy", \ + .type = TYPE_STR, .offset = offsetof(hc_policy_t, policy.app_name), \ + } + +/* Commands */ + +static const command_parser_t command_policy_create = { + .action = ACTION_CREATE, + .object = OBJECT_POLICY, + .nparams = 2 + POLICY_TAG_N, + .parameters = {prefix, app_name, +#define _(x, y) \ + { \ + .name = "flag:" #x, \ + .help = \ + "A value among [neutral|require|prefer|avoid|prohibit] with an " \ + "optional '!' character prefix for disabling changes", \ + .type = TYPE_POLICY_STATE(POLICY_TAG_##x), \ + .offset = offsetof(hc_policy_t, policy.tags), \ + }, + foreach_policy_tag +#undef _ + }, +}; +COMMAND_REGISTER(command_policy_create); + +static const command_parser_t command_policy_list = { + .action = ACTION_LIST, + .object = OBJECT_POLICY, + .nparams = 0, +}; +COMMAND_REGISTER(command_policy_list); +#endif diff --git a/ctrl/libhicnctrl/src/commands/command_punting.c b/ctrl/libhicnctrl/src/commands/command_punting.c new file mode 100644 index 000000000..a274583b1 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_punting.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_punting.h + * \brief Implementation of punting command. + */ + +#if 0 +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define symbolic_or_id \ + { \ + .name = "symbolic_or_id", \ + .help = \ + "The symbolic name for an egress, or the egress punting id (see " \ + "'help list puntings')", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_punting_t, face_id), \ + } + +#define prefix \ + { \ + .name = "prefix", \ + .help = "Prefix to add as a punting rule. (example 1234::0/64)", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_punting_t, prefix), \ + .offset2 = offsetof(hc_punting_t, prefix_len), \ + .offset3 = offsetof(hc_punting_t, family), \ + } + +/* Commands */ + +static const command_parser_t command_punting_create = { + .action = ACTION_CREATE, + .object = OBJECT_PUNTING, + .nparams = 2, + .parameters = {symbolic_or_id, prefix}, +}; +COMMAND_REGISTER(command_punting_create); + +static const command_parser_t command_punting_list = { + .action = ACTION_LIST, + .object = OBJECT_PUNTING, + .nparams = 0, +}; +COMMAND_REGISTER(command_punting_list); +#endif diff --git a/ctrl/libhicnctrl/src/commands/command_route.c b/ctrl/libhicnctrl/src/commands/command_route.c new file mode 100644 index 000000000..95d0a3a43 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_route.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_route.c + * \brief Implementation of route command. + */ + +#include <math.h> +#include <hicn/ctrl/command.h> +#include "../objects/route.h" + +/* Parameters */ + +#define symbolic_or_id \ + { \ + .name = "symbolic_or_id", \ + .help = \ + "The symbolic name for an egress, or the egress route id (see 'help " \ + "list routes')", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_route_t, face_name), \ + } + +#define prefix \ + { \ + .name = "prefix", \ + .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_route_t, remote_addr), \ + .offset2 = offsetof(hc_route_t, len), \ + .offset3 = offsetof(hc_route_t, family), \ + } + +#define p_cost \ + { \ + .name = "cost", .help = "Positive integer representing cost.", \ + .type = TYPE_INT(1, 255), .offset = offsetof(hc_route_t, cost), \ + } + +/* Face parameters */ + +#define type_tcp_udp \ + { \ + .name = "type", .help = "face type [tcp | udp]", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_route_t, face.type), \ + } + +#define local_address \ + { \ + .name = "local_addr", .help = "local IP address on which to bind.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_route_t, face.local_addr), \ + .offset2 = offsetof(hc_route_t, face.family), \ + } + +#define local_port \ + { \ + .name = "local_port", .help = "Local port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_route_t, face.local_port), \ + } + +#define remote_address \ + { \ + .name = "remote_address", \ + .help = "The IPv4 or IPv6 or hostname of the remote system.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_route_t, face.remote_addr), \ + .offset2 = offsetof(hc_route_t, face.family), \ + } + +#define remote_port \ + { \ + .name = "remote_port", .help = "Remote port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_route_t, face.remote_port), \ + } + +#define interface \ + { \ + .name = "interface", .help = "Interface on which to bind", \ + .type = TYPE_INTERFACE_NAME, \ + .offset = offsetof(hc_route_t, face.netdevice.name), \ + } + +/* Commands */ + +int on_route_parsed(hc_route_t* route) { + if (hc_route_has_face(route)) { + route->face.admin_state = FACE_STATE_UP; + route->face.id = INVALID_FACE_ID; + } + route->face_id = INVALID_FACE_ID; // we populate face name + if (route->cost == 0) route->cost = 1; + return 0; +} + +static const command_parser_t command_route_create1 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 1, + .parameters = {prefix}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create1); + +static const command_parser_t command_route_create2 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 2, + .parameters = {symbolic_or_id, prefix}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create2); + +static const command_parser_t command_route_create3 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 3, + .parameters = {symbolic_or_id, prefix, p_cost}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create3); + +static const command_parser_t command_route_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 5, + .parameters = {prefix, p_cost, type_tcp_udp, remote_address, remote_port}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create5); + +static const command_parser_t command_route_create6 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 6, + .parameters = {prefix, p_cost, type_tcp_udp, remote_address, remote_port, + interface}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create6); + +static const command_parser_t command_route_create7 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 7, + .parameters = {prefix, p_cost, type_tcp_udp, local_address, local_port, + remote_address, remote_port}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create7); + +static const command_parser_t command_route_create8 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 8, + .parameters = {prefix, p_cost, type_tcp_udp, local_address, local_port, + remote_address, remote_port, interface}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_create8); + +static const command_parser_t command_route_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 0, +}; +COMMAND_REGISTER(command_route_list); + +static const command_parser_t command_route_remove = { + .action = ACTION_DELETE, + .object_type = OBJECT_TYPE_ROUTE, + .nparams = 2, + .parameters = {symbolic_or_id, prefix}, + .post_hook = (parser_hook_t)on_route_parsed, +}; +COMMAND_REGISTER(command_route_remove); diff --git a/ctrl/libhicnctrl/src/commands/command_stats.c b/ctrl/libhicnctrl/src/commands/command_stats.c new file mode 100644 index 000000000..d69f22a19 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_stats.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_stats.h + * \brief Implementation of stats command. + */ +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Commands */ + +static const command_parser_t command_stats_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_STATS, + .nparams = 0, +}; +COMMAND_REGISTER(command_stats_list); + +static const command_parser_t command_face_stats_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_FACE_STATS, + .nparams = 0, +}; +COMMAND_REGISTER(command_face_stats_list); diff --git a/ctrl/libhicnctrl/src/commands/command_strategy.c b/ctrl/libhicnctrl/src/commands/command_strategy.c new file mode 100644 index 000000000..2aac924c4 --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_strategy.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_strategy.h + * \brief Implementation of strategy command. + */ +#include <hicn/ctrl/command.h> + +/* Parameters */ +#define prefix \ + { \ + .name = "prefix", \ + .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, address), \ + .offset2 = offsetof(hc_strategy_t, len), \ + .offset3 = offsetof(hc_strategy_t, family), \ + } + +#define strategy \ + { \ + .name = "strategy", \ + .help = \ + "Strategy type (e.g. 'random', 'loadbalancer', 'low_latency', " \ + "'replication', 'bestpath', local_remote).", \ + .type = TYPE_ENUM(strategy_type), .offset = offsetof(hc_strategy_t, type), \ + } + +#define local_prefix \ + { \ + .name = "local_prefix", \ + .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ + .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, local_address), \ + .offset2 = offsetof(hc_strategy_t, local_len), \ + .offset3 = offsetof(hc_strategy_t, local_family), \ + } + +/* Commands */ + +static const command_parser_t command_strategy_list = { + .action = ACTION_SET, + .object_type = OBJECT_TYPE_STRATEGY, + .nparams = 2, + .parameters = {prefix, strategy}, +}; +COMMAND_REGISTER(command_strategy_list); + +static const command_parser_t local_prefix_add = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_LOCAL_PREFIX, + .nparams = 3, + .parameters = {prefix, strategy, local_prefix}, +}; +COMMAND_REGISTER(local_prefix_add); diff --git a/ctrl/libhicnctrl/src/commands/command_subscription.c b/ctrl/libhicnctrl/src/commands/command_subscription.c new file mode 100644 index 000000000..ee2455b1c --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_subscription.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 command_subscription.h + * \brief Implementation of subscription command. + */ +#include <limits.h> + +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define topics \ + { \ + .name = "topics", \ + .help = \ + "Topics to subscribe to, e.g. 6 (110 in binary) means topic 2 (10 in " \ + "binary, TOPIC_CONNECTION) and topic 4 (100 in binary, " \ + "TOPIC_LISTENER).", \ + .type = TYPE_INT(1, INT_MAX), \ + .offset = offsetof(hc_subscription_t, topics), \ + } + +/* Commands */ + +static const command_parser_t command_subscription_create = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_SUBSCRIPTION, + .nparams = 1, + .parameters = {topics}, +}; +COMMAND_REGISTER(command_subscription_create); diff --git a/ctrl/libhicnctrl/src/data.c b/ctrl/libhicnctrl/src/data.c new file mode 100644 index 000000000..605e23601 --- /dev/null +++ b/ctrl/libhicnctrl/src/data.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2021-2022 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 data.c + * \brief Implementation of request result data. + */ + +#include <assert.h> +#include <stdlib.h> + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/util/log.h> + +#define MIN_ALLOC_SIZE 8 +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +struct hc_data_s { + hc_object_type_t object_type; + bool complete; + + /** + * >=0 success, indicates the number of records in array + * <0 error + */ + ssize_t size; + size_t alloc_size; /** Allocated size (a power of 2 when managed + automatically) */ + size_t max_size; /** Maximum size defined at creation (0 = unlimited) */ + + uint8_t *buffer; +}; + +void _hc_data_clear(hc_data_t *data) { + data->complete = false; + data->buffer = NULL; + data->max_size = 0; + data->alloc_size = 0; + data->size = 0; +} + +hc_data_t *hc_data_create(hc_object_type_t object_type) { + hc_data_t *data = malloc(sizeof(hc_data_t)); + if (!data) return NULL; + + data->object_type = object_type; + + _hc_data_clear(data); + + return data; + // data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); + // if (!data->buffer) goto ERR_BUFFER; +} + +void hc_data_free(hc_data_t *data) { + assert(data); + + if (data->buffer) free(data->buffer); + free(data); +} + +int hc_data_set_max_size(hc_data_t *data, size_t max_size) { + if (data->size > max_size) return -1; + data->max_size = max_size; + return 0; +} + +const uint8_t *hc_data_get_buffer(hc_data_t *data) { return data->buffer; } + +const uint8_t *hc_data_get_free(hc_data_t *data) { + if (!data) return NULL; + if (data->max_size > 0 && data->size >= data->max_size) return NULL; + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + return data->buffer + data->size * object_size; +} + +void hc_data_inc_size(hc_data_t *data) { data->size++; } + +hc_object_type_t hc_data_get_object_type(const hc_data_t *data) { + return data->object_type; +} + +void hc_data_set_object_type(hc_data_t *data, hc_object_type_t object_type) { + data->object_type = object_type; +} + +ssize_t hc_data_get_size(const hc_data_t *data) { return data->size; } + +int hc_data_clear(hc_data_t *data) { + free(data->buffer); + _hc_data_clear(data); + return 0; +} + +int _hc_data_allocate(hc_data_t *data, size_t size) { + data->buffer = + realloc(data->buffer, size * hc_object_size(data->object_type)); + if (!data->buffer) goto ERR; + data->alloc_size = size; + return 0; +ERR: + data->alloc_size = 0; + return -1; +} + +int hc_data_allocate(hc_data_t *data, size_t size) { + /* Do not allocate twice */ + if (data->buffer) return -1; + if (data->max_size > 0 && size > data->max_size) return -1; + return _hc_data_allocate(data, size); +} + +int hc_data_ensure_available(hc_data_t *data, size_t count) { + size_t new_size = data->size + count; + if (new_size < data->alloc_size) return 0; + if (data->max_size > 0 && new_size > data->max_size) return -1; + + size_t new_alloc_size = MAX(MIN_ALLOC_SIZE, next_pow2(new_size)); + if (data->max_size > 0 && new_alloc_size > data->max_size) + new_alloc_size = data->max_size; + + return _hc_data_allocate(data, new_alloc_size); +} + +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) { + if (!data) return -1; + if (!elements) return -1; + if (count < 1) return -1; + + if (hc_data_ensure_available(data, count) < 0) return -1; + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + + uint8_t *dst = data->buffer + data->size * object_size; + memcpy(dst, elements, count * object_size); + data->size += count; + + return 0; +} + +int hc_data_push(hc_data_t *data, const void *element) { + return hc_data_push_many(data, element, 1); +} +#if 0 +/** + * + * NOTE: This function make sure there is enough room available in the data + * structure. + */ +u8 *hc_data_get_next(hc_data_t *data) { + if (hc_data_ensure_available(data, 1) < 0) return NULL; + + return data->buffer + data->size * data->out_element_size; +} + +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) { + data->complete_cb = cb; + data->complete_cb_data = cb_data; + return 0; +} +#endif + +void hc_data_set_complete(hc_data_t *data) { data->complete = true; } + +bool hc_data_is_complete(const hc_data_t *data) { return data->complete; } + +void hc_data_set_error(hc_data_t *data) { + data->size = -1; + data->complete = true; +} + +bool hc_data_get_result(hc_data_t *data) { return (data->size >= 0); } + +hc_object_t *hc_data_find(hc_data_t *data, hc_object_t *object) { + hc_object_type_t object_type = hc_data_get_object_type(data); + hc_data_foreach(data, found, { + if (hc_object_cmp(object_type, object, found) == 0) return found; + }); + return NULL; +} + +const hc_object_t *hc_data_get_object(const hc_data_t *data, off_t pos) { + size_t size = hc_data_get_size(data); + if (pos >= size) return NULL; + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + + return (const hc_object_t *)(data->buffer + pos * object_size); +} + +#if 0 +int hc_data_reset(hc_data_t *data) { + data->size = 0; + return 0; +} +#endif diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c deleted file mode 100644 index e617ff8a4..000000000 --- a/ctrl/libhicnctrl/src/face.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * 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 face.c - * \brief Implementation of face abstraction - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <hicn/util/token.h> - -#include <hicn/ctrl/face.h> -#include "util/hash.h" - -#define member_size(type, member) sizeof(((type *)0)->member) - - -/* Netdevice */ - -const char * netdevice_type_str[] = { -#define _(x) [NETDEVICE_TYPE_ ## x] = STRINGIZE(x), -foreach_netdevice_type -#undef _ -}; - -netdevice_t * -netdevice_create_from_index(u32 index) -{ - netdevice_t * netdevice = malloc(sizeof(netdevice_t)); - if (!netdevice) - goto ERR_MALLOC; - - int rc = netdevice_set_index(netdevice, index); - if (rc < 0) - goto ERR_INIT; - - return netdevice; - -ERR_INIT: - free(netdevice); -ERR_MALLOC: - return NULL; -} - -netdevice_t * -netdevice_create_from_name(const char * name) -{ - netdevice_t * netdevice = malloc(sizeof(netdevice_t)); - if (!netdevice) - goto ERR_MALLOC; - - int rc = netdevice_set_name(netdevice, name); - if (rc < 0) - goto ERR_INIT; - - return netdevice; - -ERR_INIT: - free(netdevice); -ERR_MALLOC: - return NULL; -} - -/** - * \brief Update the index of the netdevice based on the name - */ -int -netdevice_update_index(netdevice_t * netdevice) -{ - netdevice->index = if_nametoindex(netdevice->name); - if (netdevice->index == 0) - return -1; - return 0; -} - -int -netdevice_update_name(netdevice_t * netdevice) -{ - if (!if_indextoname(netdevice->index, netdevice->name)) - return -1; - return 0; -} - -void -netdevice_free(netdevice_t * netdevice) -{ - free(netdevice); -} - -int -netdevice_get_index(const netdevice_t * netdevice, u32 * index) -{ - if (netdevice->index == 0) - return -1; - *index = netdevice->index; - return 0; -} - -int -netdevice_set_index(netdevice_t * netdevice, u32 index) -{ - netdevice->index = index; - return netdevice_update_name(netdevice); -} - -int -netdevice_get_name(const netdevice_t * netdevice, const char ** name) -{ - if (netdevice->name[0] == '\0') - return -1; - *name = netdevice->name; - return 0; -} - -int -netdevice_set_name(netdevice_t * netdevice, const char * name) -{ - memset(netdevice->name, 0, sizeof(netdevice->name)); - int rc = snprintf(netdevice->name, IFNAMSIZ, "%s", name); - if (rc < 0) - return -1; - if (rc >= IFNAMSIZ) - return -2; /* truncated */ - return netdevice_update_index(netdevice); -} - -int -netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2) -{ - return (nd1->index - nd2->index); -} - - -/* Face state */ - -const char * face_state_str[] = { -#define _(x) [FACE_STATE_ ## x] = STRINGIZE(x), -foreach_face_state -#undef _ -}; - - -/* Face type */ - -const char * face_type_str[] = { -#define _(x) [FACE_TYPE_ ## x] = STRINGIZE(x), -foreach_face_type -#undef _ -}; - - -/* Face */ - -int -face_initialize(face_t * face) -{ - memset(face, 0, sizeof(face_t)); /* 0'ed for hash */ - return 1; -} - -int -face_initialize_udp(face_t * face, const char * interface_name, const - ip_address_t * local_addr, u16 local_port, - const ip_address_t * remote_addr, u16 remote_port, - int family) -{ - if (!local_addr) - return -1; - - *face = (face_t) { - .type = FACE_TYPE_UDP, - .family = family, - .local_addr = *local_addr, - .local_port = local_port, - .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY, - .remote_port = remote_port, - }; - - snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name); - - return 1; -} - -int -face_initialize_udp_sa(face_t * face, const char * interface_name, - const struct sockaddr * local_addr, - const struct sockaddr * remote_addr) -{ - if (!local_addr) - return -1; - - if (remote_addr && (local_addr->sa_family != remote_addr->sa_family)) - return -1; - - switch (local_addr->sa_family) { - case AF_INET: - { - struct sockaddr_in *lsai = (struct sockaddr_in *)local_addr; - struct sockaddr_in *rsai = (struct sockaddr_in *)remote_addr; - *face = (face_t) { - .type = FACE_TYPE_UDP, - .family = AF_INET, - .local_addr.v4.as_inaddr = lsai->sin_addr, - .local_port = lsai ? ntohs(lsai->sin_port) : 0, - .remote_addr = IP_ADDRESS_EMPTY, - .remote_port = rsai ? ntohs(rsai->sin_port) : 0, - }; - if (rsai) - face->remote_addr.v4.as_inaddr = rsai->sin_addr; - } - break; - case AF_INET6: - { - struct sockaddr_in6 *lsai = (struct sockaddr_in6 *)local_addr; - struct sockaddr_in6 *rsai = (struct sockaddr_in6 *)remote_addr; - *face = (face_t) { - .type = FACE_TYPE_UDP, - .family = AF_INET6, - .local_addr.v6.as_in6addr = lsai->sin6_addr, - .local_port = lsai ? ntohs(lsai->sin6_port) : 0, - .remote_addr = IP_ADDRESS_EMPTY, - .remote_port = rsai ? ntohs(rsai->sin6_port) : 0, - }; - if (rsai) - face->remote_addr.v6.as_in6addr = rsai->sin6_addr; - } - break; - default: - return -1; - } - - snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name); - - return 1; -} - -face_t * face_create() -{ - face_t * face = calloc(1, sizeof(face_t)); /* 0'ed for hash */ - return face; -} - -face_t * face_create_udp(const char * interface_name, - const ip_address_t * local_addr, u16 local_port, - const ip_address_t * remote_addr, u16 remote_port, int family) -{ - face_t * face = face_create(); - if (face_initialize_udp(face, interface_name, local_addr, local_port, remote_addr, remote_port, family) < 0) - goto ERR_INIT; - return face; - -ERR_INIT: - free(face); - return NULL; -} - -face_t * face_create_udp_sa(const char * interface_name, - const struct sockaddr * local_addr, - const struct sockaddr * remote_addr) -{ - face_t * face = face_create(); - if (face_initialize_udp_sa(face, interface_name, local_addr, remote_addr) < 0) - goto ERR_INIT; - return face; - -ERR_INIT: - free(face); - return NULL; -} - -void face_free(face_t * face) -{ - free(face); -} - -/** - * \brief Compare two faces - * \param [in] f1 - First face - * \param [in] f2 - Second face - * \return whether faces are equal, ie both their types are parameters are - * equal. - * - * NOTE: this function implements a partial order. - */ -int -face_cmp(const face_t * f1, const face_t * f2) -{ - - int ret = f1->type - f2->type; - if (ret != 0) - return ret; - - ret = f1->family - f2->family; - if (ret != 0) - return ret; - - /* - * FIXME As hicn-light API might not return the netdevice, we can discard the - * comparison when one of the two is not set for now... - */ - if ((f1->netdevice.index != 0) && (f2->netdevice.index != 0)) { - ret = netdevice_cmp(&f1->netdevice, &f2->netdevice); - if (ret != 0) - return ret; - } - - switch(f1->type) { - case FACE_TYPE_HICN: - ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family); - if (ret != 0) - return ret; - - ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family); - if (ret != 0) - return ret; - - break; - - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family); - if (ret != 0) - return ret; - - ret = f1->local_port - f2->local_port; - if (ret != 0) - return ret; - - ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family); - if (ret != 0) - return ret; - - ret = f1->remote_port - f2->remote_port; - if (ret != 0) - return ret; - - break; - default: - break; - } - - return 0; -} - -unsigned int -face_hash(const face_t * face) -{ - /* Assuming the unused part of the struct is set to zero */ - return hash_struct(face); -} - -/* /!\ Please update constants in header file upon changes */ -size_t -face_snprintf(char * s, size_t size, const face_t * face) -{ - switch(face->type) { - case FACE_TYPE_HICN: - { - char local[MAXSZ_IP_ADDRESS]; - char remote[MAXSZ_IP_ADDRESS]; - char tags[MAXSZ_POLICY_TAGS]; - - ip_address_snprintf(local, MAXSZ_IP_ADDRESS, - &face->local_addr, - face->family); - ip_address_snprintf(remote, MAXSZ_IP_ADDRESS, - &face->remote_addr, - face->family); - policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags); - return snprintf(s, size, "%s [%s -> %s] [%s]", - face_type_str[face->type], - local, - remote, - tags); - } - case FACE_TYPE_UNDEFINED: - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - { - char local[MAXSZ_IP_ADDRESS]; - char remote[MAXSZ_IP_ADDRESS]; - char tags[MAXSZ_POLICY_TAGS]; - - ip_address_snprintf(local, MAXSZ_IP_ADDRESS, - &face->local_addr, - face->family); - ip_address_snprintf(remote, MAXSZ_IP_ADDRESS, - &face->remote_addr, - face->family); - policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags); - - return snprintf(s, size, "%s [%s:%d -> %s:%d] [%s]", - face_type_str[face->type], - local, - face->local_port, - remote, - face->remote_port, - tags); - } - default: - return -1; - } - -} - -policy_tags_t face_get_tags(const face_t * face) -{ - return face->tags; -} - -int -face_set_tags(face_t * face, policy_tags_t tags) -{ - face->tags = tags; - return 1; -} diff --git a/ctrl/libhicnctrl/src/fw_interface.c b/ctrl/libhicnctrl/src/fw_interface.c new file mode 100644 index 000000000..6d5e5fb34 --- /dev/null +++ b/ctrl/libhicnctrl/src/fw_interface.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2021-2022 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 fw_interface.c + * \brief Implementation of fw interface + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/callback.h> +#include <hicn/util/log.h> +#include <hicn/ctrl/fw_interface.h> + +const char *fw_state_str[] = { +#define _(x) [FW_STATE_##x] = #x, + foreach_fw_state +#undef _ +}; + +struct fw_interface_s { + /* + * Type of forwarder to which we are connecting/connected : HICNLIGHT, VPP + */ + forwarder_type_t type; + fw_state_t state; + + hc_sock_t *sock; + char *url; + + bool has_subscribe_all; + + hc_enable_callback_t enable_callback; + hc_state_callback_t state_callback; + void *state_callback_data; + hc_result_callback_t result_callback; + void *result_callback_data; + hc_notification_callback_t notification_callback; + void *notification_callback_data; +}; + +fw_interface_t *fw_interface_create_url(forwarder_type_t type, + const char *url) { + fw_interface_t *fi = malloc(sizeof(fw_interface_t)); + if (!fi) goto ERR_MALLOC; + + fi->type = type; + /* Let's assume for now the forwarder is always on */ + fi->state = FW_STATE_AVAILABLE; + fi->sock = NULL; + fi->has_subscribe_all = false; + fi->url = NULL; + + // XXX make a single request to probe for forwarder size? + + return fi; + +ERR_MALLOC: + return NULL; +} + +fw_interface_t *fw_interface_create(forwarder_type_t type) { + return fw_interface_create_url(type, NULL); +} + +void fw_interface_free(fw_interface_t *fi) { + fw_interface_disconnect(fi); + free(fi); +} + +int fw_interface_get_fd(const fw_interface_t *fi) { + if (!fi) return 0; + return hc_sock_get_fd(fi->sock); +} + +int fw_interface_set_enable_callback(fw_interface_t *fi, + hc_enable_callback_t callback) { + fi->enable_callback = callback; + return 0; +} + +int fw_interface_set_state_callback(fw_interface_t *fi, + hc_state_callback_t callback, + void *callback_data) { + fi->state_callback = callback; + fi->state_callback_data = callback_data; + return 0; +} + +int fw_interface_set_result_callback(fw_interface_t *fi, + hc_result_callback_t callback, + void *callback_data) { + fi->result_callback = callback; + fi->result_callback_data = callback_data; + return 0; +} + +int fw_interface_set_notification_callback(fw_interface_t *fi, + hc_notification_callback_t callback, + void *callback_data) { + fi->notification_callback = callback; + fi->notification_callback_data = callback_data; + return 0; +} + +int fw_interface_enable(fw_interface_t *fi) { + // TODO + return 0; +} + +int fw_interface_disable(fw_interface_t *fi) { + // TODO + return 0; +} + +// XXX blocking or non blocking ? +int fw_interface_reschedule_connect(fw_interface_t *fi) { + INFO("Scheduling reconnect..."); + // XXX TODO timer + return 0; +} + +int _fw_interface_connect(fw_interface_t *fi, bool reattempt) { + fi->sock = hc_sock_create(fi->type, fi->url); + if (!fi->sock) goto ERR_SOCK; + + if (hc_sock_set_async(fi->sock) < 0) goto ERR_ASYNC; + + if (hc_sock_connect(fi->sock) < 0) { + ERROR("Error connecting to forwarder"); + return -1; + } + + return 0; + +ERR_ASYNC: + hc_sock_free(fi->sock); +ERR_SOCK: + + if (reattempt) return fw_interface_reschedule_connect(fi); + return -1; +} + +int fw_interface_connect(fw_interface_t *fi) { + switch (fi->state) { + case FW_STATE_UNDEFINED: + // XXX connect, enable, (poll)? + break; + case FW_STATE_DISABLED: + fw_interface_enable(fi); + break; + case FW_STATE_REQUESTED: + // XXX waiting ? polling connect ? + break; + case FW_STATE_AVAILABLE: + _fw_interface_connect(fi, true); + // XXX + break; + case FW_STATE_CONNECTING: + case FW_STATE_CONNECTED: + case FW_STATE_READY: + /* Nothing to do */ + return 0; + case FW_STATE_N: + return -1; + } + return 0; +} + +int _fw_interface_disconnect(fw_interface_t *fi) { + if (fi->has_subscribe_all) fw_interface_unsubscribe_all(fi); + hc_sock_free(fi->sock); + return 0; +} + +int fw_interface_disconnect(fw_interface_t *fi) { + switch (fi->state) { + case FW_STATE_UNDEFINED: + case FW_STATE_DISABLED: + case FW_STATE_REQUESTED: + case FW_STATE_AVAILABLE: + /* Nothing to do */ + return 0; + case FW_STATE_CONNECTING: + case FW_STATE_CONNECTED: + case FW_STATE_READY: + _fw_interface_disconnect(fi); + return 0; + case FW_STATE_N: + return -1; + } + return 0; +} + +fw_state_t fw_interface_get_state(const fw_interface_t *fi) { + return fi->state; +} + +bool fw_interface_is_connected(const fw_interface_t *fi) { + return ((fi->state == FW_STATE_CONNECTED) || (fi->state == FW_STATE_READY)); +} + +bool fw_interface_is_ready(const fw_interface_t *fi) { + return (fi->state == FW_STATE_READY); +} + +int fw_interface_subscribe_all(fw_interface_t *fi) { + INFO("fw_interface_subscribe_all"); + int rc = hc_execute_async(fi->sock, ACTION_SUBSCRIBE, OBJECT_TYPE_UNDEFINED, + NULL, fi->notification_callback, + fi->notification_callback_data); + if (rc < 0) { + return -1; + } + fi->has_subscribe_all = true; + return 0; +} + +int fw_interface_unsubscribe_all(fw_interface_t *fi) { + fi->has_subscribe_all = false; + return 0; +} + +// face manager : upon completion, same as notification, CREATE/GET FACE +// hproxy = event = function to call to proceed through state machine (also +// depends if we handle face+route), for notifications, telemetry. +// NOTE we should have a notif for our own events. how to handle ? +// XXX user_data .... or user_callback +int fw_interface_execute(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_data_t **pdata) { + return hc_execute(fi->sock, action, object_type, object, pdata); +} + +int fw_interface_execute_async(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + if (!callback) { + callback = fi->result_callback; + callback_data = fi->result_callback_data; + } + return hc_execute_async(fi->sock, action, object_type, object, callback, + callback_data); +} + +int fw_interface_on_receive(fw_interface_t *fi, size_t count) { + return hc_sock_on_receive(fi->sock, count); +} + +int fw_interface_get_recv_buffer(fw_interface_t *fi, uint8_t **buffer, + size_t *size) { + return hc_sock_get_recv_buffer(fi->sock, buffer, size); +} diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c new file mode 100644 index 000000000..478997ec1 --- /dev/null +++ b/ctrl/libhicnctrl/src/hicnctrl.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 hicnctrl.c + * \brief Command line interface + */ +#include <ctype.h> // isalpha isalnum +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> // getopt + +#include <hicn/ctrl.h> +#include <hicn/util/ip_address.h> +#include <hicn/util/log.h> +#include <hicn/util/token.h> +#include <hicn/validation.h> + +#include <hicn/ctrl/parse.h> + +#define die(LABEL, MESSAGE) \ + do { \ + printf(MESSAGE "\n"); \ + goto ERR_##LABEL; \ + } while (0) + +void usage_header() { fprintf(stderr, "Usage:\n"); } + +void usage_face_create(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, + "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT " + "[INTERFACE_NAME]\n", + prog); + if (verbose) + fprintf(stderr, " Create a face on specified address and port.\n"); +} + +void usage_face_delete(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -df ID\n", prog); + // fprintf(stderr, "%s -df NAME\n", prog); + fprintf(stderr, + "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT " + "[INTERFACE_NAME]\n", + prog); + if (verbose) fprintf(stderr, " Delete a face...\n"); +} + +void usage_face_list(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -F\n", prog); + if (verbose) fprintf(stderr, " List all faces.\n"); +} + +void usage_face(const char *prog, bool header, bool verbose) { + usage_face_create(prog, header, verbose); + usage_face_delete(prog, header, verbose); + usage_face_list(prog, header, verbose); +} + +void usage_route_create(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog); + // fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog); + if (verbose) fprintf(stderr, " Create a route...\n"); +} + +void usage_route_delete(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog); + // fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog); + if (verbose) fprintf(stderr, " Delete a route...\n"); +} + +void usage_route_list(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -R\n", prog); + if (verbose) fprintf(stderr, " List all routes.\n"); +} + +void usage_route(const char *prog, bool header, bool verbose) { + usage_route_create(prog, header, verbose); + usage_route_delete(prog, header, verbose); + usage_route_list(prog, header, verbose); +} + +void usage_forwarding_strategy_create(const char *prog, bool header, + bool verbose) { + if (header) usage_header(); +} +void usage_forwarding_strategy_delete(const char *prog, bool header, + bool verbose) { + if (header) usage_header(); +} + +void usage_forwarding_strategy_list(const char *prog, bool header, + bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -S\n", prog); + if (verbose) + fprintf(stderr, " List all availble forwarding strategies.\n"); +} + +void usage_forwarding_strategy(const char *prog, bool header, bool verbose) { + usage_forwarding_strategy_create(prog, header, verbose); + usage_forwarding_strategy_delete(prog, header, verbose); + usage_forwarding_strategy_list(prog, header, verbose); +} + +void usage_listener_create(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -l TYPE NAME LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", + prog); + if (verbose) + fprintf(stderr, " Create a listener on specified address and port.\n"); +} + +void usage_listener_delete(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -dl ID\n", prog); + fprintf(stderr, "%s -dl NAME\n", prog); + fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", + prog); + if (verbose) fprintf(stderr, " Delete a listener...\n"); +} + +void usage_listener_list(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -L\n", prog); + if (verbose) fprintf(stderr, " List all listeners.\n"); +} + +void usage_listener(const char *prog, bool header, bool verbose) { + usage_listener_create(prog, header, verbose); + usage_listener_delete(prog, header, verbose); + usage_listener_list(prog, header, verbose); +} +void usage_connection_create(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, + "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT " + "[INTERFACE_NAME]\n", + prog); + if (verbose) + fprintf(stderr, " Create a connection on specified address and port.\n"); +} + +void usage_connection_delete(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -dc ID\n", prog); + fprintf(stderr, "%s -dc NAME\n", prog); + fprintf(stderr, + "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT " + "[INTERFACE_NAME]\n", + prog); + if (verbose) fprintf(stderr, " Delete a connection...\n"); +} + +void usage_connection_list(const char *prog, bool header, bool verbose) { + if (header) usage_header(); + fprintf(stderr, "%s -C\n", prog); + if (verbose) fprintf(stderr, " List all connections.\n"); +} + +void usage_connection(const char *prog, bool header, bool verbose) { + usage_connection_create(prog, header, verbose); + usage_connection_delete(prog, header, verbose); + usage_connection_list(prog, header, verbose); +} + +void usage(const char *prog) { + fprintf(stderr, + "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] " + "PARAMETERS | [-F|-L|-C|-R] ]\n", + prog); + fprintf(stderr, "\n"); + fprintf(stderr, "High-level commands\n"); + fprintf(stderr, "\n"); + usage_face(prog, false, true); + usage_route(prog, false, true); + usage_forwarding_strategy(prog, false, true); + fprintf(stderr, "\n"); + fprintf(stderr, "Low level commands (hicn-light specific)\n"); + fprintf(stderr, "\n"); + usage_listener(prog, false, true); + usage_connection(prog, false, true); +} + +/* + * We only allow settings commands and object types once, with the default + * action being set to CREATE + */ +#define set_command(ACTION, OBJECT_TYPE) \ + do { \ + if ((ACTION) != ACTION_UNDEFINED) { \ + if (command->action != ACTION_CREATE) goto USAGE; \ + command->action = (ACTION); \ + } \ + if ((OBJECT_TYPE) != OBJECT_TYPE_UNDEFINED) { \ + if (command->object_type != OBJECT_TYPE_UNDEFINED) goto USAGE; \ + command->object_type = (OBJECT_TYPE); \ + } \ + } while (0) + +int parse_options(int argc, char *argv[], hc_command_t *command, + forwarder_type_t *forwarder) { + command->object_type = OBJECT_TYPE_UNDEFINED; + command->action = ACTION_CREATE; + int opt; + + while ((opt = getopt(argc, argv, "cCdDfFlLrRsShz:")) != -1) { + switch (opt) { + case 'z': + *forwarder = forwarder_type_from_str(optarg); + if (*forwarder == FORWARDER_TYPE_UNDEFINED) goto USAGE; + break; + case 'd': + set_command(ACTION_DELETE, OBJECT_TYPE_UNDEFINED); + break; + case 's': + set_command(ACTION_SUBSCRIBE, OBJECT_TYPE_UNDEFINED); + break; + case 'f': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_FACE); + break; + case 'c': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_CONNECTION); + break; + case 'l': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_LISTENER); + break; + case 'r': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_ROUTE); + break; + case 'F': + set_command(ACTION_LIST, OBJECT_TYPE_FACE); + break; + case 'L': + set_command(ACTION_LIST, OBJECT_TYPE_LISTENER); + break; + case 'C': + set_command(ACTION_LIST, OBJECT_TYPE_CONNECTION); + break; + case 'R': + set_command(ACTION_LIST, OBJECT_TYPE_ROUTE); + break; + case 'S': + set_command(ACTION_LIST, OBJECT_TYPE_STRATEGY); + break; + case 'D': + log_conf.log_level = LOG_DEBUG; + break; + default: /* "h" */ + usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + // XXX The rest could be made a single parse function + + /* A default action is always defined, let's verify we have an object type, + * unless we are subscribing to notifications. In that case, we can monitor + * all objects. + * XXX handle later + */ + if ((command->object_type == OBJECT_TYPE_UNDEFINED) && + (command->action != ACTION_SUBSCRIBE)) { + ERROR("Missing object specification"); + goto USAGE; + } + + /* Check the adequation between the number of parameters and the command */ + size_t nparams = argc - optind; + if (nparams > 0) { + if (command->action == ACTION_LIST) command->action = ACTION_GET; + } else { + if ((command->action != ACTION_LIST) && + (command->action != ACTION_SUBSCRIBE)) + goto USAGE; + } + + /* + * This checks is important even with 0 parameters as it checks whether the + * command exists. + */ + if (command->action != ACTION_SUBSCRIBE) { + const command_parser_t *parser = + command_search(command->action, command->object_type, nparams); + if (!parser) { + ERROR("Could not find parser for command '%s %s'", + action_str(command->action), object_type_str(command->object_type)); + return -1; + } + + if (nparams > 0) { + if (parse_getopt_args(parser, argc - optind, argv + optind, command) < + 0) { + ERROR("Error parsing command arguments"); + goto USAGE; + } + } + } + + return 0; + +USAGE: + usage(argv[0]); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) { + int rc = 1; + hc_command_t command; + memset(&command, 0, sizeof(command)); + char buf[MAXSZ_HC_OBJECT]; + + log_conf.log_level = LOG_INFO; + + forwarder_type_t forwarder = FORWARDER_TYPE_HICNLIGHT; + + if (parse_options(argc, argv, &command, &forwarder) < 0) + die(OPTIONS, "Bad arguments"); + + hc_sock_t *s = hc_sock_create(forwarder, /* url= */ NULL); + if (!s) die(SOCKET, "Error creating socket."); + + if (hc_sock_connect(s) < 0) + die(CONNECT, "Error connecting to the forwarder."); + + hc_data_t *data = NULL; + + rc = hc_execute(s, command.action, command.object_type, &command.object, + &data); + + if (rc < 0) { + switch (rc) { + case INPUT_ERROR: + ERROR("Wrong input parameters"); + break; + case UNSUPPORTED_CMD_ERROR: + ERROR("Unsupported command"); + break; + default: + ERROR("Error executing command"); + break; + } + goto ERR_COMMAND; + } + + if (!data) goto ERR_QUERY; + + if (!hc_data_get_result(data)) goto ERR_DATA; + + size_t size = hc_data_get_size(data); + if (size > 0) { + printf("Success: got %ld %s\n", size, object_type_str(command.object_type)); + } else { + printf("Success.\n"); + } + + if (command.action == ACTION_LIST) { + hc_data_foreach(data, obj, { + rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj); + if (rc < 0) + WARN("Display error"); + else if (rc >= MAXSZ_HC_OBJECT) + WARN("Output truncated"); + else + printf("%s\n", buf); + }); + } + + hc_data_free(data); + hc_sock_free(s); + return EXIT_SUCCESS; + +ERR_DATA: + hc_data_free(data); +ERR_QUERY: +ERR_COMMAND: +ERR_CONNECT: + hc_sock_free(s); +ERR_SOCKET: +ERR_OPTIONS: + printf("Error.\n"); + return EXIT_FAILURE; +} diff --git a/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in new file mode 100644 index 000000000..a27d85cde --- /dev/null +++ b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in @@ -0,0 +1,8 @@ +@PACKAGE_INIT@ + +set(Libhicnctrl_VERSION_MAJOR "@VERSION_MAJOR@") +set(Libhicnctrl_VERSION_MINOR "@VERSION_MINOR@") +set(Libhicnctrl_VERSION_PATCH "@VERSION_PATCH@") + +set_and_check(Libhicnctrl_INCLUDE_DIRS "@PACKAGE_Libhicnctrl_INCLUDE_DIRS@") +include("${CMAKE_CURRENT_LIST_DIR}/libhicnctrl-targets.cmake") diff --git a/ctrl/libhicnctrl/src/module.h b/ctrl/libhicnctrl/src/module.h new file mode 100644 index 000000000..51fd9f942 --- /dev/null +++ b/ctrl/libhicnctrl/src/module.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 modules.h + * \brief hicn-light module interface. + */ + +#ifndef HICNCTRL_MODULE_H +#define HICNCTRL_MODULE_H + +#include <stdint.h> + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/socket.h> + +#include "request.h" + +/* + * execute is used for sync code (eg. in VPP), while serialize/parse for + * sync/async code (eg. in hicn-light). + */ +typedef int (*hc_execute_t)(hc_sock_t *, hc_object_t *, hc_data_t *); +typedef int (*hc_serialize_t)(const hc_object_t *, uint8_t *); + +typedef struct { + int (*parse)(const uint8_t *buffer, size_t size, hc_object_t *object); + size_t serialized_size; + hc_serialize_t serialize[ACTION_N]; + hc_execute_t execute[ACTION_N]; +} hc_module_object_ops_t; + +#define HC_MODULE_OBJECT_OPS_EMPTY \ + (hc_module_object_ops_t) { \ + .parse = NULL, .serialized_size = 0, \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + [ACTION_SET] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + [ACTION_SET] = NULL, \ + }, \ + } + +#define DECLARE_MODULE_OBJECT_OPS_H(PREFIX, NAME) \ + extern const hc_module_object_ops_t PREFIX##_##NAME##_module_ops; + +/* Underscore'd functions take a hc_object_t as a parameter */ + +#define HC_MODULE_OBJECT_OPS(PREFIX, NAME) \ + (hc_module_object_ops_t) { \ + .parse = _##PREFIX##_##NAME##_parse, \ + .serialized_size = sizeof(cmd_##NAME##_list_item_t), \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + [ACTION_SET] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = PREFIX##_##NAME##_serialize_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_serialize_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_serialize_list, \ + [ACTION_SET] = PREFIX##_##NAME##_serialize_set, \ + } \ + } + +#define DECLARE_MODULE_OBJECT_OPS(PREFIX, NAME) \ + const hc_module_object_ops_t PREFIX##_##NAME##_module_ops = { \ + .parse = _##PREFIX##_##NAME##_parse, \ + .serialized_size = sizeof(cmd_##NAME##_list_item_t), \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + [ACTION_SET] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = PREFIX##_##NAME##_serialize_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_serialize_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_serialize_list, \ + [ACTION_SET] = PREFIX##_##NAME##_serialize_set, \ + }}; + +#define DECLARE_VPP_MODULE_OBJECT_OPS(PREFIX, NAME) \ + const hc_module_object_ops_t PREFIX##_##NAME##_module_ops = { \ + .execute = \ + { \ + [ACTION_CREATE] = PREFIX##_##NAME##_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_list, \ + [ACTION_SET] = PREFIX##_##NAME##_set, \ + }, \ + .serialize = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + [ACTION_SET] = NULL, \ + }, \ + }; + +typedef struct { + /** Create module-specific data storage */ + void *(*create_data)(const char *); + + /** Release module-specific data storage */ + void (*free_data)(void *); + + /** Retrieve underlying file descriptor */ + int (*get_fd)(hc_sock_t *); + + /** Retrieve underlying receive buffer */ + int (*get_recv_buffer)(hc_sock_t *, uint8_t **buffer, size_t *size); + + /** Connect control socket to the forwarder */ + int (*connect)(hc_sock_t *); + + /** Disconnect control socket from forwarder */ + int (*disconnect)(hc_sock_t *); + + /** Populate the TX buffer with the serialization of the next request to be + * sent */ + ssize_t (*prepare)(hc_sock_t *, hc_request_t *, uint8_t **buffer); + + /** Send the content of the TX buffer */ + int (*send)(hc_sock_t *, uint8_t *buffer, size_t size); + + /** Receive responses in the RX buffer */ + int (*recv)(hc_sock_t *); + + /** Process the content of the RX buffer to populate result data */ + int (*process)(hc_sock_t *, size_t count); + + hc_module_object_ops_t object_vft[OBJECT_TYPE_N]; +} hc_sock_ops_t; + +#endif /* HICNCTRL_MODULE_H */ diff --git a/ctrl/libhicnctrl/src/module_object.c b/ctrl/libhicnctrl/src/module_object.c new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ctrl/libhicnctrl/src/module_object.c @@ -0,0 +1 @@ + diff --git a/ctrl/libhicnctrl/src/module_object.h b/ctrl/libhicnctrl/src/module_object.h new file mode 100644 index 000000000..5081aa715 --- /dev/null +++ b/ctrl/libhicnctrl/src/module_object.h @@ -0,0 +1,10 @@ +#ifndef HICNCTRL_MODULES_OBJECT_H +#define HICNCTRL_MODULES_OBJECT_H + +ssize_t hc_object_serialize(hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_msg_t *msg); + +int hc_object_parse(hc_object_type_t object_type, uint8_t *buffer, + hc_object_t *object); + +#endif /* HICNCTRL_MODULES_OBJECT_H */ diff --git a/ctrl/libhicnctrl/src/modules/CMakeLists.txt b/ctrl/libhicnctrl/src/modules/CMakeLists.txt index e07ab8c99..f3e1a6342 100644 --- a/ctrl/libhicnctrl/src/modules/CMakeLists.txt +++ b/ctrl/libhicnctrl/src/modules/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2021-2023 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,38 +11,99 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - - +############################################################## +# Hicn Light NG Module +############################################################## list(APPEND HICNLIGHT_MODULE_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_api.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/mapme.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/stats.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/subscription.c ) +list(APPEND HICNLIGHT_MODULE_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/stats.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/subscription.h + ) + build_module(hicnlightctrl_module - SHARED - SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES} - DEPENDS ${DEPENDENCIES} - COMPONENT ${LIBHICNCTRL_COMPONENT} - INCLUDE_DIRS ${INCLUDE_DIRS} - DEFINITIONS ${COMPILER_DEFINITIONS} - COMPILE_OPTIONS ${COMPILE_FLAGS} + SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES} ${HICNLIGHT_MODULE_HEADER_FILES} + DEPENDS ${DEPENDENCIES} + COMPONENT ${LIBHICNCTRL_COMPONENT} + LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES} + INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS} + DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS PRIVATE ${COMPILE_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) + +############################################################## +# VPP Module +############################################################## if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux") - list(APPEND HICNLIGHT_PLUGIN_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c + if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED) + find_package(Safevapi ${CURRENT_VERSION} REQUIRED) + else() + list(APPEND DEPENDENCIES + ${SAFE_VAPI_SHARED} + ) + endif() + + + list(APPEND HICN_PLUGIN_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/strategy.c ) - build_module(vppctrl_module - SHARED - SOURCES ${HICNLIGHT_PLUGIN_SOURCE_FILES} - DEPENDS ${DEPENDENCIES} - LINK_LIBRARIES ${HICNPLUGIN_LIBRARIES} ${SAFE_VAPI_LIBRARIES} - COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES} - INCLUDE_DIRS ${INCLUDE_DIRS} - DEFINITIONS ${COMPILER_DEFINITIONS} - COMPILE_OPTIONS ${COMPILE_FLAGS} - LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs" + list(APPEND HICN_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/strategy.h + ) + + ############################################################## + # Compiler Options + ############################################################## + set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} + ${MARCH_COMPILER_OPTIONS} + PRIVATE "-Wno-address-of-packed-member" + ) + + ############################################################## + # Compiler Definitions + ############################################################## + list(APPEND COMPILER_DEFINITIONS + PRIVATE "-DHICN_VPP_PLUGIN=1" ) -endif()
\ No newline at end of file + build_module(vppctrl_module + SOURCES ${HICN_PLUGIN_SOURCE_FILES} ${HICN_PLUGIN_HEADER_FILES} + DEPENDS ${DEPENDENCIES} + LINK_LIBRARIES + PRIVATE ${HICN_LIBRARIES} + PRIVATE ${HICNPLUGIN_LIBRARIES} + PRIVATE ${SAFE_VAPI_LIBRARIES} + COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES} + INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS} + DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} + ) +endif() diff --git a/ctrl/libhicnctrl/src/modules/hicn_light.c b/ctrl/libhicnctrl/src/modules/hicn_light.c new file mode 100644 index 000000000..96cdda2d2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light.c @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 modules/hicn_light.c + * \brief Implementation of hicn-light module. + */ + +#include <assert.h> // assert +#include <fcntl.h> // fcntl +#include <stdbool.h> +#include <stdio.h> // snprintf +#include <string.h> // memmove, strcasecmp +#include <sys/socket.h> // socket +#include <sys/types.h> // getpid +#include <unistd.h> // close, fcntl, getpid + +#ifdef __linux__ +#include <sys/syscall.h> +#define gettid() syscall(SYS_gettid) +#endif /* __linux__ */ + +#include <strings.h> + +#include <hicn/ctrl/hicn-light.h> +#include <hicn/ctrl/socket.h> + +#include "../api_private.h" +#include "../objects/connection.h" // hc_connection_has_local +#include "../objects/listener.h" // hc_listener_is_local +#include "../objects/route.h" // hc_route_has_face +#include "../objects/stats.h" +#include "../request.h" +#include "../socket_private.h" +#include "hicn_light.h" + +#include "hicn_light/base.h" +#include "hicn_light/connection.h" +#include "hicn_light/face.h" +#include "hicn_light/listener.h" +#include "hicn_light/mapme.h" +#include "hicn_light/route.h" +#include "hicn_light/stats.h" +#include "hicn_light/strategy.h" +#include "hicn_light/subscription.h" + +#pragma GCC diagnostic ignored "-Warray-bounds" + +#define DEFAULT_SOCK_RECV_TIMEOUT_MS 100 + +#define PORT 9695 + +#define BOOLSTR(x) ((x) ? "true" : "false") + +hc_sock_light_data_t *hc_sock_light_data_create(const char *url) { + hc_sock_light_data_t *s = malloc(sizeof(hc_sock_light_data_t)); + if (!s) goto ERR_MALLOC; + + s->roff = s->woff = 0; + s->remaining = 0; + s->got_header = false; + + s->url = url ? strdup(url) : NULL; + + s->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (s->fd < 0) goto ERR_SOCKET; + +#if 0 + struct timeval tv = {.tv_sec = 0, + .tv_usec = DEFAULT_SOCK_RECV_TIMEOUT_MS * 1000}; + if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt"); + goto ERR_TIMEOUT; + } +#endif + + return s; + +#if 0 +ERR_TIMEOUT: +#endif + close(s->fd); +ERR_SOCKET: + if (s->url) free(s->url); + free(s); +ERR_MALLOC: + return NULL; +} + +void hc_sock_light_data_free(hc_sock_light_data_t *data) { + if (data->url) free(data->url); + free(data); +} + +static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +#define AVAILABLE(s) ((s)->woff - (s)->roff) + +/** + * \brief Parse a connection URL into a sockaddr + * \param [in] url - URL + * \param [out] sa - Resulting struct sockaddr, expected zero'ed. + * \return 0 if parsing succeeded, a negative error value otherwise. + */ +static int hicnlight_parse_url(const char *url, struct sockaddr *sa) { + char ip[100]; + char protocol[100]; + int port = PORT; + if (url) { + int ret = sscanf(url, "%99[^:]://%99[^:]:%99d[^/]", protocol, ip, &port); + if (ret == EOF) return -1; + } + +#ifdef __linux__ + srand(time(NULL) ^ getpid() ^ gettid()); +#else + srand((unsigned int)(time(NULL) ^ getpid())); +#endif /* __linux__ */ + + /* + * A temporary solution is to inspect the sa_family fields of the passed in + * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP + * connection to localhost. + */ + switch (sa->sa_family) { + case AF_UNSPEC: + case AF_INET: { + struct sockaddr_in *sai = (struct sockaddr_in *)sa; + sai->sin_family = AF_INET; + sai->sin_port = htons(port); + if (url) { + int ret = inet_pton(AF_INET, ip, &(sai->sin_addr.s_addr)); + if (ret != 1) return -1; + } else { + sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + break; + } + case AF_INET6: { + struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa; + sai6->sin6_family = AF_INET6; + sai6->sin6_port = htons(port); + if (url) { + int ret = inet_pton(AF_INET6, ip, &(sai6->sin6_addr)); + if (ret != 1) return -1; + } else { + sai6->sin6_addr = loopback_addr; + } + break; + } + default: + return -1; + } + + return 0; +} + +/* + * Return codes: + * < 0 : error; invalid buffer data -> flush + * otherwise, seq_num of the identified request + */ +static int hicnlight_process_header(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + hc_object_type_t object_type = OBJECT_TYPE_UNDEFINED; + + /* Check we have at least a header's worth of data, and consume it */ + if (AVAILABLE(s) < sizeof(hc_msg_header_t)) return 0; + + hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff); + + // INFO("Processing header header %s", command_type_str(msg->hdr.command_id)); + s->roff += sizeof(hc_msg_header_t); + s->got_header = true; + + /* How many elements are we expecting in the reply ? */ + s->remaining = msg->header.length; + + /* Identify request being parsed */ + int seq = msg->header.seq_num; + hc_request_t *request = NULL; + if (hc_sock_map_get(sock->map, seq, &request) < 0) { + ERROR("[hc_sock_light_process] Error searching for matching request"); + return -1; + } + if (!request) { + ERROR("[hc_sock_light_process] No request matching sequence number"); + /* + * Currently: Ignore packet (alternatively: return 0 to discard in case of + * error; move s->got_header later in this case) + */ + return -1; + } + + sock->current_request = request; + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + _ASSERT(data); + + switch (msg->header.message_type) { + case ACK_LIGHT: + _ASSERT(s->remaining == 0); + + s->got_header = false; + if (!hc_request_is_subscription(request)) hc_data_set_complete(data); + break; + + case NACK_LIGHT: + _ASSERT(s->remaining == 0); + + s->got_header = false; + hc_data_set_error(data); + break; + + case RESPONSE_LIGHT: + if (s->remaining == 0) { + /* Empty response (i.e. containing 0 elements) */ + s->got_header = false; + hc_data_set_complete(data); + return 0; + } + + /* Allocate buffer for response */ + if (hc_data_allocate(data, s->remaining) < 0) { + ERROR("[hc_sock_light_process] Cannot allocate result buffer"); + return -99; + } + break; + + case NOTIFICATION_LIGHT: { + _ASSERT(s->remaining == 1); + /* + * Assumption: the whole notification data is returned in a single read + * and we immediately parse it. + */ + // XXX assert enough buffer for object type + validate returned object + object_type = (hc_object_type_t)msg->header.command_id; + hc_data_clear(data); + hc_data_set_object_type(data, object_type); + if (hc_data_allocate(data, s->remaining) < 0) { + ERROR("[hc_sock_light_process] Cannot allocate result buffer"); + return -1; + } + + hc_data_push(data, s->buf + s->roff); + + s->roff += AVAILABLE(s); + + hc_request_on_notification(request); + + /* + * The buffer is cleared just before the next notification, which means + * it will have to be released upon exit. Otherwise we break the code + * dumping the notification synchronously (eg. hicnctrl -s). + */ + // hc_data_clear(data); + + s->got_header = false; + break; + } + + default: + ERROR("[hc_sock_light_process] Invalid response received"); + return -99; + } + + return 0; +} + +size_t hc_light_object_size(hc_object_type_t object_type); + +static int hicnlight_process_payload(hc_sock_t *sock) { + int err = 0; + int rc; + + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + hc_request_t *request = hc_sock_get_request(sock); + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_light_object_size(object_type); + if (object_size == 0) return -1; + + /* We only process full elements (size is stored in data) */ + size_t num_chunks = AVAILABLE(s) / object_size; + + /* Check whether we have enough data to process */ + if (num_chunks == 0) return 0; + + /* Safeguard: _ASSERT(num_chunks < s->remaining); */ + if (num_chunks > s->remaining) { + WARN( + "[hicnlight_process_payload] Unexpected num_chunks > " + "s->remaining"); + num_chunks = s->remaining; + } + + for (size_t i = 0; i < num_chunks; i++) { + /* + * Get storage offset in hc_data_t, which we assume is correctly + * provisioned. + * XXX + */ + u8 *src = s->buf + s->roff; + hc_object_t *dst = (hc_object_t *)hc_data_get_free(data); + if (!dst) { + ERROR("[hc_sock_light_process] Error in hc_data_get_next"); + err = -2; + break; + } + + // XXX we might want to display even incomplete data when printing (eg. + // string truncation), and be very strict when processing. + rc = hc_sock_parse_object(sock, hc_data_get_object_type(data), src, + object_size, dst); + s->roff += object_size; + if (rc < 0) { + ERROR("Error parsing received object"); + continue; + } + hc_data_inc_size(data); + } + + /* + * If we are not expecting any more data, mark the reply as complete + */ + s->remaining -= num_chunks; + if (s->remaining == 0) { + s->got_header = false; + hc_data_set_complete(data); + } + + return err; +} + +/*---------------------------------------------------------------------------- + * Socket operations + *----------------------------------------------------------------------------*/ + +static int hicnlight_get_fd(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + return s->fd; +} + +static int hicnlight_get_recv_buffer(hc_sock_t *sock, uint8_t **buffer, + size_t *size) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + *buffer = s->buf + s->woff; + *size = RECV_BUFLEN - s->woff; + + return 0; +} + +static int hicnlight_connect(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + struct sockaddr_storage ss; + memset(&ss, 0, sizeof(struct sockaddr_storage)); + + if (hicnlight_parse_url(s->url, (struct sockaddr *)&ss) < 0) goto ERR_PARSE; + + size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6); + if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) { + perror("connect error"); + goto ERR_CONNECT; + } + return 0; + +ERR_CONNECT: +ERR_PARSE: + return -1; +} + +static int hicnlight_disconnect(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + /* Remove the connection created to send the command. + * + * Note this is done as a best effort and we don't expect to receive any + * answer from the forwarder (hence the NULL pdata pointer in the request). + */ + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection.id = 0; + int rc = + strcpy_s(object.connection.name, sizeof(object.connection.name), "SELF"); + if (rc == EOK) + hc_execute_async(sock, ACTION_DELETE, OBJECT_TYPE_CONNECTION, &object, NULL, + NULL); + + close(s->fd); + + return 0; +} + +static ssize_t hicnlight_prepare_generic(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + /* We discard any result from the child request */ + hc_request_reset_data(current_request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + _ASSERT(hc_request_get_data(current_request) == NULL); + hc_data_t *data = hc_data_create(object_type); + if (!data) { + ERROR("[hicnlight_prepare_generic] Could not create data storage"); + return -1; + } + hc_request_set_data(current_request, data); + + /* Serialize request into message */ + DEBUG("Calling serialize on %s %s", action_str(action), + object_type_str(object_type)); + ssize_t msg_len = hc_sock_serialize_object(sock, action, object_type, object, + (uint8_t *)&s->msg); + if (msg_len < 0) { + ERROR("[hicnlight_prepare_generic] Could not serialize command %s %s", + action_str(action), object_type_str(object_type)); + return INPUT_ERROR; + } + + s->msg.header.seq_num = hc_request_get_seq(current_request); + + *buffer = (uint8_t *)&s->msg; + return msg_len; +} + +static int hicnlight_send(hc_sock_t *sock, uint8_t *buffer, size_t size) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + int rc = (int)send(s->fd, buffer, size, 0); + if (rc < 0) { + perror("[hicnlight_send] Error sending message"); + return -1; + } + + // XXX regular behaviour for others + return 0; +} + +// Example : face create udp +// 1) face to connection (immediate) +// connection to local listener (immediate) : why not both at the same +// time listener get +// listener create / nothing +// connection create +// connection get (if needed for populating face_id for instance, aka +// if we +// need to return data) + +static ssize_t hicnlight_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer); + +static ssize_t hicnlight_prepare_subrequest( + hc_sock_t *sock, hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, uint8_t **buffer) { + WITH_DEBUG({ + if (object) { + char buf[MAXSZ_HC_OBJECT]; + hc_object_snprintf(buf, sizeof(buf), object_type, object); + DEBUG("Creating subrequest %s/%s %s", action_str(action), + object_type_str(object_type), buf); + } + }); + hc_request_make_subrequest(request, action, object_type, object); + return hicnlight_prepare(sock, request, buffer); +} + +/* + * XXX shall we update the object in the request for faces ? it is not done + * for other objects, but for faces it is needed to further add a route !!! + */ +static ssize_t hicnlight_prepare_face_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_face_t *face = &object->face; + + // XXX those objects are created on stack and expected to be valid across + // several calls. A quick fix is to make them static + static hc_object_t connection; + static hc_object_t listener; + + hc_request_state_t state; + const hc_connection_t *conn; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_face_create > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + + switch (face->type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_CREATE); + goto NEXT; + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_LISTENER_CREATE); + goto NEXT; + case FACE_TYPE_UNDEFINED: + case FACE_TYPE_N: + return -99; // Not implemented + } + + case REQUEST_STATE_FACE_CREATE_CONNECTION_CREATE: + if (hc_face_to_connection(face, &connection.connection, true) < 0) { + ERROR("[hc_face_create] Could not convert face to connection."); + return -1; + } + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_CHECK); + + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_CONNECTION, &connection, + buffer); + + case REQUEST_STATE_FACE_CREATE_CONNECTION_CHECK: + /* + * If the newly created face_id was not need, we would only + * need to return the same data result, which contains a ack/nack, + * simply updating the object type. + * + * With the current API, once the connection is created, our only + * solution is to list all connections and compare with the current one + * to find the created connection ID, and thus face ID. + */ + /* Has the connection been successfully created ? */ + if (!data || !hc_data_get_result(data)) return -1; + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_GET); + goto NEXT; + + case REQUEST_STATE_FACE_CREATE_CONNECTION_GET: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_VERIFY); + return hicnlight_prepare_subrequest(sock, request, ACTION_GET, + OBJECT_TYPE_CONNECTION, &connection, + buffer); + + case REQUEST_STATE_FACE_CREATE_CONNECTION_VERIFY: + if (!data || hc_data_get_size(data) != 1) return -1; + + /* Newly created connection was found */ + conn = (hc_connection_t *)hc_data_get_buffer(data); + DEBUG("created connection id=%d", conn->id); + object->face.id = conn->id; + + break; + + case REQUEST_STATE_FACE_CREATE_LISTENER_CREATE: + if (hc_face_to_listener(face, &listener.listener) < 0) { + ERROR("Could not convert face to listener."); + return -1; + } + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_LISTENER_CHECK); + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_LISTENER, &listener, + buffer); + + break; + + case REQUEST_STATE_FACE_CREATE_LISTENER_CHECK: + /* + * No need for face id here, simply return the hc_data_t structure + * with the ack/nack, and the proper object type + */ + if (!data) return -1; + hc_data_set_object_type(data, OBJECT_TYPE_FACE); + break; + +#if 0 + case REQUEST_STATE_COMPLETE: + hc_data_set_complete(data); + break; +#endif + + default: + return -1; + } + return 0; +} + +static ssize_t hicnlight_prepare_face_delete(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_face_t *face = &object->face; + + // XXX those objects are created on stack and expected to be valid across + // several calls. A quick fix is to make them static + static hc_object_t connection; + + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_face_delete > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + + switch (face->type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_DELETE_CONNECTION_DELETE); + goto NEXT; + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + case FACE_TYPE_UNDEFINED: + case FACE_TYPE_N: + return -99; // Not implemented + } + + case REQUEST_STATE_FACE_DELETE_CONNECTION_DELETE: + if (hc_face_to_connection(face, &connection.connection, true) < 0) { + ERROR("[hc_face_create] Could not convert face to connection."); + return -1; + } + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + + return hicnlight_prepare_subrequest(sock, request, ACTION_DELETE, + OBJECT_TYPE_CONNECTION, &connection, + buffer); + case REQUEST_STATE_COMPLETE: + break; + + default: + return -1; + } + + return 0; +} + +static ssize_t hicnlight_prepare_face_list(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_face_t face; + + _ASSERT(action == ACTION_LIST); + _ASSERT(object_type == OBJECT_TYPE_FACE); + + hc_request_state_t state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_face_list > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_LIST_CONNECTION_LIST); + return hicnlight_prepare_subrequest( + sock, request, ACTION_LIST, OBJECT_TYPE_CONNECTION, object, buffer); + + case REQUEST_STATE_FACE_LIST_CONNECTION_LIST: + _ASSERT(data); + /* + * 'list connection' succeeded, we just need to allocate hc_data_t, + * create faces from connections, and return the data structure as if it + * was created by the query + */ + hc_data_t *face_data = hc_data_create(object_type); + hc_data_allocate(face_data, hc_data_get_size(data)); + foreach_connection(c, data) { + if (hc_face_from_connection(c, &face) < 0) { + ERROR("[hc_face_list] Could not convert connection to face."); + return -1; + } + hc_data_push(face_data, &face); + } + hc_data_set_complete(face_data); + + hc_request_reset_data(current_request); + hc_request_set_data(current_request, face_data); + + /* FACE/LIST could be part of FACE/GET */ + break; + + default: + return -1; + } + + return 0; +} + +static ssize_t hicnlight_prepare_get(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_object_t *found; + + hc_request_state_t state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_get > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + hc_request_set_state(current_request, REQUEST_STATE_GET_LIST); + return hicnlight_prepare_subrequest(sock, request, ACTION_LIST, + object_type, NULL, buffer); + case REQUEST_STATE_GET_LIST: + _ASSERT(data); + + found = hc_data_find(data, object); + hc_data_t *found_data = hc_data_create(object_type); + if (found) { + hc_data_allocate(found_data, 1); + hc_data_push(found_data, found); + } + hc_data_set_complete(found_data); + hc_request_reset_data(current_request); + hc_request_set_data(current_request, found_data); + return 0; + default: + return -1; /* Unexpected */ + } +} + +// XXX This should process the content of pdata (unless at init), and +// terminate by sending something +static ssize_t hicnlight_prepare_face(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + + _ASSERT(object_type == OBJECT_TYPE_FACE); + + switch (action) { + case ACTION_CREATE: + return hicnlight_prepare_face_create(sock, request, buffer); + case ACTION_DELETE: + return hicnlight_prepare_face_delete(sock, request, buffer); + case ACTION_LIST: + return hicnlight_prepare_face_list(sock, request, buffer); + default: + return -99; // Not implemented + } + return 0; +} + +static ssize_t hicnlight_prepare_connection_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(action == ACTION_CREATE); + _ASSERT(object_type == OBJECT_TYPE_CONNECTION); + + hc_data_t *data = hc_request_get_data(current_request); + + size_t size; + unsigned pos; + static hc_object_t listener; + const hc_object_t *obj_listener; + hc_data_t *listener_data = NULL; + + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_connection_create > %s", + hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + /* Two behaviours depending on the content of local_addr and local_port: + * - empty : create connection on all existing listeners, and raise an + * error if none + * - otherwise, check whether a corresponding listener exists, and + * create it if necessary + * + * We assume connection has been already validated. + */ + if (hc_connection_has_local(&object->connection)) { + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_GET); + } else { + /* + * At least part of the local socket specification is missing, match + * against existing listeners + */ + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_LIST); + } + goto NEXT; + + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_LIST: + + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_ITERATE); + // XXX We are currently assuming an object is present for rewrite, fix + // this + return hicnlight_prepare_subrequest(sock, request, ACTION_LIST, + OBJECT_TYPE_LISTENER, NULL, buffer); + + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_ITERATE: + /* + * NOTE: we could create all connections in parallel to speed up + * processing + */ + size = hc_data_get_size(data); + if (size < 0) return -1; + if (size == 0) + /* We are done, we cannot create a connection, return a Nack */ + ; // XXX TODO + // + /* Save the list of listeners for later iteration */ + listener_data = data; + hc_request_clear_data(current_request); // don't free data + data = NULL; + hc_request_set_state_count(current_request, 0); + hc_request_set_state(current_request, REQUEST_STATE_CONNECTION_CREATE_N); + goto NEXT; /* Start iteration */ + + case REQUEST_STATE_CONNECTION_CREATE_N: + /* + * IMPORTANT + * + * For now we only create a connection with the first non-local + * listener. + * + * Creating N connections in a single commands requires other + * changes to the code that we might done later: + * - ack/nack is not sufficient, all create function should return the + * list of created connections + * - this would allow us to avoid a GET at the end of face creation to + * retrieve the connection id. + * - face create should correspond to N connection create (should work + * out of the box provided we don't expect a single connection back). + * - route+face creation might then create N faces, and thus we would + * have to add N routes. + */ + assert(listener_data); + + // We need to back it up as the subrequest will clear the results + pos = hc_request_get_state_count(current_request); + size = hc_data_get_size(listener_data); + /* We have data if pos > 0, and we did not skipped previous ones */ + if (data && !hc_data_get_result(data)) { + INFO("Failed to create connection for listener %d / %d", pos - 1, size); + // XXX we might allow connections that already exist... how to manage + // the names + return -1; + } + + /* + * Previous connection was successfully created, let's continue but + * first check whether we reached the last one, which would complete the + * request. + */ + if (pos >= size) { + hc_data_free(listener_data); + hc_request_set_state(request, REQUEST_STATE_COMPLETE); + goto NEXT; + } + + /* Sending count'th connection creation */ + obj_listener = hc_data_get_object(listener_data, pos); + + // Filter which listener we use + // same protocol ? ip ? port ? + // avoid local ? + if (hc_listener_is_local(&obj_listener->listener)) { + /* Skip listener */ + DEBUG("Skipped local listener"); + hc_request_set_state_count(current_request, pos + 1); + goto NEXT; + } + + DEBUG("Creating connection with listener # %d / %d", pos, size); + /* We complement missing information from listener */ + // XXX is_family, etc. + object->connection.family = obj_listener->listener.family; + object->connection.local_addr = obj_listener->listener.local_addr; + object->connection.local_port = obj_listener->listener.local_port; + snprintf(object->connection.interface_name, INTERFACE_LEN, "%s", + obj_listener->listener.interface_name); + + hc_request_set_state_count(current_request, pos + 1); + return hicnlight_prepare_subrequest( + sock, request, ACTION_CREATE, OBJECT_TYPE_CONNECTION, object, buffer); + + /* Request listener to further check existence */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_GET: + /* Ensure we have a corresponding local listener */ + if (hc_connection_to_local_listener(&object->connection, + &listener.listener) < 0) { + ERROR( + "[hicnlight_prepare_connection_create] Could not " + "convert connection to local listener."); + return -1; + } + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_VERIFY); + return hicnlight_prepare_subrequest( + sock, request, ACTION_GET, OBJECT_TYPE_LISTENER, &listener, buffer); + + break; + + /* Check whether listener exists in GET results */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_VERIFY: + if (!data) return -1; + switch (hc_data_get_size(data)) { + case 0: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_CREATE); + break; + case 1: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE); + break; + default: + return -1; + } + goto NEXT; + + /* Create associated listener */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_CREATE: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_CHECK); + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_LISTENER, &listener, + buffer); + + /* Check whether listener creation succeeded */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_CHECK: + if (!data || !hc_data_get_result(data)) return -1; + hc_request_set_state(current_request, REQUEST_STATE_CONNECTION_CREATE); + goto NEXT; + + /* Create connection */ + case REQUEST_STATE_CONNECTION_CREATE: + /* + * Break recursion by directly calling hicnlight_prepare_generic on + * the initial request, that can now be executed since all + * prerequisites are validated. + */ + // return hicnlight_prepare_subrequest( + // sock, request, ACTION_CREATE, OBJECT_TYPE_CONNECTION, object, + // buffer); + hc_request_reset_data(current_request); + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + return hicnlight_prepare_generic(sock, request, buffer); + + case REQUEST_STATE_COMPLETE: + if (data) { + hc_data_set_complete(data); + } else { + /* + * No connection has been created, and we freed the data due to + * subrequest + */ + data = hc_data_create(OBJECT_TYPE_CONNECTION); + hc_data_set_error(data); + } + break; + + default: + return -1; + } + return 0; +} + +static ssize_t hicnlight_prepare_route_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(action == ACTION_CREATE); + _ASSERT(object_type == OBJECT_TYPE_ROUTE); + + hc_data_t *data = hc_request_get_data(current_request); + const hc_object_t *face_obj; + + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_route_create > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + if (hc_route_has_face(&object->route)) + hc_request_set_state(current_request, + REQUEST_STATE_ROUTE_CREATE_FACE_CREATE); + else + hc_request_set_state(current_request, REQUEST_STATE_ROUTE_CREATE); + goto NEXT; + + case REQUEST_STATE_ROUTE_CREATE_FACE_CREATE: + hc_request_set_state(current_request, + REQUEST_STATE_ROUTE_CREATE_FACE_CHECK); + return hicnlight_prepare_subrequest( + sock, request, ACTION_CREATE, OBJECT_TYPE_FACE, + (hc_object_t *)&object->route.face, buffer); + + case REQUEST_STATE_ROUTE_CREATE_FACE_CHECK: + if (!data) return -1; + int rc = hc_data_get_result(data); + if (rc < 0) return -1; + + if (hc_data_get_size(data) != 1) return -1; + + face_obj = hc_data_get_object(data, 0); + DEBUG("Created face id=%d", face_obj->face.id); + object->route.face_id = face_obj->face.id; + + hc_request_set_state(current_request, REQUEST_STATE_ROUTE_CREATE); + goto NEXT; + + /* Create route */ + case REQUEST_STATE_ROUTE_CREATE: + /* + * Break recursion by directly calling hicnlight_prepare_generic on the + * initial request, that can now be executed since all prerequisites are + * validated. + */ + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + return hicnlight_prepare_generic(sock, request, buffer); + + case REQUEST_STATE_COMPLETE: + hc_data_set_complete(data); + break; + + default: + return -1; + } + return 0; +} + +static ssize_t hicnlight_prepare_connection_delete(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(action == ACTION_DELETE); + _ASSERT(object_type == OBJECT_TYPE_CONNECTION); + + hc_data_t *data = hc_request_get_data(current_request); + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_connection_delete > %s", + hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + /* Two behaviours depending on the content of the connection id: + * - Valid Id : delete connection with provided ID + * - Invalid Id: Retrieve ID and then delete connection + * + * We assume connection has been already validated. + */ + if (hc_connection_has_valid_id(&object->connection)) { + // Id is valid. Proceed with deleting the connection. + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_DELETE_WITH_ID); + } else { + // Id is not valid. Try to retrieve it using the info in the connection. + hc_request_set_state(current_request, REQUEST_STATE_CONNECTION_GET); + } + goto NEXT; + + case REQUEST_STATE_CONNECTION_DELETE_WITH_ID: + // We have a valid id. Let's delete the connection. + hc_request_reset_data(current_request); + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + return hicnlight_prepare_generic(sock, request, buffer); + + case REQUEST_STATE_CONNECTION_GET: + // Get the connection info from the forwarder. + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_DELETE_AFTER_GET); + return hicnlight_prepare_subrequest( + sock, request, ACTION_GET, OBJECT_TYPE_CONNECTION, object, buffer); + + case REQUEST_STATE_CONNECTION_DELETE_AFTER_GET: + // We got the response from the forwarder. If valid, let's take the ID and + // delete the connection by ID. + if (!data) return -1; + + int rc = hc_data_get_result(data); + if (rc < 0) { + return -1; + } + + if (hc_data_get_size(data) != 1) { + return -1; + } + + _ASSERT(hc_data_get_object_type(data) == OBJECT_TYPE_CONNECTION); + + object->connection.id = hc_data_get_object(data, 0)->connection.id; + + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_DELETE_WITH_ID); + goto NEXT; + + case REQUEST_STATE_COMPLETE: + // Connection delete complete. + hc_data_set_complete(data); + break; + + default: + return -1; + } + + return 0; +} + +static int hicnlight_recv(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + int rc; + + /* + * This condition should be ensured to guarantee correct processing of + * messages. With TCP, we need at least a header as we will receive part of + * the stream. With UDP, we need the be able to receive the full datagram, + * otherwise the rest will be lost. + * + * Let's be sure to always be able to receive at least 1 JUMBO_MTU, which + * should be fine for al situations. + */ + _ASSERT(RECV_BUFLEN - s->woff > JUMBO_MTU); + + rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0); + if (rc == 0) { + /* Connection has been closed */ + return 0; + } + if (rc < 0) { + /* + * Let's not return 0 which currently means the socket has been closed + */ + if (errno == EWOULDBLOCK) { + // XXX TODO ?if (hc_request_get_action(request) == ACTION_SUBSCRIBE) + // return 0; + return -1; + } + if (errno == EINTR) { + WARN("recv has been stopped by signal"); + return -1; + } + perror("hc_sock_light_recv"); + return -1; + } + DEBUG("Received rc=%ld bytes", rc); + s->woff += rc; + + return rc; +} + +/* + * + * @param [in] data - hc_data_t structure allocated for the request + * + * This function is the entry point for all requests, and from there we will + * decide whether + * + */ +static ssize_t hicnlight_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + // XXX when do we create data... once for every step + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + static hc_object_t object_subscribe; + + WITH_DEBUG({ + char buf[MAXSZ_HC_OBJECT]; + hc_request_state_t state = hc_request_get_state(current_request); + hc_object_snprintf(buf, sizeof(buf), object_type, object); + DEBUG("[hicnlight_prepare] %s %s [%s] %s", action_str(action), + object_type_str(object_type), hc_request_state_str(state), buf); + }); + + /* + * Here the request is in progress and we just need to iterate through the + * FSM, or complete it. + */ + /* + * Specific treatment for + * CREATE/ROUTE with face + * SUBSCRIBE/(*) + * GET/(*) + * (*)/FACE + */ + + /* + * Special treatment for faces. + * + * This function will be called multiple times in order to process the + * complex request, involving several calls to the API. The process is + * responsible for going through the related state machine, and complete the + * request when appropriate. + */ + if (object_type == OBJECT_TYPE_FACE) + return hicnlight_prepare_face(sock, request, buffer); + + switch (action) { + case ACTION_CREATE: + switch (object_type) { + case OBJECT_TYPE_ROUTE: + /* Route might require face creation */ + return hicnlight_prepare_route_create(sock, request, buffer); + case OBJECT_TYPE_CONNECTION: + /* Connection could have no corresponging listener, or no local info + * provided */ + return hicnlight_prepare_connection_create(sock, request, buffer); + default: + break; + } + break; + + case ACTION_GET: + return hicnlight_prepare_get(sock, request, buffer); + + case ACTION_SUBSCRIBE: + /* Transform subscription queries */ + memset(&object_subscribe, 0, sizeof(hc_object_t)); + object->subscription.topics = topic_from_object_type(object_type); + + hc_request_set(request, ACTION_CREATE, OBJECT_TYPE_SUBSCRIPTION, object); + break; + + case ACTION_DELETE: + switch (object_type) { + case OBJECT_TYPE_CONNECTION: + return hicnlight_prepare_connection_delete(sock, request, buffer); + break; + + default: + break; + } + + default: + break; + } + + /* + * Generic requests should complete after a single call to hicnlight_send, + * with *pdata = NULL. If *pdata is not NULL, that means the request has + * completed and we can close it. + * It is the responsability of each state machine to complete the request + * otherwise. + */ + hc_data_t *data = hc_request_get_data(current_request); + if (data) { + hc_request_set_complete(current_request); + return 0; + } + + return hicnlight_prepare_generic(sock, request, buffer); +} + +/* + * This function processes incoming data in the ring buffer. Multiple requests + * might be interleaves, including regular requests and notifications. + * Responses might arrive fragment over several read events, but our + * assumption is that fragments arrive consecutively and are not interleaves + * with fragments from other requests... otherwise we would have to way to + * reconstruct a message. + * + * count != 0 when an external process has added data to the ring buffer + * without updating indices + */ +static int hicnlight_process(hc_sock_t *sock, size_t count) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + int rc = -99; + + if (count > 0) s->woff += count; + + /* + * We loop consuming messages until there is no more data in the ring + * buffer, or that we can find an entire message. Messages are received + * sequentially, and we keep track of incomplete requests in s->cur_request. + */ + while (AVAILABLE(s) > 0) { + if (!s->got_header) { + rc = hicnlight_process_header(sock); + } else { + rc = hicnlight_process_payload(sock); + } + if (rc < 0) break; + } + + if ((rc == -99) || (s->roff == s->woff)) { + /* Flush buffer */ + s->woff = 0; + } else { + /* Clean up read data from buffer */ + memmove(s->buf, s->buf + s->roff, AVAILABLE(s)); + s->woff -= s->roff; + } + s->roff = 0; + + return rc; +} + +hc_sock_ops_t hc_sock_light = (hc_sock_ops_t) { + .create_data = (void *(*)(const char *))hc_sock_light_data_create, + .free_data = (void (*)(void *))hc_sock_light_data_free, + .get_fd = hicnlight_get_fd, .get_recv_buffer = hicnlight_get_recv_buffer, + .connect = hicnlight_connect, .disconnect = hicnlight_disconnect, + .prepare = hicnlight_prepare, .send = hicnlight_send, .recv = hicnlight_recv, + .process = hicnlight_process, +#if 0 + .object_vft = { + [OBJECT_TYPE_LISTENER] = HC_MODULE_OBJECT_OPS(hicnlight, listener), + [OBJECT_TYPE_CONNECTION] = HC_MODULE_OBJECT_OPS(hicnlight, connection), + [OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_MAPME] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_ROUTE] = HC_MODULE_OBJECT_OPS(hicnlight, route), + [OBJECT_TYPE_STRATEGY] = HC_MODULE_OBJECT_OPS(hicnlight, strategy), + [OBJECT_TYPE_SUBSCRIPTION] = HC_MODULE_OBJECT_OPS(hicnlight, subscription), +} +#endif +}; + +size_t hc_light_object_size(hc_object_type_t object_type) { + hc_module_object_ops_t *vft = &hc_sock_light.object_vft[object_type]; + if (!vft) return 0; + return vft->serialized_size; +} + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + hc_module_object_ops_t *vft = &hc_sock_light.object_vft[object_type]; + if (!vft || !vft->serialize[action]) return 0; + return vft->serialize[action](object, msg); +} + +// Public constructor + +int hc_sock_initialize_module(hc_sock_t *s) { + // + /* + * We do this because initialization in the static struct fails with + * 'initializer element is not constant' + */ + hc_sock_light.object_vft[OBJECT_TYPE_LISTENER] = + hicnlight_listener_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_CONNECTION] = + hicnlight_connection_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_MAPME] = hicnlight_mapme_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_ROUTE] = hicnlight_route_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_STATS] = hicnlight_stats_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_FACE_STATS] = + hicnlight_face_stats_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_STRATEGY] = + hicnlight_strategy_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_SUBSCRIPTION] = + hicnlight_subscription_module_ops; + + if (s) s->ops = hc_sock_light; + return 0; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light.h b/ctrl/libhicnctrl/src/modules/hicn_light.h new file mode 100644 index 000000000..0bdcf0b30 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 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 modules/hicn_light.h + * \brief hicn-light module. + */ + +#ifndef HICNCTRL_MODULES_HICN_LIGHT_H +#define HICNCTRL_MODULES_HICN_LIGHT_H + +#include "hicn_light/base.h" + +typedef struct { + char *url; + int fd; + + /* Send buffer */ + hc_msg_t msg; + + /* Partial receive buffer */ + u8 buf[RECV_BUFLEN]; + size_t roff; /**< Read offset */ + size_t woff; /**< Write offset */ + + bool got_header; + /* + * Because received messages are potentially unbounded in size, we might not + * guarantee that we can store a full packet before processing it. We must + * implement a very simple state machine remembering the current parsing + * status in order to partially process the packet. + */ + size_t remaining; + u32 send_id; + + /* Next sequence number to be used for requests */ + int seq; +} hc_sock_light_data_t; + +extern hc_sock_light_data_t *hc_sock_light_data_create(const char *url); +extern void hc_sock_light_data_free(hc_sock_light_data_t *data); + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +#endif /* HICNCTRL_MODULES_HICN_LIGHT_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/base.h b/ctrl/libhicnctrl/src/modules/hicn_light/base.h new file mode 100644 index 000000000..ea6fc1bc9 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/base.h @@ -0,0 +1,49 @@ +#ifndef HICNCTRL_MODULES_HICNLIGHT_BASE_H +#define HICNCTRL_MODULES_HICNLIGHT_BASE_H + +#include <hicn/ctrl/hicn-light.h> + +#ifdef __APPLE__ +#define RANDBYTE() (u8)(arc4random() & 0xFF) +#else +#define RANDBYTE() (u8)(random() & 0xFF) +#endif + +// TODO: is this used? +#define foreach_hc_command \ + _(connection_add) \ + _(connection_remove) \ + _(connection_list) \ + _(listener_add) \ + _(listener_remove) \ + _(listener_list) \ + _(route_add) \ + _(route_remove) \ + _(route_list) \ + _(cache_set_store) \ + _(cache_set_serve) \ + _(cache_clear) \ + _(cache_list) \ + _(strategy_set) \ + _(strategy_add_local_prefix) \ + _(wldr_set) \ + _(punting_add) \ + _(mapme_activator) \ + _(mapme_timing) \ + _(subscription_add) \ + _(subscription_remove) + +typedef union { +#define _(x) cmd_##x##_t x; + foreach_hc_command +#undef _ +} hc_msg_payload_t; + +typedef cmd_header_t hc_msg_header_t; + +typedef struct hc_msg_s { + hc_msg_header_t header; + hc_msg_payload_t payload; +} hc_msg_t; + +#endif /* HICNCTRL_MODULES_HICNLIGHT_BASE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/cache.c b/ctrl/libhicnctrl/src/modules/hicn_light/cache.c new file mode 100644 index 000000000..e085142d7 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/cache.c @@ -0,0 +1,178 @@ +#include "cache.h" + +/* CACHE SET STORE */ + +static int _hcng_cache_set_store_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_set_store_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_SET_STORE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = cache->store, + }}; + + hc_command_params_t params = { + .cmd = ACTION_STORE, + .cmd_id = COMMAND_TYPE_CACHE_SET_STORE, + .size_in = sizeof(cmd_cache_set_store_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_cache_set_store(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_store_internal(s, cache, false); +} + +static int _hcng_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_store_internal(s, cache, true); +} + +/* CACHE SET SERVE */ + +static int _hcng_cache_set_serve_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_set_serve_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_SET_SERVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = cache->serve, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SERVE, + .cmd_id = COMMAND_TYPE_CACHE_SET_SERVE, + .size_in = sizeof(cmd_cache_set_serve_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; /// added +} + +static int _hcng_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_serve_internal(s, cache, false); +} + +static int _hcng_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_serve_internal(s, cache, true); +} + +/* CACHE CLEAR */ + +static int _hcng_cache_clear_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_clear_t msg = {.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_CLEAR, + .length = 1, + .seq_num = 0, + }}; + + hc_command_params_t params = { + .cmd = ACTION_CLEAR, + .cmd_id = COMMAND_TYPE_CACHE_CLEAR, + .size_in = sizeof(cmd_cache_clear_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_cache_clear(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_clear_internal(s, cache, false); +} + +/* CACHE PARSE */ + +static int hc_cache_parse(void *in, hc_cache_info_t *cache_info) { + cmd_cache_list_reply_t *item = (cmd_cache_list_reply_t *)in; + *cache_info = (hc_cache_info_t){.store = item->store_in_cs, + .serve = item->serve_from_cs, + .cs_size = item->cs_size, + .num_stale_entries = item->num_stale_entries}; + + return 0; +} + +/* CACHE LIST */ + +static hc_result_t *_hcng_cache_list_serialize(hc_sock_t *socket, + hc_data_t **pdata, bool async) { + hc_result_t *res = malloc(sizeof(*res)); + DEBUG("[hc_cache_list] async=%s", BOOLSTR(async)); + + msg_cache_list_t msg = {.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_LIST, + .length = 0, + .seq_num = 0, + }}; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = COMMAND_TYPE_CACHE_LIST, + .size_in = sizeof(cmd_cache_list_reply_t), + .size_out = sizeof(hc_cache_info_t), + .parse = (HC_PARSE)hc_cache_parse, + }; + + *res = (hc_result_t){ + .msg = + (hc_msg_t){ + .header = msg.header, + .payload.cache_list = msg.payload, + }, + .params = params, + .async = async, + .success = true, + }; + return res; +} + +static int _hcng_cache_list_internal(hc_sock_t *socket, hc_data_t **pdata, + bool async) { +#if 0 + hc_result_t *result = _hcng_cache_list_serialize(socket, pdata, async); + + int ret = INPUT_ERROR; + if (result->success) { + ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, + sizeof(result->msg), &result->params, pdata, + result->async); + } + + hc_result_free(result); + return ret; +#endif + return 0; // XXX added +} + +static int _hcng_cache_list(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_cache_list_internal(s, pdata, false); +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/connection.c b/ctrl/libhicnctrl/src/modules/hicn_light/connection.c new file mode 100644 index 000000000..d5648d794 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/connection.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2022 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 <assert.h> +#include <stdint.h> + +#include <hicn/util/log.h> + +#include "base.h" +#include "connection.h" +#include "../../object_private.h" + +int hc_connection_to_local_listener(const hc_connection_t *connection, + hc_listener_t *listener) { + int rc; + + face_type_t listener_type; + switch (connection->type) { + case FACE_TYPE_UDP: + listener_type = FACE_TYPE_UDP_LISTENER; + break; + case FACE_TYPE_TCP: + listener_type = FACE_TYPE_TCP_LISTENER; + break; + default: + return -1; + } + + *listener = (hc_listener_t){ + .id = ~0, + .type = listener_type, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + }; + rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", + RANDBYTE()); // generate name + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_connection_to_local_listener] Unexpected truncation of " + "symbolic name string"); + rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", + connection->interface_name); + if (rc >= INTERFACE_LEN) + WARN( + "[hc_connection_to_local_listener] Unexpected truncation of " + "interface name string"); + + return 0; +} + +/* CONNECTION PARSE */ + +static int hicnlight_connection_parse(const uint8_t *buffer, size_t size, + hc_connection_t *connection) { + int rc; + + if (size != sizeof(cmd_connection_list_item_t)) return -1; + cmd_connection_list_item_t *item = (cmd_connection_list_item_t *)buffer; + + if (!IS_VALID_ID(item->id)) { + ERROR("[hc_connection_parse] Invalid id received"); + return -1; + } + + if (!IS_VALID_NAME(item->name)) { + ERROR("[hc_connection_parse] Invalid name received"); + return -1; + } + if (!IS_VALID_INTERFACE_NAME(item->interface_name)) { + ERROR("[hc_connection_parse] Invalid interface_name received"); + return -1; + } + + if (!IS_VALID_TYPE(item->type)) { + ERROR("[hc_connection_parse] Invalid type received"); + return -1; + } + + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_connection_parse] Invalid family received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->local_address)) { + ERROR("[hc_connection_parse] Invalid local address received"); + return -1; + } + + if (!IS_VALID_PORT(ntohs(item->local_port))) { + ERROR("[hc_connection_parse] Invalid local port received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->remote_address)) { + ERROR("[hc_connection_parse] Invalid remote address received"); + return -1; + } + + if (!IS_VALID_PORT(ntohs(item->remote_port))) { + ERROR("[hc_connection_parse] Invalid remote port received"); + return -1; + } + + if (!IS_VALID_FACE_STATE(item->admin_state)) { + ERROR("[hc_connection_parse] Invalid admin_state received"); + return -1; + } + + // PRIORITY + // TAGS + + if (!IS_VALID_FACE_STATE(item->state)) { + ERROR("[hc_connection_parse] Invalid state received"); + return -1; + } + + *connection = (hc_connection_t){ + .id = item->id, + .type = (face_type_t)item->type, + .family = (int)item->family, + .local_addr = item->local_addr, + .local_port = ntohs(item->local_port), + .remote_addr = item->remote_addr, + .remote_port = ntohs(item->remote_port), + .admin_state = (face_state_t)item->admin_state, + .priority = item->priority, + .tags = item->tags, + .state = (face_state_t)item->state, + }; + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", + item->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + if (hc_connection_validate(connection, false) < 0) return -1; + return 0; +} + +int _hicnlight_connection_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_connection_parse(buffer, size, &object->connection); +} + +/* CONNECTION CREATE */ + +int hicnlight_connection_serialize_create(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_add_t *msg = (msg_connection_add_t *)packet; + *msg = (msg_connection_add_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .remote_ip = connection->remote_addr, + .local_ip = connection->local_addr, + .remote_port = htons(connection->remote_port), + .local_port = htons(connection->local_port), + .family = (uint8_t)connection->family, + .type = (uint8_t)connection->type, + .admin_state = (uint8_t)connection->admin_state, + .__pad = 0, + .priority = connection->priority, + .tags = connection->tags, + }}; + + rc = snprintf(msg->payload.symbolic, SYMBOLIC_NAME_LEN, "%s", + connection->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_connection_add_t); +} + +/* CONNECTION DELETE */ + +int hicnlight_connection_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_remove_t *msg = (msg_connection_remove_t *)packet; + *msg = (msg_connection_remove_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_REMOVE, + .length = 1, + .seq_num = 0, + }, + }; + + if (connection->id) { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + connection->id); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); + } else if (*connection->name) { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + connection->name); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); +#if 0 + } else { + hc_connection_t *connection_found; + if (hc_connection_get(socket, connection, &connection_found) < 0) + return res; + if (!connection_found) return res; + rc = snprintf(payload->symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + connection_found->id); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); + free(connection_found); +#endif + } + + return sizeof(msg_connection_remove_t); +} + +// XXX How to update a connection XXX +// Key attributes are mandatory +// Enum can be undefined +// family UNSPEC +// ip address NULL +// port NULL +// priority = int ????????? specific negative value == unspec +// tags = bitmap ????????? 0xFFFFFF special value == unspec + +// u32 id; /* Kr. */ +// char name[SYMBOLIC_NAME_LEN]; /* K.w */ +// char interface_name[INTERFACE_LEN]; /* Kr. */ +// +// netdevice_type_t netdevice_type; undefined +// face_type_t type; +// int family; +// ip_address_t local_addr; +// u16 local_port; +// ip_address_t remote_addr; +// u16 remote_port; +// face_state_t admin_state; +// uint32_t priority; /* .rw */ +// policy_tags_t tags; /* .rw */ +// face_state_t state; /* .r. */ +int hicnlight_connection_serialize_update(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_update_t *msg = (msg_connection_update_t *)packet; + *msg = (msg_connection_update_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_UPDATE, + .length = 1, + .seq_num = 0, + }, + .payload = { + //.remote_ip = connection->remote_updater, + //.local_ip = connection->local_updater, + //.remote_port = htons(connection->remote_port), + //.local_port = htons(connection->local_port), + //.family = connection->family, + //.type = connection->type, + .admin_state = connection->admin_state, + .priority = connection->priority, + .tags = connection->tags, + }}; + + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + connection->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + // snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s", + // connection->interface_name); + + return sizeof(msg_connection_update_t); +} + +#if 0 +/* CONNECTION SET ADMIN STATE */ + +static int _hicnlight_connection_set_admin_state_internal( + hc_sock_t *socket, const char *conn_id_or_name, face_state_t state, + bool async) { + int rc; + DEBUG( + "[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s " + "async=%s", + conn_id_or_name, face_state_str(state), BOOLSTR(async)); + + struct { + cmd_header_t hdr; + cmd_connection_set_admin_state_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .admin_state = state, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_admin_state] Unexpected truncation of symbolic " + "name string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, + .size_in = sizeof(cmd_connection_set_admin_state_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +} + +static int _hicnlight_connection_set_admin_state(hc_sock_t *s, + const char *conn_id_or_name, + face_state_t state) { + return _hicnlight_connection_set_admin_state_internal(s, conn_id_or_name, state, + false); +} + +static int _hicnlight_connection_set_admin_state_async(hc_sock_t *s, + const char *conn_id_or_name, + face_state_t state) { + return _hicnlight_connection_set_admin_state_internal(s, conn_id_or_name, state, + true); +} + + +static int _hicnlight_connection_set_priority_internal(hc_sock_t *socket, + const char *conn_id_or_name, + uint32_t priority, + bool async) { + int rc; + DEBUG( + "[hc_connection_set_priority] connection_id/name=%s priority=%d " + "async=%s", + conn_id_or_name, priority, BOOLSTR(async)); + struct { + cmd_header_t hdr; + cmd_connection_set_priority_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .priority = priority, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_priority] Unexpected truncation of symbolic " + "name " + "string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, + .size_in = sizeof(cmd_connection_set_priority_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +} + +static int _hicnlight_connection_set_priority(hc_sock_t *s, + const char *conn_id_or_name, + uint32_t priority) { + return _hicnlight_connection_set_priority_internal(s, conn_id_or_name, priority, + false); +} + +static int _hicnlight_connection_set_priority_async(hc_sock_t *s, + const char *conn_id_or_name, + uint32_t priority) { + return _hicnlight_connection_set_priority_internal(s, conn_id_or_name, priority, + true); +} + + +static int _hicnlight_connection_set_tags_internal(hc_sock_t *s, + const char *conn_id_or_name, + policy_tags_t tags, bool async) { + int rc; + DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s", + conn_id_or_name, tags, BOOLSTR(async)); + struct { + cmd_header_t hdr; + cmd_connection_set_tags_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .tags = tags, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_tags] Unexpected truncation of symbolic name " + "string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_TAGS, + .size_in = sizeof(cmd_connection_set_tags_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, + async); +} + +static int _hicnlight_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags) { + return _hicnlight_connection_set_tags_internal(s, conn_id_or_name, tags, false); +} + +static int _hicnlight_connection_set_tags_async(hc_sock_t *s, + const char *conn_id_or_name, + policy_tags_t tags) { + return _hicnlight_connection_set_tags_internal(s, conn_id_or_name, tags, true); +} +#endif + +/* CONNECTION LIST */ + +int hicnlight_connection_serialize_list(const hc_object_t *object, + uint8_t *packet) { + msg_connection_list_t *msg = (msg_connection_list_t *)packet; + *msg = (msg_connection_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_LIST, + .length = 0, + .seq_num = 0, + }}; + return sizeof(msg_header_t); // Do not use msg_connection_list_t +} + +int hicnlight_connection_serialize_set(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, connection); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/connection.h b/ctrl/libhicnctrl/src/modules/hicn_light/connection.h new file mode 100644 index 000000000..21f3a2fbc --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/connection.h @@ -0,0 +1,11 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H +#define HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H + +#include "../../module.h" + +int hc_connection_to_local_listener(const hc_connection_t *connection, + hc_listener_t *listener); + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, connection); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/face.c b/ctrl/libhicnctrl/src/modules/hicn_light/face.c new file mode 100644 index 000000000..4dcd96191 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/face.c @@ -0,0 +1,165 @@ +#include <hicn/ctrl/objects/listener.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "face.h" + +int hc_face_from_connection(const hc_connection_t *connection, + hc_face_t *face) { + int rc; + switch (connection->type) { + case FACE_TYPE_TCP: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_TCP, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + case FACE_TYPE_UDP: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_UDP, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + case FACE_TYPE_HICN: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_HICN, + .family = connection->family, + .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX + .local_addr = connection->local_addr, + .remote_addr = connection->remote_addr, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + default: + return -1; + } + face->netdevice.name[0] = '\0'; + face->netdevice.index = 0; + rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_connection_to_face] Unexpected truncation of symbolic name " + "string"); + rc = snprintf(face->netdevice.name, INTERFACE_LEN, "%s", + connection->interface_name); + if (rc >= INTERFACE_LEN) + WARN( + "[hc_connection_to_face] Unexpected truncation of interface name " + "string"); + netdevice_update_index(&face->netdevice); + return 0; +} + +int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, + bool generate_name) { + int rc; + + switch (face->type) { + case FACE_TYPE_HICN: + *connection = (hc_connection_t){ + .type = FACE_TYPE_HICN, + .family = face->family, + .local_addr = face->local_addr, + .local_port = 0, + .remote_addr = face->remote_addr, + .remote_port = 0, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", + face->netdevice.name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of symbolic " + "name string"); + break; + case FACE_TYPE_TCP: + *connection = (hc_connection_t){ + .type = FACE_TYPE_TCP, + .family = face->family, + .local_addr = face->local_addr, + .local_port = face->local_port, + .remote_addr = face->remote_addr, + .remote_port = face->remote_port, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + if (generate_name) { + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE()); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of " + "symbolic name string"); + } else { + memset(connection->name, 0, SYMBOLIC_NAME_LEN); + } + break; + case FACE_TYPE_UDP: + *connection = (hc_connection_t){ + .type = FACE_TYPE_UDP, + .family = face->family, + .local_addr = face->local_addr, + .local_port = face->local_port, + .remote_addr = face->remote_addr, + .remote_port = face->remote_port, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + if (generate_name) { + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE()); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of " + "symbolic name string"); + } else { + memset(connection->name, 0, SYMBOLIC_NAME_LEN); + } + snprintf(connection->interface_name, INTERFACE_LEN, "%s", + face->netdevice.name); + break; + default: + return -1; + } + + connection->id = face->id; + rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", + face->netdevice.name); + if (rc >= INTERFACE_LEN) + WARN( + "hc_face_to_connection] Unexpected truncation of interface name " + "string"); + + return 0; +} + +int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) { + return -99; /* XXX Not implemented */ +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/face.h b/ctrl/libhicnctrl/src/modules/hicn_light/face.h new file mode 100644 index 000000000..6f202b4ce --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/face.h @@ -0,0 +1,16 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_FACE +#define HICNCTRL_MODULE_HICNLIGHT_FACE + +#include <hicn/ctrl/objects/connection.h> +#include <hicn/ctrl/objects/face.h> + +int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face); + +int hc_face_from_connection(const hc_connection_t *connection, hc_face_t *face); + +int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, + bool generate_name); + +int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener); + +#endif /* HICNCTRL_MODULES_HICNLIGHT_FACE */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/listener.c b/ctrl/libhicnctrl/src/modules/hicn_light/listener.c new file mode 100644 index 000000000..46fded2ca --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/listener.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022 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 <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "../../object_private.h" +#include "listener.h" + +static int hicnlight_listener_parse(const u8 *buffer, size_t size, + hc_listener_t *listener) { + int rc; + + if (size != sizeof(cmd_listener_list_item_t)) return -1; + cmd_listener_list_item_t *item = (cmd_listener_list_item_t *)buffer; + + if (!IS_VALID_ADDRESS(item->local_address)) { + ERROR("[hc_listener_parse] Invalid address received"); + return -1; + } + if (!IS_VALID_NAME(item->name)) { + ERROR("[hc_listener_parse] Invalid name received"); + return -1; + } + if (!IS_VALID_INTERFACE_NAME(item->interface_name)) { + ERROR("[hc_listener_parse] Invalid interface_name received"); + return -1; + } + if (!IS_VALID_ID(item->id)) { + ERROR("[hc_listener_parse] Invalid id received"); + return -1; + } + if (!IS_VALID_PORT(ntohs(item->local_port))) { + ERROR("[hc_listener_parse] Invalid port received"); + return -1; + } + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_listener_parse] Invalid family received"); + return -1; + } + if (!IS_VALID_TYPE(item->type)) { + ERROR("[hc_listener_parse] Invalid type received"); + return -1; + } + // if (!(IS_VALID_CONNECTION_TYPE(item->type))) + // return -1; + + *listener = (hc_listener_t){ + .id = item->id, + .type = (face_type_t)(item->type), + .family = (int)(item->family), + .local_addr = + item->local_addr, // UNION_CAST(item->local_addr, ip_address_t), + .local_port = ntohs(item->local_port), + }; + + rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", + item->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + if (hc_listener_validate(listener, false) < 0) return -1; + return 0; +} + +int _hicnlight_listener_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_listener_parse(buffer, size, &object->listener); +} + +/* LISTENER CREATE */ + +int hicnlight_listener_serialize_create(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_listener_t *listener = &object->listener; + + msg_listener_add_t *msg = (msg_listener_add_t *)packet; + *msg = (msg_listener_add_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_ADD, + .length = 1, + .seq_num = 0, + }, + + .payload = { + .address = listener->local_addr, + .port = htons(listener->local_port), + .family = (uint8_t)listener->family, + .type = (uint8_t)listener->type, + }}; + + rc = snprintf(msg->payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(msg->payload.interface_name, INTERFACE_LEN, "%s", + listener->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + return sizeof(msg_listener_add_t); +} + +/* LISTENER DELETE */ + +int hicnlight_listener_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_listener_t *listener = &object->listener; + + msg_listener_remove_t *msg = (msg_listener_remove_t *)packet; + *msg = (msg_listener_remove_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_REMOVE, + .length = 1, + .seq_num = 0, + }}; + + if (listener->id) { + rc = snprintf(msg->payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", + listener->id); + } else if (*listener->name) { + rc = snprintf(msg->payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", + listener->name); + } else { + return -1; + } + + // For now we only support delete by name or id +#if 0 + hc_listener_t *listener_found; + if (hc_listener_get(socket, listener, &listener_found) < 0) return -1; + if (!listener_found) return -1; + rc = snprintf(payload->symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", + listener_found->id); + free(listener_found); + } +#endif + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_listener_remove_t); +} + +/* LISTENER LIST */ + +int hicnlight_listener_serialize_list(const hc_object_t *object, + uint8_t *packet) { + msg_listener_list_t *msg = (msg_listener_list_t *)packet; + *msg = (msg_listener_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_listener_list_t +} + +int hicnlight_listener_serialize_set(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, listener); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/listener.h b/ctrl/libhicnctrl/src/modules/hicn_light/listener.h new file mode 100644 index 000000000..67eadfbb1 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/listener.h @@ -0,0 +1,8 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_LISTENER_H +#define HICNCTRL_MODULE_HICNLIGHT_LISTENER_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, listener); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c new file mode 100644 index 000000000..04eb36e24 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 modules/hicn_light/mapme.c + * \brief Implementation of mapme object VFT for hicn_light. + */ + +#include <hicn/ctrl/hicn-light.h> +#include "mapme.h" + +static int hicnlight_mapme_parse(const uint8_t *buffer, size_t size, + hc_mapme_t *mapme) { + return -1; +} + +int _hicnlight_mapme_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_mapme_parse(buffer, size, &object->mapme); +} + +int hicnlight_mapme_serialize_create(const hc_object_t *object, + uint8_t *packet) { + const hc_mapme_t *mapme = &object->mapme; + + msg_mapme_add_t *msg = (msg_mapme_add_t *)packet; + *msg = (msg_mapme_add_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_ADD, + .length = 1, + .seq_num = 0, + }, + + .payload = {.face_id = mapme->face_id, + .family = mapme->family, + .address = mapme->address, + .len = mapme->len}}; + + return sizeof(msg_mapme_add_t); +} + +int hicnlight_mapme_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_mapme_serialize_list(const hc_object_t *object, uint8_t *packet) { + return -1; +} + +int hicnlight_mapme_serialize_set(const hc_object_t *object, uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, mapme); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/mapme.h b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.h new file mode 100644 index 000000000..58a943b67 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 modules/hicn_light/mapme.h + * \brief mapme object VFT for hicn_light. + */ + +#ifndef HICNCTRL_MODULE_HICNLIGHT_MAPME_H +#define HICNCTRL_MODULE_HICNLIGHT_MAPME_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, mapme); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_MAPME_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/policy.c b/ctrl/libhicnctrl/src/modules/hicn_light/policy.c new file mode 100644 index 000000000..d48ce014d --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/policy.c @@ -0,0 +1,162 @@ +#include "policy.h" + +/* POLICY CREATE */ + +static int _hcng_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy, + bool async) { +#if 0 + if (!IS_VALID_FAMILY(policy->family)) return -1; + + struct { + cmd_header_t hdr; + cmd_policy_add_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + COMMAND_TYPE_POLICY_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = policy->remote_addr, + .family = policy->family, + .len = policy->len, + .policy = policy->policy, + }}; + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = COMMAND_TYPE_POLICY_ADD, + .size_in = sizeof(cmd_policy_add_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_create(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_create_internal(s, policy, false); +} + +static int _hcng_policy_create_async(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_create_internal(s, policy, true); +} + +/* POLICY DELETE */ + +static int _hcng_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy, + bool async) { +#if 0 + if (!IS_VALID_FAMILY(policy->family)) return -1; + + struct { + cmd_header_t hdr; + cmd_policy_remove_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_POLICY_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = policy->remote_addr, + .family = policy->family, + .len = policy->len, + }}; + + hc_command_params_t params = { + .cmd = ACTION_DELETE, + .cmd_id = COMMAND_TYPE_POLICY_REMOVE, + .size_in = sizeof(cmd_policy_remove_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_delete(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_delete_internal(s, policy, false); +} + +static int _hcng_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_delete_internal(s, policy, true); +} + +/* POLICY PARSE */ + +static int hc_policy_parse(void *in, hc_policy_t *policy) { + hc_policy_t *item = (hc_policy_t *)in; + + if (!IS_VALID_ADDRESS(item->address)) { + ERROR("[hc_policy_parse] Invalid address"); + return -1; + } + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_policy_parse] Invalid family"); + return -1; + } + if (!IS_VALID_PREFIX_LEN(item->len)) { + ERROR("[hc_policy_parse] Invalid len"); + return -1; + } + if (!IS_VALID_POLICY(item->policy)) { + ERROR("[hc_policy_parse] Invalid policy"); + return -1; + } + + *policy = (hc_policy_t){ + .family = item->family, + .remote_addr = item->remote_addr, + .len = item->len, + .policy = item->policy, + }; + return 0; +} + +/* POLICY LIST */ + +static int _hcng_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata, + bool async) { +#if 0 + struct { + cmd_header_t hdr; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_POLICY_LIST, + .length = 0, + .seq_num = 0, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = COMMAND_TYPE_POLICY_LIST, + .size_in = sizeof(hc_policy_t), + .size_out = sizeof(hc_policy_t), + .parse = (HC_PARSE)hc_policy_parse, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + pdata, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_list(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_policy_list_internal(s, pdata, false); +} + +static int _hcng_policy_list_async(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_policy_list_internal(s, pdata, true); +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/punting.c b/ctrl/libhicnctrl/src/modules/hicn_light/punting.c new file mode 100644 index 000000000..7886ff839 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/punting.c @@ -0,0 +1,74 @@ +#include "punting.h" + +static int _hcng_punting_create_internal(hc_sock_t *socket, + hc_punting_t *punting, bool async) { +#if 0 + int rc; + + if (hc_punting_validate(punting) < 0) return -1; + + struct { + cmd_header_t hdr; + cmd_punting_add_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_PUNTING_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = punting->prefix, + .family = punting->family, + .len = punting->prefix_len, + }}; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + punting->face_id); + if (rc >= SYMBOLIC_NAME_LEN) + WARN("[_hc_punting_create] Unexpected truncation of symbolic name string"); + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = COMMAND_TYPE_PUNTING_ADD, + .size_in = sizeof(cmd_punting_add_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_punting_create(hc_sock_t *s, hc_punting_t *punting) { + return _hcng_punting_create_internal(s, punting, false); +} + +static int _hcng_punting_create_async(hc_sock_t *s, hc_punting_t *punting) { + return _hcng_punting_create_internal(s, punting, true); +} + +static int _hcng_punting_get(hc_sock_t *s, hc_punting_t *punting, + hc_punting_t **punting_found) { + ERROR("hc_punting_get not (yet) implemented."); + return -1; +} + +static int _hcng_punting_delete(hc_sock_t *s, hc_punting_t *punting) { + ERROR("hc_punting_delete not (yet) implemented."); + return -1; +} + +#if 0 +static int hc_punting_parse(void * in, hc_punting_t * punting) +{ + ERROR("hc_punting_parse not (yet) implemented."); + return -1; +} +#endif + +static int _hcng_punting_list(hc_sock_t *s, hc_data_t **pdata) { + ERROR("hc_punting_list not (yet) implemented."); + return -1; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/route.c b/ctrl/libhicnctrl/src/modules/hicn_light/route.c new file mode 100644 index 000000000..38510704c --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/route.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021-2022 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 modules/hicn_light/route.c + * \brief Implementation of route object VFT for hicn_light. + */ + +#include <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> +#include "base.h" +#include "route.h" +#include <hicn/ctrl/hicn-light.h> + +#include "../../object_private.h" + +static int hicnlight_route_parse(const uint8_t *buffer, size_t size, + hc_route_t *route) { + if (size != sizeof(cmd_route_list_item_t)) return -1; + cmd_route_list_item_t *item = (cmd_route_list_item_t *)buffer; + + if (!IS_VALID_NAME(item->face_name)) { + ERROR("[hc_route_parse] Invalid face_name received"); + return -1; + } + + if (!IS_VALID_ID(item->face_id)) { + ERROR("[hc_route_parse] Invalid face_id received"); + return -1; + } + + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_route_parse] Invalid family received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->remote_addr)) { + ERROR("[hc_route_parse] Invalid address received"); + return -1; + } + + // LEN + // COST + + *route = (hc_route_t){ + .face_name = "", /* This is not reported back */ + .face_id = item->face_id, + .family = (int)(item->family), + .remote_addr = item->remote_addr, + .len = item->len, + .cost = item->cost, + }; + + if (hc_route_validate(route, false) < 0) return -1; + return 0; +} + +int _hicnlight_route_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_route_parse(buffer, size, &object->route); +} + +/* ROUTE CREATE */ + +int hicnlight_route_serialize_create(const hc_object_t *object, + uint8_t *packet) { + const hc_route_t *route = &object->route; + int rc; + + msg_route_add_t *msg = (msg_route_add_t *)packet; + *msg = (msg_route_add_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = route->remote_addr, + .cost = route->cost, + .family = route->family, + .len = route->len, + }}; + + /* + * The route commands expects the ID or name as part of the + * symbolic_or_connid attribute. + */ + if (route->face_name[0] != '\0') { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + route->face_name); + } else { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + route->face_id); + } + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_route_add_t); +} + +/* ROUTE DELETE */ + +int hicnlight_route_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + const hc_route_t *route = &object->route; + int rc; + + msg_route_remove_t *msg = (msg_route_remove_t *)packet; + memset(msg, 0, sizeof(msg_route_remove_t)); + *msg = (msg_route_remove_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .family = (uint8_t)route->family, + .len = route->len, + }}; + + /* + * Direct copy as part of the previous assignment does not work correctly... + * to be investigated + */ + memcpy(&msg->payload.address, &route->remote_addr, sizeof(hicn_ip_address_t)); + + /* + * The route commands expects the ID or name as part of the + * symbolic_or_connid attribute. + */ + if (route->face_name[0] != '\0') { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + route->face_name); + } else { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + route->face_id); + } + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_route_remove_t); +} + +/* ROUTE LIST */ + +int hicnlight_route_serialize_list(const hc_object_t *object, uint8_t *packet) { + msg_route_list_t *msg = (msg_route_list_t *)packet; + *msg = (msg_route_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_route_list_t +} + +int hicnlight_route_serialize_set(const hc_object_t *object, uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, route); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/route.h b/ctrl/libhicnctrl/src/modules/hicn_light/route.h new file mode 100644 index 000000000..825253a42 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/route.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 modules/hicn_light/route.h + * \brief route object VFT for hicn_light. + */ + +#ifndef HICNCTRL_MODULE_HICNLIGHT_ROUTE_H +#define HICNCTRL_MODULE_HICNLIGHT_ROUTE_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, route); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/stats.c b/ctrl/libhicnctrl/src/modules/hicn_light/stats.c new file mode 100644 index 000000000..a60190a13 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/stats.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022 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 modules/hicn_light/stats.c + * \brief Implementation of stats object VFT for hicn_light. + */ + +#include <hicn/util/log.h> +#include "base.h" +#include "stats.h" + +/* GENERAL STATS */ + +int hicnlight_stats_parse(const uint8_t *buffer, size_t size, + hc_stats_t *stats) { + if (size != sizeof(cmd_stats_list_item_t)) return -1; + + cmd_stats_list_item_t *item = (cmd_stats_list_item_t *)buffer; + *stats = item->stats; + return 0; +} + +int _hicnlight_stats_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_stats_parse(buffer, size, &object->stats); +} + +int hicnlight_stats_serialize_create(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_stats_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_stats_serialize_list(const hc_object_t *object, uint8_t *packet) { + msg_stats_list_t *msg = (msg_stats_list_t *)packet; + *msg = (msg_stats_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_STATS_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_stats_list_t +} + +int hicnlight_stats_serialize_set(const hc_object_t *object, uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, stats); + +/* PER-FACE STATS */ + +int hicnlight_face_stats_parse(const uint8_t *buffer, size_t size, + hc_face_stats_t *stats) { + if (size != sizeof(cmd_face_stats_list_item_t)) return -1; + + cmd_face_stats_list_item_t *item = (cmd_face_stats_list_item_t *)buffer; + *stats = item->stats; + return 0; +} + +int _hicnlight_face_stats_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_face_stats_parse(buffer, size, &object->face_stats); +} + +int hicnlight_face_stats_serialize_create(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_face_stats_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_face_stats_serialize_list(const hc_object_t *object, + uint8_t *packet) { + msg_face_stats_list_t *msg = (msg_face_stats_list_t *)packet; + *msg = (msg_face_stats_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_FACE_STATS_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_stats_list_t +} + +int hicnlight_face_stats_serialize_set(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, face_stats); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/stats.h b/ctrl/libhicnctrl/src/modules/hicn_light/stats.h new file mode 100644 index 000000000..9509be86c --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/stats.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef HICNCTRL_MODULE_HICNLIGHT_STATS_H +#define HICNCTRL_MODULE_HICNLIGHT_STATS_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, stats); +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, face_stats); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_STATS_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c new file mode 100644 index 000000000..16ce2d047 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c @@ -0,0 +1,138 @@ +#include <assert.h> +#include "strategy.h" + +#include <hicn/ctrl/hicn-light.h> + +static int hicnlight_strategy_parse(const u8 *buffer, size_t size, + hc_strategy_t *strategy) { + return -1; +} + +int _hicnlight_strategy_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_strategy_parse(buffer, size, &object->strategy); +} + +int hicnlight_strategy_serialize_create(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_strategy_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_strategy_serialize_list(const hc_object_t *object, + uint8_t *packet) { + assert(!object); + return -1; +} + +int hicnlight_strategy_serialize_set(const hc_object_t *object, + uint8_t *packet) { + const hc_strategy_t *strategy = &object->strategy; + + msg_strategy_set_t *msg = (msg_strategy_set_t *)packet; + *msg = (msg_strategy_set_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_STRATEGY_SET, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = strategy->address, + .family = strategy->family, + .len = strategy->len, + .type = strategy->type, + }}; + + return sizeof(msg_strategy_set_t); +} + +#if 0 +static hc_result_t *_strategy_add_local_prefix_serialize( + hc_sock_t *socket, hc_strategy_t *strategy) { + hc_result_t *res = malloc(sizeof(*res)); + char strategy_s[MAXSZ_HC_STRATEGY]; + strncpy(strategy->name, strategy_str(strategy->type), + MAXSZ_STRATEGY_NAME - 1); + + int rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy); + if (rc >= MAXSZ_HC_STRATEGY) + WARN("[hicnlight_strategy_create] Unexpected truncation of strategy string"); + DEBUG("[hicnlight_strategy_create] strategy=%s", strategy_s); + + if (!IS_VALID_FAMILY(strategy->family) || + !IS_VALID_STRATEGY_TYPE(strategy->type) || + !IS_VALID_FAMILY(strategy->local_family)) { + res->success = false; + return res; + } + + msg_strategy_add_local_prefix_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, + .length = 1, + .seq_num = 0, + }, + .payload = { + .type = strategy->type, + .address = strategy->address, + .family = strategy->family, + .len = strategy->len, + .local_address = strategy->local_address, + .local_family = strategy->local_family, + .local_len = strategy->local_len, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, + .size_in = sizeof(cmd_strategy_add_local_prefix_t), + .size_out = 0, + .parse = NULL, + }; + + *res = (hc_result_t){ + .msg = + (hc_msg_t){ + .header = msg.header, + .payload.strategy_add_local_prefix = msg.payload, + }, + .params = params, + .async = false, + .success = true, + }; + return res; +} + +/* How to retrieve that from the forwarder ? */ +static const char *strategies[] = { + "random", + "load_balancer", +}; + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) + +static int hicnlight_strategy_list(hc_sock_t *s, hc_data_t **data) { + int rc; + + *data = hc_data_create(0, sizeof(hc_strategy_t), NULL); + + for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) { + hc_strategy_t *strategy = (hc_strategy_t *)hc_data_get_next(*data); + if (!strategy) return -1; + rc = snprintf(strategy->name, MAXSZ_STRATEGY_NAME, "%s", strategies[i]); + if (rc >= MAXSZ_STRATEGY_NAME) + WARN("[hc_strategy_list] Unexpected truncation of strategy name string"); + (*data)->size++; + } + return -1; +} +#endif + +DECLARE_MODULE_OBJECT_OPS(hicnlight, strategy); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h new file mode 100644 index 000000000..9fa809751 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h @@ -0,0 +1,8 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H +#define HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, strategy); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c new file mode 100644 index 000000000..e2de09bf5 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c @@ -0,0 +1,71 @@ +#include <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "../../object_private.h" +#include "subscription.h" + +static int hicnlight_subscription_parse(const u8 *buffer, size_t size, + hc_subscription_t *subscription) { + /* We should never have to parse subscriptions */ + return -1; +} + +int _hicnlight_subscription_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_subscription_parse(buffer, size, &object->subscription); +} + +/* SUBSCRIPTION CREATE */ + +int hicnlight_subscription_serialize_create(const hc_object_t *object, + uint8_t *packet) { + const hc_subscription_t *subscription = &object->subscription; + + msg_subscription_add_t *msg = (msg_subscription_add_t *)packet; + *msg = (msg_subscription_add_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_SUBSCRIPTION_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = {.topics = subscription->topics}}; + + return sizeof(msg_subscription_add_t); +} + +/* SUBSCRIPTION DELETE */ + +int hicnlight_subscription_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + const hc_subscription_t *subscription = &object->subscription; + + msg_subscription_remove_t *msg = (msg_subscription_remove_t *)packet; + *msg = (msg_subscription_remove_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = {.topics = subscription->topics}}; + + return sizeof(msg_subscription_remove_t); +} + +int hicnlight_subscription_serialize_list(const hc_object_t *object, + uint8_t *packet) { + assert(!object); + return -1; +} + +int hicnlight_subscription_serialize_set(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, subscription); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h new file mode 100644 index 000000000..d67bdd9ba --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h @@ -0,0 +1,8 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H +#define HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, subscription); + +#endif /* HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c b/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c new file mode 100644 index 000000000..7d1812ab2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c @@ -0,0 +1,3 @@ +#include "wldr.h" + +static int _hcng_wldr_set(hc_sock_t *s /* XXX */) { return 0; } diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_api.c deleted file mode 100644 index d1a055777..000000000 --- a/ctrl/libhicnctrl/src/modules/hicn_light_api.c +++ /dev/null @@ -1,2278 +0,0 @@ -/* - * 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 api.c - * \brief Implementation of hICN control library API - */ - -#include "api_private.h" - -#include <assert.h> // assert -#include <stdbool.h> -#include <stdio.h> // snprintf -#include <string.h> // memmove, strcasecmp -#include <sys/socket.h> // socket -#include <unistd.h> // close, fcntl -#include <fcntl.h> // fcntl -#include <sys/types.h> // getpid -#include <unistd.h> // getpid -#ifdef __linux__ -#include <sys/syscall.h> -#define gettid() syscall(SYS_gettid) -#endif /* __linux__ */ -#include <strings.h> - -#define PORT 9695 - -#define BOOLSTR(x) ((x) ? "true" : "false") - -/* - * Internal state associated to a pending request - */ -typedef struct { - int seq; - hc_data_t * data; - /* Information used to process results */ - int size_in; - int (*parse)(const u8 * src, u8 * dst); -} hc_sock_request_t; - -/** - * Messages to the forwarder might be multiplexed thanks to the seqNum fields in - * the header_control_message structure. The forwarder simply answers back the - * original sequence number. We maintain a map of such sequence number to - * outgoing queries so that replied can be demultiplexed and treated - * appropriately. - */ -TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *); -TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf); - -struct hc_sock_light_s { - /* This must be the first element of the struct */ - hc_sock_t vft; - - char * url; - int fd; - - /* Partial receive buffer */ - u8 buf[RECV_BUFLEN]; - size_t roff; /**< Read offset */ - size_t woff; /**< Write offset */ - - /* - * Because received messages are potentially unbounded in size, we might not - * guarantee that we can store a full packet before processing it. We must - * implement a very simple state machine remembering the current parsing - * status in order to partially process the packet. - */ - size_t remaining; - u32 send_id; - - /* Next sequence number to be used for requests */ - int seq; - - /* Request being parsed (NULL if none) */ - hc_sock_request_t * cur_request; - - bool async; - hc_sock_map_t * map; -}; - -typedef struct hc_sock_light_s hc_sock_light_t; - -#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t*)(s) - -hc_sock_request_t * -hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse) -{ - assert(data); - - hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t)); - if (!request) - return NULL; - request->seq = seq; - request->data = data; - request->parse = parse; - return request; -} - -void -hc_sock_light_request_free(hc_sock_request_t * request) -{ - free(request); -} - -/* - * list was working with all seq set to 0, but it seems hicnLightControl uses - * 1, and replies with the same seqno - */ -#define HICN_CTRL_SEND_SEQ_INIT 1 -#define HICN_CTRL_RECV_SEQ_INIT 1 - -#define MAX(x, y) ((x > y) ? x : y) - -/** - * In practise, we want to preserve enough room to store a full packet of - * average expected size (say a header + N payload elements). - */ -#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG) -#define AVG_BUFLEN (sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t)) - -/* - * We should at least have buffer space allowing to store one processable unit - * of data, either the header of the maximum possible payload - */ -#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t)) - -static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; - -/****************************************************************************** - * Message helper types and aliases - ******************************************************************************/ - -#define foreach_hc_command \ - _(add_connection) \ - _(remove_connection) \ - _(list_connections) \ - _(add_listener) \ - _(remove_listener) \ - _(list_listeners) \ - _(add_route) \ - _(remove_route) \ - _(list_routes) \ - _(cache_store) \ - _(cache_serve) \ - /*_(cache_clear) */ \ - _(set_strategy) \ - _(set_wldr) \ - _(add_punting) \ - _(mapme_activator) \ - _(mapme_timing) - -typedef header_control_message hc_msg_header_t; - -typedef union { -#define _(x) x ## _command x; - foreach_hc_command -#undef _ -} hc_msg_payload_t; - - -typedef struct hc_msg_s { - hc_msg_header_t hdr; - hc_msg_payload_t payload; -} hc_msg_t; - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -/** - * \brief Parse a connection URL into a sockaddr - * \param [in] url - URL - * \param [out] sa - Resulting struct sockaddr, expected zero'ed. - * \return 0 if parsing succeeded, a negative error value otherwise. - */ -static int -_hc_sock_light_parse_url(const char * url, struct sockaddr * sa) -{ - /* FIXME URL parsing is currently not implemented */ - assert(!url); - -#ifdef __linux__ - srand(time(NULL) ^ getpid() ^ gettid()); -#else - srand((unsigned int )(time(NULL) ^ getpid())); -#endif /* __linux__ */ - - /* - * A temporary solution is to inspect the sa_family fields of the passed in - * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP - * connection to localhost. - */ - switch (sa->sa_family) { - case AF_UNSPEC: - case AF_INET: - { - struct sockaddr_in * sai = (struct sockaddr_in *)sa; - sai->sin_family = AF_INET; - sai->sin_port = htons(PORT); - sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - break; - } - case AF_INET6: - { - struct sockaddr_in6 * sai6 = (struct sockaddr_in6 *)sa; - sai6->sin6_family = AF_INET6; - sai6->sin6_port = htons(PORT); - sai6->sin6_addr = loopback_addr; - break; - } - default: - return -1; - } - - return 0; -} - -static int -_hc_sock_light_reset(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - s->roff = s->woff = 0; - s->remaining = 0; - return 0; -} - -void -_hc_sock_light_free(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - hc_sock_request_t ** request_array = NULL; - int n = hc_sock_map_get_value_array(s->map, &request_array); - if (n < 0) { - ERROR("Could not retrieve pending request array for freeing up resources"); - } else { - for (unsigned i = 0; i < n; i++) { - hc_sock_request_t * request = request_array[i]; - if (hc_sock_map_remove(s->map, request->seq, NULL) < 0) - ERROR("[hc_sock_light_process] Error removing request from map"); - hc_sock_light_request_free(request); - } - free(request_array); - } - - hc_sock_map_free(s->map); - if (s->url) - free(s->url); - close(s->fd); - free(s); -} - -static int -_hc_sock_light_get_next_seq(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return s->seq++; -} - -static int -_hc_sock_light_set_nonblocking(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0); -} - -static int -_hc_sock_light_get_fd(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return s->fd; -} - -static int -_hc_sock_light_connect(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - struct sockaddr_storage ss; - memset(&ss, 0, sizeof(struct sockaddr_storage)); - - if (_hc_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0) - goto ERR_PARSE; - - size_t size = ss.ss_family == AF_INET - ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6); - if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) //sizeof(struct sockaddr)) < 0) - goto ERR_CONNECT; - - return 0; - -ERR_CONNECT: -ERR_PARSE: - return -1; -} - -static int -_hc_sock_light_send(hc_sock_t * socket, hc_msg_t * msg, size_t msglen, int seq) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int rc; - msg->hdr.seqNum = seq; - rc = (int)send(s->fd, msg, msglen, 0); - if (rc < 0) { - perror("hc_sock_light_send"); - return -1; - } - return 0; -} - -static int -_hc_sock_light_get_available(hc_sock_t * socket, u8 ** buffer, size_t * size) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - *buffer = s->buf + s->woff; - *size = RECV_BUFLEN - s->woff; - - return 0; -} - -static int -_hc_sock_light_recv(hc_sock_t * socket) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int rc; - - /* - * This condition should be ensured to guarantee correct processing of - * messages - */ - assert(RECV_BUFLEN - s->woff > MIN_BUFLEN); - - rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0); - if (rc == 0) { - /* Connection has been closed */ - return 0; - } - if (rc < 0) { - /* - * Let's not return 0 which currently means the socket has been closed - */ - if (errno == EWOULDBLOCK) - return -1; - perror("hc_sock_light_recv"); - return -1; - } - s->woff += rc; - return rc; -} - -/* - * Returns -99 in case of internal error, -1 in case of API command failure - */ -static int -_hc_sock_light_process(hc_sock_t * socket, hc_data_t ** data) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int err = 0; - - /* We must have received at least one byte */ - size_t available = s->woff - s->roff; - - while(available > 0) { - - if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0) - hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff); - - /* We expect a message header */ - if (available < sizeof(hc_msg_header_t)) { - break; - } - - hc_sock_request_t * request = NULL; - if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) { - ERROR("[hc_sock_light_process] Error searching for matching request"); - return -99; - } - if (!request) { - ERROR("[hc_sock_light_process] No request matching received sequence number"); - return -99; - } - - s->remaining = msg->hdr.length; - switch(msg->hdr.messageType) { - case ACK_LIGHT: - assert(s->remaining == 1); - assert(!data); - s->cur_request = request; - break; - case NACK_LIGHT: - assert(s->remaining == 1); - assert(!data); - hc_data_set_error(request->data); - s->cur_request = request; - err = -1; - break; - case RESPONSE_LIGHT: - assert(data); - if (s->remaining == 0) { - hc_data_set_complete(request->data); - *data = request->data; - if (hc_sock_map_remove(s->map, request->seq, NULL) < 0) - ERROR("[hc_sock_light_process] Error removing request from map"); - hc_sock_light_request_free(request); - } else { - /* We only remember it if there is still data to parse */ - s->cur_request = request; - } - break; - default: - ERROR("[hc_sock_light_process] Invalid response received"); - return -99; - } - - available -= sizeof(hc_msg_header_t); - s->roff += sizeof(hc_msg_header_t); - } else { - /* We expect the complete payload, or at least a chunk of it */ - size_t num_chunks = available / s->cur_request->data->in_element_size; - if (num_chunks == 0) - break; - if (num_chunks > s->remaining) - num_chunks = s->remaining; - - if (!s->cur_request->parse) { - /* If we don't need to parse results, then we can directly push - * all of them into the result data structure */ - hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks); - } else { - int rc; - rc = hc_data_ensure_available(s->cur_request->data, num_chunks); - if (rc < 0) { - ERROR("[hc_sock_light_process] Error in hc_data_ensure_available"); - return -99; - } - for (int i = 0; i < num_chunks; i++) { - u8 * dst = hc_data_get_next(s->cur_request->data); - if (!dst) { - ERROR("[hc_sock_light_process] Error in hc_data_get_next"); - return -99; - } - - rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst); - if (rc < 0) { - ERROR("[hc_sock_light_process] Error in parse"); - err = -99; /* FIXME we let the loop complete (?) */ - } - s->cur_request->data->size++; - } - } - - s->remaining -= num_chunks; - available -= num_chunks * s->cur_request->data->in_element_size; - s->roff += num_chunks * s->cur_request->data->in_element_size; - if (s->remaining == 0) { - if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) { - ERROR("[hc_sock_light_process] Error removing request from map"); - return -99; - } - hc_data_set_complete(s->cur_request->data); - if (data) - *data = s->cur_request->data; - hc_sock_light_request_free(s->cur_request); - s->cur_request = NULL; - } - - } - } - - /* Make sure there is enough remaining space in the buffer */ - if (RECV_BUFLEN - s->woff < AVG_BUFLEN) { - /* - * There should be no overlap provided a sufficiently large BUFLEN, but - * who knows. - */ - memmove(s->buf, s->buf + s->roff, s->woff - s->roff); - s->woff -= s->roff; - s->roff = 0; - } - - return err; -} - -static int -_hc_sock_light_callback(hc_sock_t * socket, hc_data_t ** pdata) -{ - hc_data_t * data; - - for (;;) { - int n = _hc_sock_light_recv(socket); - if (n == 0) - goto ERR_EOF; - if (n < 0) { - switch(errno) { - case ECONNRESET: - case ENODEV: - /* Forwarder restarted */ - WARN("Forwarder likely restarted: not (yet) implemented"); - goto ERR; - case EWOULDBLOCK: - //DEBUG("Would block... stop reading from socket"); - goto END; - default: - perror("hc_sock_light_recv"); - goto ERR; - } - } - if (_hc_sock_light_process(socket, &data) < 0) { - goto ERR; - } - } -END: - if (pdata) - *pdata = data; - else - hc_data_free(data); - return 0; - -ERR: - hc_data_free(data); -ERR_EOF: - return -1; -} - -/****************************************************************************** - * Command-specific structures and functions - ******************************************************************************/ - -typedef int (*HC_PARSE)(const u8 *, u8 *); - -typedef struct { - hc_action_t cmd; - command_id cmd_id; - size_t size_in; - size_t size_out; - HC_PARSE parse; -} hc_command_params_t; - -static int -_hc_execute_command(hc_sock_t * socket, hc_msg_t * msg, size_t msg_len, - hc_command_params_t * params, hc_data_t ** pdata, bool async) -{ - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int ret; - if (async) - assert(!pdata); - - /* Sanity check */ - switch(params->cmd) { - case ACTION_CREATE: - assert(params->size_in != 0); /* payload repeated */ - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - case ACTION_DELETE: - assert(params->size_in != 0); /* payload repeated */ - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - case ACTION_LIST: - assert(params->size_in != 0); - assert(params->size_out != 0); - assert(params->parse != NULL); - break; - case ACTION_SET: - assert(params->size_in != 0); - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - default: - return -1; - } - - //hc_sock_light_reset(s); - - /* XXX data will at least store the result (complete) */ - hc_data_t * data = hc_data_create(params->size_in, params->size_out, NULL); - if (!data) { - ERROR("[_hc_execute_command] Could not create data storage"); - goto ERR_DATA; - } - - int seq = _hc_sock_light_get_next_seq(socket); - - /* Create state used to process the request */ - hc_sock_request_t * request = NULL; - request = hc_sock_request_create(seq, data, params->parse); - if (!request) { - ERROR("[_hc_execute_command] Could not create request state"); - goto ERR_REQUEST; - } - - /* Add state to map */ - if (hc_sock_map_add(s->map, seq, request) < 0) { - ERROR("[_hc_execute_command] Error adding request state to map"); - goto ERR_MAP; - } - - if (_hc_sock_light_send(socket, msg, msg_len, seq) < 0) { - ERROR("[_hc_execute_command] Error sending message"); - goto ERR_PROCESS; - } - - if (async) - return 0; - - while(!data->complete) { - /* - * As the socket is non blocking it might happen that we need to read - * several times before success... shall we alternate between blocking - * and non-blocking mode ? - */ - int n = _hc_sock_light_recv(socket); - if (n == 0) - goto ERR_EOF; - if (n < 0) - continue; //break; - int rc = _hc_sock_light_process(socket, pdata); - switch(rc) { - case 0: - break; - case -1: - ret = rc; - break; - case -99: - ERROR("[_hc_execute_command] Error processing socket results"); - goto ERR; - break; - default: - ERROR("[_hc_execute_command] Unexpected return value"); - goto ERR; - } - } - -ERR_EOF: - ret = data->ret; - if (!data->complete) - return -1; - if (!pdata) - hc_data_free(data); - - return ret; - -ERR_PROCESS: -ERR_MAP: - hc_sock_light_request_free(request); -ERR: -ERR_REQUEST: - hc_data_free(data); -ERR_DATA: - return -99; -} - -/*----------------------------------------------------------------------------* - * Listeners - *----------------------------------------------------------------------------*/ - -/* LISTENER CREATE */ - -static int -_hc_listener_create_internal(hc_sock_t * socket, hc_listener_t * listener, bool async) -{ - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[_hc_listener_create] Unexpected truncation of listener string"); - DEBUG("[_hc_listener_create] listener=%s async=%s", listener_s, - BOOLSTR(async)); - - if (!IS_VALID_FAMILY(listener->family)) - return -1; - - if (!IS_VALID_CONNECTION_TYPE(listener->type)) - return -1; - - struct { - header_control_message hdr; - add_listener_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = ADD_LISTENER, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = listener->local_addr, - .port = htons(listener->local_port), - .addressType = (u8)map_to_addr_type[listener->family], - .listenerMode = (u8)map_to_listener_mode[listener->type], - .connectionType = (u8)map_to_connection_type[listener->type], - } - }; - - rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_listener_create] Unexpected truncation of symbolic name string"); - - rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name); - if (rc >= INTERFACE_LEN) - WARN("[_hc_listener_create] Unexpected truncation of interface name string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = ADD_LISTENER, - .size_in = sizeof(add_listener_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_listener_create(hc_sock_t * s, hc_listener_t * listener) -{ - return _hc_listener_create_internal(s, listener, false); -} - -static int -_hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener) -{ - return _hc_listener_create_internal(s, listener, true); -} - -/* LISTENER LIST */ - -static int -_hc_listener_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) -{ - DEBUG("[hc_listener_list] async=%s", BOOLSTR(async)); - - struct { - header_control_message hdr; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = LIST_LISTENERS, - .length = 0, - .seqNum = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = LIST_LISTENERS, - .size_in = sizeof(list_listeners_command), - .size_out = sizeof(hc_listener_t), - .parse = (HC_PARSE)hc_listener_parse, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, pdata, async); -} - -static int -_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_listener_list_internal(s, pdata, false); -} - -static int -_hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_listener_list_internal(s, pdata, true); -} - -/* LISTENER GET */ - -static int -_hc_listener_get(hc_sock_t * socket, hc_listener_t * listener, - hc_listener_t ** listener_found) -{ - hc_data_t * listeners; - hc_listener_t * found; - - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[hc_listener_get] Unexpected truncation of listener string"); - DEBUG("[hc_listener_get] listener=%s", listener_s); - - if (_hc_listener_list(socket, &listeners) < 0) - return -1; - - /* Test */ - if (hc_listener_find(listeners, listener, &found) < 0) { - hc_data_free(listeners); - return -1; - } - - if (found) { - *listener_found = malloc(sizeof(hc_listener_t)); - if (!*listener_found) - return -1; - **listener_found = *found; - } else { - *listener_found = NULL; - } - - hc_data_free(listeners); - - return 0; -} - - -/* LISTENER DELETE */ - -static int -_hc_listener_delete_internal(hc_sock_t * socket, hc_listener_t * listener, bool async) -{ - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[_hc_listener_delete] Unexpected truncation of listener string"); - DEBUG("[_hc_listener_delete] listener=%s async=%s", listener_s, - BOOLSTR(async)); - - struct { - header_control_message hdr; - remove_listener_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = REMOVE_LISTENER, - .length = 1, - .seqNum = 0, - }, - }; - - if (listener->id) { - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string"); - } else if (*listener->name) { - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string"); - } else { - hc_listener_t * listener_found; - if (_hc_listener_get(socket, listener, &listener_found) < 0) - return -1; - if (!listener_found) - return -1; - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string"); - free(listener_found); - } - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = REMOVE_LISTENER, - .size_in = sizeof(remove_listener_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener) -{ - return _hc_listener_delete_internal(s, listener, false); -} - -static int -_hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener) -{ - return _hc_listener_delete_internal(s, listener, true); -} - -/*----------------------------------------------------------------------------* - * CONNECTION - *----------------------------------------------------------------------------*/ - -/* CONNECTION CREATE */ - -static int -_hc_connection_create_internal(hc_sock_t * socket, hc_connection_t * connection, bool async) -{ - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN("[_hc_connection_create] Unexpected truncation of connection string"); - DEBUG("[_hc_connection_create] connection=%s async=%s", connection_s, BOOLSTR(async)); - - if (hc_connection_validate(connection) < 0) - return -1; - - struct { - header_control_message hdr; - add_connection_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = ADD_CONNECTION, - .length = 1, - .seqNum = 0, - }, - .payload = { - .remoteIp = connection->remote_addr, - .localIp = connection->local_addr, - .remotePort = htons(connection->remote_port), - .localPort = htons(connection->local_port), - .ipType = (u8)map_to_addr_type[connection->family], - .connectionType = (u8)map_to_connection_type[connection->type], - .admin_state = connection->admin_state, -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - } - }; - rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_create] Unexpected truncation of symbolic name string"); - //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = ADD_CONNECTION, - .size_in = sizeof(add_connection_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_connection_create(hc_sock_t * s, hc_connection_t * connection) -{ - return _hc_connection_create_internal(s, connection, false); -} - -static int -_hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection) -{ - return _hc_connection_create_internal(s, connection, true); -} - -/* CONNECTION LIST */ - -static int -_hc_connection_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) -{ - DEBUG("[hc_connection_list] async=%s", BOOLSTR(async)); - - struct { - header_control_message hdr; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = LIST_CONNECTIONS, - .length = 0, - .seqNum = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = LIST_CONNECTIONS, - .size_in = sizeof(list_connections_command), - .size_out = sizeof(hc_connection_t), - .parse = (HC_PARSE)hc_connection_parse, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, pdata, async); -} - -static int -_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_connection_list_internal(s, pdata, false); -} - -static int -_hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_connection_list_internal(s, pdata, true); -} - -/* CONNECTION GET */ - -static int -_hc_connection_get(hc_sock_t * socket, hc_connection_t * connection, - hc_connection_t ** connection_found) -{ - hc_data_t * connections; - hc_connection_t * found; - - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN("[hc_connection_get] Unexpected truncation of connection string"); - DEBUG("[hc_connection_get] connection=%s", connection_s); - - if (_hc_connection_list(socket, &connections) < 0) - return -1; - - /* Test */ - if (hc_connection_find(connections, connection, &found) < 0) { - hc_data_free(connections); - return -1; - } - - if (found) { - *connection_found = malloc(sizeof(hc_connection_t)); - if (!*connection_found) - return -1; - **connection_found = *found; - } else { - *connection_found = NULL; - } - - hc_data_free(connections); - - return 0; -} - - -/* CONNECTION DELETE */ - -static int -_hc_connection_delete_internal(hc_sock_t * socket, hc_connection_t * connection, bool async) -{ - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN("[_hc_connection_delete] Unexpected truncation of connection string"); - DEBUG("[_hc_connection_delete] connection=%s async=%s", connection_s, BOOLSTR(async)); - - struct { - header_control_message hdr; - remove_connection_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = REMOVE_CONNECTION, - .length = 1, - .seqNum = 0, - }, - }; - - if (connection->id) { - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string"); - } else if (*connection->name) { - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string"); - } else { - hc_connection_t * connection_found; - if (_hc_connection_get(socket, connection, &connection_found) < 0) - return -1; - if (!connection_found) - return -1; - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string"); - free(connection_found); - } - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = REMOVE_CONNECTION, - .size_in = sizeof(remove_connection_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection) -{ - return _hc_connection_delete_internal(s, connection, false); -} - -static int -_hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection) -{ - return _hc_connection_delete_internal(s, connection, true); -} - -static int -_hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection) -{ - // Not implemented - return -1; -} - -static int -_hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, - hc_connection_t *connection_updated) -{ - // Not implemented - return -1; -} - -/* CONNECTION SET ADMIN STATE */ - -static int -_hc_connection_set_admin_state_internal(hc_sock_t * socket, const char * conn_id_or_name, - face_state_t state, bool async) -{ - int rc; - DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s", - conn_id_or_name, face_state_str[state], BOOLSTR(async)); - struct { - header_control_message hdr; - connection_set_admin_state_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = CONNECTION_SET_ADMIN_STATE, - .length = 1, - .seqNum = 0, - }, - .payload = { - .admin_state = state, - }, - }; - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_set_admin_state] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = CONNECTION_SET_ADMIN_STATE, - .size_in = sizeof(connection_set_admin_state_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, - face_state_t state) -{ - return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, false); -} - -static int -_hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name, - face_state_t state) -{ - return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, true); -} - -#ifdef WITH_POLICY - -static int -_hc_connection_set_priority_internal(hc_sock_t * socket, const char * conn_id_or_name, - uint32_t priority, bool async) -{ - int rc; - DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s", - conn_id_or_name, priority, BOOLSTR(async)); - struct { - header_control_message hdr; - connection_set_priority_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = CONNECTION_SET_PRIORITY, - .length = 1, - .seqNum = 0, - }, - .payload = { - .priority = priority, - }, - }; - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = CONNECTION_SET_PRIORITY, - .size_in = sizeof(connection_set_priority_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, - uint32_t priority) -{ - return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, false); -} - -static int -_hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, - uint32_t priority) -{ - return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, true); -} - -#endif // WITH_POLICY - -static int -_hc_connection_set_tags_internal(hc_sock_t * s, const char * conn_id_or_name, - policy_tags_t tags, bool async) -{ - int rc; - DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s", - conn_id_or_name, tags, BOOLSTR(async)); - struct { - header_control_message hdr; - connection_set_tags_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = CONNECTION_SET_TAGS, - .length = 1, - .seqNum = 0, - }, - .payload = { - .tags = tags, - }, - }; - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_connection_set_tags] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = CONNECTION_SET_TAGS, - .size_in = sizeof(connection_set_tags_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, - policy_tags_t tags) -{ - return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, false); -} - -static int -_hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name, - policy_tags_t tags) -{ - return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, true); -} - -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -/* ROUTE CREATE */ - -static int -_hc_route_create_internal(hc_sock_t * socket, hc_route_t * route, bool async) -{ - char route_s[MAXSZ_HC_ROUTE]; - int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route); - if (rc >= MAXSZ_HC_ROUTE) - WARN("[_hc_route_create] Unexpected truncation of route string"); - if (rc < 0) - WARN("[_hc_route_create] Error building route string"); - else - DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async)); - - if (!IS_VALID_FAMILY(route->family)) - return -1; - - struct { - header_control_message hdr; - add_route_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = ADD_ROUTE, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = route->remote_addr, - .cost = route->cost, - .addressType = (u8)map_to_addr_type[route->family], - .len = route->len, - } - }; - - /* - * The route commands expects the ID (or name that we don't use) as part of - * the symbolicOrConnid attribute. - */ - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_route_create] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = ADD_ROUTE, - .size_in = sizeof(add_route_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_route_create(hc_sock_t * s, hc_route_t * route) -{ - return _hc_route_create_internal(s, route, false); -} - -static int -_hc_route_create_async(hc_sock_t * s, hc_route_t * route) -{ - return _hc_route_create_internal(s, route, true); -} - -/* ROUTE DELETE */ - -static int -_hc_route_delete_internal(hc_sock_t * socket, hc_route_t * route, bool async) -{ - char route_s[MAXSZ_HC_ROUTE]; - int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route); - if (rc >= MAXSZ_HC_ROUTE) - WARN("[_hc_route_delete] Unexpected truncation of route string"); - DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async)); - - if (!IS_VALID_FAMILY(route->family)) - return -1; - - struct { - header_control_message hdr; - remove_route_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = REMOVE_ROUTE, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = route->remote_addr, - .addressType = (u8)map_to_addr_type[route->family], - .len = route->len, - } - }; - - /* - * The route commands expects the ID (or name that we don't use) as part of - * the symbolicOrConnid attribute. - */ - snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id); - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = REMOVE_ROUTE, - .size_in = sizeof(remove_route_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_route_delete(hc_sock_t * s, hc_route_t * route) -{ - return _hc_route_delete_internal(s, route, false); -} - -static int -_hc_route_delete_async(hc_sock_t * s, hc_route_t * route) -{ - return _hc_route_delete_internal(s, route, true); -} - -/* ROUTE LIST */ - -static int -_hc_route_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) -{ - //DEBUG("[hc_route_list] async=%s", BOOLSTR(async)); - - struct { - header_control_message hdr; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = LIST_ROUTES, - .length = 0, - .seqNum = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = LIST_ROUTES, - .size_in = sizeof(list_routes_command), - .size_out = sizeof(hc_route_t), - .parse = (HC_PARSE)hc_route_parse, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, pdata, async); -} - -static int -_hc_route_list(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_route_list_internal(s, pdata, false); -} - -static int -_hc_route_list_async(hc_sock_t * s) -{ - return _hc_route_list_internal(s, NULL, true); -} - -/*----------------------------------------------------------------------------* - * Face - * - * Face support is not directly available in hicn-light, but we can offer such - * an interface through a combination of listeners and connections. The code - * starts with some conversion functions between faces/listeners/connections. - * - * We also need to make sure that there always exist a (single) listener when a - * connection is created, and in the hICN face case, that there is a single - * connection attached to this listener. - * - *----------------------------------------------------------------------------*/ - -/* FACE CREATE */ - -static int -_hc_face_create(hc_sock_t * socket, hc_face_t * face) -{ - hc_listener_t listener; - hc_listener_t * listener_found; - - hc_connection_t connection; - hc_connection_t * connection_found; - - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_create] Unexpected truncation of face string"); - DEBUG("[hc_face_create] face=%s", face_s); - - switch(face->face.type) - { - case FACE_TYPE_HICN: - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - if (hc_face_to_connection(face, &connection, true) < 0) { - ERROR("[hc_face_create] Could not convert face to connection."); - return -1; - } - - /* Ensure we have a corresponding local listener */ - if (hc_connection_to_local_listener(&connection, &listener) < 0) { - ERROR("[hc_face_create] Could not convert face to local listener."); - return -1; - } - - if (_hc_listener_get(socket, &listener, &listener_found) < 0) { - ERROR("[hc_face_create] Could not retrieve listener"); - return -1; - } - - if (!listener_found) { - /* We need to create the listener if it does not exist */ - if (_hc_listener_create(socket, &listener) < 0) { - ERROR("[hc_face_create] Could not create listener."); - free(listener_found); - return -1; - } - } else { - free(listener_found); - } - - /* Create corresponding connection */ - if (_hc_connection_create(socket, &connection) < 0) { - ERROR("[hc_face_create] Could not create connection."); - return -1; - } - - /* - * Once the connection is created, we need to list all connections - * and compare with the current one to find the created face ID. - */ - if (_hc_connection_get(socket, &connection, &connection_found) < 0) { - ERROR("[hc_face_create] Could not retrieve connection"); - return -1; - } - - if (!connection_found) { - ERROR("[hc_face_create] Could not find newly created connection."); - return -1; - } - - face->id = connection_found->id; - free(connection_found); - - break; - - case FACE_TYPE_HICN_LISTENER: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - if (hc_face_to_listener(face, &listener) < 0) { - ERROR("Could not convert face to listener."); - return -1; - } - if (_hc_listener_create(socket, &listener) < 0) { - ERROR("[hc_face_create] Could not create listener."); - return -1; - } - return -1; - break; - default: - ERROR("[hc_face_create] Unknwon face type."); - - return -1; - }; - - return 0; -} - -static int -_hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found) -{ - hc_listener_t listener; - hc_listener_t * listener_found; - - hc_connection_t connection; - hc_connection_t * connection_found; - - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_get] Unexpected truncation of face string"); - DEBUG("[hc_face_get] face=%s", face_s); - - switch(face->face.type) - { - case FACE_TYPE_HICN: - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - if (hc_face_to_connection(face, &connection, false) < 0) - return -1; - if (_hc_connection_get(socket, &connection, &connection_found) < 0) - return -1; - if (!connection_found) { - *face_found = NULL; - return 0; - } - *face_found = malloc(sizeof(hc_face_t)); - hc_connection_to_face(connection_found, *face_found); - free(connection_found); - break; - - case FACE_TYPE_HICN_LISTENER: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - if (hc_face_to_listener(face, &listener) < 0) - return -1; - if (_hc_listener_get(socket, &listener, &listener_found) < 0) - return -1; - if (!listener_found) { - *face_found = NULL; - return 0; - } - *face_found = malloc(sizeof(hc_face_t)); - hc_listener_to_face(listener_found, *face_found); - free(listener_found); - break; - - default: - return -1; - } - - return 0; - -} - -/* FACE DELETE */ - -static int -_hc_face_delete(hc_sock_t * socket, hc_face_t * face) -{ - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_delete] Unexpected truncation of face string"); - DEBUG("[hc_face_delete] face=%s", face_s); - - hc_connection_t connection; - if (hc_face_to_connection(face, &connection, false) < 0) { - ERROR("[hc_face_delete] Could not convert face to connection."); - return -1; - } - - if (_hc_connection_delete(socket, &connection) < 0) { - ERROR("[hc_face_delete] Error removing connection"); - return -1; - } - - /* If this is the last connection attached to the listener, remove it */ - - hc_data_t * connections; - hc_listener_t listener = {{0}}; - - /* - * Ensure we have a corresponding local listener - * NOTE: hc_face_to_listener is not appropriate - */ - if (hc_connection_to_local_listener(&connection, &listener) < 0) { - ERROR("[hc_face_create] Could not convert face to local listener."); - return -1; - } -#if 1 - /* - * The name is generated to prepare listener creation, we need it to be - * empty for deletion. The id should not need to be reset though. - */ - listener.id = 0; - memset(listener.name, 0, sizeof(listener.name)); -#endif - if (_hc_connection_list(socket, &connections) < 0) { - ERROR("[hc_face_delete] Error getting the list of listeners"); - return -1; - } - - bool delete = true; - foreach_connection(c, connections) { - if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) && - (c->local_port == listener.local_port) && - (strcmp(c->interface_name, listener.interface_name) == 0)) { - delete = false; - } - } - - if (delete) { - if (_hc_listener_delete(socket, &listener) < 0) { - ERROR("[hc_face_delete] Error removing listener"); - return -1; - } - } - - hc_data_free(connections); - - return 0; - - -} - -/* FACE LIST */ - -static int -_hc_face_list(hc_sock_t * socket, hc_data_t ** pdata) -{ - hc_data_t * connection_data; - hc_face_t face; - - //DEBUG("[hc_face_list]"); - - if (_hc_connection_list(socket, &connection_data) < 0) { - ERROR("[hc_face_list] Could not list connections."); - return -1; - } - - hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL); - foreach_connection(c, connection_data) { - if (hc_connection_to_face(c, &face) < 0) { - ERROR("[hc_face_list] Could not convert connection to face."); - goto ERR; - } - hc_data_push(face_data, &face); - } - - *pdata = face_data; - hc_data_free(connection_data); - return 0; - -ERR: - hc_data_free(connection_data); - return -1; -} - -static int -_hc_face_list_async(hc_sock_t * socket) -{ - struct { - header_control_message hdr; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = LIST_CONNECTIONS, - .length = 0, - .seqNum = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = LIST_CONNECTIONS, - .size_in = sizeof(list_connections_command), - .size_out = sizeof(hc_face_t), - .parse = (HC_PARSE)hc_connection_parse_to_face, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, true); -} - -static int -_hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, - face_state_t admin_state) -{ - return hc_connection_set_admin_state(s, conn_id_or_name, admin_state); -} - -#ifdef WITH_POLICY -static int -_hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, - uint32_t priority) -{ - return hc_connection_set_priority(s, conn_id_or_name, priority); -} - -static int -_hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, - policy_tags_t tags) -{ - return hc_connection_set_tags(s, conn_id_or_name, tags); -} -#endif // WITH_POLICY - -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ - -static int -_hc_punting_create_internal(hc_sock_t * socket, hc_punting_t * punting, bool async) -{ - int rc; - - if (hc_punting_validate(punting) < 0) - return -1; - - struct { - header_control_message hdr; - add_punting_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = ADD_PUNTING, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = punting->prefix, - .addressType = (u8)map_to_addr_type[punting->family], - .len = punting->prefix_len, - } - }; - rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_punting_create] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = ADD_PUNTING, - .size_in = sizeof(add_punting_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_punting_create(hc_sock_t * s, hc_punting_t * punting) -{ - return _hc_punting_create_internal(s, punting, false); -} - -static int -_hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting) -{ - return _hc_punting_create_internal(s, punting, true); -} - -static int -_hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found) -{ - ERROR("hc_punting_get not (yet) implemented."); - return -1; -} - -static int -_hc_punting_delete(hc_sock_t * s, hc_punting_t * punting) -{ - ERROR("hc_punting_delete not (yet) implemented."); - return -1; -} - -static int -_hc_punting_list(hc_sock_t * s, hc_data_t ** pdata) -{ - ERROR("hc_punting_list not (yet) implemented."); - return -1; -} - - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -static int -_hc_cache_set_store_internal(hc_sock_t * socket, int enabled, bool async) -{ - struct { - header_control_message hdr; - cache_store_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = CACHE_STORE, - .length = 1, - .seqNum = 0, - }, - .payload = { - .activate = enabled, - } - }; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = CACHE_STORE, - .size_in = sizeof(cache_store_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_cache_set_store(hc_sock_t * s, int enabled) -{ - return _hc_cache_set_store_internal(s, enabled, false); -} - -static int -_hc_cache_set_store_async(hc_sock_t * s, int enabled) -{ - return _hc_cache_set_store_internal(s, enabled, true); -} - -static int -_hc_cache_set_serve_internal(hc_sock_t * socket, int enabled, bool async) -{ - struct { - header_control_message hdr; - cache_serve_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = CACHE_SERVE, - .length = 1, - .seqNum = 0, - }, - .payload = { - .activate = enabled, - } - }; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = CACHE_SERVE, - .size_in = sizeof(cache_serve_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_cache_set_serve(hc_sock_t * s, int enabled) -{ - return _hc_cache_set_serve_internal(s, enabled, false); -} - -static int -_hc_cache_set_serve_async(hc_sock_t * s, int enabled) -{ - return _hc_cache_set_serve_internal(s, enabled, true); -} - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -// per prefix -static int -_hc_strategy_set(hc_sock_t * s /* XXX */) -{ - return 0; -} - -/* How to retrieve that from the forwarder ? */ -static const char * strategies[] = { - "random", - "load_balancer", -}; - -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) - -static int -_hc_strategy_list(hc_sock_t * s, hc_data_t ** data) -{ - int rc; - - *data = hc_data_create(0, sizeof(hc_strategy_t), NULL); - - for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) { - hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data); - if (!strategy) - return -1; - rc = snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]); - if (rc >= MAXSZ_HC_STRATEGY) - WARN("[hc_strategy_list] Unexpected truncation of strategy name string"); - (*data)->size++; - } - - return 0; -} - -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -static int -_hc_wldr_set(hc_sock_t * s /* XXX */) -{ - return 0; -} - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -static int -_hc_mapme_set(hc_sock_t * s, int enabled) -{ - return 0; -} - -static int -_hc_mapme_set_discovery(hc_sock_t * s, int enabled) -{ - return 0; -} - -static int -_hc_mapme_set_timescale(hc_sock_t * s, double timescale) -{ - return 0; -} - -static int -_hc_mapme_set_retx(hc_sock_t * s, double timescale) -{ - return 0; -} - -/*----------------------------------------------------------------------------* - * Policy - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -/* POLICY CREATE */ - -static int -_hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) -{ - if (!IS_VALID_FAMILY(policy->family)) - return -1; - - struct { - header_control_message hdr; - add_policy_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = ADD_POLICY, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = policy->remote_addr, - .addressType = (u8)map_to_addr_type[policy->family], - .len = policy->len, - .policy = policy->policy, - } - }; - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = ADD_POLICY, - .size_in = sizeof(add_policy_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_policy_create(hc_sock_t * s, hc_policy_t * policy) -{ - return _hc_policy_create_internal(s, policy, false); -} - -static int -_hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy) -{ - return _hc_policy_create_internal(s, policy, true); -} - -/* POLICY DELETE */ - -static int -_hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) -{ - if (!IS_VALID_FAMILY(policy->family)) - return -1; - - struct { - header_control_message hdr; - remove_policy_command payload; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = REMOVE_POLICY, - .length = 1, - .seqNum = 0, - }, - .payload = { - .address = policy->remote_addr, - .addressType = (u8)map_to_addr_type[policy->family], - .len = policy->len, - } - }; - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = REMOVE_POLICY, - .size_in = sizeof(remove_policy_command), - .size_out = 0, - .parse = NULL, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); -} - -static int -_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy) -{ - return _hc_policy_delete_internal(s, policy, false); -} - -static int -_hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy) -{ - return _hc_policy_delete_internal(s, policy, true); -} - -/* POLICY LIST */ - -static int -_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) -{ - struct { - header_control_message hdr; - } msg = { - .hdr = { - .messageType = REQUEST_LIGHT, - .commandID = LIST_POLICIES, - .length = 0, - .seqNum = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = LIST_POLICIES, - .size_in = sizeof(list_policies_command), - .size_out = sizeof(hc_policy_t), - .parse = (HC_PARSE)hc_policy_parse, - }; - - return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), ¶ms, pdata, async); -} - -static int -_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_policy_list_internal(s, pdata, false); -} - -static int -_hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata) -{ - return _hc_policy_list_internal(s, pdata, true); -} - -#endif /* WITH_POLICY */ - -static hc_sock_t hc_sock_light_interface = (hc_sock_t) { - .hc_sock_get_next_seq = _hc_sock_light_get_next_seq, - .hc_sock_set_nonblocking = _hc_sock_light_set_nonblocking, - .hc_sock_get_fd = _hc_sock_light_get_fd, - .hc_sock_connect = _hc_sock_light_connect, - .hc_sock_get_available = _hc_sock_light_get_available, - .hc_sock_send = _hc_sock_light_send, - .hc_sock_recv = _hc_sock_light_recv, - .hc_sock_process = _hc_sock_light_process, - .hc_sock_callback = _hc_sock_light_callback, - .hc_sock_reset = _hc_sock_light_reset, - .hc_sock_free = _hc_sock_light_free, - .hc_listener_create = _hc_listener_create, - .hc_listener_create_async = _hc_listener_create_async, - .hc_listener_get = _hc_listener_get, - .hc_listener_delete = _hc_listener_delete, - .hc_listener_delete_async = _hc_listener_delete_async, - .hc_listener_list = _hc_listener_list, - .hc_listener_list_async = _hc_listener_list_async, - .hc_connection_create = _hc_connection_create, - .hc_connection_create_async = _hc_connection_create_async, - .hc_connection_get = _hc_connection_get, - .hc_connection_update_by_id = _hc_connection_update_by_id, - .hc_connection_update = _hc_connection_update, - .hc_connection_delete = _hc_connection_delete, - .hc_connection_delete_async = _hc_connection_delete_async, - .hc_connection_list = _hc_connection_list, - .hc_connection_list_async = _hc_connection_list_async, - .hc_connection_set_admin_state = _hc_connection_set_admin_state, - .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async, - -#ifdef WITH_POLICY - .hc_connection_set_priority = _hc_connection_set_priority, - .hc_connection_set_priority_async = _hc_connection_set_priority_async, - .hc_connection_set_tags = _hc_connection_set_tags, - .hc_connection_set_tags_async = _hc_connection_set_tags_async, -#endif // WITH_POLICY - - .hc_face_create = _hc_face_create, - .hc_face_get = _hc_face_get, - .hc_face_delete = _hc_face_delete, - .hc_face_list = _hc_face_list, - .hc_face_list_async = _hc_face_list_async, - .hc_face_set_admin_state = _hc_face_set_admin_state, - -#ifdef WITH_POLICY - .hc_face_set_priority = _hc_face_set_priority, - .hc_face_set_tags = _hc_face_set_tags, -#endif // WITH_POLICY - - .hc_route_create = _hc_route_create, - .hc_route_create_async = _hc_route_create_async, - .hc_route_delete = _hc_route_delete, - .hc_route_delete_async = _hc_route_delete_async, - .hc_route_list = _hc_route_list, - .hc_route_list_async = _hc_route_list_async, - - .hc_punting_create = _hc_punting_create, - .hc_punting_create_async = _hc_punting_create_async, - .hc_punting_get = _hc_punting_get, - .hc_punting_delete = _hc_punting_delete, - .hc_punting_list = _hc_punting_list, - - .hc_cache_set_store = _hc_cache_set_store, - .hc_cache_set_store_async = _hc_cache_set_store_async, - .hc_cache_set_serve = _hc_cache_set_serve, - .hc_cache_set_serve_async = _hc_cache_set_serve_async, - - .hc_strategy_list = _hc_strategy_list, - .hc_strategy_set = _hc_strategy_set, - .hc_wldr_set = _hc_wldr_set, - - .hc_mapme_set = _hc_mapme_set, - .hc_mapme_set_discovery = _hc_mapme_set_discovery, - .hc_mapme_set_timescale = _hc_mapme_set_timescale, - .hc_mapme_set_retx = _hc_mapme_set_retx, - -#ifdef WITH_POLICY - .hc_policy_create = _hc_policy_create, - .hc_policy_create_async = _hc_policy_create_async, - .hc_policy_delete = _hc_policy_delete, - .hc_policy_delete_async = _hc_policy_delete_async, - .hc_policy_list = _hc_policy_list, - .hc_policy_list_async = _hc_policy_list_async -#endif // WITH_POLICY -}; - -// Public contructors - -hc_sock_t * -_hc_sock_create_url(const char * url) -{ - hc_sock_light_t * s = malloc(sizeof(hc_sock_light_t)); - if (!s) - goto ERR_MALLOC; - - s->vft = hc_sock_light_interface; - s->url = url ? strdup(url) : NULL; - - s->fd = socket(AF_INET, SOCK_STREAM, 0); - if (s->fd < 0) - goto ERR_SOCKET; - - if (_hc_sock_light_reset((hc_sock_t*)s) < 0) - goto ERR_RESET; - - s->seq = 0; - s->cur_request = NULL; - - s->map = hc_sock_map_create(); - if (!s->map) - goto ERR_MAP; - - return (hc_sock_t*)(s); - - //hc_sock_light_map_free(s->map); -ERR_MAP: -ERR_RESET: - if (s->url) - free(s->url); - close(s->fd); -ERR_SOCKET: - free(s); -ERR_MALLOC: - return NULL; -} - -hc_sock_t * -_hc_sock_create(void) -{ - return _hc_sock_create_url(NULL); -} diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin.c b/ctrl/libhicnctrl/src/modules/hicn_plugin.c new file mode 100644 index 000000000..b8606daf7 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2021 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 api.c + * \brief Implementation of hICN control library API + */ + +#include <assert.h> // assert +#include <fcntl.h> // fcntl +#include <math.h> // log2 +#include <stdbool.h> +#include <stdio.h> // snprintf +#include <string.h> // memmove, strcasecmp +#include <sys/socket.h> // socket +#include <unistd.h> // close, fcntl + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/socket.h> + +#include <vapi/vapi_safe.h> +#include <vppinfra/clib.h> +#include <vpp_plugins/hicn/error.h> + +#include "../socket_private.h" + +#include "hicn_plugin/base.h" // hc_sock_vpp_data_t +#include "hicn_plugin/listener.h" +#include "hicn_plugin/route.h" +#include "hicn_plugin/strategy.h" + +/****************************************************************************** + * Message helper types and aliases + ******************************************************************************/ + +#if 0 + +#define foreach_hc_command \ + _(hicn_api_node_params_set) \ + _(hicn_api_node_params_set_reply) \ + _(hicn_api_node_params_get_reply) \ + _(hicn_api_node_stats_get_reply) \ + _(hicn_api_face_get) \ + _(hicn_api_faces_details) \ + _(hicn_api_face_stats_details) \ + _(hicn_api_face_get_reply) \ + _(hicn_api_route_get) \ + _(hicn_api_route_get_reply) \ + _(hicn_api_routes_details) \ + _(hicn_api_strategies_get_reply) \ + _(hicn_api_strategy_get) \ + _(hicn_api_strategy_get_reply) + + +typedef vapi_type_msg_header2_t hc_msg_header_t; + +typedef union { +#define _(a) vapi_payload_##a a; + foreach_hc_command +#undef _ +} hc_msg_payload_t; + +typedef struct __attribute__((__packed__)) { + hc_msg_header_t hdr; + hc_msg_payload_t payload; +} hc_hicnp_t; + +typedef void (*NTOH)(void *msg); + +typedef struct __attribute__((__packed__)) { + hc_data_t *data; + uint32_t curr_msg; +} callback_ctx_t; + +typedef struct __attribute__((__packed__)) { + hc_hicnp_t *msg; + vapi_cb_t callback; + callback_ctx_t *callback_ctx; + NTOH ntoh; +} hc_msg_s; + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +static void vpp_free(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + if (s->url) free(s->url); + free(s); + + vapi_disconnect_safe(); +} + +static int vpp_get_next_seq(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + return vapi_gen_req_context(s->g_vapi_ctx_instance); +} + +static int vpp_set_nonblocking(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + return 0; +} + +static int vpp_callback(hc_sock_t *socket, hc_data_t **pdata) { + // NOT IMPLEMENTED + return -1; +} + +static int vpp_reset(hc_sock_t *socket) { + // NOT IMPLEMENTED + return -1; +} +#endif + +/*----------------------------------------------------------------------------* + * Listeners + *----------------------------------------------------------------------------*/ + +/****************************************************************************** + * Module functions + ******************************************************************************/ + +hc_sock_vpp_data_t *hc_sock_vpp_data_create(const char *url) { + hc_sock_vpp_data_t *s = malloc(sizeof(hc_sock_vpp_data_t)); + if (!s) goto ERR_MALLOC; + + s->roff = s->woff = 0; + s->url = url ? strdup(url) : NULL; + + return s; + +ERR_MALLOC: + return NULL; +} + +void hc_sock_vpp_data_free(hc_sock_vpp_data_t *s) { + vapi_disconnect_safe(); + + if (s->url) free(s->url); + free(s); +} + +static int vpp_connect(hc_sock_t *sock) { + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + vapi_error_e rv = + vapi_connect_safe(&s->g_vapi_ctx_instance, hc_sock_is_async(sock)); + if (rv != VAPI_OK) goto ERR_CONNECT; + + return 0; + +ERR_CONNECT: + ERROR("[hc_sock_connect] connection failed"); + return -1; +} + +static ssize_t vpp_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + assert(!buffer); + + // XXX all the beginning is generic and could be shared across multiple + // modules + + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + _ASSERT(!hc_request_get_data(current_request)); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(hc_request_get_data(current_request) == NULL); + hc_data_t *data = hc_data_create(object_type); + if (!data) { + ERROR("[vpp_prepare] Could not create data storage"); + goto ERR; + } + hc_request_set_data(current_request, data); + + hc_module_object_ops_t *vft = &sock->ops.object_vft[object_type]; + if (!vft) goto ERR; + hc_execute_t execute = vft->execute[action]; + if (!execute) goto ERR; + int rc = execute(sock, object, data); + if (rc < 0) goto ERR; + + /* The result is fully contained in data */ + (void)rc; + + hc_request_set_complete(request); + return 0; + +ERR: + hc_data_set_error(data); + hc_request_set_complete(request); + return 0; +} + +static hc_sock_ops_t hc_sock_vpp = (hc_sock_ops_t){ + .create_data = (void *(*)(const char *))hc_sock_vpp_data_create, + .free_data = (void (*)(void *))hc_sock_vpp_data_free, + .get_fd = NULL, // not fd based + .get_recv_buffer = NULL, // no async support + .connect = vpp_connect, + .prepare = vpp_prepare, + .send = NULL, + .recv = NULL, + .process = NULL, +}; + +ssize_t vpp_command_serialize(hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + return hc_sock_vpp.object_vft[object_type].serialize[action](object, msg); +} + +// Public constructor + +int hc_sock_initialize_module(hc_sock_t *s) { + s->ops = hc_sock_vpp; + // XXX shall we memset the VFT ? + /* LISTENER: CREATE, GET, DELETE not implemented, LIST ok */ + s->ops.object_vft[OBJECT_TYPE_LISTENER] = vpp_listener_module_ops; + /* CONNECTION : CREATE, GET, UPDATE, DELETE, LIST, SET_* not + implemented */ + s->ops.object_vft[OBJECT_TYPE_CONNECTION] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_MAPME] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_ROUTE] = vpp_route_module_ops; + s->ops.object_vft[OBJECT_TYPE_STRATEGY] = vpp_strategy_module_ops; + s->ops.object_vft[OBJECT_TYPE_SUBSCRIPTION] = HC_MODULE_OBJECT_OPS_EMPTY; + return 0; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h new file mode 100644 index 000000000..05565e938 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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 modules/hicn_plugin/base.h + * \brief Base structures for hICN plugin module + */ + +#include <vapi/vapi_safe.h> +#include "../../module.h" +#include "../../socket_private.h" + +typedef struct { + vapi_ctx_t g_vapi_ctx_instance; + char *url; + + size_t roff; /**< Read offset */ + size_t woff; /**< Write offset */ + u32 buffer[RECV_BUFLEN]; + /* Next sequence number to be used for requests */ + int seq; + + bool async; +} hc_sock_vpp_data_t; diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c new file mode 100644 index 000000000..4d9792256 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 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 modules/hicn_plugin/listener.c + * \brief Implementation of listener object VFT for hicn_plugin. + */ + +#include <hicn/util/vector.h> + +#include "base.h" +#include "listener.h" + +struct listener_data_s { + hc_listener_t listener; + hc_data_t *data; +}; + +/** + * This is a callback used to append in callback_ctx which is a hc_data_t + * designed to hold hc_listener_t, a list of listener, each corresponding to an + * IP address (v4 then v6) of the interfaces, and thus build a list of hICN + * listeners. + */ +static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, void *callback_ctx, + vapi_error_e rv, bool is_last, + vapi_payload_ip_address_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + if (reply && is_last) printf("COUCOU\n"); + if (is_last) return 0; + + struct listener_data_s *ld = (struct listener_data_s *)callback_ctx; + + if (reply->prefix.address.af == ADDRESS_IP4) { + memcpy(&(ld->listener.local_addr.v4), reply->prefix.address.un.ip4, + IPV4_ADDR_LEN); + ld->listener.family = AF_INET; + } else { + memcpy(&(ld->listener.local_addr.v6), reply->prefix.address.un.ip6, + IPV6_ADDR_LEN); + ld->listener.family = AF_INET6; + } + ld->listener.local_port = 0; + + ld->listener.id = reply->sw_if_index; + hc_data_t *data = ld->data; + hc_listener_t *listener = &ld->listener; + hc_data_push(data, listener); + + return rv; +} + +/* LISTENER LIST */ + +typedef struct { + u32 swif; + char interface_name[INTERFACE_LEN]; +} hc_vapi_interface_t; + +/* + * A pointer to hc_data_t is passed in the callback context + * Objective is to store a vector of hc_vapi_interface_t inside + */ +static vapi_error_e on_listener_list_complete_cb( + struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_sw_interface_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (is_last) return 0; + + hc_vapi_interface_t **vpp_interfaces_vec = + (hc_vapi_interface_t **)callback_ctx; + + hc_vapi_interface_t interface = {.swif = reply->sw_if_index}; + // XXX bug + memcpy(interface.interface_name, reply->interface_name, INTERFACE_LEN); + + vector_push(*vpp_interfaces_vec, interface); + + return rv; +} + +static int _vpp_listener_list(hc_sock_t *sock, hc_data_t *data) { + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + int retval = -1; // VAPI_OK; + + hc_vapi_interface_t *vpp_interfaces_vec = NULL; + vector_init(vpp_interfaces_vec, 0, 0); + + vapi_lock(); + + vapi_msg_sw_interface_dump *msg = + vapi_alloc_sw_interface_dump(s->g_vapi_ctx_instance); + if (!msg) { + retval = VAPI_ENOMEM; + goto ERR_MSG; + } + msg->payload.sw_if_index = ~0; + msg->payload.name_filter_valid = 0; + + /* Retrieve the list of interfaces in vpp_interfaces_vec */ + int ret = + vapi_sw_interface_dump(s->g_vapi_ctx_instance, msg, + on_listener_list_complete_cb, &vpp_interfaces_vec); + + if (ret != VAPI_OK) goto ERR_LIST_INTERFACES; + + /* Query the forwarder for each interface */ + // stored in data->buffer == hc_vapi_interface_t* [] + // 2 calls for each interface + // + // This function is called twice for each interface, to get resp. the v4 and + // v6 IP addresses associated to it: + // ip_address_dump(sw_if_index, is_ipv6) + // + // Function call : + // vapi_msg_XXX *msg = vapi_alloc_XXX(s->g_vapi_ctx_instance); + // msg->payload.ATTR = VALUE; + // [...] + // int ret = vapi_XXX((s->g_vapi_ctx_instance, msg, CALLBACK, USER_DATA); + // + // CALLBACK = process_ip_info + // USER_DATA = data2 + // + // We can assume the callbacks are executed before the function returns, and + // that there is no async code. + // + int rc; + + hc_vapi_interface_t *interface; + vapi_msg_ip_address_dump *msg2; + + struct listener_data_s ld; + vector_foreach(vpp_interfaces_vec, interface, { + memset(&ld, 0, sizeof(struct listener_data_s)); + ld.listener.type = FACE_TYPE_HICN; + rc = snprintf(ld.listener.interface_name, INTERFACE_LEN, "%s", + interface->interface_name); + if (rc < 0 || rc >= INTERFACE_LEN) goto ERR_FOREACH; + + ld.data = data; + + for (unsigned i = 0; i < 2; i++) { + msg2 = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); + msg2->payload.sw_if_index = interface->swif; + msg2->payload.is_ipv6 = i; + retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, + process_ip_info, &ld); + if (ret != VAPI_OK) goto ERR_GET_IP; + } + }); + retval = 0; +ERR_GET_IP: +ERR_FOREACH: + vector_free(vpp_interfaces_vec); +ERR_LIST_INTERFACES: +ERR_MSG: + vapi_unlock(); + return retval; +} + +#define vpp_listener_create NULL +#define vpp_listener_delete NULL + +static int vpp_listener_list(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + assert(!object || hc_object_is_empty(object)); + return _vpp_listener_list(sock, data); +} + +static int vpp_listener_set(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + return -1; +} + +DECLARE_VPP_MODULE_OBJECT_OPS(vpp, listener); diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.h new file mode 100644 index 000000000..f75c58db6 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 modules/hicn_plugin/listener.h + * \brief listener object VFT for hicn_plugin. + */ + +#ifndef HICNCTRL_MODULE_VPP_LISTENER_H +#define HICNCTRL_MODULE_VPP_LISTENER_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(vpp, listener); + +#endif /* HICNCTRL_MODULE_VPP_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c new file mode 100644 index 000000000..4c9f8a638 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2021 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 modules/hicn_plugin/route.c + * \brief Implementation of route object VFT for hicn_plugin. + */ + +#include "base.h" +#include "route.h" + +static vapi_error_e create_udp_tunnel_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (reply->retval != VAPI_OK) return reply->retval; + + u32 *uei = (u32 *)callback_ctx; + *uei = reply->uei; + + return reply->retval; +} + +static vapi_error_e parse_route_create( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_ip_route_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + return reply->retval; +} + +static vapi_error_e hicn_enable_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_enable_disable_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + face_id_t *faceid = (face_id_t *)callback_ctx; + + if (reply->nfaces) { + *faceid = reply->faceids[0]; + } + + return reply->retval; +} + +static int _vpp_route_create(hc_sock_t *sock, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return -1; + + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + int ret = -1; + vapi_lock(); + + vapi_msg_ip_route_add_del *msg = + vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); + + msg->payload.is_add = 1; + if (route->family == AF_INET) { + memcpy(&msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, + 4); + msg->payload.route.prefix.address.af = ADDRESS_IP4; + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, + 16); + msg->payload.route.prefix.address.af = ADDRESS_IP6; + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg->payload.route.prefix.len = route->len; + + msg->payload.route.paths[0].sw_if_index = ~0; + msg->payload.route.paths[0].table_id = 0; + + hc_face_t *face = &(route->face); + + face->netdevice.index = ~0; + face->id = INVALID_FACE_ID; + + switch (face->type) { + case FACE_TYPE_HICN: { + if (hicn_ip_address_is_v4(&(face->remote_addr))) { + memcpy(&(msg->payload.route.paths[0].nh.address.ip4), + &face->remote_addr.v4, sizeof(ip4_address_t)); + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&(msg->payload.route.paths[0].nh.address.ip6), + &face->remote_addr.v6, sizeof(ip6_address_t)); + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; + msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + + break; + } + case FACE_TYPE_UDP: { + vapi_msg_hicn_api_udp_tunnel_add_del *msg2 = NULL; + u32 uei = ~0; + + if (hicn_ip_address_is_v4(&(face->remote_addr)) && + hicn_ip_address_is_v4(&(face->local_addr))) { + msg2 = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); + if (msg2 == NULL) { + ret = -1; + goto done; + } + memcpy(msg2->payload.src_addr.un.ip4, &face->local_addr.v4, + sizeof(ip4_address_t)); + msg2->payload.src_addr.af = ADDRESS_IP4; + + memcpy(msg2->payload.dst_addr.un.ip4, &face->remote_addr.v4, + sizeof(ip4_address_t)); + msg2->payload.dst_addr.af = ADDRESS_IP4; + + } else if (!hicn_ip_address_is_v4(&(route->face.remote_addr)) && + !hicn_ip_address_is_v4(&(route->face.local_addr))) { + msg2 = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); + if (msg2 == NULL) { + ret = -1; + goto done; + } + memcpy(msg2->payload.src_addr.un.ip6, &face->local_addr.v6, + sizeof(ip6_address_t)); + msg2->payload.src_addr.af = ADDRESS_IP6; + + memcpy(msg2->payload.dst_addr.un.ip6, &face->remote_addr.v6, + sizeof(ip6_address_t)); + msg2->payload.dst_addr.af = ADDRESS_IP6; + } else { + // NOT IMPLEMENTED + ret = -1; + goto done; + } + + msg2->payload.src_port = face->local_port; + msg2->payload.dst_port = face->remote_port; + msg2->payload.is_add = 1; + + int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg2, + create_udp_tunnel_cb, &uei); + + if (ret) { + ERROR("Error in vapi_hicn_api_udp_tunnel_add_del"); + vapi_msg_free(s->g_vapi_ctx_instance, msg); + goto done; + } + + msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; + msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + msg->payload.route.paths[0].nh.obj_id = uei; + + face->netdevice.index = uei; + + break; + } + default: + ret = -1; + goto done; + } + + ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, msg, parse_route_create, + NULL); + + if (ret) { + ERROR("Error in vapi_ip_route_add_del"); + goto done; + } + + vapi_msg_hicn_api_enable_disable *msg3 = + vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); + + if (route->family == AF_INET) { + memcpy(&msg3->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); + msg3->payload.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg3->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); + msg3->payload.prefix.address.af = ADDRESS_IP6; + } + + msg3->payload.prefix.len = route->len; + msg3->payload.enable_disable = 1; + + ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg3, + hicn_enable_cb, &face->id); + + if (ret) { + ERROR("Error in vapi_hicn_api_enable_disable"); + } + +done: + vapi_unlock(); + return ret; +} + +static vapi_error_e hicn_disable_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_enable_disable_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + return reply->retval; +} + +static vapi_error_e parse_route_delete( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_ip_route_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + return reply->retval; +} + +static int _vpp_route_delete(hc_sock_t *sock, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return -1; + + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + vapi_lock(); + + vapi_msg_hicn_api_enable_disable *msg = + vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); + + if (route->family == AF_INET) { + memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); + msg->payload.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); + msg->payload.prefix.address.af = ADDRESS_IP6; + } + + msg->payload.prefix.len = route->len; + msg->payload.enable_disable = 0; + + vapi_error_e ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, + hicn_disable_cb, NULL); + + if (ret) { + ERROR("Error in vapi_hicn_api_enable_disable in route delete"); + goto done; + } + + vapi_msg_ip_route_add_del *msg2 = + vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); + + msg2->payload.is_add = 0; + if (route->family == AF_INET) { + memcpy(&msg2->payload.route.prefix.address.un.ip4[0], + &route->remote_addr.v4, 4); + msg2->payload.route.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg2->payload.route.prefix.address.un.ip6[0], + &route->remote_addr.v6, 16); + msg2->payload.route.prefix.address.af = ADDRESS_IP6; + } + + msg2->payload.route.prefix.len = route->len; + + msg2->payload.route.paths[0].sw_if_index = ~0; + msg2->payload.route.paths[0].table_id = 0; + + hc_face_t *face = &(route->face); + switch (face->type) { + case FACE_TYPE_HICN: { + if (hicn_ip_address_is_v4(&(face->remote_addr))) { + memcpy(&(msg2->payload.route.paths[0].nh.address.ip4), + &face->remote_addr.v4, sizeof(ip4_address_t)); + msg2->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&(msg2->payload.route.paths[0].nh.address.ip6), + &face->remote_addr.v6, sizeof(ip6_address_t)); + msg2->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg2->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; + msg2->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + + break; + } + case FACE_TYPE_UDP: { + msg2->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; + msg2->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + msg2->payload.route.paths[0].nh.obj_id = face->netdevice.index; + break; + } + default: + return -1; + } + + ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, msg2, parse_route_delete, + NULL); + + if (ret) { + ERROR("Error in vapi_ip_route_add_del in route delete"); + goto done; + } + +done: + + vapi_unlock(); + return ret; +} + +/* ROUTE LIST */ + +static vapi_error_e parse_udp_encap_list( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_udp_encap_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + hc_face_t *face = (hc_face_t *)callback_ctx; + + if (face->netdevice.index == reply->udp_encap.id) { + switch (reply->udp_encap.src_ip.af) { + case ADDRESS_IP4: { + memcpy(&face->local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), + sizeof(ip4_address_t)); + memcpy(&face->remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), + sizeof(ip4_address_t)); + break; + } + case ADDRESS_IP6: { + memcpy(&face->local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), + sizeof(ip6_address_t)); + memcpy(&face->remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), + sizeof(ip6_address_t)); + break; + } + default: + break; + } + + face->local_port = reply->udp_encap.src_port; + face->remote_port = reply->udp_encap.dst_port; + } + return rv; +} + +static int _fill_face_with_info(hc_face_t *face, vapi_type_fib_path *path) { + switch (path->type) { + case FIB_API_PATH_FLAG_NONE: { + face->type = FACE_TYPE_HICN; + switch (path->proto) { + case FIB_API_PATH_NH_PROTO_IP4: + memcpy(&face->remote_addr.v4, &(path->nh.address.ip4), + sizeof(ipv4_address_t)); + break; + case FIB_API_PATH_NH_PROTO_IP6: + memcpy(&face->remote_addr.v6, &(path->nh.address.ip6), + sizeof(ipv6_address_t)); + break; + default: + break; + } + face->netdevice.index = path->sw_if_index; + } break; + case FIB_API_PATH_TYPE_UDP_ENCAP: { + face->type = FACE_TYPE_UDP; + face->netdevice.index = clib_net_to_host_u32(path->nh.obj_id); + // Let's make the compiler happy + (void)parse_udp_encap_list; + // vapi_msg_udp_encap_dump *msg; + // msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance); + // vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, + // face); + } break; + default: + return -1; + } + return 0; +} + +static vapi_error_e parse_route_list(vapi_ctx_t ctx, void *callback_ctx, + vapi_error_e rv, bool is_last, + vapi_payload_ip_route_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + // XXX DEBUG XXX + if (reply && is_last) printf("COUCOU\n"); + + if (is_last) return 0; + + hc_data_t *data = (hc_data_t *)callback_ctx; + + /* + * Implementation: + * A route has n paths... we iterate for each path and search for a + * corresponding face in the hc_data_t result struct... and we fill the face + * info with the route path. + * + * TODO + * - comment on paths + * - explain the jump to END, this was previously implemented with a + * boolean flags skipping all remaining tests in the function... + */ + for (int j = 0; j < reply->route.n_paths; j++) { + hc_data_foreach(data, obj, { + hc_route_t *route = &obj->route; + + if (hicn_ip_address_is_v4(&(route->remote_addr)) && + memcmp(route->remote_addr.v4.as_u8, + reply->route.prefix.address.un.ip4, + sizeof(ipv4_address_t)) == 0 && + route->len == reply->route.prefix.len && route->face_id == ~0) { + _fill_face_with_info(&(route->face), &reply->route.paths[j]); + goto END; + + } else if (memcmp(route->remote_addr.v6.as_u8, + reply->route.prefix.address.un.ip6, + sizeof(ipv6_address_t)) == 0 && + route->len == reply->route.prefix.len && + route->face_id == ~0) { + _fill_face_with_info(&(route->face), &reply->route.paths[j]); + goto END; + } + }); + } + +END: + return rv; +} + +/** + * Populates the hc_data_t structure passed as the context with... + */ +static vapi_error_e parse_hicn_route_list( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_routes_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (reply && is_last) printf("COUCOU\n"); + if (is_last) return 0; + + hc_data_t *data = (hc_data_t *)callback_ctx; + + for (int i = 0; i < reply->nfaces; i++) { + hc_route_t route; + memset(&route, 0, sizeof(hc_route_t)); + + /* + * We set the face_id to ~0 to act as a marker in parse_route_list that + * the route is missing face information. + */ + route.face_id = ~0; + route.cost = 1; + route.len = reply->prefix.len; + if (reply->prefix.address.af == ADDRESS_IP6) { + memcpy(route.remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16); + route.family = AF_INET6; + } else { + memcpy(route.remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4); + route.family = AF_INET; + } + + hc_data_push(data, &route); + } + + return rv; +} + +/* + * hicn_api_routes_dump + * ip_route_dump + * + * @returns hc_data_t<hc_route_t> + */ +static int _vpp_route_list(hc_sock_t *sock, hc_data_t *data) { + int ret; + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + vapi_lock(); + + /* Start by retrieving hicn routes (we have no face information at this + * stage)... */ + vapi_msg_hicn_api_routes_dump *msg; + msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance); + if (!msg) goto ERR_MSG; + + ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, + parse_hicn_route_list, data); + if (ret != VAPI_OK) goto ERR_API; + + /* + * ... an complement them using IP (v4 and v6 routes). Similar routes will + * be aggregated, based on IP prefix, in parse_*_route_list. + */ + vapi_msg_ip_route_dump *msg2; + for (unsigned i = 0; i < 2; i++) { + msg2 = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); + if (!msg2) goto ERR_MSG; + + msg2->payload.table.table_id = 0; + msg2->payload.table.is_ip6 = i; + + ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, msg2, parse_route_list, + data); + if (ret != VAPI_OK) goto ERR_API; + } + + goto END; + +ERR_MSG: + ret = VAPI_ENOMEM; + goto END; + +ERR_API: +END: + vapi_unlock(); + return ret; +} + +static int vpp_route_create(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + int rc = _vpp_route_create(sock, &object->route); + if (rc < 0) + hc_data_set_complete(data); + else + hc_data_set_error(data); + return rc; +} + +static int vpp_route_delete(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + int rc = _vpp_route_delete(sock, &object->route); + if (rc < 0) + hc_data_set_complete(data); + else + hc_data_set_error(data); + return rc; +} + +static int vpp_route_list(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + assert(!object || hc_object_is_empty(object)); + return _vpp_route_list(sock, data); +} + +static int vpp_route_set(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + return -1; +} + +DECLARE_VPP_MODULE_OBJECT_OPS(vpp, route); diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h new file mode 100644 index 000000000..652d3e89a --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 modules/hicn_plugin/route.h + * \brief route object VFT for hicn_plugin. + */ + +#ifndef HICNCTRL_MODULE_VPP_ROUTE_H +#define HICNCTRL_MODULE_VPP_ROUTE_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(vpp, route); + +#endif /* HICNCTRL_MODULE_VPP_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.c new file mode 100644 index 000000000..17d29a1d7 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 "base.h" +#include "strategy.h" + +#include <vpp_plugins/hicn/hicn_enums.h> + +static int _ip_prefix_encode(const hicn_ip_address_t *address, + int prefix_length, int family, + vapi_type_prefix *out) { + out->len = prefix_length; + int ret = 0; + + switch (family) { + case AF_INET: + memcpy(&out->address.un.ip4[0], &address->v4, 4); + out->address.af = ADDRESS_IP4; + break; + case AF_INET6: + memcpy(&out->address.un.ip6[0], &address->v6, 16); + out->address.af = ADDRESS_IP6; + break; + default: + // This should never happen + ret = -1; + } + + return ret; +} + +static vapi_enum_hicn_strategy _vpp_strategy_libhicn_to_hicnplugin_strategy( + strategy_type_t strategy) { + switch (strategy) { + case STRATEGY_TYPE_LOADBALANCER: + return HICN_STRATEGY_RR; + case STRATEGY_TYPE_LOCAL_REMOTE: + return HICN_STRATEGY_LR; + case STRATEGY_TYPE_REPLICATION: + return HICN_STRATEGY_RP; + case STRATEGY_TYPE_BESTPATH: + return HICN_STRATEGY_MW; + default: + return HICN_STRATEGY_NULL; + } +} + +static vapi_error_e _hicn_strategy_set_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_strategy_set_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + return reply->retval; +} + +static int _vpp_strategy_set(hc_sock_vpp_data_t *s, + const hc_strategy_t *strategy) { + int ret = -1; + + // Convert libhicn strategy enum to hicnplugin strategy enum and make sure it + // is valid + vapi_enum_hicn_strategy strategy_id = + _vpp_strategy_libhicn_to_hicnplugin_strategy(strategy->type); + + if (strategy_id == HICN_STRATEGY_NULL) { + return -1; + } + + // Construct API message + vapi_msg_hicn_api_strategy_set *msg = + vapi_alloc_hicn_api_strategy_set(s->g_vapi_ctx_instance); + + // Fill it + msg->payload.strategy_id = strategy_id; + ret = _ip_prefix_encode(&strategy->address, strategy->len, strategy->family, + &msg->payload.prefix); + + if (ret != 0) { + return -1; + } + + vapi_lock(); + ret = vapi_hicn_api_strategy_set(s->g_vapi_ctx_instance, msg, + _hicn_strategy_set_cb, NULL); + vapi_unlock(); + + return ret; +} + +int vpp_strategy_create(hc_sock_t *sock, hc_object_t *object, hc_data_t *data) { + return -1; +} + +int vpp_strategy_delete(hc_sock_t *sock, hc_object_t *object, hc_data_t *data) { + return -1; +} + +int vpp_strategy_list(hc_sock_t *sock, hc_object_t *object, hc_data_t *data) { + return -1; +} + +int vpp_strategy_set(hc_sock_t *sock, hc_object_t *object, hc_data_t *data) { + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + return _vpp_strategy_set(s, &object->strategy); +} + +DECLARE_VPP_MODULE_OBJECT_OPS(vpp, strategy); diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.h new file mode 100644 index 000000000..6dd6df6e4 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/strategy.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 modules/hicn_plugin/route.h + * \brief route object VFT for hicn_plugin. + */ + +#ifndef HICNCTRL_MODULE_VPP_STRATEGY_H +#define HICNCTRL_MODULE_VPP_STRATEGY_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(vpp, strategy); + +#endif /* HICNCTRL_MODULE_VPP_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c deleted file mode 100644 index e59a2e41e..000000000 --- a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c +++ /dev/null @@ -1,1305 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 api.c - * \brief Implementation of hICN control library API - */ - -#include "api_private.h" - -#include <assert.h> // assert -#include <fcntl.h> // fcntl -#include <math.h> // log2 -#include <stdbool.h> -#include <stdio.h> // snprintf -#include <string.h> // memmove, strcasecmp -#include <sys/socket.h> // socket -#include <unistd.h> // close, fcntl -#include <vapi/vapi_safe.h> -#include <vapi/hicn.api.vapi.h> -#include <vapi/ip.api.vapi.h> -#include <vapi/udp.api.vapi.h> -#include <vapi/interface.api.vapi.h> - - -#if __GNUC__ >= 9 -#pragma GCC diagnostic ignored "-Waddress-of-packed-member" -#endif - -#include <vnet/ip/ip46_address.h> - -#if __GNUC__ >= 9 -#pragma GCC diagnostic pop -#endif - -#define APP_NAME "hicn_plugin" -#define MAX_OUTSTANDING_REQUESTS 4 -#define RESPONSE_QUEUE_SIZE 2 - -DEFINE_VAPI_MSG_IDS_HICN_API_JSON -DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON -DEFINE_VAPI_MSG_IDS_IP_API_JSON -DEFINE_VAPI_MSG_IDS_UDP_API_JSON - -typedef struct { - vapi_ctx_t g_vapi_ctx_instance; - bool async; -} vapi_skc_ctx_t; - -vapi_skc_ctx_t vapi_skc = { - .g_vapi_ctx_instance = NULL, - .async = false, -}; - -/** - * Messages to the forwarder might be multiplexed thanks to the seqNum fields in - * the header_control_message structure. The forwarder simply answers back the - * original sequence number. We maintain a map of such sequence number to - * outgoing queries so that replied can be demultiplexed and treated - * appropriately. - */ -/* TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *); */ -/* TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, */ -/* generic_snprintf); */ - -struct hc_sock_vpp_s { - /* This must be the first element of the struct */ - hc_sock_t vft; - - vapi_ctx_t g_vapi_ctx_instance; - char *url; - int fd; - - size_t roff; /**< Read offset */ - size_t woff; /**< Write offset */ - u32 buffer[RECV_BUFLEN]; - /* Next sequence number to be used for requests */ - int seq; - - bool async; -}; - -typedef struct hc_sock_vpp_s hc_sock_vpp_t; - -#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t*)(s) - -/****************************************************************************** - * Message helper types and aliases - ******************************************************************************/ - -#define foreach_hc_command \ - _(hicn_api_node_params_set) \ - _(hicn_api_node_params_set_reply) \ - _(hicn_api_node_params_get_reply) \ - _(hicn_api_node_stats_get_reply) \ - _(hicn_api_face_get) \ - _(hicn_api_faces_details) \ - _(hicn_api_face_stats_details) \ - _(hicn_api_face_get_reply) \ - _(hicn_api_route_get) \ - _(hicn_api_route_get_reply) \ - _(hicn_api_routes_details) \ - _(hicn_api_strategies_get_reply) \ - _(hicn_api_strategy_get) \ - _(hicn_api_strategy_get_reply) - - -typedef vapi_type_msg_header2_t hc_msg_header_t; - -typedef union { -#define _(a) vapi_payload_ ## a a; - foreach_hc_command -#undef _ -} hc_msg_payload_t; - -typedef struct __attribute__ ((__packed__)) { - hc_msg_header_t hdr; - hc_msg_payload_t payload; -} hc_hicnp_t; - -typedef void (* NTOH)(void *msg); - -typedef struct __attribute__((__packed__)) { - hc_data_t *data; - uint32_t curr_msg; -} callback_ctx_t; - -typedef struct __attribute__((__packed__)) { - hc_hicnp_t * hicnp_msg; - vapi_cb_t callback; - callback_ctx_t *callback_ctx; - NTOH ntoh; -} hc_msg_s; - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -static void _hc_sock_vpp_free(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - if (s->url) free(s->url); - close(s->fd); - free(s); - - vapi_disconnect_safe(); - vapi_skc.g_vapi_ctx_instance = NULL; -} - -static int _hc_sock_vpp_get_next_seq(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - return vapi_gen_req_context(s->g_vapi_ctx_instance); -} - -static int _hc_sock_vpp_set_nonblocking(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - s->async = 1; - return 0; -} - -static int _hc_sock_vpp_get_fd(hc_sock_t *s) { return 1; } - -static int _hc_sock_vpp_connect(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - vapi_error_e rv = vapi_connect_safe(&s->g_vapi_ctx_instance, s->async); - if (rv != VAPI_OK) - goto ERR_CONNECT; - - return 0; - -ERR_CONNECT: - ERROR("[hc_sock_connect] connection failed"); - return -1; -} - -static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) { - return -1; -} - -static int _hc_sock_vpp_get_available(hc_sock_t *s, u8 **buffer, size_t *size) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_recv(hc_sock_t *s) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_process(hc_sock_t *s, hc_data_t **pdata) { - //NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_callback(hc_sock_t * socket, hc_data_t ** pdata) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_reset(hc_sock_t * socket) { - // NOT IMPLEMENTED - return -1; -} - -/****************************************************************************** - * Command-specific structures and functions - ******************************************************************************/ - - -/*----------------------------------------------------------------------------* - * Listeners - *----------------------------------------------------------------------------*/ - -/* LISTENER CREATE */ - -static int _hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -/* LISTENER GET */ -static int _hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found) { - // NOT IMPLEMENTED - return -1; -} - -/* LISTENER DELETE */ - -static int _hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_ip_address_details *reply) { - - if (is_last) - return 0; - hc_data_t *data = (hc_data_t *)callback_ctx; - - if (data->size == data->current) { - data->buffer = realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2); - - if (!data->buffer) - return VAPI_ENOMEM; - - data->size *=2; - } - - hc_listener_t * listener = (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t)); - - if(reply->prefix.address.af == ADDRESS_IP4) { - memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4, IPV4_ADDR_LEN); - listener->family = AF_INET; - } - else { - memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6, IPV6_ADDR_LEN); - listener->family = AF_INET6; - } - - listener->id = reply->sw_if_index; - data->current++; - return rv; -} - -typedef struct { - u32 swif; - char interface_name[INTERFACE_LEN]; -} hc_vapi_interface_t; - -static vapi_error_e listener_list_complete_cb ( - struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_sw_interface_details *reply) { - - if (reply == NULL || rv != VAPI_OK) - return rv; - - if (is_last) - return 0; - - hc_data_t *data = (hc_data_t *)callback_ctx; - - if (data->size == data->current) { - data->buffer = realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2); - - if (!data->buffer) - return VAPI_ENOMEM; - - data->size *=2; - } - - hc_vapi_interface_t *swif = &((hc_vapi_interface_t*)data->buffer)[data->current]; - - swif[0].swif = reply->sw_if_index; - memcpy(swif[0].interface_name, reply->interface_name, INTERFACE_LEN); - - data->current++; - - return rv; -} - - -/* LISTENER LIST */ -static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - int retval = VAPI_OK; - vapi_lock(); - vapi_msg_sw_interface_dump *hicnp_msg; - hicnp_msg = vapi_alloc_sw_interface_dump(s->g_vapi_ctx_instance); - - if (!hicnp_msg) { - retval = VAPI_ENOMEM; - goto END; - } - - hicnp_msg->payload.sw_if_index = ~0; - hicnp_msg->payload.name_filter_valid = 0; - - hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t),NULL); - - if (!data) { - retval = -1; - goto END; - } - - hc_data_t *data2 = hc_data_create(0, 1,NULL); - - if (!data2) { - retval = -1; - goto END; - } - - data->buffer = malloc(sizeof(hc_vapi_interface_t)); - data->size = 1; - - if (!data->buffer) { - free (data); - retval = -1; - goto FREE_DATA; - } - - int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg, listener_list_complete_cb, data); - - if (ret != VAPI_OK) { - free(data->buffer); - free(data); - retval = -1; - goto FREE_DATA_BUFFER; - } - - data2->buffer = malloc(sizeof(hc_listener_t)); - data2->size = 1; - data2->out_element_size = 1; - - if (!data2->buffer) { - free (data2->buffer); - retval =1 -1; - goto CLEAN; - } - - /* Query the forwarder for each interface */ - for(int i = 0; i < data->current; i++) { - int index = data2->current; - vapi_msg_ip_address_dump* msg = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); - msg->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif; - msg->payload.is_ipv6 = 0; - retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info, data2); - vapi_msg_ip_address_dump* msg2 = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); - - if (retval) goto CLEAN; - - msg2->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif; - msg2->payload.is_ipv6 = 1; - retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, data2); - for (size_t j = index; j < data2->current; j++) { - memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name, ((hc_vapi_interface_t*)(data->buffer))[i].interface_name, INTERFACE_LEN); - ((hc_listener_t *)(data2->buffer))[j].type = CONNECTION_TYPE_HICN; - } - - if (retval) goto CLEAN; - } - -CLEAN: -FREE_DATA_BUFFER: - free(data->buffer); -FREE_DATA: - free(data); - - data2->size = data2->current; - data2->out_element_size = sizeof(hc_listener_t); - *pdata = data2; - END: - vapi_unlock(); - return retval; -} - -static int _hc_listener_list_async(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -/*----------------------------------------------------------------------------* - * CONNECTION - *----------------------------------------------------------------------------*/ - -/* CONNECTION CREATE */ - -static int _hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION GET */ - -static int _hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection) { - // Not implemented - return -1; -} - -static int _hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated) { - // Not implemented - return -1; -} - -/* CONNECTION DELETE */ - -static int _hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_delete_async(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION LIST */ - -static int _hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION SET ADMIN STATE */ - -static int _hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, - face_state_t state) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_admin_state_async(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state) { - // NOT IMPLEMENTED - return -1; -} - -#ifdef WITH_POLICY - -static int _hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) { - // NOT IMPLEMENTED - return -1; -} - -#endif // WITH_POLICY - -static int _hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) { - // NOT IMPLEMENTED - return -1; -} - -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -static vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) - return rv; - - if (reply->retval != VAPI_OK) - return reply->retval; - - u32 * uei = (u32*) callback_ctx; - *uei = reply->uei; - - return reply->retval; -} - -/* ROUTE CREATE */ -static vapi_error_e parse_route_create( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_ip_route_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) - return rv; - - if (reply->retval != VAPI_OK) - return reply->retval; - - return reply->retval; -} - -static vapi_error_e hicn_enable_cb( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_enable_disable_reply *reply) { - if (reply == NULL || rv != VAPI_OK) - return rv; - - return reply->retval; -} - -static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool async) { - if (!IS_VALID_FAMILY(route->family)) return -1; - - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - int ret; - vapi_lock(); - - vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); - - hicnp_msg->payload.is_add = 1; - if (route->family == AF_INET) { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4; - } - else { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6; - } - - hicnp_msg->payload.route.prefix.len = route->len; - - hicnp_msg->payload.route.paths[0].sw_if_index = ~0; - hicnp_msg->payload.route.paths[0].table_id = 0; - - hc_face_t *face = &(route->face); - switch (face->face.type) { - case FACE_TYPE_HICN: - { - if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; - } - else{ - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - - break; - } - case FACE_TYPE_UDP: - { - vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL; - u32 uei = ~0; - - if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr))) && - ip46_address_is_ip4((ip46_address_t *)(&(face->face.local_addr)))) { - - msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); - memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4, sizeof(ip4_address_t)); - msg->payload.src_addr.af = ADDRESS_IP4; - - memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4, sizeof(ip4_address_t)); - msg->payload.dst_addr.af = ADDRESS_IP4; - - } else if (!ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.remote_addr))) && - !ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.local_addr)))) { - - msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); - memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6, sizeof(ip6_address_t)); - msg->payload.src_addr.af = ADDRESS_IP4; - - memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6, sizeof(ip6_address_t)); - msg->payload.dst_addr.af = ADDRESS_IP6; - - } else { - //NOT IMPLEMENTED - ret = -1; - goto done; - } - - msg->payload.src_port = face->face.local_port; - msg->payload.dst_port = face->face.remote_port; - msg->payload.is_add = 1; - - int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg, create_udp_tunnel_cb, &uei); - - if(ret) { - vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg); - goto done; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].nh.obj_id = uei; - break; - } - default: - ret = -1; - goto done; - } - - ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_create, NULL); - - if (ret) - goto done; - - vapi_msg_hicn_api_enable_disable *msg = vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); - - if (route->family == AF_INET) { - memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); - msg->payload.prefix.address.af = ADDRESS_IP4; - } - else { - memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - msg->payload.prefix.len = route->len; - msg->payload.enable_disable = 1; - - ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, hicn_enable_cb, NULL); -done: - vapi_unlock(); - return ret; -} - -static int _hc_route_create(hc_sock_t *s, hc_route_t *route) { - return _hc_route_create_internal(s, route, false); -} - -static int _hc_route_create_async(hc_sock_t *s, hc_route_t *route) { - return _hc_route_create_internal(s, route, true); -} - -/* ROUTE DELETE */ -static vapi_error_e parse_route_delete( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_ip_route_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) - return rv; - - return reply->retval; -} - -static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool async) { - if (!IS_VALID_FAMILY(route->family)) return -1; - - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - - vapi_lock(); - vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); - - hicnp_msg->payload.is_add = 0; - if (route->family == AF_INET) { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4; - } - else { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6; - } - - hicnp_msg->payload.route.prefix.len = route->len; - - hicnp_msg->payload.route.paths[0].sw_if_index = ~0; - hicnp_msg->payload.route.paths[0].table_id = 0; - - hc_face_t *face = &(route->face); - switch (face->face.type) { - case FACE_TYPE_HICN: - { - if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; - } - else{ - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - - break; - } - case FACE_TYPE_UDP: - { - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index; - break; - } - default: - return -1; - } - - vapi_error_e ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_delete, NULL); - - vapi_unlock(); - return ret; -} - -static int _hc_route_delete(hc_sock_t *s, hc_route_t *route) { - return _hc_route_delete_internal(s, route, false); -} - -static int _hc_route_delete_async(hc_sock_t *s, hc_route_t *route) { - return _hc_route_delete_internal(s, route, true); -} - -static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_udp_encap_details *reply) { - if (reply == NULL || rv != VAPI_OK) - return rv; - - hc_face_t * face = (hc_face_t *)callback_ctx; - - if (face->face.netdevice.index == reply->udp_encap.id) - { - switch(reply->udp_encap.src_ip.af) { - case ADDRESS_IP4: - { - memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), sizeof(ip4_address_t)); - memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), sizeof(ip4_address_t)); - break; - } - case ADDRESS_IP6: - { - memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), sizeof(ip6_address_t)); - memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), sizeof(ip6_address_t)); - break; - } - default: - break; - } - - face->face.local_port = reply->udp_encap.src_port; - face->face.remote_port = reply->udp_encap.dst_port; - } - return rv; -} - -static int _fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) { - switch(path->type){ - case FIB_API_PATH_FLAG_NONE: - { - face->face.type = FACE_TYPE_HICN; - switch(path->proto){ - case FIB_API_PATH_NH_PROTO_IP4: - memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4), sizeof(ip4_address_t)); - break; - case FIB_API_PATH_NH_PROTO_IP6: - memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6), sizeof(ip6_address_t)); - break; - default: - break; - } - face->face.netdevice.index = path->sw_if_index; - } - break; - case FIB_API_PATH_TYPE_UDP_ENCAP: - { - face->face.type = FACE_TYPE_UDP; - face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id); - // Let's make the compiler happy - (void)parse_udp_encap_list; - //vapi_msg_udp_encap_dump *msg; - //msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance); - //vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, face); - } - break; - default: - return -1; - } - return 0; -} - -/* ROUTE LIST */ -typedef struct hicn_route_socket_s { - hc_data_t *data; - hc_sock_t *s; -} hicn_route_socket_t; - -static vapi_error_e parse_route_list( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_ip_route_details *reply) { - - if (reply == NULL || rv != VAPI_OK) - return rv; - - hicn_route_socket_t *rs = (hicn_route_socket_t *)callback_ctx; - hc_data_t *data = rs->data; - - u8 found = false; - for (int j = 0; j < reply->route.n_paths; j++){ - for (int i = 0; i < data->size && !found; i++) { - hc_route_t * route = &((hc_route_t*)(data->buffer))[i]; - - if(ip46_address_is_ip4((ip46_address_t *)&(route->remote_addr)) && - memcmp(route->remote_addr.v4.as_u8, reply->route.prefix.address.un.ip4, sizeof(ip4_address_t)) == 0 && - route->len == reply->route.prefix.len && route->face_id == ~0) { - _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s); - found = true; - } else if (memcmp(route->remote_addr.v6.as_u8, reply->route.prefix.address.un.ip6, sizeof(ip6_address_t)) == 0 && - route->len == reply->route.prefix.len && route->face_id == ~0) { - _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s); - found = true; - } - } - } - - return rv; -} - -static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_routes_details *reply) { - - if (reply == NULL || rv != VAPI_OK) - return rv; - - hc_data_t *data = (hc_data_t *)callback_ctx; - - int empty_spots = data->size - data->current; - if (empty_spots < reply->nfaces) { - int new_size = data->size + (reply->nfaces - empty_spots); - data->buffer = realloc(data->buffer, sizeof(hc_route_t) * (new_size)); - if (!data->buffer) - return VAPI_ENOMEM; - - data->size =new_size; - } - - for (int i = 0; i < reply->nfaces; i++) { - hc_route_t * route = &((hc_route_t*)(data->buffer))[data->current]; - route->face_id = ~0; - route->cost = 1; - route->len = reply->prefix.len; - if (reply->prefix.address.af == ADDRESS_IP6) - { - memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16); - } - else - { - memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4); - } - route->family = reply->prefix.address.af == ADDRESS_IP6? AF_INET6 : AF_INET; - data->current++; - } - - return rv; -} - -static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool async) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - vapi_lock(); - - vapi_msg_hicn_api_routes_dump *msg; - msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance); - - hc_data_t *data = hc_data_create(0, sizeof(hc_route_t),NULL); - int ret = VAPI_OK; - - if (!data){ - ret = -1; - goto err; - } - - data->buffer = malloc(sizeof(hc_route_t)); - data->size = 1; - - if (!data->buffer) { - ret = -1; - goto err_free; - } - - ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, parse_hicn_route_list, data); - - if (ret != VAPI_OK) - goto err_free; - - vapi_msg_ip_route_dump *hicnp_msg; - hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); - hicnp_msg->payload.table.table_id = 0; - hicnp_msg->payload.table.is_ip6 = 1; - - hicn_route_socket_t ctx = { - .data = data, - .s = socket, - }; - - ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx); - - hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); - hicnp_msg->payload.table.table_id = 0; - hicnp_msg->payload.table.is_ip6 = 0; - - ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx); - - if (ret != VAPI_OK) - goto err_free; - - *pdata = data; - - vapi_unlock(); - return ret; - - err_free: - free(data); - err: - vapi_unlock(); - return ret; -} - -static int _hc_route_list(hc_sock_t *s, hc_data_t **pdata) { - return _hc_route_list_internal(s, pdata, false); -} - -static int _hc_route_list_async(hc_sock_t *s) { - return _hc_route_list_internal(s, NULL, true); -} - -/*----------------------------------------------------------------------------* - * Face - * - * Face support is not directly available in hicn-light, but we can offer such - * an interface through a combination of listeners and connections. The code - * starts with some conversion functions between faces/listeners/connections. - * - * We also need to make sure that there always exist a (single) listener when a - * connection is created, and in the hICN face case, that there is a single - * connection attached to this listener. - * - *----------------------------------------------------------------------------*/ - -static int _hc_face_create(hc_sock_t *s, hc_face_t *face) { - ERROR("Face creation implemented."); - return -1; -} - -static int _hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found) { - ERROR("Face deletion not implemented."); - return -1; -} - -static int _hc_face_delete(hc_sock_t *s, hc_face_t *face) { - ERROR("Face deletion not implemented."); - return -1; -} - -/* FACE LIST */ - -static int _hc_face_list(hc_sock_t *s, hc_data_t **pdata) { - ERROR("Face list not implemented."); - return -1; -} - -static int _hc_face_list_async(hc_sock_t *s) { - return 0; -} - -static int _hc_face_set_admin_state( - hc_sock_t *s, const char *conn_id_or_name, // XXX wrong identifier - face_state_t admin_state) { - return 0; -} - -#ifdef WITH_POLICY -static int _hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) { - ERROR("Face set priority not implemented."); - return -1; -} - -static int _hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) { - ERROR("Face set tags not implemented."); - return -1; -} -#endif // WITH_POLICY - -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ - -static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting, bool async) { - return -1; -} - -static int _hc_punting_create(hc_sock_t *s, hc_punting_t *punting) { - return _hc_punting_create_internal(s, punting, false); -} - -static int _hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) { - return _hc_punting_create_internal(s, punting, true); -} - -static int _hc_punting_get(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found) { - ERROR("hc_punting_get not (yet) implemented."); - return -1; -} - -static int _hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) { - ERROR("hc_punting_delete not (yet) implemented."); - return -1; -} - -static int _hc_punting_list(hc_sock_t *s, hc_data_t **pdata) { - ERROR("hc_punting_list not (yet) implemented."); - return -1; -} - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -static int _hc_cache_set_store_internal(hc_sock_t *s, int enabled, bool async) { - return 0; -} - -static int _hc_cache_set_store(hc_sock_t *s, int enabled) { - return _hc_cache_set_store_internal(s, enabled, false); -} - -static int _hc_cache_set_store_async(hc_sock_t *s, int enabled) { - return _hc_cache_set_store_internal(s, enabled, true); -} - -static int _hc_cache_set_serve_internal(hc_sock_t *s, int enabled, bool async) { - return 0; -} - -static int _hc_cache_set_serve(hc_sock_t *s, int enabled) { - return _hc_cache_set_serve_internal(s, enabled, false); -} - -static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) { - return _hc_cache_set_serve_internal(s, enabled, true); -} - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -// per prefix -static int _hc_strategy_set(hc_sock_t *s /* XXX */) { return 0; } - -static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) { - return 0; -} - -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -static int _hc_wldr_set(hc_sock_t *s /* XXX */) { return 0; } - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -static int _hc_mapme_set(hc_sock_t *s, int enabled) { return 0; } - -static int _hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; } - -static int _hc_mapme_set_timescale(hc_sock_t *s, double timescale) { return 0; } - -static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; } - -/*----------------------------------------------------------------------------* - * Policy - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -/* POLICY CREATE */ - -static int _hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) { - return -1; -} - -static int -_hc_policy_create(hc_sock_t * s, hc_policy_t * policy) { - return _hc_policy_create_internal(s, policy, false); -} - -static int _hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy) { - return _hc_policy_create_internal(s, policy, true); -} - -/* POLICY DELETE */ - -static int _hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) { - return -1; -} - -static int _hc_policy_delete(hc_sock_t * s, hc_policy_t * policy) { - return _hc_policy_delete_internal(s, policy, false); -} - -static int _hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy) { - return _hc_policy_delete_internal(s, policy, true); -} - -/* POLICY LIST */ - -static int -_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) { - return -1; -} - -static int _hc_policy_list(hc_sock_t * s, hc_data_t ** pdata) { - return _hc_policy_list_internal(s, pdata, false); -} - -static int _hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata) { - return _hc_policy_list_internal(s, pdata, true); -} - -#endif /* WITH_POLICY */ - -static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) { - .hc_sock_get_next_seq = _hc_sock_vpp_get_next_seq, - .hc_sock_set_nonblocking = _hc_sock_vpp_set_nonblocking, - .hc_sock_get_fd = _hc_sock_vpp_get_fd, - .hc_sock_connect = _hc_sock_vpp_connect, - .hc_sock_get_available = _hc_sock_vpp_get_available, - .hc_sock_send = _hc_sock_vpp_send, - .hc_sock_recv = _hc_sock_vpp_recv, - .hc_sock_process = _hc_sock_vpp_process, - .hc_sock_callback = _hc_sock_vpp_callback, - .hc_sock_reset = _hc_sock_vpp_reset, - .hc_sock_free = _hc_sock_vpp_free, - .hc_listener_create = _hc_listener_create, - .hc_listener_create_async = _hc_listener_create_async, - .hc_listener_get = _hc_listener_get, - .hc_listener_delete = _hc_listener_delete, - .hc_listener_delete_async = _hc_listener_delete_async, - .hc_listener_list = _hc_listener_list, - .hc_listener_list_async = _hc_listener_list_async, - .hc_connection_create = _hc_connection_create, - .hc_connection_create_async = _hc_connection_create_async, - .hc_connection_get = _hc_connection_get, - .hc_connection_update_by_id = _hc_connection_update_by_id, - .hc_connection_update = _hc_connection_update, - .hc_connection_delete = _hc_connection_delete, - .hc_connection_delete_async = _hc_connection_delete_async, - .hc_connection_list = _hc_connection_list, - .hc_connection_list_async = _hc_connection_list_async, - .hc_connection_set_admin_state = _hc_connection_set_admin_state, - .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async, - -#ifdef WITH_POLICY - .hc_connection_set_priority = _hc_connection_set_priority, - .hc_connection_set_priority_async = _hc_connection_set_priority_async, - .hc_connection_set_tags = _hc_connection_set_tags, - .hc_connection_set_tags_async = _hc_connection_set_tags_async, -#endif // WITH_POLICY - - .hc_face_create = _hc_face_create, - .hc_face_get = _hc_face_get, - .hc_face_delete = _hc_face_delete, - .hc_face_list = _hc_face_list, - .hc_face_list_async = _hc_face_list_async, - .hc_face_set_admin_state = _hc_face_set_admin_state, - -#ifdef WITH_POLICY - .hc_face_set_priority = _hc_face_set_priority, - .hc_face_set_tags = _hc_face_set_tags, -#endif // WITH_POLICY - - .hc_route_create = _hc_route_create, - .hc_route_create_async = _hc_route_create_async, - .hc_route_delete = _hc_route_delete, - .hc_route_delete_async = _hc_route_delete_async, - .hc_route_list = _hc_route_list, - .hc_route_list_async = _hc_route_list_async, - - .hc_punting_create = _hc_punting_create, - .hc_punting_create_async = _hc_punting_create_async, - .hc_punting_get = _hc_punting_get, - .hc_punting_delete = _hc_punting_delete, - .hc_punting_list = _hc_punting_list, - - .hc_cache_set_store = _hc_cache_set_store, - .hc_cache_set_store_async = _hc_cache_set_store_async, - .hc_cache_set_serve = _hc_cache_set_serve, - .hc_cache_set_serve_async = _hc_cache_set_serve_async, - - .hc_strategy_list = _hc_strategy_list, - .hc_strategy_set = _hc_strategy_set, - .hc_wldr_set = _hc_wldr_set, - - .hc_mapme_set = _hc_mapme_set, - .hc_mapme_set_discovery = _hc_mapme_set_discovery, - .hc_mapme_set_timescale = _hc_mapme_set_timescale, - .hc_mapme_set_retx = _hc_mapme_set_retx, - -#ifdef WITH_POLICY - .hc_policy_create = _hc_policy_create, - .hc_policy_create_async = _hc_policy_create_async, - .hc_policy_delete = _hc_policy_delete, - .hc_policy_delete_async = _hc_policy_delete_async, - .hc_policy_list = _hc_policy_list, - .hc_policy_list_async = _hc_policy_list_async -#endif // WITH_POLICY -}; - -hc_sock_t *_hc_sock_create_url(const char *url) { - // NOT IMPLEMENTED - return NULL; -} - -hc_sock_t *_hc_sock_create(void) { - hc_sock_vpp_t *s = malloc(sizeof(hc_sock_vpp_t)); - - if (!s) goto ERR_SOCK; - - memset(s, 0, sizeof(hc_sock_vpp_t)); - - s->vft = hc_sock_vpp_interface; - - // By default the socket is blocking -- not async - s->async = 0; - - return (hc_sock_t *)(s); - -ERR_SOCK: - return NULL; -}
\ No newline at end of file diff --git a/ctrl/libhicnctrl/src/object.c b/ctrl/libhicnctrl/src/object.c new file mode 100644 index 000000000..d9863308e --- /dev/null +++ b/ctrl/libhicnctrl/src/object.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-2022 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 object.c + * \brief Implementation of API object representation. + */ + +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/object.h> + +#include "objects/base.h" // iszero +#include "object_vft.h" + +bool hc_object_is_empty(const hc_object_t *object) { + return iszero(object, sizeof(hc_object_t)); +} + +int hc_object_validate(hc_object_type_t object_type, hc_object_t *object, + bool allow_partial) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->validate(object, allow_partial); +} + +int hc_object_cmp(hc_object_type_t object_type, hc_object_t *object1, + hc_object_t *object2) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->cmp(object1, object2); +} + +int hc_object_snprintf(char *s, size_t size, hc_object_type_t object_type, + hc_object_t *object) { + if (!object) { + if (size == 0) return -1; + *s = '\0'; + return 1; + } + + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->obj_snprintf(s, size, object); +} + +size_t hc_object_size(hc_object_type_t object_type) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->size; +} diff --git a/ctrl/libhicnctrl/src/object_private.h b/ctrl/libhicnctrl/src/object_private.h new file mode 100644 index 000000000..1aea86639 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_private.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 object_private.h + * \brief Helper functions for object management. + */ + +#ifndef HICNCTRL_OBJECT_PRIVATE_H +#define HICNCTRL_OBJECT_PRIVATE_H + +#include <hicn/face.h> + +#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0) + +// XXX Those are always true +#define IS_VALID_ADDRESS(x) (1) +#define IS_VALID_CONNECTION_ID(x) (x != INVALID_FACE_ID) +#define IS_VALID_ROUTE_COST(x) (1) +#define IS_VALID_PREFIX_LEN(x) (1) +#define IS_VALID_POLICY(x) (1) +#define IS_VALID_ID(x) (1) +#define IS_VALID_INTERFACE_NAME(x) (1) +#define IS_VALID_NAME(x) (1) +#define IS_VALID_TYPE(x) IS_VALID_ENUM_TYPE(FACE_TYPE, x) +#define IS_VALID_FACE_STATE(x) (1) + +#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX)) + +#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x) + +#define GENERATE_FIND(TYPE) \ + int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \ + hc_##TYPE##_t **found) { \ + foreach_type(hc_##TYPE##_t, x, data) { \ + if (hc_##TYPE##_cmp(x, element) == 0) { \ + *found = x; \ + return 0; \ + } \ + }; \ + *found = NULL; /* this is optional */ \ + return 0; \ + } + +#endif /* HICNCTRL_OBJECT_PRIVATE_H */ diff --git a/ctrl/libhicnctrl/src/object_type.c b/ctrl/libhicnctrl/src/object_type.c new file mode 100644 index 000000000..0303fce75 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_type.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-2022 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 object_type.c + * \brief Implementation of object type. + */ + +#include <strings.h> + +#include <hicn/ctrl/object_type.h> + +const char *object_type_str[] = { +#define _(x) [OBJECT_TYPE_##x] = #x, + foreach_object_type +#undef _ +}; + +hc_object_type_t object_type_from_str(const char *object_str) { +#define _(x) \ + if (strcasecmp(object_str, #x) == 0) \ + return OBJECT_TYPE_##x; \ + else + foreach_object_type +#undef _ + return OBJECT_TYPE_UNDEFINED; +} diff --git a/ctrl/libhicnctrl/src/object_vft.c b/ctrl/libhicnctrl/src/object_vft.c new file mode 100644 index 000000000..4dc59c378 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_vft.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 object_vft.c + * \brief Implementation of object VFT. + */ + +#include "object_vft.h" + +#include "objects/listener.h" +#include "objects/connection.h" +#include "objects/route.h" +#include "objects/face.h" +#include "objects/mapme.h" +#include "objects/stats.h" +#include "objects/strategy.h" +#include "objects/subscription.h" +#include "objects/active_interface.h" + +const hc_object_ops_t *object_vft[] = { + [OBJECT_TYPE_CONNECTION] = &hc_connection_ops, + [OBJECT_TYPE_LISTENER] = &hc_listener_ops, + [OBJECT_TYPE_ROUTE] = &hc_route_ops, + [OBJECT_TYPE_FACE] = &hc_face_ops, + [OBJECT_TYPE_STRATEGY] = &hc_strategy_ops, + [OBJECT_TYPE_MAPME] = &hc_mapme_ops, + [OBJECT_TYPE_SUBSCRIPTION] = &hc_subscription_ops, + [OBJECT_TYPE_ACTIVE_INTERFACE] = &hc_active_interface_ops, + [OBJECT_TYPE_STATS] = &hc_stats_ops, + [OBJECT_TYPE_FACE_STATS] = &hc_face_stats_ops, +}; diff --git a/ctrl/libhicnctrl/src/object_vft.h b/ctrl/libhicnctrl/src/object_vft.h new file mode 100644 index 000000000..e27fe5d36 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_vft.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-2022 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 object_vft.h + * \brief Object VFT. + */ + +#ifndef HICNCTRL_OBJECT_VFT +#define HICNCTRL_OBJECT_VFT + +#include <stddef.h> // size_t +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/object.h> + +typedef struct { + hc_object_type_t object_type; + const char *object_name; + size_t size; + int (*validate)(const hc_object_t *object, bool allow_partial); + int (*cmp)(const hc_object_t *object1, const hc_object_t *object2); + /* cannot be named snprintf as it collides with a macro in clang/iOS */ + int (*obj_snprintf)(char *s, size_t size, const hc_object_t *object); +} hc_object_ops_t; + +#define DECLARE_OBJECT_OPS_H(TYPE, NAME) \ + extern const hc_object_ops_t hc_##NAME##_ops; + +#define DECLARE_OBJECT_OPS(TYPE, NAME) \ + const hc_object_ops_t hc_##NAME##_ops = { \ + .object_type = TYPE, \ + .object_name = #NAME, \ + .size = sizeof(hc_##NAME##_t), \ + .validate = _hc_##NAME##_validate, \ + .cmp = _hc_##NAME##_cmp, \ + .obj_snprintf = _hc_##NAME##_snprintf, \ + }; + +extern const hc_object_ops_t *object_vft[]; + +#endif /* HICNCTRL_OBJECT_VFT */ diff --git a/ctrl/libhicnctrl/src/objects/active_interface.c b/ctrl/libhicnctrl/src/objects/active_interface.c new file mode 100644 index 000000000..796123963 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/active_interface.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-2022 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 active_interface.c + * \brief Implementation of active_interface object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/active_interface.h> +#include <hicn/util/log.h> +#include <hicn/util/ip_address.h> + +#include "../object_private.h" +#include "../object_vft.h" + +/* ACTIVE_INTERFACE VALIDATE */ + +int hc_active_interface_validate(const hc_active_interface_t *active_interface, + bool allow_partial) { + return 0; // XXX TODO +} + +int _hc_active_interface_validate(const hc_object_t *object, + bool allow_partial) { + return hc_active_interface_validate(&object->active_interface, allow_partial); +} + +/* ACTIVE_INTERFACE CMP */ + +// XXX TODO +int hc_active_interface_cmp(const hc_active_interface_t *active_interface1, + const hc_active_interface_t *active_interface2) { + return -1; +} + +int _hc_active_interface_cmp(const hc_object_t *object1, + const hc_object_t *object2) { + return hc_active_interface_cmp(&object1->active_interface, + &object2->active_interface); +} + +/* ACTIVE_INTERFACE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_active_interface_snprintf( + char *s, size_t size, const hc_active_interface_t *active_interface) { + int rc; + char *pos = s; + + rc = hicn_ip_prefix_snprintf(pos, size, &active_interface->prefix); + if ((rc < 0) || (rc >= size)) return rc; + pos += rc; + size -= rc; + + for (netdevice_type_t type = NETDEVICE_TYPE_UNDEFINED + 1; + type < NETDEVICE_TYPE_N; type++) { + if (!netdevice_flags_has(active_interface->interface_types, type)) continue; + rc = snprintf(pos, size, " %s", netdevice_type_str(type)); + if ((rc < 0) || (rc >= size)) return (int)(pos - s + rc); + + pos += rc; + size -= rc; + } + return (int)(pos - s); +} + +int _hc_active_interface_snprintf(char *s, size_t size, + const hc_object_t *object) { + return hc_active_interface_snprintf(s, size, &object->active_interface); +} + +DECLARE_OBJECT_OPS(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface); diff --git a/ctrl/libhicnctrl/src/objects/active_interface.h b/ctrl/libhicnctrl/src/objects/active_interface.h new file mode 100644 index 000000000..973b08e40 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/active_interface.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-2022 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 active_interface.h + * \brief Route. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H +#define HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface); + +#endif /* HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H */ diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c b/ctrl/libhicnctrl/src/objects/base.c index 6c4f938ce..86e4bfb72 100644 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c +++ b/ctrl/libhicnctrl/src/objects/base.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2022 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: @@ -12,22 +12,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "hicn_light_comm.h" -hc_sock_t * hsocket; +/** + * \file base.c + * \brief Implementation of base functions for object APIs. + */ + +#include <stdbool.h> -int hicn_connect_light() { +#include "base.h" - hsocket = hc_sock_create(); - if (!hsocket) - HICN_LOG_ERR_MSG("Error creating socket\n"); - if (hc_sock_connect(hsocket) < 0) - HICN_LOG_ERR_MSG("Error connecting to the forwarder\n"); - return 0; +#include <hicn/util/log.h> +bool iszero(const void *ptr, int bytes) { + char *bptr = (char *)ptr; + while (bytes--) + if (*bptr++) return false; + return true; } -int hicn_disconnect_light() { - hc_sock_free(hsocket); - return 0; -}
\ No newline at end of file +bool isempty(const char *str) { return str[0] == '\0'; } diff --git a/ctrl/libhicnctrl/src/objects/base.h b/ctrl/libhicnctrl/src/objects/base.h new file mode 100644 index 000000000..eb85483e9 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/base.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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 base.h + * \brief Base functions for object APIs. + */ + +#ifndef HICNCTRL_OBJECTS_BASE_H +#define HICNCTRL_OBJECTS_BASE_H + +bool iszero(const void *ptr, int bytes); +bool isempty(const char *str); + +#endif /* HICNCTRL_OBJECTS_BASE_H */ diff --git a/ctrl/libhicnctrl/src/objects/connection.c b/ctrl/libhicnctrl/src/objects/connection.c new file mode 100644 index 000000000..ca09d9a54 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/connection.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2021-2022 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 connection.c + * \brief Implementation of connection object. + */ + +#include <assert.h> + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/connection.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" +#include "base.h" + +bool hc_connection_is_local(const hc_connection_t *connection) { + return (strncmp(connection->interface_name, "lo", INTERFACE_LEN) == 0); +} + +bool hc_connection_has_local(const hc_connection_t *connection) { + assert(connection); + return IS_VALID_PORT(connection->local_port) && + IS_VALID_ADDRESS(connection->local_addr); +} + +/* CONNECTION VALIDATE */ + +int hc_connection_validate(const hc_connection_t *connection, + bool allow_partial) { + int has_id = 0; + int has_name = 0; +#if 0 + int has_interface_name = 0; +#endif + int has_netdevice_type = 0; + int has_type = 0; + int has_family = 0; + int has_local_addr = 0; + int has_local_port = 0; + int has_remote_addr = 0; + int has_remote_port = 0; + int has_admin_state = 0; + int has_priority = 0; + int has_tags = 0; + int has_state = 0; + + if (connection->id == ~0) { + ERROR("[hc_listener_validate] Invalid id specified"); + return -1; + } + has_id = 1; + + if (!isempty(connection->name)) { + if (!IS_VALID_NAME(connection->name)) { + ERROR("[hc_connection_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + +#if 0 + if (!isempty(connection->interface_name)) { + if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) { + ERROR("[hc_connection_validate] Invalid interface_name specified"); + return -1; + } + has_interface_name = 1; + } +#endif + + if (connection->type != FACE_TYPE_UNDEFINED) { + if (!IS_VALID_TYPE(connection->type)) { + ERROR("[hc_connection_validate] Invalid type specified"); + return -1; + } + has_type = 1; + } + + if (connection->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(connection->family)) { + ERROR("[hc_connection_validate] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&connection->local_addr)) { + if (!IS_VALID_ADDRESS(connection->local_addr)) { + ERROR("[hc_connection_validate] Invalid local_addr specified"); + return -1; + } + has_local_addr = 1; + } + + if (connection->local_port != 0) { + if (!IS_VALID_PORT(connection->local_port)) { + ERROR("[hc_connection_validate] Invalid local_port specified"); + return -1; + } + has_local_port = 1; + } + + if (!hicn_ip_address_empty(&connection->remote_addr)) { + if (!IS_VALID_ADDRESS(connection->remote_addr)) { + ERROR("[hc_connection_validate] Invalid remote_addr specified"); + return -1; + } + has_remote_addr = 1; + } + + if (connection->remote_port != 0) { + if (!IS_VALID_PORT(connection->remote_port)) { + ERROR("[hc_connection_validate] Invalid remote_port specified"); + return -1; + } + has_remote_port = 1; + } + + /* Interface name is optional */ + int has_key = has_id || has_name; + int has_mandatory_attributes = has_type && has_family && has_local_addr && + has_local_port && has_remote_addr && + has_remote_port; + int has_optional_attributes = + has_netdevice_type && has_admin_state && has_state; + has_optional_attributes = has_optional_attributes && has_priority && has_tags; + + if (allow_partial) { + if (has_key && !has_mandatory_attributes && !has_optional_attributes) + return 0; + else if (has_mandatory_attributes) + return 0; + else + return -1; + } else { + if (has_key && has_mandatory_attributes) return 0; + return -1; + } +} + +int _hc_connection_validate(const hc_object_t *object, bool allow_partial) { + return hc_connection_validate(&object->connection, allow_partial); +} + +/* CONNECTION CMP */ + +/* + * hICN light uses ports even for hICN connections, but their value is + * ignored. As connections are specific to hicn-light, we can safely use IP + * and ports for comparison independently of the face type. + */ +int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) { + int rc; + + rc = INT_CMP(c1->type, c2->type); + if (rc != 0) return rc; + + rc = INT_CMP(c1->family, c2->family); + if (rc != 0) return rc; + + if (!isempty(c1->interface_name) && !isempty(c2->interface_name)) { + rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN); + if (rc != 0) return rc; + } + + rc = hicn_ip_address_cmp(&c1->local_addr, &c2->local_addr); + if (rc != 0) return rc; + + rc = INT_CMP(c1->local_port, c2->local_port); + if (rc != 0) return rc; + + rc = hicn_ip_address_cmp(&c1->remote_addr, &c2->remote_addr); + if (rc != 0) return rc; + + rc = INT_CMP(c1->remote_port, c2->remote_port); + + return rc; +} + +int _hc_connection_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_connection_cmp(&object1->connection, &object2->connection); +} + +int hc_connection_has_valid_id(const hc_connection_t *connection) { + return connection->id != INVALID_FACE_ID; +} + +/* CONNECTION SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_connection_snprintf(char *s, size_t size, + const hc_connection_t *connection) { + char local[MAXSZ_URL]; + char remote[MAXSZ_URL]; + int rc; + + // assert(connection->connection_state) + if (strcmp(connection->name, "SELF") == 0) { + return snprintf(s, size, "%s", connection->name); + } + + rc = url_snprintf(local, MAXSZ_URL, &connection->local_addr, + connection->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = url_snprintf(remote, MAXSZ_URL, &connection->remote_addr, + connection->remote_port); + if (rc >= MAXSZ_URL) + WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s %s %s", connection->name, local, remote, + face_type_str(connection->type)); +} + +int _hc_connection_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_connection_snprintf(s, size, &object->connection); +} + +int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, + hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_CONNECTION, &object, pdata); +} + +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_CONNECTION, NULL, pdata); +} + +int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.admin_state = state; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.priority = priority; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.tags = tags; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +GENERATE_FIND(connection); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_CONNECTION, connection); diff --git a/ctrl/libhicnctrl/src/objects/connection.h b/ctrl/libhicnctrl/src/objects/connection.h new file mode 100644 index 000000000..1e9bf0376 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/connection.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021-2022 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 connection.h + * \brief Connection. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_CONNECTION_H +#define HICNCTRL_IMPL_OBJECTS_CONNECTION_H + +#include "../object_vft.h" + +bool hc_connection_is_local(const hc_connection_t *connection); +bool hc_connection_has_local(const hc_connection_t *connection); +bool hc_connection_has_valid_id(const hc_connection_t *connection); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_CONNECTION, connection); + +#endif /* HICNCTRL_IMPL_OBJECTS_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/src/objects/face.c b/ctrl/libhicnctrl/src/objects/face.c new file mode 100644 index 000000000..5dbe1c8dc --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/face.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021-2022 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 face.c + * \brief Implementation of face object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/face.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" + +bool hc_face_has_netdevice(const hc_face_t *face) { + return netdevice_is_empty(&face->netdevice); +} + +/* FACE VALIDATE */ + +int hc_face_validate(const hc_face_t *face, bool allow_partial) { + if ((!allow_partial || !hc_face_has_netdevice(face)) && + !IS_VALID_INTERFACE_NAME(face->interface_name)) { + ERROR("[hc_face_validate] Invalid interface_name specified"); + return -1; + } + if (!IS_VALID_TYPE(face->type)) { + ERROR("[hc_face_validate] Invalid type specified"); + return -1; + } + if ((!allow_partial || face->family != AF_UNSPEC) && + !IS_VALID_FAMILY(face->family)) { + ERROR("[hc_face_validate] Invalid family specified"); + return -1; + } + if ((!allow_partial || !hicn_ip_address_empty(&face->local_addr)) && + !IS_VALID_ADDRESS(face->local_addr)) { + ERROR("[hc_face_validate] Invalid local_addr specified"); + return -1; + } + if ((!allow_partial || !(face->local_port == 0)) && + !IS_VALID_PORT(face->local_port)) { + ERROR("[hc_face_validate] Invalid local_port specified"); + return -1; + } + if (!IS_VALID_ADDRESS(face->remote_addr)) { + ERROR("[hc_face_validate] Invalid remote_addr specified"); + return -1; + } + if (!IS_VALID_PORT(face->remote_port)) { + ERROR("[hc_face_validate] Invalid remote_port specified"); + return -1; + } + return 0; +} + +int _hc_face_validate(const hc_object_t *object, bool allow_partial) { + return hc_face_validate(&object->face, allow_partial); +} + +/* FACE CMP */ + +int hc_face_cmp(const hc_face_t *c1, const hc_face_t *c2) { + return -99; // Not implemented +} + +int _hc_face_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_face_cmp(&object1->face, &object2->face); +} + +/* FACE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_face_snprintf(char *s, size_t size, const hc_face_t *face) { + /* URLs are also big enough to contain IP addresses in the hICN case */ + char local[MAXSZ_URL]; + char remote[MAXSZ_URL]; + char tags[MAXSZ_POLICY_TAGS]; + int rc; + + switch (face->type) { + case FACE_TYPE_HICN: + case FACE_TYPE_HICN_LISTENER: + rc = hicn_ip_address_snprintf(local, MAXSZ_URL, &face->local_addr); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = hicn_ip_address_snprintf(remote, MAXSZ_URL, &face->remote_addr); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + break; + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + rc = url_snprintf(local, MAXSZ_URL, &face->local_addr, face->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = url_snprintf(remote, MAXSZ_URL, &face->remote_addr, + face->remote_port); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + break; + default: + return -1; + } + + // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS) + rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags); + if (rc >= MAXSZ_POLICY_TAGS) + WARN("[hc_face_snprintf] Unexpected truncation of policy tags string"); + if (rc < 0) return rc; + + return snprintf( + s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name, + face->netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->netdevice.name + : "*", + face_type_str(face->type), local, remote, face_state_str(face->state), + face_state_str(face->admin_state), face->priority, tags); +} + +int _hc_face_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_face_snprintf(s, size, &object->face); +} + +int hc_face_create(hc_sock_t *s, hc_face_t *face) { + int rc; + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + rc = hc_execute(s, ACTION_CREATE, OBJECT_TYPE_FACE, &object, NULL); + face->id = object.face.id; + return rc; +} + +int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_FACE, &object, pdata); +} + +int hc_face_delete(hc_sock_t *s, hc_face_t *face) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_FACE, &object, NULL); +} + +int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, pdata); +} + +int hc_face_list_async(hc_sock_t *s) { + return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, NULL, NULL); +} + +int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority) { + return -1; // Not implemented +#if 0 + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_FACE, &object, NULL); +#endif +} + +GENERATE_FIND(face); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_FACE, face); diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h b/ctrl/libhicnctrl/src/objects/face.h index 36698115a..08f90f195 100644 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h +++ b/ctrl/libhicnctrl/src/objects/face.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 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: @@ -13,19 +13,18 @@ * limitations under the License. */ +/** + * \file face.h + * \brief Face. + */ -#ifndef __TLOCK_H__ -#define __TLOCK_H__ - - -// limit on the number of locks: it shoud be matched with the number of hicn-state leaves -#define MAX_LOCK_SIZE 5 +#ifndef HICNCTRL_IMPL_OBJECTS_FACE_H +#define HICNCTRL_IMPL_OBJECTS_FACE_H -volatile long int En[MAX_LOCK_SIZE] , De[MAX_LOCK_SIZE] ; // For Ticket Algorithm +#include "../object_vft.h" +int hc_face_validate(const hc_face_t *face, bool allow_partial); -void Ticket_init ( int Lock_Number , long int init ); -void Ticket_Lock(int Lock_Number ); -void Ticket_Unlock(int Lock_Number ); +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_FACE, face); -#endif /* __IETF_HICN_H__ */
\ No newline at end of file +#endif /* HICNCTRL_IMPL_OBJECTS_FACE_H */ diff --git a/ctrl/libhicnctrl/src/objects/listener.c b/ctrl/libhicnctrl/src/objects/listener.c new file mode 100644 index 000000000..97a2430d8 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/listener.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021-2022 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 listener.c + * \brief Implementation of listener. + */ + +#include <string.h> + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/listener.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" +#include "base.h" + +bool hc_listener_is_local(const hc_listener_t *listener) { + return (strncmp(listener->interface_name, "lo", INTERFACE_LEN) == 0); +} + +/* LISTENER VALIDATE */ + +int hc_listener_validate(const hc_listener_t *listener, bool allow_partial) { + // if a field is specified it should be valid + // then we allow different specification, by key or by attributes, if + // allow_partial + + int has_id = 0; + int has_name = 0; +#if 0 + int has_interface_name = 0; +#endif + int has_type = 0; + int has_family = 0; + int has_local_addr = 0; + int has_local_port = 0; + + if (listener->id == ~0) { + ERROR("[hc_listener_validate] Invalid id specified"); + return -1; + } + has_id = 1; + + if (!isempty(listener->name)) { + if (!IS_VALID_NAME(listener->name)) { + ERROR("[hc_listener_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + +#if 0 + if (!isempty(listener->interface_name)) { + if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) { + ERROR("[hc_listener_validate] Invalid interface_name specified"); + return -1; + } + has_interface_name = 1; + } +#endif + + if (listener->type != FACE_TYPE_UNDEFINED) { + if (!IS_VALID_TYPE(listener->type)) { + ERROR("[hc_listener_validate] Invalid type specified"); + return -1; + } + has_type = 1; + } + + if (listener->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(listener->family)) { + ERROR("[hc_listener_validat] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&listener->local_addr)) { + if (!IS_VALID_ADDRESS(listener->local_addr)) { + ERROR("[hc_listener_validate] Invalid local_addr specified"); + return -1; + } + has_local_addr = 1; + } + + if (listener->local_port != 0) { + if (!IS_VALID_PORT(listener->local_port)) { + ERROR("[hc_listener_validate] Invalid local_port specified"); + return -1; + } + has_local_port = 1; + } + + if (allow_partial) { + if ((has_id || has_name) && !has_type && !has_family && !has_local_port && + !has_local_port) + return 0; + else if (has_name && has_type && has_family && has_local_addr && + has_local_port) + return 0; + else + return -1; + } else { + /* name and interface are optional */ + if (has_id && has_type && has_family && has_local_addr && has_local_port) + return 0; + return -1; + } +} + +int _hc_listener_validate(const hc_object_t *object, bool allow_partial) { + return hc_listener_validate(&object->listener, allow_partial); +} + +/* LISTENER CMP */ + +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) { + int rc; + + rc = INT_CMP(l1->type, l2->type); + if (rc != 0) return rc; + + rc = INT_CMP(l1->family, l2->family); + if (rc != 0) return rc; + + if (!isempty(l1->interface_name) && !isempty(l2->interface_name)) { + rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN); + if (rc != 0) return rc; + } + + rc = hicn_ip_address_cmp(&l1->local_addr, &l2->local_addr); + if (rc != 0) return rc; + + rc = INT_CMP(l1->local_port, l2->local_port); + if (rc != 0) return rc; + + return 0; +} + +int _hc_listener_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_listener_cmp(&object1->listener, &object2->listener); +} + +/* LISTENER SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_listener_snprintf(char *s, size_t size, const hc_listener_t *listener) { + char local[MAXSZ_URL]; + int rc; + rc = url_snprintf(local, MAXSZ_URL, &listener->local_addr, + listener->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_listener_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s %s interface=%s", listener->name, local, + face_type_str(listener->type), listener->interface_name); +} + +int _hc_listener_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_listener_snprintf(s, size, &object->listener); +} + +/* OPERATIONS */ + +int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_LISTENER, &object, NULL); +} + +int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_LISTENER, &object, pdata); +} + +int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_LISTENER, &object, NULL); +} + +int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_LISTENER, NULL, pdata); +} + +GENERATE_FIND(listener); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_LISTENER, listener); diff --git a/ctrl/libhicnctrl/src/objects/listener.h b/ctrl/libhicnctrl/src/objects/listener.h new file mode 100644 index 000000000..515c8f0ad --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/listener.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022 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 listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_LISTENER_H +#define HICNCTRL_IMPL_OBJECTS_LISTENER_H + +#include "../object_vft.h" + +bool hc_listener_is_local(const hc_listener_t *listener); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_LISTENER, listener); + +#endif /* HICNCTRL_IMPL_OBJECTS_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/objects/mapme.c b/ctrl/libhicnctrl/src/objects/mapme.c new file mode 100644 index 000000000..1acdcb35a --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/mapme.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 mapme.c + * \brief Implementation of mapme object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/mapme.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" +#include "face.h" +#include "base.h" + +/* MAPME VALIDATE */ + +int hc_mapme_validate(const hc_mapme_t *mapme, bool allow_partial) { + int has_family = 0; + int has_address = 0; + int has_len = 0; + + if (allow_partial) return 0; + + if (mapme->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(mapme->family)) { + ERROR("[hc_mapme_validate] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&mapme->address)) { + if (!IS_VALID_ADDRESS(mapme->address)) { + ERROR("[hc_mapme_validate] Invalid remote_addr specified"); + return -1; + } + has_address = 1; + } + + if (!IS_VALID_PREFIX_LEN(mapme->len)) { + ERROR("[hc_mapme_validate] Invalid len"); + return -1; + } + has_len = 1; + return has_family && has_address && has_len; +} + +int _hc_mapme_validate(const hc_object_t *object, bool allow_partial) { + return hc_mapme_validate(&object->mapme, allow_partial); +} + +/* MAPME CMP */ + +int hc_mapme_cmp(const hc_mapme_t *mapme1, const hc_mapme_t *mapme2) { + return -1; +} + +int _hc_mapme_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return -1; +} + +/* MAPME SNPRINTF */ + +int hc_mapme_snprintf(char *s, size_t size, const hc_mapme_t *mapme) { + return -1; +} + +int _hc_mapme_snprintf(char *s, size_t size, const hc_object_t *object) { + return -1; +} + +int hc_mapme_create(hc_sock_t *s, hc_mapme_t *mapme) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.mapme = *mapme; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_MAPME, &object, NULL); +} + +DECLARE_OBJECT_OPS(OBJECT_TYPE_MAPME, mapme); diff --git a/ctrl/libhicnctrl/src/objects/mapme.h b/ctrl/libhicnctrl/src/objects/mapme.h new file mode 100644 index 000000000..488f97cd5 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/mapme.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 mapme.h + * \brief Route. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_MAPME_H +#define HICNCTRL_IMPL_OBJECTS_MAPME_H + +#include "../object_vft.h" + +bool hc_mapme_has_face(const hc_mapme_t* mapme); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_MAPME, mapme); + +#endif /* HICNCTRL_IMPL_OBJECTS_MAPME_H */ diff --git a/ctrl/libhicnctrl/src/objects/route.c b/ctrl/libhicnctrl/src/objects/route.c new file mode 100644 index 000000000..4bdaa0afb --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/route.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2021-2023 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * 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 route.c + * \brief Implementation of route object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/route.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" +#include "face.h" +#include "base.h" + +bool hc_route_has_face(const hc_route_t *route) { + return !iszero(&route->face, sizeof(hc_face_t)); +} + +/* ROUTE VALIDATE */ + +int hc_route_validate(const hc_route_t *route, bool allow_partial) { + int has_id = 0; + int has_name = 0; + int has_face = 0; + + int has_family = 0; + int has_remote_addr = 0; + + if (IS_VALID_CONNECTION_ID(route->face_id)) { + has_id = 1; + } + + if (!isempty(route->face_name)) { + if (!IS_VALID_NAME(route->face_name)) { + ERROR("[hc_route_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + + if (route->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(route->family)) { + ERROR("[hc_route_validate] Invalid family specified"); + return -1; + } + has_family = 1; + } + + //::/0 is a valid remote addr +#if 0 + if (!hicn_ip_address_empty(&route->remote_addr)) { + if (!IS_VALID_ADDRESS(route->remote_addr)) { + ERROR("[hc_route_validate] Invalid remote_addr specified"); + return -1; + } + has_remote_addr = 1; + } +#else + has_remote_addr = 1; +#endif + + if (!IS_VALID_ROUTE_COST(route->cost)) { + ERROR("[hc_route_validate] Invalid cost"); + return -1; + } + +#if 0 + if (!IS_VALID_PREFIX_LEN(route->len)) { + ERROR("[hc_route_validate] Invalid len"); + return -1; + } +#endif + + if (hc_route_has_face(route)) { + if (hc_face_validate(&route->face, allow_partial) < 0) { + ERROR("[hc_route_validate] Invalid face"); + return -1; + } + has_face = 1; + } + + /* We also allow routes without faces, hence the '>' sign */ + if (allow_partial && (has_id + has_name + has_face > 1)) return -1; + // if (has_face_info && has_family && has_remote_addr) return 0; + if (has_family && has_remote_addr) return 0; + + return -1; +} + +int _hc_route_validate(const hc_object_t *object, bool allow_partial) { + return hc_route_validate(&object->route, allow_partial); +} + +/* ROUTE CMP */ + +// XXX TODO +int hc_route_cmp(const hc_route_t *route1, const hc_route_t *route2) { + return -1; +} + +int _hc_route_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_route_cmp(&object1->route, &object2->route); +} + +/* ROUTE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_route_snprintf(char *s, size_t size, const hc_route_t *route) { + /* interface cost prefix length */ + + char prefix[MAXSZ_IP_ADDRESS]; + int rc; + + rc = hicn_ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr); + if (rc >= MAXSZ_IP_ADDRESS) + ; + if (rc < 0) return rc; + + return snprintf(s, size, "%d (%s) %*d %s %*d", route->face_id, + route->face_name, MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, + route->len); +} + +int _hc_route_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_route_snprintf(s, size, &object->route); +} + +int hc_route_create(hc_sock_t *s, hc_route_t *route) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_ROUTE, &object, NULL); +} + +int hc_route_get(hc_sock_t *s, hc_route_t *route, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_ROUTE, &object, pdata); +} + +int hc_route_delete(hc_sock_t *s, hc_route_t *route) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_ROUTE, &object, NULL); +} + +int hc_route_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, pdata); +} + +int hc_route_list_async(hc_sock_t *s) { + return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, NULL, NULL); +} + +// XXX difference between GET and FIND +GENERATE_FIND(route); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_ROUTE, route); diff --git a/ctrl/libhicnctrl/src/objects/route.h b/ctrl/libhicnctrl/src/objects/route.h new file mode 100644 index 000000000..854bd70a6 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/route.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022 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 route.h + * \brief Route. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_ROUTE_H +#define HICNCTRL_IMPL_OBJECTS_ROUTE_H + +#include "../object_vft.h" + +bool hc_route_has_face(const hc_route_t* route); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ROUTE, route); + +#endif /* HICNCTRL_IMPL_OBJECTS_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/objects/stats.c b/ctrl/libhicnctrl/src/objects/stats.c new file mode 100644 index 000000000..f9d0e1de7 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/stats.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021-2022 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 stats.c + * \brief Implementation of stats. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" + +/* GENERAL STATS */ + +int _hc_stats_validate(const hc_object_t *object, bool allow_partial) { + // Nothing to validate + return 0; +} + +int _hc_stats_cmp(const hc_object_t *object1, const hc_object_t *object2) { + ERROR("[_hc_stats_cmp] Not implemented"); + return -1; +} + +int _hc_stats_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_stats_snprintf(s, size, &object->stats); +} + +int hc_stats_snprintf(char *s, size_t size, const hc_stats_t *stats) { + return snprintf( + s, size, + "*** STATS ***\nreceived = %u (interest = %u, data = %u)\ndropped = %u " + "(interest = %u, data = %u, other = %u)\nforwarded = { interests = " + "%u, data = %u }\ndropped_reason = { connection_not_found = %u, " + "send_failure = %u, no_route_in_fib = %u }\ninterest processing = { " + "aggregated = %u, retransmitted = %u, satisfied_from_cs = %u, " + "expired_interests = %u, expired_data = %u }\ndata processing = { " + "no_reverse_path = %u }\npacket cache = {PIT size = %u, CS size = %u, " + "eviction = %u}", + stats->forwarder.countReceived, stats->forwarder.countInterestsReceived, + stats->forwarder.countObjectsReceived, stats->forwarder.countDropped, + stats->forwarder.countInterestsDropped, + stats->forwarder.countObjectsDropped, stats->forwarder.countOtherDropped, + stats->forwarder.countInterestForwarded, + stats->forwarder.countObjectsForwarded, + stats->forwarder.countDroppedConnectionNotFound, + stats->forwarder.countSendFailures, stats->forwarder.countDroppedNoRoute, + stats->forwarder.countInterestsAggregated, + stats->forwarder.countInterestsRetransmitted, + stats->forwarder.countInterestsSatisfiedFromStore, + stats->forwarder.countInterestsExpired, stats->forwarder.countDataExpired, + stats->forwarder.countDroppedNoReversePath, + stats->pkt_cache.n_pit_entries, stats->pkt_cache.n_cs_entries, + stats->pkt_cache.n_lru_evictions); +} + +int hc_stats_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STATS, NULL, pdata); +} + +DECLARE_OBJECT_OPS(OBJECT_TYPE_STATS, stats); + +/* PER-FACE STATS */ + +int _hc_face_stats_validate(const hc_object_t *object, bool allow_partial) { + // Nothing to validate + return 0; +} + +int _hc_face_stats_cmp(const hc_object_t *object1, const hc_object_t *object2) { + ERROR("[_hc_stats_cmp] Not implemented"); + return -1; +} + +int _hc_face_stats_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_face_stats_snprintf(s, size, &object->face_stats); +} + +int hc_face_stats_snprintf(char *s, size_t size, const hc_face_stats_t *stats) { + return snprintf( + s, size, + "conn #%u:\tinterests =\t{ rx packets = %u, rx bytes = %u, " + "tx packets = %u, tx bytes = %u }\n\t\tdata =\t\t{ rx packets " + "= %u, rx bytes = %u, " + "tx packets = %u, tx bytes = %u }", + stats->conn_id, stats->interests.rx_pkts, stats->interests.rx_bytes, + stats->interests.tx_pkts, stats->interests.tx_bytes, stats->data.rx_pkts, + stats->data.rx_bytes, stats->data.tx_pkts, stats->data.tx_bytes); +} + +int hc_face_stats_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_FACE_STATS, NULL, pdata); +} + +DECLARE_OBJECT_OPS(OBJECT_TYPE_FACE_STATS, face_stats);
\ No newline at end of file diff --git a/ctrl/libhicnctrl/src/objects/stats.h b/ctrl/libhicnctrl/src/objects/stats.h new file mode 100644 index 000000000..3a4f04b2e --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/stats.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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 stats.h + * \brief Stats. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_STATS_H +#define HICNCTRL_IMPL_OBJECTS_STATS_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_STATS, stats); +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_FACE_STATS, face_stats); + +#endif /* HICNCTRL_IMPL_OBJECTS_STATS_H */
\ No newline at end of file diff --git a/ctrl/libhicnctrl/src/objects/strategy.c b/ctrl/libhicnctrl/src/objects/strategy.c new file mode 100644 index 000000000..0e7a5787e --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/strategy.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022 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 strategy.c + * \brief Implementation of strategy. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/strategy.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" + +/* STREATEGY VALIDATE */ + +int hc_strategy_validate(const hc_strategy_t *strategy, bool allow_partial) { + // TODO verify name + return 0; +} + +int _hc_strategy_validate(const hc_object_t *object, bool allow_partial) { + return hc_strategy_validate(&object->strategy, allow_partial); +} + +/* STRATEGY CMP */ + +int hc_strategy_cmp(const hc_strategy_t *s1, const hc_strategy_t *s2) { + return strcmp(s1->name, s2->name); +} + +int _hc_strategy_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_strategy_cmp(&object1->strategy, &object2->strategy); +} + +/* STRATEGY SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_strategy_snprintf(char *s, size_t size, const hc_strategy_t *strategy) { + return snprintf(s, size, "%s", strategy->name); +} + +int _hc_strategy_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_strategy_snprintf(s, size, &object->strategy); +} + +/* OPERATIONS */ + +int hc_strategy_create(hc_sock_t *s, hc_strategy_t *strategy) { return -1; } + +int hc_strategy_get(hc_sock_t *s, hc_strategy_t *strategy, hc_data_t **pdata) { + return -1; +} + +int hc_strategy_delete(hc_sock_t *s, hc_strategy_t *strategy) { return -1; } + +int hc_strategy_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STRATEGY, NULL, pdata); +} + +/* new api */ + +int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.strategy = *strategy; + return hc_execute(s, ACTION_SET, OBJECT_TYPE_STRATEGY, &object, NULL); +} + +#if 0 +int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) { + return s->hc_strategy_add_local_prefix(s, strategy); +} +#endif + +GENERATE_FIND(strategy); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_STRATEGY, strategy); diff --git a/ctrl/libhicnctrl/src/objects/strategy.h b/ctrl/libhicnctrl/src/objects/strategy.h new file mode 100644 index 000000000..0cc4f525d --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/strategy.h @@ -0,0 +1,29 @@ + +/* + * Copyright (c) 2021-2022 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 listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_STRATEGY_H +#define HICNCTRL_IMPL_OBJECTS_STRATEGY_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_STRATEGY, strategy); + +#endif /* HICNCTRL_IMPL_OBJECTS_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/src/objects/subscription.c b/ctrl/libhicnctrl/src/objects/subscription.c new file mode 100644 index 000000000..8db55660d --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/subscription.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-2022 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 subscription.c + * \brief Implementation of subscription. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/subscription.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" + +/* SUBSCRIPTION VALIDATE */ + +int hc_subscription_validate(const hc_subscription_t *subscription, + bool allow_partial) { + /* Any topic is considered valid */ + return 0; +} + +int _hc_subscription_validate(const hc_object_t *object, bool allow_partial) { + return hc_subscription_validate(&object->subscription, allow_partial); +} + +/* LISTENER CMP */ + +int hc_subscription_cmp(const hc_subscription_t *l1, + const hc_subscription_t *l2) { + return -1; +} + +int _hc_subscription_cmp(const hc_object_t *object1, + const hc_object_t *object2) { + return hc_subscription_cmp(&object1->subscription, &object2->subscription); +} + +/* SUBSCRIPTION SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_subscription_snprintf(char *s, size_t size, + const hc_subscription_t *subscription) { + return -99; /* Not implemented */ +} + +int _hc_subscription_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_subscription_snprintf(s, size, &object->subscription); +} + +/* OPERATIONS */ + +int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL); +} + +int hc_subscription_get(hc_sock_t *s, hc_subscription_t *subscription, + hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_SUBSCRIPTION, &object, pdata); +} + +int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL); +} + +int hc_subscription_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_SUBSCRIPTION, NULL, pdata); +} + +GENERATE_FIND(subscription); +DECLARE_OBJECT_OPS(OBJECT_TYPE_SUBSCRIPTION, subscription); diff --git a/ctrl/libhicnctrl/src/objects/subscription.h b/ctrl/libhicnctrl/src/objects/subscription.h new file mode 100644 index 000000000..6eb7583c6 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/subscription.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-2022 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 subscription.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H +#define HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_SUBSCRIPTION, subscription); + +#endif /* HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H */ diff --git a/ctrl/libhicnctrl/src/parse.c b/ctrl/libhicnctrl/src/parse.c new file mode 100644 index 000000000..25fa98de2 --- /dev/null +++ b/ctrl/libhicnctrl/src/parse.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2022 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 <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> + +//#include <hicn/ctrl/cli.h> +#include <hicn/ctrl/action.h> +#include <hicn/util/log.h> +#include <hicn/util/sstrncpy.h> +#include <hicn/ctrl/parse.h> + +/* + * As there is no portable way to generate a va_list to use with sscanf to + * support a variable number of arguments, and no way to use a variable array + * initialize in a nested struct, we use a fixed maximum number of parameters + * + * NOTE: update sscanf accordingly + */ + +//#include "command.h" + +const char *action_to_cmd_action(hc_action_t action) { + switch (action) { + case ACTION_CREATE: + return "add"; + case ACTION_UPDATE: + return "update"; + case ACTION_DELETE: + return "remove"; + case ACTION_LIST: + return "list"; + case ACTION_SET: + return "set"; + case ACTION_SERVE: + return "serve"; + case ACTION_STORE: + return "store"; + case ACTION_CLEAR: + return "clear"; + default: + return "UNDEFINED"; + } +} + +/* + * This function now assumes all parameteres in src are received as string + */ +int parser_type_func(const parser_type_t *type, const char *src, void *dst, + void *dst2, void *dst3) { + hicn_ip_address_t addr; + char *addr_str; + char *len_str; + int len, rc; + long tmp; + + switch (type->name) { + case TYPENAME_INT: + tmp = strtol(src, NULL, 10); + if ((tmp < INT32_MIN) || (tmp > INT32_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + if (tmp > INT_MAX) return -1; + *(int *)dst = (int)tmp; + break; + case TYPENAME_UINT: + tmp = strtol(src, NULL, 10); + if ((tmp < 0) || (tmp > UINT32_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + if (tmp > UINT_MAX) return -1; + *(unsigned *)dst = (unsigned)tmp; + break; + case TYPENAME_INT16: + tmp = strtol(src, NULL, 10); + if ((tmp < INT16_MIN) || (tmp > INT16_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + *(int16_t *)dst = tmp; + break; + case TYPENAME_UINT16: + tmp = strtol(src, NULL, 10); + if ((tmp < 0) || (tmp > UINT16_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + *(uint16_t *)dst = tmp; + break; + case TYPENAME_STR: + rc = strcpy_s(dst, type->str.max_size, src); + if (rc != EOK) { + ERROR("Input string is too long"); + return -1; + } + break; + case TYPENAME_IP_ADDRESS: + rc = hicn_ip_address_pton((char *)src, &addr); + if (rc < 0) { + ERROR("Wrong IP address format"); + return -1; + } + + *(hicn_ip_address_t *)dst = addr; + *(int *)dst2 = hicn_ip_address_str_get_family((char *)src); + break; + case TYPENAME_ON_OFF: + if (strcmp((char *)src, "off") == 0) { + *(unsigned *)dst = 0; + } else if (strcmp((char *)src, "on") == 0) { + *(unsigned *)dst = 1; + } else { + ERROR("on/off are the only possible values"); + return -1; + } + break; + case TYPENAME_IP_PREFIX: + addr_str = strtok((char *)src, "/"); + len_str = strtok(NULL, " "); + rc = hicn_ip_address_pton((char *)src, &addr); + if (rc < 0) { + ERROR("Wrong IP address format"); + return -1; + } + len = atoi(len_str); + + *(hicn_ip_address_t *)dst = addr; + *(int *)dst2 = len; + *(int *)dst3 = hicn_ip_address_str_get_family(addr_str); + break; + case TYPENAME_ENUM: + /* Enum index from string */ + assert(type->enum_.from_str); + *(int *)dst = type->enum_.from_str((char *)src); + break; + case TYPENAME_POLICY_STATE: { + assert(IS_VALID_POLICY_TAG(type->policy_state.tag)); + policy_tag_t tag = type->policy_state.tag; + /* Format string is "%ms" */ + const char *str = *(const char **)src; + policy_tag_state_t *pts = ((policy_tag_state_t *)dst); + pts[tag].disabled = (str[0] == '!') ? 1 : 0; + pts[tag].state = policy_state_from_str(str + pts[tag].disabled); + break; + } + case TYPENAME_UNDEFINED: + default: + ERROR("Unknown format"); + return -1; + } + return 0; +} + +// NEW FUNCTION +int parse_getopt_args(const command_parser_t *parser, int argc, char *argv[], + hc_command_t *command) { + /* Loop over remaining commandline positional arguments */ + for (unsigned i = 0; i < argc; i++) { + const command_parameter_t *p = &parser->parameters[i]; + + if (parser_type_func(&p->type, argv[i], + &command->object.as_uint8 + p->offset, + &command->object.as_uint8 + p->offset2, + &command->object.as_uint8 + p->offset3) < 0) { + ERROR("Error during parsing of parameter '%s' value", p->name); + goto ERR; + } + } + if (parser->post_hook) parser->post_hook(&command->object.as_uint8); + return 0; + +ERR: + return -1; +} + +/* Build a format string to parse all params as a string */ +int parse_params(const command_parser_t *parser, const char *params_s, + hc_command_t *command) { + char fmt[1024]; + int n; + size_t size = 0; + char *pos = fmt; + /* Update MAX_PARAMETERS accordingly in command.h */ + char sscanf_params[MAX_PARAMETERS][MAX_SCANF_PARAM_LEN]; + + unsigned count = 0; + for (unsigned i = 0; i < parser->nparams; i++) { + const char *_fmt = "%s"; + n = snprintf(pos, 1024 - size, "%s", _fmt); + pos += n; + + *pos = ' '; + pos++; + + size += n + 1; + count++; + } + *pos = '\0'; + DEBUG("parser format: %s", fmt); + + int ret = sscanf(params_s, fmt, sscanf_params[0], sscanf_params[1], + sscanf_params[2], sscanf_params[3], sscanf_params[4], + sscanf_params[5], sscanf_params[6], sscanf_params[7], + sscanf_params[8], sscanf_params[9]); + if (ret != parser->nparams) { + ERROR("Parsing failed: check for string used where integer was expected"); + goto ERR; + } + + for (unsigned i = 0; i < count; i++) { + const command_parameter_t *p = &parser->parameters[i]; + if (parser_type_func(&p->type, sscanf_params[i], + &command->object.as_uint8 + p->offset, + &command->object.as_uint8 + p->offset2, + &command->object.as_uint8 + p->offset3) < 0) { + ERROR("Error during parsing of parameter '%s' value", p->name); + goto ERR; + } + } + return 0; + +ERR: + return -1; +} + +int parse(const char *cmd, hc_command_t *command) { + int nparams = 0; + char action_s[MAX_SCANF_PARAM_LEN]; + char object_s[MAX_SCANF_PARAM_LEN]; + char params_s[MAX_SCANF_PARAM_LEN]; + + // if n = 2 later, params_s is uninitialized + memset(params_s, 0, MAX_SCANF_PARAM_LEN * sizeof(char)); + + errno = 0; + int n = sscanf(cmd, "%s %s%[^\n]s", action_s, object_s, params_s); + if ((n < 2) || (n > 3)) { + if (errno != 0) perror("scanf"); + return -1; + } + + command->action = action_from_str(action_s); + command->object_type = object_type_from_str(object_s); + + if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) { + for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) + nparams++; + } + + /* + * This checks is important even with 0 parameters as it checks whether the + * command exists. + */ + const command_parser_t *parser = + command_search(command->action, command->object_type, nparams); + if (!parser) { + ERROR("Could not find parser for command '%s %s'", action_s, object_s); + return -1; + } + + if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) { + if (parse_params(parser, params_s, command) < 0) return -1; + } + + if (parser->post_hook) parser->post_hook(&command->object.as_uint8); + return 0; +} + +int help(const char *cmd) { + int nparams = 1; + char action_s[MAX_SCANF_PARAM_LEN]; + char object_s[MAX_SCANF_PARAM_LEN]; + char params_s[MAX_SCANF_PARAM_LEN]; + hc_object_type_t object_type = OBJECT_TYPE_UNDEFINED; + hc_action_t action = ACTION_UNDEFINED; + + int n = sscanf(cmd, "help %[^\n]s", params_s); + + // No arguments provided to the help command: just list available objects + if (n != 1) goto CMD_LIST; + + // Count number of provided parameters + for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) nparams++; + if (nparams > 2) { + fprintf(stderr, "Error: too many arguments.\n"); + return -1; + } + + // Object specified: list actions available for that object + if (nparams == 1) { + object_type = object_type_from_str(params_s); + if (object_type == OBJECT_TYPE_UNDEFINED) { + fprintf(stderr, "Error: undefined object type.\n"); + return -1; + } + + goto CMD_LIST; + } + + // Object and action specified: list detailed commands + n = sscanf(params_s, "%s %[^\n]s", object_s, action_s); + assert(n == 2); + object_type = object_type_from_str(object_s); + if (object_type == OBJECT_TYPE_UNDEFINED) { + fprintf(stderr, "Error: undefined object type.\n"); + return -1; + } + action = action_from_str(action_s); + assert(action != ACTION_UNDEFINED); + +CMD_LIST: + printf("Available commands:\n"); + command_list(object_type, action); + return 0; +} + +#if 0 // tests +/* For the tests, we will need to test all non-compliant inputs */ +const char * cmds[] = { + "add connection hicn conn1 8.8.8.8 127.0.0.1 eth0", + "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port> eth0", + "add listener udp lst1 127.0.0.1 9695 eth0", + //"add face", + "add route 3 b001::/16 1", + //"add punting", + //"add strategy", + "add policy b001::/16 webex require avoid prohibit !prohibit neutral !require prefer", + "list connection", // need pluralize + "list listener", + "list face", + "list route", + "list punting", + "list strategy", + "list policy", + "remove connection 1", + "remove listener 1", + //"remove face", + "remove route 1 b001::/16", + //"remove punting", + //"remove policy", + "set debug", + "unset debug", + "set strategy b001::/16 random", // related prefixes (10 max) ? + "set strategy b001::/16 load_balancer", + "set strategy b001::/16 low_latency", + "set strategy b001::/16 replication", + "set strategy b001::/16 bestpath", + "set strategy b001::/16 local_remote", + "set wldr <on|off> <connection_id>", // on-off vs unset + "cache clear", + "cache store on/off", // set/unset + "cache serve on/off", + "mapme enable on/off", + "mapme discovery on/off", + "mapme timescale 500ms", + "mapme retx 500ms", + "update connection conn1 WT", +}; + +#define array_size(x) sizeof(x) / sizeof(typeof(x[0])) +int main() +{ + for (unsigned i = 0; i < array_size(cmds); i++) { + printf("PARSING [%d] %s\n", i, cmds[i]); + if (parse(cmds[i]) < 0) { + ERROR("Could not parse command: %s\n", cmds[i]); + continue; + } + } + exit(EXIT_SUCCESS); + +ERR: + exit(EXIT_FAILURE); +} +#endif diff --git a/ctrl/libhicnctrl/src/request.c b/ctrl/libhicnctrl/src/request.c new file mode 100644 index 000000000..0e1d07b04 --- /dev/null +++ b/ctrl/libhicnctrl/src/request.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2021-2022 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 request.c + * \brief Implementation of pending requests. + */ + +#include <assert.h> +#include <stdlib.h> + +#include <hicn/util/log.h> + +#include "request.h" + +const char *hc_request_state_str[] = { +#define _(x) [REQUEST_STATE_##x] = #x, + foreach_request_state +#undef _ +}; + +struct hc_request_s { + int seq; + hc_action_t action; + hc_object_type_t object_type; + hc_object_t *object; + +#if 0 + int (*parse)(const uint8_t *src, uint8_t *dst); +#endif + + /* Callbacks */ + hc_result_callback_t callback; + void *callback_data; + + /* Temp data used for the execution of the request */ + hc_data_t *data; + + /* Nested requests support + * + * In order to answer complex requests, involving a combination of requests to + * the forwarder, we will allow maintaining a Finite State Machine in the + * requests (and a tree of requests) + * + * The entry point for the modules will always remain the initial request, + * however, we will chain nested requests in their parent fields, and point to + * the one currently under execution in current. + * */ + hc_request_state_t state; + unsigned state_count; /* Usefor for iterative requests */ + hc_request_t *parent; + hc_request_t *current; +}; + +hc_request_t *hc_request_create(int seq, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + hc_request_t *request = malloc(sizeof(hc_request_t)); + if (!request) return NULL; + request->seq = seq; + + request->action = action; + request->object_type = object_type; + request->object = object; + + request->callback = callback; + request->callback_data = callback_data; + + request->data = NULL; + + request->state = REQUEST_STATE_INIT; + request->state_count = 0; + request->parent = NULL; + request->current = NULL; + + return request; +} + +void hc_request_free(hc_request_t *request) { free(request); } + +void hc_request_set(hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object) { + request->action = action; + request->object_type = object_type; + request->object = object; +} + +int hc_request_get_seq(const hc_request_t *request) { return request->seq; } + +hc_request_t *hc_request_get_current(hc_request_t *request) { + return request->current ? request->current : request; +} + +hc_request_t *hc_request_pop(hc_request_t *request) { + hc_request_t *current_request = hc_request_get_current(request); + hc_request_t *parent = current_request->parent; + request->current = parent; + if (parent) { + parent->data = current_request->data; + /* We only free the current_request if it was not the root */ + hc_request_free(current_request); + } + return parent; +} + +hc_request_state_t hc_request_get_state(const hc_request_t *request) { + return request->state; +} + +void hc_request_set_state(hc_request_t *request, hc_request_state_t state) { + request->state = state; +} + +int hc_request_get_state_count(const hc_request_t *request) { + return request->state_count; +} + +void hc_request_set_state_count(hc_request_t *request, unsigned count) { + request->state_count = count; +} + +hc_action_t hc_request_get_action(const hc_request_t *request) { + return request->action; +} + +hc_object_type_t hc_request_get_object_type(const hc_request_t *request) { + return request->object_type; +} + +hc_object_t *hc_request_get_object(const hc_request_t *request) { + return request->object; +} + +hc_data_t *hc_request_get_data(const hc_request_t *request) { + return request->data; +} + +void hc_request_set_data(hc_request_t *request, hc_data_t *data) { + assert(!request->data); + request->data = data; +} + +void hc_request_reset_data(hc_request_t *request) { + if (!request->data) return; + hc_data_free(request->data); + request->data = NULL; +} + +bool hc_request_is_subscription(const hc_request_t *request) { + hc_action_t action = hc_request_get_action(request); + hc_object_type_t object_type = hc_request_get_object_type(request); + return (action == ACTION_SUBSCRIBE) || + (action == ACTION_CREATE && object_type == OBJECT_TYPE_SUBSCRIPTION); +} + +bool hc_request_requires_object(const hc_request_t *request) { + hc_action_t action = hc_request_get_action(request); + return (action != ACTION_LIST) && (action != ACTION_SUBSCRIBE); +} + +void hc_request_clear_data(hc_request_t *request) { request->data = NULL; } + +void hc_request_set_complete(hc_request_t *request) { + request->state = REQUEST_STATE_COMPLETE; +} + +bool hc_request_is_complete(const hc_request_t *request) { + return request->state == REQUEST_STATE_COMPLETE; +} + +void hc_request_on_complete(hc_request_t *request) { + // request->state = REQUEST_STATE_COMPLETE; + if (!request->callback) return; + request->callback(request->data, request->callback_data); +} + +void hc_request_on_notification(hc_request_t *request) { + if (!request->callback) return; + request->callback(request->data, request->callback_data); +} + +hc_request_t *hc_request_make_subrequest(hc_request_t *request, + hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object) { + hc_request_t *sr = + hc_request_create(request->seq, action, object_type, object, + request->callback, request->callback_data); + + /* The parent is either the current one, or the request itself if NULL */ + hc_request_t *current_request = hc_request_get_current(request); + hc_request_reset_data(current_request); + sr->parent = current_request; + request->current = sr; + return sr; +} diff --git a/ctrl/libhicnctrl/src/request.h b/ctrl/libhicnctrl/src/request.h new file mode 100644 index 000000000..aa07cad00 --- /dev/null +++ b/ctrl/libhicnctrl/src/request.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021-2022 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 request.h + * \brief Pending requests. + */ + +#ifndef HC_REQUEST_H +#define HC_REQUEST_H + +#include <stdbool.h> + +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/callback.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> + +#if 0 +typedef int (*HC_PARSE)(const uint8_t *, uint8_t *); +#endif + +#define foreach_request_state \ + _(UNDEFINED) \ + _(INIT) \ + _(CONNECTION_CREATE_LISTENER_LIST) \ + _(CONNECTION_CREATE_LISTENER_ITERATE) \ + _(CONNECTION_CREATE_LISTENER_GET) \ + _(CONNECTION_CREATE_LISTENER_VERIFY) \ + _(CONNECTION_CREATE_LISTENER_CREATE) \ + _(CONNECTION_CREATE_LISTENER_CHECK) \ + _(CONNECTION_CREATE) \ + _(CONNECTION_CREATE_N) \ + _(CONNECTION_GET) \ + _(CONNECTION_DELETE_WITH_ID) \ + _(CONNECTION_DELETE_AFTER_GET) \ + _(FACE_CREATE_CONNECTION_CREATE) \ + _(FACE_DELETE_CONNECTION_DELETE) \ + _(FACE_CREATE_CONNECTION_CHECK) \ + _(FACE_CREATE_CONNECTION_GET) \ + _(FACE_CREATE_CONNECTION_VERIFY) \ + _(FACE_CREATE_LISTENER_CREATE) \ + _(FACE_CREATE_LISTENER_CHECK) \ + _(FACE_LIST_CONNECTION_LIST) \ + _(ROUTE_CREATE_FACE_CREATE) \ + _(ROUTE_CREATE_FACE_CHECK) \ + _(ROUTE_CREATE) \ + _(GET_LIST) \ + _(COMPLETE) \ + _(N) + +typedef enum { +#define _(x) REQUEST_STATE_##x, + foreach_request_state +#undef _ +} hc_request_state_t; + +extern const char *hc_request_state_str[]; + +#define hc_request_state_str(x) hc_request_state_str[x] + +/* + * Internal state associated to a pending request + */ +typedef struct hc_request_s hc_request_t; + +hc_request_t *hc_request_create(int seq, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +void hc_request_free(hc_request_t *request); + +void hc_request_set(hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object); + +int hc_request_get_seq(const hc_request_t *request); +hc_request_t *hc_request_get_current(hc_request_t *request); +hc_request_t *hc_request_pop(hc_request_t *request); + +hc_request_state_t hc_request_get_state(const hc_request_t *request); +void hc_request_set_state(hc_request_t *request, hc_request_state_t state); + +int hc_request_get_state_count(const hc_request_t *request); +void hc_request_set_state_count(hc_request_t *request, unsigned count); + +hc_action_t hc_request_get_action(const hc_request_t *request); +hc_object_type_t hc_request_get_object_type(const hc_request_t *request); +hc_object_t *hc_request_get_object(const hc_request_t *request); +hc_data_t *hc_request_get_data(const hc_request_t *request); +void hc_request_set_data(hc_request_t *request, hc_data_t *data); +void hc_request_reset_data(hc_request_t *request); + +bool hc_request_is_subscription(const hc_request_t *request); +bool hc_request_requires_object(const hc_request_t *request); + +// do not free data which might be invalid +// XXX to be removed if we replace "ensure_data_size_and_free" functions and the +// like, with equivalent functions acting on request +void hc_request_clear_data(hc_request_t *request); + +void hc_request_set_complete(hc_request_t *request); +bool hc_request_is_complete(const hc_request_t *request); + +void hc_request_on_complete(hc_request_t *request); +void hc_request_on_notification(hc_request_t *request); + +/* + * Same seq & callbacks + */ +hc_request_t *hc_request_make_subrequest(hc_request_t *request, + hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object); + +#endif /* HC_REQUEST_H */ diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c index 703b4763f..71e39d7ad 100644 --- a/ctrl/libhicnctrl/src/route.c +++ b/ctrl/libhicnctrl/src/route.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,84 +25,64 @@ #define DEFAULT_HICN_ROUTE_COST 1 struct hicn_route_s { - ip_prefix_t prefix; - face_id_t face_id; - route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */ + hicn_ip_prefix_t prefix; + face_id_t face_id; + route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */ }; -hicn_route_t * -hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost) -{ - hicn_route_t * route = malloc(sizeof(hicn_route_t)); - if (!route) - return NULL; - route->prefix = *prefix; - route->face_id = face_id; - route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST; +hicn_route_t* hicn_route_create(hicn_ip_prefix_t* prefix, face_id_t face_id, + route_cost_t cost) { + hicn_route_t* route = malloc(sizeof(hicn_route_t)); + if (!route) return NULL; + route->prefix = *prefix; + route->face_id = face_id; + route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST; - return route; + return route; } -hicn_route_t * -hicn_route_dup(const hicn_route_t * route) -{ - hicn_route_t * new_route = malloc(sizeof(hicn_route_t)); - if (!route) - return NULL; - memcpy(new_route, route, sizeof(hicn_route_t)); - return new_route; +hicn_route_t* hicn_route_dup(const hicn_route_t* route) { + hicn_route_t* new_route = malloc(sizeof(hicn_route_t)); + if (!route) return NULL; + memcpy(new_route, route, sizeof(hicn_route_t)); + return new_route; } -void hicn_route_free(hicn_route_t * route) -{ - free(route); -} +void hicn_route_free(hicn_route_t* route) { free(route); } -int -hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2) -{ - int rc; - rc = ip_prefix_cmp(&route1->prefix, &route2->prefix); - if (rc != 0) - return rc; +int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2) { + int rc; + rc = hicn_ip_prefix_cmp(&route1->prefix, &route2->prefix); + if (rc != 0) return rc; - return (route1->face_id > route2->face_id) ? 1 : - (route1->face_id < route2->face_id) ? -1 : 0; + return (route1->face_id > route2->face_id) ? 1 + : (route1->face_id < route2->face_id) ? -1 + : 0; } -int -hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix) -{ - *prefix = route->prefix; - return 0; +int hicn_route_get_prefix(const hicn_route_t* route, hicn_ip_prefix_t* prefix) { + *prefix = route->prefix; + return 0; } -int -hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix) -{ - route->prefix = prefix; - return 0; +int hicn_route_set_prefix(hicn_route_t* route, const hicn_ip_prefix_t prefix) { + route->prefix = prefix; + return 0; } -int -hicn_route_get_cost(const hicn_route_t * route, int * cost) -{ - *cost = route->cost; - return 0; +int hicn_route_get_cost(const hicn_route_t* route, int* cost) { + *cost = route->cost; + return 0; } -int -hicn_route_set_cost(hicn_route_t * route, const int cost) -{ - route->cost = cost; - return 0; +int hicn_route_set_cost(hicn_route_t* route, const int cost) { + route->cost = cost; + return 0; } /* /!\ Please update constants in header file upon changes */ -size_t -hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route) -{ - char prefix_s[MAXSZ_PREFIX]; - ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_PREFIX); - return snprintf(s, size, "%s [%d]", prefix_s, route->cost); +size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route) { + char prefix_s[MAXSZ_IP_PREFIX]; + hicn_ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_IP_PREFIX); + return snprintf(s, size, "%s [%d]", prefix_s, route->cost); } diff --git a/ctrl/libhicnctrl/src/socket.c b/ctrl/libhicnctrl/src/socket.c new file mode 100644 index 000000000..956dc07c8 --- /dev/null +++ b/ctrl/libhicnctrl/src/socket.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2021-2022 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 socket.c + * \brief Implementation of control socket. + */ + +#include <dlfcn.h> +#include <stdio.h> + +#include <hicn/ctrl/socket.h> +#include <hicn/util/log.h> + +#ifdef ANDROID +/* + * In android we do not load a module at runtime but we link the hicnlight + * implementation directly to the main library. + */ +#include "modules/hicn_light.h" +#endif /* ANDROID */ + +#include "socket_private.h" + +TYPEDEF_MAP(hc_sock_map, int, hc_request_t *, int_cmp, int_snprintf, + generic_snprintf); + +const char *forwarder_type_str[] = { +#define _(x) [FORWARDER_TYPE_##x] = #x, + foreach_forwarder_type +#undef _ +}; + +forwarder_type_t forwarder_type_from_str(const char *str) { + for (forwarder_type_t i = FORWARDER_TYPE_UNDEFINED + 1; i < FORWARDER_TYPE_N; + i++) { + if (strcasecmp(str, forwarder_type_str[i]) == 0) return i; + } + return FORWARDER_TYPE_UNDEFINED; +} + +#ifndef ANDROID +static int hc_sock_set_ops(hc_sock_t *s, const char *name, const char *url) { + char complete_name[128]; +#ifdef __APPLE__ + sprintf(complete_name, "%s.dylib", name); +#elif defined(__linux__) + snprintf(complete_name, 128, "%s.so", name); +#else +#error "System not supported for dynamic lynking" +#endif + + void *handle = 0; + const char *error = 0; + int (*initialize_module)(hc_sock_t *) = 0; + int rc = 0; + + // open module + handle = dlopen(complete_name, RTLD_LAZY); + if (!handle) { + if ((error = dlerror()) != 0) { + ERROR("%s", error); + } + goto ERR_DL; + return -1; + } + s->handle = handle; + + // get factory method + initialize_module = + (int (*)(hc_sock_t *))dlsym(handle, "hc_sock_initialize_module"); + if (!initialize_module) { + if ((error = dlerror()) != 0) { + ERROR("%s", error); + } + goto ERR_INIT; + } + initialize_module(s); + + return rc; +ERR_INIT: + dlclose(s->handle); + s->handle = NULL; +ERR_DL: + return -1; +} +#endif /* ! ANDROID */ + +int hc_sock_is_async(hc_sock_t *s) { return s->async; } + +int hc_sock_set_async(hc_sock_t *s) { + s->async = true; + return 0; +} + +hc_sock_t *hc_sock_create(forwarder_type_t forwarder, const char *url) { +#ifndef ANDROID + int rc; +#endif + + hc_sock_t *s = malloc(sizeof(hc_sock_t)); + if (!s) goto ERR_MALLOC; + +#ifdef ANDROID + assert(forwarder == HICNLIGHT); + s->data = hc_sock_light_data_create(url); + s->handle = NULL; +#else + switch (forwarder) { + case FORWARDER_TYPE_HICNLIGHT: + rc = hc_sock_set_ops(s, "hicnlightctrl_module", url); + break; + case FORWARDER_TYPE_VPP: + rc = hc_sock_set_ops(s, "vppctrl_module", url); + break; + default: + goto ERR_INIT; + } + + if (rc < 0) goto ERR_INIT; + + s->data = s->ops.create_data(url); +#endif + + if (!s->data) goto ERR_DATA; + + s->map = hc_sock_map_create(); + if (!s->map) goto ERR_MAP; + + s->async = false; + + s->seq_request = 0; + s->current_request = NULL; + + return s; + +ERR_MAP: +#ifdef ANDROID + hc_sock_light_data_free(s->data); +#else + ; // XXX VFT() free +#endif +ERR_DATA: +#ifndef ANDROID +ERR_INIT: +#endif + free(s); +ERR_MALLOC: + return NULL; +} + +hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder) { + return hc_sock_create(forwarder, NULL); +} + +void hc_sock_free(hc_sock_t *s) { + if (s->ops.disconnect) s->ops.disconnect(s); +#ifdef ANDROID + hc_sock_light_data_free(s->data); +#else + if (s->ops.free_data) s->ops.free_data(s->data); + if (s->handle) { + dlclose(s->handle); + } +#endif /* ANDROID */ + + hc_request_t **request_array = NULL; + int n = hc_sock_map_get_value_array(s->map, &request_array); + if (n < 0) { + ERROR("Could not retrieve pending request array for freeing up resources"); + } else { + for (unsigned i = 0; i < n; i++) { + hc_request_t *request = request_array[i]; + if (hc_sock_map_remove(s->map, hc_request_get_seq(request), NULL) < 0) + ERROR("[hc_sock_light_process] Error removing request from map"); + hc_request_free(request); + } + free(request_array); + } + + hc_sock_map_free(s->map); + + free(s); +} + +#if 0 +int hc_sock_get_next_seq(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } + +int hc_sock_set_nonblocking(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } + +#endif + +int hc_sock_get_fd(hc_sock_t *s) { return s->ops.get_fd(s); } + +int hc_sock_connect(hc_sock_t *s) { return s->ops.connect(s); } + +int hc_sock_get_recv_buffer(hc_sock_t *s, u8 **buffer, size_t *size) { + return s->ops.get_recv_buffer(s, buffer, size); +} +#if 0 + +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq) { + return s->hc_sock_send(s, msg, msglen, seq); +} + +int hc_sock_recv(hc_sock_t *s) { return s->ops.recv(s); } +#endif + +#if 0 +int hc_sock_process(hc_sock_t *s, hc_data_t **data) { + return s->hc_sock_process(s, data); +} + +int hc_sock_callback(hc_sock_t *s, hc_data_t **data) { + return s->hc_sock_callback(s, data); +} + +int hc_sock_reset(hc_sock_t *s) { return s->hc_sock_reset(s); } + +void hc_sock_increment_woff(hc_sock_t *s, size_t bytes) { + s->hc_sock_increment_woff(s, bytes); +} + +int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, + data_callback_t complete_cb, void *complete_cb_data) { + return s->hc_sock_prepare_send(s, result, complete_cb, complete_cb_data); +} + +int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms) { + return s->hc_sock_set_recv_timeout_ms(s, timeout_ms); +} +#endif + +hc_request_t *hc_sock_create_request(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + /* Create request state */ + int seq = s->seq_request++; + hc_request_t *request = hc_request_create(seq, action, object_type, object, + callback, callback_data); + if (!request) goto ERR_MALLOC; + + hc_request_set_state(request, REQUEST_STATE_INIT); + + // Add state to map + if (hc_sock_map_add(s->map, seq, request) < 0) { + ERROR("[hc_sock_create_request] Error adding request state to map"); + goto ERR_MAP; + } + + return request; + +ERR_MAP: + free(request); +ERR_MALLOC: + return NULL; +} + +hc_request_t *hc_sock_get_request(hc_sock_t *s) { return s->current_request; } + +void hc_sock_free_request(hc_sock_t *s, hc_request_t *request, bool recursive) { + if (hc_sock_map_remove(s->map, hc_request_get_seq(request), NULL) < 0) { + ERROR("[hc_sock_free_request] Error removing request from map"); + } + if (recursive) { + hc_request_t *r = NULL; + do { + r = hc_request_pop(request); + } while (r); + } + hc_request_free(request); + s->current_request = NULL; +} + +/** + * TODO: return code: + * -1 object not found + * -2 action not found + * -3 error during serialization + * + * @return the size of the created message + */ +ssize_t hc_sock_serialize_object(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + hc_serialize_t fn = (s->ops.object_vft[object_type]).serialize[action]; + if (!fn) return -1; + return fn(object, msg); +} + +int hc_sock_parse_object(hc_sock_t *s, hc_object_type_t object_type, + uint8_t *buffer, size_t size, hc_object_t *object) { + return s->ops.object_vft[object_type].parse(buffer, size, object); +} diff --git a/ctrl/libhicnctrl/src/socket_private.h b/ctrl/libhicnctrl/src/socket_private.h new file mode 100644 index 000000000..30f3bcb6e --- /dev/null +++ b/ctrl/libhicnctrl/src/socket_private.h @@ -0,0 +1,47 @@ +#ifndef HICNCTRL_SOCKET_PRIVATE_H +#define HICNCTRL_SOCKET_PRIVATE_H + +#include <hicn/util/map.h> +#include <hicn/ctrl/socket.h> + +#include "module.h" + +TYPEDEF_MAP_H(hc_sock_map, int, hc_request_t *); + +struct hc_sock_s { + int request_seq; + hc_sock_map_t *map; + + bool async; + int seq_request; + + /* + * Stores the current request being parsed in case of fragmented reception or + * analysis (as it is the case now) between header and payload + */ + hc_request_t *current_request; + + hc_sock_ops_t ops; + + void *data; + void *handle; +}; + +hc_request_t *hc_sock_create_request(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +hc_request_t *hc_sock_get_request(hc_sock_t *s); + +void hc_sock_free_request(hc_sock_t *s, hc_request_t *request, bool recursive); + +ssize_t hc_sock_serialize_object(hc_sock_t *sock, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +int hc_sock_parse_object(hc_sock_t *sock, hc_object_type_t object_type, + uint8_t *buffer, size_t size, hc_object_t *object); + +#endif /* HICNCTRL_SOCKET_PRIVATE_H */ diff --git a/ctrl/libhicnctrl/src/test/CMakeLists.txt b/ctrl/libhicnctrl/src/test/CMakeLists.txt new file mode 100644 index 000000000..7fdff476d --- /dev/null +++ b/ctrl/libhicnctrl/src/test/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (c) 2021-2022 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. + +############################################################## +# Test sources +############################################################## +list(APPEND TESTS_SRC + main.cc + common.cc + test_data.cc + test_hicnlight_listener.cc + test_hicnlight_connection.cc + test_hicnlight_route.cc + ../modules/hicn_light/connection.c + ../modules/hicn_light/face.c + ../modules/hicn_light/listener.c + ../modules/hicn_light/route.c +) + +############################################################## +# Build single unit test executable and add it to test list +############################################################## +build_executable(libhicnctrl_tests + NO_INSTALL + SOURCES ${TESTS_SRC} + LINK_LIBRARIES + ${LIBRARIES} + ${LIBHICNCTRL_SHARED} + ${GTEST_LIBRARIES} + pthread + INCLUDE_DIRS + $<TARGET_PROPERTY:${LIBHICNCTRL_SHARED},INCLUDE_DIRECTORIES> + ${GTEST_INCLUDE_DIRS} + DEPENDS gtest ${LIBHICNCTRL_SHARED} + COMPONENT ${LIBHICNCTRL_COMPONENT} + DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} + LINK_FLAGS ${LINK_FLAGS} +) + +add_test_internal(libhicnctrl_tests) diff --git a/ctrl/libhicnctrl/src/test/common.cc b/ctrl/libhicnctrl/src/test/common.cc new file mode 100644 index 000000000..075281d2e --- /dev/null +++ b/ctrl/libhicnctrl/src/test/common.cc @@ -0,0 +1,13 @@ +#include "common.h" + +std::string dump_buffer(const char *name, uint8_t *buffer, size_t size) { + std::ostringstream oss; + oss << "const std::vector<uint8_t> " << name << " = {"; + for (size_t i = 0; i < size; i++) { + if (i > 0) oss << ", "; + oss << "0x" << std::setw(2) << std::setfill('0') << std::hex + << static_cast<int>(buffer[i]); + } + oss << "};" << std::endl; + return oss.str(); +} diff --git a/ctrl/libhicnctrl/src/test/common.h b/ctrl/libhicnctrl/src/test/common.h new file mode 100644 index 000000000..8927c86ec --- /dev/null +++ b/ctrl/libhicnctrl/src/test/common.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef HICNCTRL_TEST_COMMON +#define HICNCTRL_TEST_COMMON + +#define BUFSIZE 8192 + +#include <gtest/gtest.h> + +class TestHicnLight : public ::testing::Test { + protected: + TestHicnLight() {} + virtual ~TestHicnLight() {} + virtual void SetUp() {} + virtual void TearDown() {} +}; + +class TestHicnLightSerialize : public TestHicnLight { + // TestHicnLightSerialize() {} + // virtual ~TestHicnLightSerialize() {} +}; + +class TestHicnLightParse : public TestHicnLight { + // TestHicnLightParse() {} + // virtual ~TestHicnLightParse() {} +}; + +std::string dump_buffer(const char *name, uint8_t *buffer, size_t size); + +#define EXPECT_PAYLOAD_EQ(BUFFER, SIZE, PAYLOAD) \ + EXPECT_EQ(memcmp((BUFFER), &(PAYLOAD)[0], PAYLOAD.size()), 0) \ + << dump_buffer(#PAYLOAD, (BUFFER), SIZE); + +#define EXPECT_PAYLOAD_EQ_STRUCT(BUFFER, SIZE, PAYLOAD) \ + EXPECT_EQ(memcmp((BUFFER), (PAYLOAD), SIZE), 0) \ + << dump_buffer("expected:", (uint8_t *)(BUFFER), SIZE); + +#endif /* HICNCTRL_TEST_COMMON */ diff --git a/ctrl/libhicnctrl/src/test/main.cc b/ctrl/libhicnctrl/src/test/main.cc new file mode 100644 index 000000000..49cc28f66 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/main.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 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 <gtest/gtest.h> + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/ctrl/libhicnctrl/src/test/test_data.cc b/ctrl/libhicnctrl/src/test/test_data.cc new file mode 100644 index 000000000..46debb0e7 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_data.cc @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 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 <gtest/gtest.h> +#include <sstream> + +extern "C" { +#include <hicn/ctrl/objects.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +} + +#include "common.h" + +namespace { + +TEST_F(TestHicnLight, TestHicnLightData) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + + int rc; + hc_data_t* data = hc_data_create(OBJECT_TYPE_FACE); + hc_data_set_max_size(data, 2); + + ASSERT_EQ(hc_data_get_size(data), 0) << "Initial data size should be zero"; + + /* Try to allocate more than max */ + rc = hc_data_allocate(data, 5); + ASSERT_EQ(rc, -1) << "Allocating above max_size should fail"; + + /* Allocate room for two objects */ + rc = hc_data_allocate(data, 2); + ASSERT_EQ(rc, 0) << "Allocating data the first time should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 0) + << "Initial size should be 0 after allocation"; + + /* Try to allocate twice */ + rc = hc_data_allocate(data, 2); + ASSERT_EQ(rc, -1) << "Allocating data multiple times should fail"; + + ASSERT_EQ(hc_data_get_size(data), 0) + << "Size after failed push should remain unchanged"; + + /* Push a first object */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "First push should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 1) + << "Data size first successful push should be 1"; + + /* Push a second object */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "Second push should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 2) + << "Data size after second successful push should be 2"; + + /* Push a third object, exceeding the allocated size */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, -1) << "Third push on full data of size 2 should fail"; + + /* Clear */ + rc = hc_data_clear(data); + ASSERT_EQ(rc, 0) << "Clear should always succeed"; + + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "Pushing element after reallocation should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 1) << "Size after first push should be one"; + // XXX + + /* Try to push an invalid object */ + // XXX so far NULL + rc = hc_data_push(data, NULL); + ASSERT_EQ(rc, -1) << "Pushing invalid element should fail"; + + ASSERT_EQ(hc_data_get_size(data), 1) + << "Size after push failure should remain unchanged"; + // XXX + + hc_data_free(data); +} + +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc new file mode 100644 index 000000000..53dd88ac3 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021-2022 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 <gtest/gtest.h> +#include <sstream> + +#include <hicn/ctrl/object.h> + +#include "../modules/hicn_light/connection.h" +#include "common.h" + +namespace { + +const hc_object_t valid_connection = { + .connection = {.id = 0, + .name = {'l', 's', 't', 0}, + .interface_name = {'l', 'o', 0}, + .netdevice_type = NETDEVICE_TYPE_WIRED, + .type = FACE_TYPE_UDP, + .family = AF_INET, + .local_addr = IPV4_LOOPBACK, + .local_port = 9695, + .remote_addr = IPV4_LOOPBACK, + .remote_port = 9695, + .admin_state = FACE_STATE_UP, + .priority = 0, + .tags = POLICY_TAGS_EMPTY, + .state = FACE_STATE_UP}}; + +const std::vector<uint8_t> valid_connection_create_payload = { + /* header */ + 0xc0, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* ip_address_t remote_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* uint16_t remote_port = 9695; */ + 0x25, 0xdf, + /* int family = AF_INET; */ + 0x02, + /* face_type_t type = FACE_TYPE_UDP_LISTENER; */ + 0x05, + /* uint8_t admin_state = FACE_STATE_UP; */ + 0x02, + /* Padding ? */ + 0x00, + /* uint32_t priority = 0; */ + 0x00, 0x00, 0x00, 0x00, + /* policy_tags_t tags; */ + 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_connection_delete_payload = { + 0xc0, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x73, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_connection_list_payload = { + 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.connection, &valid_connection, sizeof(hc_connection_t)); + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + // XXX debug + // THIS HAS UNINIT VALUES + std::cout << "n=" << n << std::endl; + EXPECT_EQ(memcmp(buf, buf, 60), 0); + EXPECT_EQ(memcmp(buf, buf, 62), 0); + EXPECT_EQ(memcmp(buf, buf, 64), 0); // XXX we start having issues + EXPECT_EQ(memcmp(buf, buf, 66), 0); + EXPECT_EQ(memcmp(buf, buf, 68), 0); + EXPECT_EQ(memcmp(buf, buf, 70), 0); + EXPECT_EQ(memcmp(buf, buf, 72), 0); + // XXX debug + + EXPECT_EQ(n, valid_connection_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_create_payload); +} + +// TODO +// - create with id != 0 +// - create with invalid fields, non zero-terminated strings, etc. + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.connection, &valid_connection, sizeof(hc_connection_t)); + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_connection_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionList) { + uint8_t buf[BUFSIZE]; + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_LIST]; + size_t n = fn(NULL, buf); + + EXPECT_EQ(n, valid_connection_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_list_payload); +} + +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc new file mode 100644 index 000000000..fb3df39a8 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021-2022 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 <sstream> + +extern "C" { +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/listener.h> +#include "../modules/hicn_light/listener.h" +} + +#include "common.h" + +namespace { + +static const hc_object_t valid_listener = { + .listener = {.name = {'l', 's', 't', 0}, + .interface_name = {'l', 'o', 0}, + .id = 0, + .type = FACE_TYPE_UDP_LISTENER, + .family = AF_INET, + .local_addr = IPV4_LOOPBACK, + .local_port = 9695}}; + +const std::vector<uint8_t> valid_listener_create_payload = { + /* header */ + 0xc0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* char interface_name[INTERFACE_LEN] = "lo"; */ + 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* int family = AF_INET; */ + 0x02, + /* face_type_t type = FACE_TYPE_UDP_LISTENER; */ + 0x06}; + +const std::vector<uint8_t> valid_listener_delete_payload = { + /* header */ + 0xc0, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char symbolicOrListenerid[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_listener_list_payload = { + /* header */ + 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* @see <hicn/ctrl/objects/listener.h> */ +const std::vector<uint8_t> valid_listener_payload = { + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* char interface_name[INTERFACE_LEN] = "lo"; */ + 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint32_t id = 0; */ + 0x00, 0x00, 0x00, 0x00, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* face_type_t type = FACE_TYPE_UDP */ + 0x06, + /* int family = AF_INET; */ + 0x02}; + +TEST_F(TestHicnLightParse, TestHicnLightParseListener) { + /* Parse payload into an object */ + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + int rc = hicnlight_listener_module_ops.parse( + &valid_listener_payload[0], valid_listener_payload.size(), &obj); + EXPECT_EQ(rc, 0); + EXPECT_EQ(hc_listener_cmp(&obj.listener, &valid_listener.listener), 0); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_create_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerList) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_LIST]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_list_payload); +} +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc new file mode 100644 index 000000000..d48066ba2 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-2022 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 <gtest/gtest.h> +#include <sstream> + +extern "C" { +#include <hicn/ctrl/object.h> +#include "../modules/hicn_light/route.h" +} + +#include "common.h" + +namespace { + +const hc_object_t valid_route = { + .route = {.face_id = 1, + .face_name = {0}, // NULL, use face_id instead + .family = AF_INET, + .remote_addr = IPV4_LOOPBACK, + .len = 16, + .cost = 1, + .face = {0}}}; + +const std::vector<uint8_t> valid_route_create_payload = { + /* uint8_t message_type = REQUEST_LIGHT */ + 0xc0, + /* uint8_t command_id = COMMAND_TYPE_ROUTE_ADD */ + 0x08, + /* uint16_t length = 1 */ + 0x01, 0x00, + /* uint32_t seq_num = 0 */ + 0x00, 0x00, 0x00, 0x00, + /* char symbolic_or_connid[16] = "1\0" */ + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* hicn_ip_address_t address = {0, 0, 0, 127.0.0.1} */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* */ + 0x01, + /* */ + 0x00, + /* */ + 0x02, + /* */ + 0x10}; + +const std::vector<uint8_t> valid_route_delete_payload = { + /* uint8_t message_type = REQUEST_LIGHT */ + 0xc0, + /* uint8_t command_id = COMMAND_TYPE_ROUTE_REMOVE */ + 0x09, + /* uint16_t length = 1 */ + 0x01, 0x00, + /* uint32_t seq_num = 0 */ + 0x00, 0x00, 0x00, 0x00, + + /* char symbolic_or_connid[16] = "1\0" */ + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* hicn_ip_address_t address = {0, 0, 0, 127.0.0.1} */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint8_t family = AF_INET (2) */ + 0x02, + /* uint8_t len = 16 */ + 0x10, + /* 2-byte padding */ + 0x00, 0x00}; + +const std::vector<uint8_t> valid_route_list_payload = {0xc0, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_create_payload); +} + +// TODO +// - create with id != 0 +// - create with invalid fields, non zero-terminated strings, etc. + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteList) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_LIST]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_list_payload); +} + +} // namespace diff --git a/ctrl/libhicnctrl/src/util/hash.h b/ctrl/libhicnctrl/src/util/hash.h index 7c7bb1e3a..f3a1eedcc 100644 --- a/ctrl/libhicnctrl/src/util/hash.h +++ b/ctrl/libhicnctrl/src/util/hash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -27,67 +27,88 @@ #ifndef UTIL_HASH_H #define UTIL_HASH_H -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 + defined(__i586__) || defined(__i686__) || defined(vax) || \ + defined(MIPSEL)) +#define HASH_LITTLE_ENDIAN 1 +#define HASH_BIG_ENDIAN 0 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 1 #else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 0 #endif -#define hashsize(n) ((uint32_t)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -#define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} +#define hashsize(n) ((uint32_t)1 << (n)) +#define hashmask(n) (hashsize(n) - 1) +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) -#define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} +#define mix(a, b, c) \ + { \ + a -= c; \ + a ^= rot(c, 4); \ + c += b; \ + b -= a; \ + b ^= rot(a, 6); \ + a += c; \ + c -= b; \ + c ^= rot(b, 8); \ + b += a; \ + a -= c; \ + a ^= rot(c, 16); \ + c += b; \ + b -= a; \ + b ^= rot(a, 19); \ + a += c; \ + c -= b; \ + c ^= rot(b, 4); \ + b += a; \ + } -static inline -uint32_t hashlittle( const void *key, size_t length, uint32_t initval) -{ - uint32_t a,b,c; /* internal state */ - union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ +#define final(a, b, c) \ + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } + +static inline uint32_t hashlittle(const void *key, size_t length, + uint32_t initval) { + uint32_t a, b, c; /* internal state */ + union { + const void *ptr; + size_t i; + } u; /* needed for Mac Powerbook G4 */ /* Set up the internal state */ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; u.ptr = key; if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { + while (length > 12) { a += k[0]; b += k[1]; c += k[2]; - mix(a,b,c); + mix(a, b, c); length -= 12; k += 3; } @@ -104,136 +125,214 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) */ #ifndef VALGRIND - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : return c; /* zero length strings require no mixing */ + switch (length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += k[2] & 0xffffff; + b += k[1]; + a += k[0]; + break; + case 10: + c += k[2] & 0xffff; + b += k[1]; + a += k[0]; + break; + case 9: + c += k[2] & 0xff; + b += k[1]; + a += k[0]; + break; + case 8: + b += k[1]; + a += k[0]; + break; + case 7: + b += k[1] & 0xffffff; + a += k[0]; + break; + case 6: + b += k[1] & 0xffff; + a += k[0]; + break; + case 5: + b += k[1] & 0xff; + a += k[0]; + break; + case 4: + a += k[0]; + break; + case 3: + a += k[0] & 0xffffff; + break; + case 2: + a += k[0] & 0xffff; + break; + case 1: + a += k[0] & 0xff; + break; + case 0: + return c; /* zero length strings require no mixing */ } #else /* make valgrind happy */ k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : return c; + switch (length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += ((uint32_t)k8[9]) << 8; /* fall through */ + case 9: + c += k8[8]; /* fall through */ + case 8: + b += k[1]; + a += k[0]; + break; + case 7: + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6: + b += ((uint32_t)k8[5]) << 8; /* fall through */ + case 5: + b += k8[4]; /* fall through */ + case 4: + a += k[0]; + break; + case 3: + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2: + a += ((uint32_t)k8[1]) << 8; /* fall through */ + case 1: + a += k8[0]; + break; + case 0: + return c; } #endif /* !valgrind */ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); + while (length > 12) { + a += k[0] + (((uint32_t)k[1]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + c += k[4] + (((uint32_t)k[5]) << 16); + mix(a, b, c); length -= 12; k += 6; } /*----------------------------- handle the last (probably partial) block */ k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : return c; /* zero length requires no mixing */ + switch (length) { + case 12: + c += k[4] + (((uint32_t)k[5]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += k[4]; + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 9: + c += k8[8]; /* fall through */ + case 8: + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 7: + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6: + b += k[2]; + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 5: + b += k8[4]; /* fall through */ + case 4: + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 3: + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2: + a += k[0]; + break; + case 1: + a += k8[0]; + break; + case 0: + return c; /* zero length requires no mixing */ } - } else { /* need to read the key one byte at a time */ + } else { /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { + while (length > 12) { a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; + a += ((uint32_t)k[1]) << 8; + a += ((uint32_t)k[2]) << 16; + a += ((uint32_t)k[3]) << 24; b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; + b += ((uint32_t)k[5]) << 8; + b += ((uint32_t)k[6]) << 16; + b += ((uint32_t)k[7]) << 24; c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); + c += ((uint32_t)k[9]) << 8; + c += ((uint32_t)k[10]) << 16; + c += ((uint32_t)k[11]) << 24; + mix(a, b, c); length -= 12; k += 12; } /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ + switch (length) /* all the case statements fall through */ { - case 12: c+=((uint32_t)k[11])<<24; - case 11: c+=((uint32_t)k[10])<<16; - case 10: c+=((uint32_t)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((uint32_t)k[7])<<24; - case 7 : b+=((uint32_t)k[6])<<16; - case 6 : b+=((uint32_t)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3])<<24; - case 3 : a+=((uint32_t)k[2])<<16; - case 2 : a+=((uint32_t)k[1])<<8; - case 1 : a+=k[0]; - break; - case 0 : return c; + case 12: + c += ((uint32_t)k[11]) << 24; + case 11: + c += ((uint32_t)k[10]) << 16; + case 10: + c += ((uint32_t)k[9]) << 8; + case 9: + c += k[8]; + case 8: + b += ((uint32_t)k[7]) << 24; + case 7: + b += ((uint32_t)k[6]) << 16; + case 6: + b += ((uint32_t)k[5]) << 8; + case 5: + b += k[4]; + case 4: + a += ((uint32_t)k[3]) << 24; + case 3: + a += ((uint32_t)k[2]) << 16; + case 2: + a += ((uint32_t)k[1]) << 8; + case 1: + a += k[0]; + break; + case 0: + return c; } } - final(a,b,c); + final(a, b, c); return c; } @@ -241,7 +340,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) #define HASH_INITVAL 1 //#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL) -#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL) +#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL) #define hash_struct(buf) hash(buf, sizeof(buf)) #endif /* UTIL_JENKINS_HASH_H */ diff --git a/ctrl/sysrepo-plugins/AUTHORS b/ctrl/sysrepo-plugins/AUTHORS deleted file mode 100644 index 35097a36c..000000000 --- a/ctrl/sysrepo-plugins/AUTHORS +++ /dev/null @@ -1,5 +0,0 @@ -hicn sysrepo plugin authors are listed below: - - Masoud Hemmatpour <mhemmatp@cisco.com> - Alberto Compagno <acompagn@cisco.com> - Luca Muscariello <lumuscar@cisco.com> diff --git a/ctrl/sysrepo-plugins/CMakeLists.txt b/ctrl/sysrepo-plugins/CMakeLists.txt deleted file mode 100644 index 2412d5688..000000000 --- a/ctrl/sysrepo-plugins/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 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. -# - -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -project(hicn_sysrepo_plugin) - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" -"${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules" -) - -include(GNUInstallDirs) -include(BuildMacros) - -find_package(PkgConfig REQUIRED) -find_package(Sysrepo REQUIRED) - -if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") - message(FATAL_ERROR "Sysrepo plugin supported only on Linux systems") -endif() - -if (NOT SRPD_PLUGINS_PATH) - if (PKG_CONFIG_FOUND) - execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} "--variable=SRPD_PLUGINS_PATH" "libsysrepo" OUTPUT_VARIABLE SRPD_PLUGINS_PATH) - string(STRIP ${SRPD_PLUGINS_PATH} SRPD_PLUGINS_PATH) - endif() -endif() - -if (NOT SRPD_PLUGINS_PATH) - message(FATAL_ERROR "Cannot get sysrepo plugins directory due to missing pkg-config, set SRPD_PLUGINS_PATH manually.") -endif() - -find_package(Vpp REQUIRED) - -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_package(HicnPlugin REQUIRED) -else() - list(APPEND DEPENDENCIES - hicn_plugin - ) -endif() - -add_subdirectory(hicn-plugin) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/yang/hicn/hicn.yang - ${CMAKE_CURRENT_SOURCE_DIR}/yang/ietf/iana-if-type@2014-05-08.yang - ${CMAKE_CURRENT_SOURCE_DIR}/yang/ietf/ietf-interfaces.yang - ${CMAKE_CURRENT_SOURCE_DIR}/yang/ietf/ietf-ip@2014-06-16.yang - ${CMAKE_CURRENT_SOURCE_DIR}/yang/ietf/ietf-yang-types@2013-07-15.yang - DESTINATION ${CMAKE_INSTALL_LIBDIR}/modules_yang/ - COMPONENT hicn-sysrepo-plugin) - - -include(Packaging) -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - include(Packager) - make_packages() -endif() diff --git a/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake b/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake deleted file mode 100644 index 323c9d01a..000000000 --- a/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# 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. - -###################### -# Packages section -###################### - -set(hicn-sysrepo-plugin_DESCRIPTION - "A Plugin to enable hICN VPP in sysrepo." - CACHE STRING "Description for deb/rpm package." -) - -set(hicn-sysrepo-plugin_DEB_DEPENDENCIES - "hicn-plugin (>= stable_version-release), sysrepo (>= 1.0)" - CACHE STRING "Dependencies for deb/rpm package." -) - -set(hicn-sysrepo-plugin_RPM_DEPENDENCIES - "hicn-plugin >= stable_version-release, sysrepo >= 1.0" - CACHE STRING "Dependencies for deb/rpm package." -) diff --git a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt deleted file mode 100644 index 5ba7045c1..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright (c) 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. -# - -# set compiler options -set(CMAKE_EXPORT_COMPILE_COMMANDS 1) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=gnu99") -set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2") -set(CMAKE_C_FLAGS_DEBUG "-g -O0") -set (CMAKE_INSTALL_LIBDIR "/usr/lib") - -project(sysrepo-light-plugins) - -# Cmake find modules -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake/Modules" -"${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Modules" -) - -find_package(PkgConfig) -find_package(HicnLight) -find_package(Sysrepo) - -#pkg_check_modules(SYSREPO libsysrepo) - -# get sysrepo plugins directory from pkgconfig -if (NOT SR_PLUGINS_DIR) - if (PKG_CONFIG_FOUND) - execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} "--variable=SR_PLUGINS_DIR" "libsysrepo" OUTPUT_VARIABLE SR_PLUGINS_DIR) - string(STRIP ${SR_PLUGINS_DIR} SR_PLUGINS_DIR) - endif() -endif() -if (NOT SR_PLUGINS_DIR) - message(FATAL_ERROR "Cannot get sysrepo plugins directory due to missing pkg-config, set SR_PLUGINS_DIR manually.") -endif() - -# plugins sources -set(PLUGINS_SOURCES - plugin/model/hicn_model.c - plugin/model/tlock.c - plugin/hicn_light_comm.c - plugin/hicn_light.c -) - -# build the source code into shared library -add_library(hicnlight SHARED ${PLUGINS_SOURCES}) -target_include_directories(hicnlight PUBLIC ${HICNLIGHT_INCLUDE_DIRS}) -target_link_libraries(hicnlight ${SYSREPO_LIBRARIES} ${HICNLIGHT_LIBRARIES}) - -# install the plugin into plugins dir -install(TARGETS hicnlight DESTINATION ${SR_PLUGINS_DIR} COMPONENT hicn_sysrepo_plugin) diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt deleted file mode 100644 index 85da0d3e9..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (c) 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. -# - -# set compiler options -set(CMAKE_EXPORT_COMPILE_COMMANDS 1) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=gnu99") -set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2") -set(CMAKE_C_FLAGS_DEBUG "-g -O0") -set (CMAKE_INSTALL_LIBDIR "/usr/lib") - -project(sysrepo-light-plugins) - -# Cmake find modules -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake") - -find_package(PkgConfig) -find_package(HicnLight) -find_package(Sysrepo) - -#pkg_check_modules(SYSREPO libsysrepo) - -# get sysrepo plugins directory from pkgconfig -if (NOT SR_PLUGINS_DIR) - if (PKG_CONFIG_FOUND) - execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} "--variable=SR_PLUGINS_DIR" "libsysrepo" OUTPUT_VARIABLE SR_PLUGINS_DIR) - string(STRIP ${SR_PLUGINS_DIR} SR_PLUGINS_DIR) - endif() -endif() -if (NOT SR_PLUGINS_DIR) - message(FATAL_ERROR "Cannot get sysrepo plugins directory due to missing pkg-config, set SR_PLUGINS_DIR manually.") -endif() - -# plugins sources -set(PLUGINS_SOURCES - model/hicn_model.c - model/tlock.c - hicn_light_comm.c - hicn_light.c -) - -# build the source code into shared library -add_library(hicnlight SHARED ${PLUGINS_SOURCES}) -target_include_directories(hicnlight PUBLIC ${HICNLIGHT_INCLUDE_DIRS}) -target_link_libraries(hicnlight ${SYSREPO_LIBRARIES} ${HICNLIGHT_LIBRARIES}) - -# install the plugin into plugins dir -install(TARGETS hicnlight DESTINATION ${SR_PLUGINS_DIR} COMPONENT hicn_sysrepo_plugin)
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c deleted file mode 100644 index 6cfc0b52b..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 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 <inttypes.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "hicn_light.h" -#include "model/hicn_model.h" - - - -sr_subscription_ctx_t *subscription = NULL; -volatile int exit_application = 0; - -int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) { - sr_subscription_ctx_t *subscription = NULL; - int rc = SR_ERR_OK; - rc = hicn_connect_light(); - if (SR_ERR_OK != rc) { - HICN_LOG_ERR("hicn light connect error , with return %d.", rc); - return SR_ERR_INTERNAL; - } - - hicn_subscribe_events(session, &subscription); - - - /* set subscription as our private context */ - *private_ctx = subscription; - return SR_ERR_OK; -} - -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx) { - /* subscription was set as our private context */ - sr_unsubscribe(private_ctx); - HICN_LOG_DBG_MSG("hicn light unload plugin ok."); - hicn_disconnect_light(); - HICN_LOG_DBG_MSG("hicn light disconnect ok."); -} - -static void sigint_handler(int signum) { exit_application = 1; } -int subscribe_all_module_events(sr_session_ctx_t *session) { - sr_plugin_init_cb(session, (void **)&subscription); - return 0; -} - -int main(int argc, char **argv) { - sr_conn_ctx_t *connection = NULL; - sr_session_ctx_t *session = NULL; - int rc = SR_ERR_OK; - - /* connect to hicn light */ - rc = hicn_connect_light(); - if (-1 == rc) { - fprintf(stderr, "hicn light connect error"); - return -1; - } - - /* connect to sysrepo */ - rc = sr_connect(SR_CONN_DEFAULT, &connection); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* start session */ - rc = sr_session_start(connection, SR_DS_STARTUP, &session); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* subscribe all module events */ - rc = subscribe_all_module_events(session); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by subscribe module events: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* loop until ctrl-c is pressed / SIGINT is received */ - signal(SIGINT, sigint_handler); - signal(SIGPIPE, SIG_IGN); - - while (!exit_application) { - sleep(2); - } - - printf("Application exit requested, exiting.\n"); - -cleanup: - if (NULL != subscription) { - sr_unsubscribe(subscription); - } - if (NULL != session) { - sr_session_stop(session); - } - if (NULL != connection) { - sr_disconnect(connection); - } - hicn_disconnect_light(); - return rc; -}
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h deleted file mode 100644 index ca67cf0b7..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 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. - */ - -#ifndef __HICN_LIGHT_COMMM_H__ -#define __HICN_LIGHT_COMMM_H__ -#include <sysrepo.h> -#include <sysrepo/values.h> - - -#include <hicn/ctrl/api.h> - -#ifndef HICN_THIS_FUNC -#ifdef __FUNCTION__ -#define HICN_THIS_FUNC __FUNCTION__ -#else -#define HICN_THIS_FUNC __func__ -#endif -#endif - -#define ARG_CHECK(retval, arg) \ - do { \ - if (NULL == (arg)) { \ - HICN_LOG_ERR_MSG(#arg ":NULL pointer passed."); \ - return (retval); \ - } \ - } while (0) - - - -#define ARG_CHECK2(retval, arg1, arg2) \ - ARG_CHECK(retval, arg1); \ - ARG_CHECK(retval, arg2) - -#define ARG_CHECK5(retval, arg1, arg2, arg3, arg4, arg5) \ - ARG_CHECK(retval, arg1); \ - ARG_CHECK(retval, arg2); \ - ARG_CHECK(retval, arg3); \ - ARG_CHECK(retval, arg4); \ - ARG_CHECK(retval, arg5) - - -#define MEM_ALIGN 4096 - -int hicn_connect_light(); -int hicn_disconnect_light(); -extern hc_sock_t * hsocket; -#endif //__HICN_LIGHT_COMMM_H__ diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c deleted file mode 100644 index 47e07d196..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 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 <stdio.h> -#include <malloc.h> -#include <sysrepo/xpath.h> - -/* Hicn headers */ - -#include "hicn_model.h" -#include "tlock.h" -#include "../hicn_light.h" -#include "../hicn_light_comm.h" - - - -/** - * @brief API to add hicn face ip in hicn-light. - */ -static int hicn_face_ip_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) { - - SRP_LOG_DBGMSG("hicn face ip add received successfully"); - hc_face_t face; - if(strcmp(input[0].data.string_val,"-1")){ - - struct sockaddr_in sa; - // store this IP address in sa: - inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); - face.face.family=AF_INET; - face.face.local_addr.v4.as_inaddr=sa.sin_addr; - - - }else if(strcmp(input[1].data.string_val,"-1")){ - - struct in6_addr *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, input[1].data.string_val, dst); - face.face.family=AF_INET6; - face.face.local_addr.v6.as_in6addr = *dst; - - }else{ - SRP_LOG_DBGMSG("Invalid local IP address"); - return SR_ERR_OPERATION_FAILED; - } - - if(strcmp(input[2].data.string_val,"-1")){ - - struct sockaddr_in sa; - // store this IP address in sa: - inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr)); - face.face.family=AF_INET; - face.face.remote_addr.v4.as_inaddr=sa.sin_addr; - - - }else if(strcmp(input[3].data.string_val,"-1")){ - - struct in6_addr *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, input[3].data.string_val, dst); - face.face.family=AF_INET6; - face.face.remote_addr.v6.as_in6addr = *dst; - - }else{ - SRP_LOG_DBGMSG("Invalid local IP address"); - return SR_ERR_OPERATION_FAILED; - } - - - face.face.netdevice.index = input[4].data.uint32_val; // This is the idx number of interface - - - face.id=0;//can be empty - strcpy(face.name,"hicn_face"); - face.face.type=1; - - int rc; - rc = hc_face_create(hsocket, &face); - if (rc > 0) { - SRP_LOG_DBGMSG("Face added successfully"); - return SR_ERR_OK; - } - - SRP_LOG_DBGMSG("Operation Failed"); - return SR_ERR_OPERATION_FAILED; -} - -/** - * @brief API to del hicn face ip in vpp. - */ -static int hicn_face_ip_del_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) { - - SRP_LOG_DBGMSG("hicn face ip del received successfully"); - face_t * face=NULL; - - - face_free(face); - - - - SRP_LOG_DBGMSG("Operation Failed"); - return SR_ERR_OPERATION_FAILED; - -} - - -/** - * @brief API to del hicn face ip in vpp. - */ -static int hicn_route_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) { - -/* - - SRP_LOG_DBG_MSG("hicn route add received successfully"); - - hc_route_t * route; - - if(strcmp(input[0].data.string_val,"-1")){ - - struct sockaddr_in sa; - // store this IP address in sa: - inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); - route.family=AF_INET; - route.face.hicn.local_addr.v4.as_inaddr=sa.sin_addr; - - - }else if(strcmp(input[1].data.string_val,"-1")){ - - struct in6_addr *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, input[1].data.string_val, dst); - face.face.hicn.family=AF_INET6; - face.face.hicn.local_addr.v6.as_in6addr = *dst; - - }else{ - SRP_LOG_DBG_MSG("Invalid local IP address"); - return SR_ERR_OPERATION_FAILED; - } - - -hc_route_create(hsocket, route); -*/ - return SR_ERR_OK; -} - - - -int hicn_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription) { - - - int rc; - rc = sr_rpc_subscribe(session, "/hicn:face-ip-add", hicn_face_ip_add_cb, - session, 100,SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription stat-get\n"); - goto error; - } - - - rc = sr_rpc_subscribe(session, "/hicn:face-ip-del", hicn_face_ip_del_cb, - session, 100,SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription face-ip-del\n"); - goto error; - } - - - rc = sr_rpc_subscribe(session, "/hicn:route-nhops-add", - hicn_route_add_cb, session, 100,SR_SUBSCR_CTX_REUSE, subscription); - if (rc!= SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription route-nhops-add\n"); - goto error; - } - - - SRP_LOG_DBGMSG("hicn light initialized successfully."); - return SR_ERR_OK; - -error: - SRP_LOG_ERRMSG("Error by initialization of the hicn plugin."); - sr_plugin_cleanup_cb(session, hsocket); - return rc; - -} diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h deleted file mode 100644 index e6e857bff..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 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. - */ - -#ifndef __IETF_HICN_H__ -#define __IETF_HICN_H__ - -#include "../hicn_light_comm.h" - - -#define MEM_ALIGN 4096 - -// Number of locks is equal to number of nodes in hicn-state -// It is a coarse grain approach later can be changed to fine grained -// better to initialize the lock by 0 -#define NLOCKS 5 -#define LOCK_INIT 0 - - -enum locks_name {lstate, lstrategy, lstrategies, lroute, lface_ip_params}; - -#define NSTATE_LEAVES 15 -#define NSTRATEGY_LEAVES 1 -#define NSTRATEGIES_LEAVES 2 -#define NROUTE_LEAVES 2 -#define NFACE_IP_PARAMS_LEAVES 3 - -int hicn_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription); - -#endif /* __IETF_HICN_H__ */
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c b/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c deleted file mode 100644 index 2f7b11efa..000000000 --- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c +++ /dev/null @@ -1,21 +0,0 @@ -#include"tlock.h" - - -void Ticket_init ( int Lock_Number , long int init ){ - -__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST ); -__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST ); -//En[Lock_Number]=init; -//De[Lock_Number]=init; -} - -void Ticket_Lock(int Lock_Number ){ - - int my_ticket = __sync_fetch_and_add(&En[Lock_Number] , 1 ); - while ( my_ticket != De[ Lock_Number ] ) {}; - -} - -void Ticket_Unlock(int Lock_Number ){ -De[Lock_Number]++; -} diff --git a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt deleted file mode 100644 index 10e106f51..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (c) 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. - -# Cmake find modules -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Modules" - "${CMAKE_CURRENT_LIST_DIR}/../cmake/Modules" -) - -# plugins sources -set(SOURCE_FILES - plugin/ietf/ietf_interface.c - plugin/model/hicn_model.c - plugin/model/tlock.c - plugin/hicn_vpp_comm.c - plugin/hicn_plugin.c -) - -list(APPEND SYSREPO_PLUGIN_INCLUDE_DIRS - ${VPP_INCLUDE_DIRS} - ${HICNPLUGIN_INCLUDE_DIRS} - ${SYSREPO_INCLUDE_DIRS} -) - -list(APPEND LIBRARIES - ${SYSREPO_LIBRARIES} - ${VPP_LIBRARIES} -) - -build_library(sysrepohicn - SHARED - SOURCES ${SOURCE_FILES} - LINK_LIBRARIES ${LIBRARIES} - DEPENDS ${DEPENDENCIES} - COMPONENT hicn-sysrepo-plugin - INCLUDE_DIRS ${SYSREPO_PLUGIN_INCLUDE_DIRS} - INSTALL_FULL_PATH_DIR ${SRPD_PLUGINS_PATH} - DEFINITIONS ${COMPILER_DEFINITIONS} -)
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/Doxyfile b/ctrl/sysrepo-plugins/hicn-plugin/Doxyfile deleted file mode 100644 index 61e503c1f..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/Doxyfile +++ /dev/null @@ -1,2494 +0,0 @@ -# Doxyfile 1.8.13 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "hICN Sysrepo plugin" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 0 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if <section_label> ... \endif and \cond <section_label> -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = plugin/ plugin/model - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f \ - *.for \ - *.tcl \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# <filter> <input-file> -# -# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use <access key> + S -# (what the <access key> is depends on the OS and browser, but it is typically -# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down -# key> to jump into the search results window, the results can be navigated -# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel -# the search. The filter options can be selected when the cursor is inside the -# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> -# to select a filter and <Enter> or <escape> to activate or cancel the filter -# option. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There -# are two flavors of web server based searching depending on the EXTERNAL_SEARCH -# setting. When disabled, doxygen will generate a PHP script for searching and -# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing -# and searching needs to be provided by external tools. See the section -# "External Indexing and Searching" for details. -# The default value is: NO. -# This tag requires that the tag SEARCHENGINE is set to YES. - -SERVER_BASED_SEARCH = NO - -# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP -# script for searching. Instead the search results are written to an XML file -# which needs to be processed by an external indexer. Doxygen will invoke an -# external search engine pointed to by the SEARCHENGINE_URL option to obtain the -# search results. -# -# Doxygen ships with an example indexer (doxyindexer) and search engine -# (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). -# -# See the section "External Indexing and Searching" for details. -# The default value is: NO. -# This tag requires that the tag SEARCHENGINE is set to YES. - -EXTERNAL_SEARCH = NO - -# The SEARCHENGINE_URL should point to a search engine hosted by a web server -# which will return the search results when EXTERNAL_SEARCH is enabled. -# -# Doxygen ships with an example indexer (doxyindexer) and search engine -# (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and -# Searching" for details. -# This tag requires that the tag SEARCHENGINE is set to YES. - -SEARCHENGINE_URL = - -# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed -# search data is written to a file for indexing by an external tool. With the -# SEARCHDATA_FILE tag the name of this file can be specified. -# The default file is: searchdata.xml. -# This tag requires that the tag SEARCHENGINE is set to YES. - -SEARCHDATA_FILE = searchdata.xml - -# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the -# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is -# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple -# projects and redirect the results back to the right project. -# This tag requires that the tag SEARCHENGINE is set to YES. - -EXTERNAL_SEARCH_ID = - -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen -# projects other than the one defined by this configuration file, but that are -# all added to the same external search index. Each project needs to have a -# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of -# to a relative location where the documentation can be found. The format is: -# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... -# This tag requires that the tag SEARCHENGINE is set to YES. - -EXTRA_SEARCH_MAPPINGS = - -#--------------------------------------------------------------------------- -# Configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. -# The default value is: YES. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: latex. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. -# -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate -# index for LaTeX. -# The default file is: makeindex. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX -# documents. This may be useful for small projects and may help to save some -# trees in general. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used by the -# printer. -# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x -# 14 inches) and executive (7.25 x 10.5 inches). -# The default value is: a4. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. The package can be specified just -# by its name or with the correct syntax as to be used with the LaTeX -# \usepackage command. To get the times font for instance you can specify : -# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} -# To use the option intlimits with the amsmath package you can specify: -# EXTRA_PACKAGES=[intlimits]{amsmath} -# If left blank no extra packages will be included. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. -# -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See -# LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_FOOTER = - -# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# LaTeX style sheets that are included after the standard style sheets created -# by doxygen. Using this option one can overrule certain style aspects. Doxygen -# will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_EXTRA_STYLESHEET = - -# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the LATEX_OUTPUT output -# directory. Note that the files will be copied as-is; there are no commands or -# markers available. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_EXTRA_FILES = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is -# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will -# contain links (just like the HTML output) instead of page references. This -# makes the output suitable for online browsing using a PDF viewer. -# The default value is: YES. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. -# The default value is: YES. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_BATCHMODE = NO - -# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the -# index chapters (such as File Index, Compound Index, etc.) in the output. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_HIDE_INDICES = NO - -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. -# The default value is: plain. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_BIB_STYLE = plain - -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The -# RTF output is optimized for Word 97 and may not look too pretty with other RTF -# readers/editors. -# The default value is: NO. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: rtf. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF -# documents. This may be useful for small projects and may help to save some -# trees in general. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will -# contain hyperlink fields. The RTF file will contain links (just like the HTML -# output) instead of page references. This makes the output suitable for online -# browsing using Word or some other Word compatible readers that support those -# fields. -# -# Note: WordPad (write) and others do not support links. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. -# -# See also section "Doxygen usage" for information on how to generate the -# default style sheet that doxygen normally uses. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_EXTENSIONS_FILE = - -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for -# classes and files. -# The default value is: NO. - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. A directory man3 will be created inside the directory specified by -# MAN_OUTPUT. -# The default directory is: man. -# This tag requires that the tag GENERATE_MAN is set to YES. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to the generated -# man pages. In case the manual section does not start with a number, the number -# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is -# optional. -# The default value is: .3. -# This tag requires that the tag GENERATE_MAN is set to YES. - -MAN_EXTENSION = .3 - -# The MAN_SUBDIR tag determines the name of the directory created within -# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by -# MAN_EXTENSION with the initial . removed. -# This tag requires that the tag GENERATE_MAN is set to YES. - -MAN_SUBDIR = - -# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it -# will generate one additional man file for each entity documented in the real -# man page(s). These additional files only source the real man page, but without -# them the man command would be unable to find the correct page. -# The default value is: NO. -# This tag requires that the tag GENERATE_MAN is set to YES. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that -# captures the structure of the code including all documentation. -# The default value is: NO. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: xml. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_OUTPUT = xml - -# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program -# listings (including syntax highlighting and cross-referencing information) to -# the XML output. Note that enabling this will significantly increase the size -# of the XML output. -# The default value is: YES. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the DOCBOOK output -#--------------------------------------------------------------------------- - -# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files -# that can be used to generate PDF. -# The default value is: NO. - -GENERATE_DOCBOOK = NO - -# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in -# front of it. -# The default directory is: docbook. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_OUTPUT = docbook - -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - -#--------------------------------------------------------------------------- -# Configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sf.net) file that captures the -# structure of the code including all documentation. Note that this feature is -# still experimental and incomplete at the moment. -# The default value is: NO. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module -# file that captures the structure of the code including all documentation. -# -# Note that this feature is still experimental and incomplete at the moment. -# The default value is: NO. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary -# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI -# output from the Perl module output. -# The default value is: NO. -# This tag requires that the tag GENERATE_PERLMOD is set to YES. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely -# formatted so it can be parsed by a human reader. This is useful if you want to -# understand what is going on. On the other hand, if this tag is set to NO, the -# size of the Perl module output will be much smaller and Perl will parse it -# just the same. -# The default value is: YES. -# This tag requires that the tag GENERATE_PERLMOD is set to YES. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file are -# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful -# so different doxyrules.make files included by the same Makefile don't -# overwrite each other's variables. -# This tag requires that the tag GENERATE_PERLMOD is set to YES. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all -# C-preprocessor directives found in the sources and include files. -# The default value is: YES. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names -# in the source code. If set to NO, only conditional compilation will be -# performed. Macro expansion can be done in a controlled way by setting -# EXPAND_ONLY_PREDEF to YES. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then -# the macro expansion is limited to the macros specified with the PREDEFINED and -# EXPAND_AS_DEFINED tags. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES, the include files in the -# INCLUDE_PATH will be searched if a #include is found. -# The default value is: YES. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by the -# preprocessor. -# This tag requires that the tag SEARCH_INCLUDES is set to YES. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will be -# used. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that are -# defined before the preprocessor is started (similar to the -D option of e.g. -# gcc). The argument of the tag is a list of macros of the form: name or -# name=definition (no spaces). If the definition and the "=" are omitted, "=1" -# is assumed. To prevent a macro definition from being undefined via #undef or -# recursively expanded use the := operator instead of the = operator. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this -# tag can be used to specify a list of macro names that should be expanded. The -# macro definition that is found in the sources will be used. Use the PREDEFINED -# tag if you want to use a different macro definition that overrules the -# definition found in the source code. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will -# remove all references to function-like macros that are alone on a line, have -# an all uppercase name, and do not end with a semicolon. Such function macros -# are typically used for boiler-plate code, and will confuse the parser if not -# removed. -# The default value is: YES. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tag files. For each tag -# file the location of the external documentation should be added. The format of -# a tag file without this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where loc1 and loc2 can be relative or absolute paths or URLs. See the -# section "Linking to external documentation" for more information about the use -# of tag files. -# Note: Each tag file must have a unique name (where the name does NOT include -# the path). If a tag file is not located in the directory in which doxygen is -# run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create a -# tag file that is based on the input files it reads. See section "Linking to -# external documentation" for more information about the usage of tag files. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. -# The default value is: NO. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be -# listed. -# The default value is: YES. - -EXTERNAL_GROUPS = YES - -# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in -# the related pages index. If set to NO, only the current project's pages will -# be listed. -# The default value is: YES. - -EXTERNAL_PAGES = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - -# If set to YES the inheritance and collaboration graphs will hide inheritance -# and usage relations if the target is undocumented or is not a class. -# The default value is: YES. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent -# Bell Labs. The other options in this section have no effect if this option is -# set to NO -# The default value is: YES. - -HAVE_DOT = YES - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed -# to run in parallel. When set to 0 doxygen will base this on the number of -# processors available in the system. You can set it explicitly to a value -# larger than 0 to get control over the balance between CPU load and processing -# speed. -# Minimum value: 0, maximum value: 32, default value: 0. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_NUM_THREADS = 0 - -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_FONTPATH = - -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a -# graph for each documented class showing the direct and indirect implementation -# dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -UML_LOOK = NO - -# If the UML_LOOK tag is enabled, the fields and methods are shown inside the -# class node. If there are many fields or methods and many nodes the graph may -# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the -# number of items for each type to make the size more manageable. Set this to 0 -# for no limit. Note that the threshold may be exceeded by 50% before the limit -# is enforced. So when you set the threshold to 10, up to 15 fields may appear, -# but if the number exceeds 15, the total amount of fields shown is limited to -# 10. -# Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. - -UML_LIMIT_NUM_FIELDS = 10 - -# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and -# collaboration graphs will show the relations between templates and their -# instances. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -TEMPLATE_RELATIONS = NO - -# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to -# YES then doxygen will generate a graph for each documented file showing the -# direct and indirect include dependencies of the file with other documented -# files. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -INCLUDE_GRAPH = YES - -# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are -# set to YES then doxygen will generate a graph for each documented file showing -# the direct and indirect include dependencies of the file with other documented -# files. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH tag is set to YES then doxygen will generate a call -# dependency graph for every global function or class method. -# -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. Disabling a call graph can be -# accomplished by means of the command \hidecallgraph. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller -# dependency graph for every global function or class method. -# -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. Disabling a caller graph can be -# accomplished by means of the command \hidecallergraph. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical -# hierarchy of all classes instead of a textual one. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the -# dependencies a directory has on other directories in a graphical way. The -# dependency relations are determined by the #include relations between the -# files in the directories. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. For an explanation of the image formats see the section -# output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). -# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order -# to make the SVG files visible in IE 9+ (other browsers do not have this -# requirement). -# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, -# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, -# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and -# png:gdiplus:gdiplus. -# The default value is: png. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_IMAGE_FORMAT = png - -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# -# Note that this requires a modern browser other than Internet Explorer. Tested -# and working are Firefox, Chrome, Safari, and Opera. -# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make -# the SVG files visible. Older versions of IE do not have SVG support. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -INTERACTIVE_SVG = NO - -# The DOT_PATH tag can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the \dotfile -# command). -# This tag requires that the tag HAVE_DOT is set to YES. - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). - -MSCFILE_DIRS = - -# The DIAFILE_DIRS tag can be used to specify one or more directories that -# contain dia files that are included in the documentation (see the \diafile -# command). - -DIAFILE_DIRS = - -# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. - -PLANTUML_JAR_PATH = - -# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a -# configuration file for plantuml. - -PLANTUML_CFG_FILE = - -# When using plantuml, the specified paths are searched for files specified by -# the !include statement in a plantuml block. - -PLANTUML_INCLUDE_PATH = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes -# that will be shown in the graph. If the number of nodes in a graph becomes -# larger than this value, doxygen will truncate the graph, which is visualized -# by representing a node as a red box. Note that doxygen if the number of direct -# children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that -# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. -# Minimum value: 0, maximum value: 10000, default value: 50. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs -# generated by dot. A depth value of 3 means that only nodes reachable from the -# root by following a path via at most 3 edges will be shown. Nodes that lay -# further from the root node will be omitted. Note that setting this option to 1 -# or 2 may greatly reduce the computation time needed for large code bases. Also -# note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. -# Minimum value: 0, maximum value: 1000, default value: 0. -# This tag requires that the tag HAVE_DOT is set to YES. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) support -# this, this feature is disabled by default. -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page -# explaining the meaning of the various boxes and arrows in the dot generated -# graphs. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot -# files that are used to generate the various graphs. -# The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_CLEANUP = YES diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c deleted file mode 100644 index bbcc2e9bf..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2019-2020 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 <inttypes.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "hicn_plugin.h" -#include "model/hicn_model.h" -#include "ietf/ietf_interface.h" - - -sr_subscription_ctx_t *subscription = NULL; -volatile int exit_application = 0; - -int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) { - - sr_subscription_ctx_t *subscription = NULL; - int rc = SR_ERR_OK; - rc = hicn_connect_vpp(); - if (SR_ERR_OK != rc) { - return SR_ERR_INTERNAL; - } - - // HICN subscribe - hicn_subscribe_events(session, &subscription); - - //sr_subscription_ctx_t *subscription2 = NULL; - - // IETF subscribe - //ietf_subscribe_events(session, &subscription2); - - - /* set subscription as our private context */ - *private_ctx = subscription; - - return SR_ERR_OK; -} - -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx) { - - /* subscription was set as our private context */ - sr_unsubscribe(private_ctx); - hicn_disconnect_vpp(); -} - -static void sigint_handler(int signum) { exit_application = 1; } -int subscribe_all_module_events(sr_session_ctx_t *session) { - sr_plugin_init_cb(session, (void **)&subscription); - return 0; -} - -int main(int argc, char **argv) { - sr_conn_ctx_t *connection = NULL; - sr_session_ctx_t *session = NULL; - int rc = SR_ERR_OK; - /* connect to vpp */ - rc = hicn_connect_vpp(); - if (-1 == rc) { - fprintf(stderr, "vpp connect error"); - return -1; - } - - /* connect to sysrepo */ - rc = sr_connect(SR_CONN_DEFAULT, &connection); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* start session */ - rc = sr_session_start(connection, SR_DS_STARTUP, &session); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* subscribe all module events */ - rc = subscribe_all_module_events(session); - if (SR_ERR_OK != rc) { - fprintf(stderr, "Error by subscribe module events: %s\n", sr_strerror(rc)); - goto cleanup; - } - - /* loop until ctrl-c is pressed / SIGINT is received */ - signal(SIGINT, sigint_handler); - signal(SIGPIPE, SIG_IGN); - - while (!exit_application) { - sleep(2); - } - - printf("Application exit requested, exiting.\n"); - -cleanup: - if (NULL != subscription) { - sr_unsubscribe(subscription); - } - if (NULL != session) { - sr_session_stop(session); - } - if (NULL != connection) { - sr_disconnect(connection); - } - hicn_disconnect_vpp(); - return rc; -}
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h deleted file mode 100644 index 0890c3f03..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 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 hicn_plugin.h - * @brief This file contains init and cleanup for the sysrepo. - */ - -#ifndef __HICN_PLUGIN_H__ -#define __HICN_PLUGIN_H__ - -#include "hicn_vpp_comm.h" - - -/** - * @brief initialize function for sysrepo plugin, - * In this function we connect to vpp from one side - * and subscribe for all hICN events as well as interface events (if any) - * @param session pointer to the sesssion context - * @param private_ctx pointer to the context - * @return in success the function returns SR_ERR_OK otherwise it pass error - */ -int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx); - -/** - * @brief cleanup function for sysrepo, - * In this function we connect to vpp from one side - * and and unsubscribe for all hICN events as well as interface events (if any) - * @param session pointer to the sesssion context - * @param private_ctx pointer to the context - */ -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx); - -#endif //__HICN_PLUGIN_H__
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c deleted file mode 100644 index 73eab66ea..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 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_vpp_comm.h" -#include <vapi/vapi.h> - -#define APP_NAME "hicn_plugin" -#define MAX_OUTSTANDING_REQUESTS 4 -#define RESPONSE_QUEUE_SIZE 2 - - -vapi_ctx_t g_vapi_ctx_instance=NULL; - - - - - -int hicn_connect_vpp() { - - if (g_vapi_ctx_instance == NULL) { - vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance); - rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, - MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, - VAPI_MODE_BLOCKING, true); - if (rv != VAPI_OK) { - SRP_LOG_DBGMSG("Error connection"); - vapi_ctx_free(g_vapi_ctx_instance); - return -1; - } - SRP_LOG_DBGMSG("*connected ok"); - } else { - SRP_LOG_DBGMSG("connection keeping"); - } - return 0; -} - -int hicn_disconnect_vpp() { - if (NULL != g_vapi_ctx_instance) { - vapi_disconnect(g_vapi_ctx_instance); - vapi_ctx_free(g_vapi_ctx_instance); - g_vapi_ctx_instance = NULL; - } - return 0; -}
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h deleted file mode 100644 index 9abe4e5d4..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 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 hicn_vpp_comm.h - * @brief This file contains binary api to connect to the VPP. - */ - - -#ifndef __HICN_VPP_COMMM_H__ -#define __HICN_VPP_COMMM_H__ -#include <sysrepo.h> -#include <sysrepo/values.h> -#include <vapi/vapi.h> - -#ifndef HICN_THIS_FUNC -#ifdef __FUNCTION__ -#define HICN_THIS_FUNC __FUNCTION__ -#else -#define HICN_THIS_FUNC __func__ -#endif -#endif - -/** - * @brief This is the context to connect to the vpp - */ - -extern vapi_ctx_t g_vapi_ctx_instance; - - -/** - * @brief This macro is interface.c to communicate with vpp - */ -#define VPP_INTFC_NAME_LEN 64 -#define VPP_MAC_ADDRESS_LEN 8 -#define VPP_IP6_ADDRESS_LEN 16 - - - -/** - * @brief This macro checks the arg is NULL or not, if the arg is NULL it returns retval - */ -#define ARG_CHECK(retval, arg) \ - do { \ - if (NULL == (arg)) { \ - SRP_LOG_DBGMSG("NULL pointer passed."); \ - return (retval); \ - } \ - } while (0) - - -/** - * @brief Please check ARG_CHECK - */ -#define ARG_CHECK2(retval, arg1, arg2) \ - ARG_CHECK(retval, arg1); \ - ARG_CHECK(retval, arg2) - -/** - * @brief This Macro is the multiple check of ARG_CHECK - */ -#define ARG_CHECK5(retval, arg1, arg2, arg3, arg4, arg5) \ - ARG_CHECK(retval, arg1); \ - ARG_CHECK(retval, arg2); \ - ARG_CHECK(retval, arg3); \ - ARG_CHECK(retval, arg4); \ - ARG_CHECK(retval, arg5) - -/** - * @brief This function is used to connect to the vpp - */ -int hicn_connect_vpp(); -/** - * @brief This function is used to close the connection of the vpp - */ -int hicn_disconnect_vpp(); - -#endif //__HICN_VPP_COMMM_H__ diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c deleted file mode 100644 index 3e0c90cf9..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (c) 2016-2020 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 <stdio.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <sysrepo.h> -#include <sysrepo/values.h> -#include <sysrepo/xpath.h> -#include <vnet/interface.h> -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vapi/interface.api.vapi.h> - -#include "ietf_interface.h" -#include "../hicn_vpp_comm.h" - - -DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON; - -typedef struct hicn_interface_ -{ - u32 sw_if_index; - char interface_name[VPP_INTFC_NAME_LEN]; - u8 l2_address[VPP_MAC_ADDRESS_LEN]; - u64 link_speed; - u32 flags; - u16 link_mtu; - u8 admin_up_down; - u8 link_up_down; -} hicnIntfc; - -typedef struct _ietf_sw_interface_dump_ctx -{ - u8 last_called; - int num_ifs; - int capacity; - hicnIntfc * intfcArray; -} ietf_sw_interface_dump_ctx; - -static i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down); -static i32 ietf_interface_name2index(const char *name, u32* if_index); -static i32 ietf_interface_add_del_addr(u32 sw_if_index, u8 is_add, u8 is_ipv6, - u8 del_all, u8 address_length, - u8 address[VPP_IP6_ADDRESS_LEN]); -static int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx); -static int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx); - -/** - * @brief Helper function for converting netmask into prefix length. - */ -static uint8_t -netmask_to_prefix(const char *netmask) -{ - in_addr_t n = 0; - uint8_t i = 0; - - inet_pton(AF_INET, netmask, &n); - - while (n > 0) { - n = n >> 1; - i++; - } - - return i; -} - -/** - * @brief Helper function for converting IPv4/IPv6 address string into binary representation. - */ -static int -ip_addr_str_to_binary(const char *ip_address_str, uint8_t *ip_address_bin, bool is_ipv6) -{ - struct in6_addr addr6 = { 0, }; - struct in_addr addr4 = { 0, }; - int ret = 0; - - if (is_ipv6) { - ret = inet_pton(AF_INET6, ip_address_str, &(addr6)); - if (1 == ret) - { - memcpy(ip_address_bin, &addr6, sizeof(addr6)); - } - } else { - ret = inet_pton(AF_INET, ip_address_str, &(addr4)); - if (1 == ret) - { - memcpy(ip_address_bin, &addr4, sizeof(addr4)); - } - } - - return ret; -} - -/** - * @brief Enable or disable given interface. - */ -static int -interface_enable_disable(const char *if_name, bool enable) -{ - uint32_t if_index = ~0; - int rc = 0; - - - /* get interface index */ - rc = ietf_interface_name2index(if_name, &if_index); - if (0 != rc) { - SRP_LOG_ERRMSG("Invalid interface name"); - return SR_ERR_INVAL_ARG; - } - - /* enable/disable interface */ - rc = ietf_setInterfaceFlags(if_index, (uint8_t)enable); - if (0 != rc) { - SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request"); - return SR_ERR_OPERATION_FAILED; - } else { - return SR_ERR_OK; - } -} - - -vapi_error_e call_sw_interface_add_del_address(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_sw_interface_add_del_address_reply *reply){ -if(!reply->retval){ - SRP_LOG_DBGMSG("Successfully done"); - return VAPI_OK; - }else - return VAPI_EUSER; -} - -vapi_error_e call_sw_interface_set_flags(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_sw_interface_set_flags_reply *reply){ -if(!reply->retval){ - SRP_LOG_DBGMSG("Successfully done"); - return VAPI_OK; - }else - return VAPI_EUSER; -} - - - -/** - * @brief Callback to be called by any config change of "/ietf-interfaces:interfaces/interface/enabled" leaf. - */ -static int -ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, - uint32_t request_id, void *private_data) -{ - char *if_name = NULL; - sr_change_iter_t *iter = NULL; - sr_change_oper_t op = SR_OP_CREATED; - sr_val_t *old_val = NULL; - sr_val_t *new_val = NULL; - sr_xpath_ctx_t xpath_ctx = { 0, }; - int rc = SR_ERR_OK, op_rc = SR_ERR_OK; - - /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */ - if (SR_EV_DONE == event) { - return SR_ERR_OK; - } - - /* get changes iterator */ - rc = sr_get_changes_iter(session, xpath, &iter); - if (SR_ERR_OK != rc) { - SRP_LOG_ERRMSG("Unable to retrieve change iterator"); - return rc; - } - - /* iterate over all changes */ - while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) && - (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) { - - SRP_LOG_DBGMSG("A change detected"); - if_name = sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx); - switch (op) { - case SR_OP_CREATED: - case SR_OP_MODIFIED: - op_rc = interface_enable_disable(if_name, new_val->data.bool_val); - break; - case SR_OP_DELETED: - op_rc = interface_enable_disable(if_name, false /* !enable */); - break; - default: - break; - } - sr_xpath_recover(&xpath_ctx); - if (SR_ERR_INVAL_ARG == op_rc) { - sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath); - } - sr_free_val(old_val); - sr_free_val(new_val); - } - sr_free_change_iter(iter); - - return op_rc; -} - -/** - * @brief Add or remove IPv4/IPv6 address to/from an interface. - */ -static int -interface_ipv46_config_add_remove(const char *if_name, uint8_t *addr, uint8_t prefix, bool is_ipv6, bool add) -{ - uint32_t if_index = ~0; - int rc = 0; - - /* get interface index */ - rc = ietf_interface_name2index(if_name, &if_index); - if (0 != rc) { - SRP_LOG_ERRMSG("Invalid interface name"); - return SR_ERR_INVAL_ARG; - } - - /* add del addr */ - rc = ietf_interface_add_del_addr(if_index, (uint8_t)add, (uint8_t)is_ipv6, 0, prefix, addr); - if (0 != rc) { - SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request"); - return SR_ERR_OPERATION_FAILED; - } else { - return SR_ERR_OK; - } -} -int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx) -{ - if(dctx == NULL) - return -1; - - dctx->intfcArray = NULL; - dctx->last_called = false; - dctx->capacity = 0; - dctx->num_ifs = 0; - return 0; -} -int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx) -{ - if(dctx == NULL) - return -1; - - if(dctx->intfcArray != NULL) - { - free(dctx->intfcArray); - } - - return ietf_initSwInterfaceDumpCTX(dctx); -} -vapi_error_e -ietf_sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_sw_interface_details * reply) -{ - ietf_sw_interface_dump_ctx *dctx = callback_ctx; - if (is_last) - { - dctx->last_called = true; - } - else - { - if(dctx->capacity == 0 && dctx->intfcArray == NULL) - { - dctx->capacity = 10; - dctx->intfcArray = (hicnIntfc*)malloc( sizeof(hicnIntfc)*dctx->capacity ); - } - if(dctx->num_ifs >= dctx->capacity-1) - { - - dctx->capacity += 10; - dctx->intfcArray = (hicnIntfc*)realloc(dctx->intfcArray, sizeof(hicnIntfc)*dctx->capacity ); - } - - hicnIntfc * thisIntfc = &dctx->intfcArray[dctx->num_ifs]; - - thisIntfc->sw_if_index = reply->sw_if_index; - memcpy(thisIntfc->interface_name, reply->interface_name, VPP_INTFC_NAME_LEN); - memcpy(thisIntfc->l2_address, reply->l2_address, VPP_MAC_ADDRESS_LEN ); - //thisIntfc->link_speed = reply->link_speed; -#define ONE_MEGABIT (uint64_t)1000000 - switch (reply->link_speed << VNET_HW_INTERFACE_FLAG_SPEED_SHIFT) - { - default: - thisIntfc->link_speed = 0; - break; - } - - thisIntfc->link_mtu = reply->link_mtu; - thisIntfc->flags = reply->flags; - - dctx->num_ifs += 1; - } - return VAPI_OK; -} - -static i32 ietf_interface_name2index(const char *name, u32* if_index) -{ - ARG_CHECK2(-1, name, if_index); - - i32 ret = -1; - ietf_sw_interface_dump_ctx dctx = {false, 0, 0, 0}; - vapi_msg_sw_interface_dump *dump; - vapi_error_e rv; - dctx.last_called = false; - - dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance); - dump->payload.name_filter_valid = true; - memcpy(&dump->payload.name_filter, name, sizeof(dump->payload.name_filter)); - - while (VAPI_EAGAIN == (rv = vapi_sw_interface_dump(g_vapi_ctx_instance, dump, ietf_sw_interface_dump_cb, &dctx))) - ; - - int i = 0; - for (; i < dctx.num_ifs; ++i) - { - if (strcmp(dctx.intfcArray[i].interface_name, name) == 0) - { - *if_index = dctx.intfcArray[i].sw_if_index; - ret = 0; - break; - } - } - ietf_freeSwInterfaceDumpCTX(&dctx); - - return ret; -} - -i32 ietf_interface_add_del_addr( u32 sw_if_index, u8 is_add, u8 is_ipv6, u8 del_all, - u8 address_length, u8 address[VPP_IP6_ADDRESS_LEN] ) -{ - i32 ret = -1; - vapi_msg_sw_interface_add_del_address *msg = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance); - msg->payload.sw_if_index = sw_if_index; - msg->payload.is_add = is_add; - msg->payload.prefix.address.af = is_ipv6 ? ADDRESS_IP6 : ADDRESS_IP4; - msg->payload.del_all = del_all; - msg->payload.prefix.len = address_length; - memcpy(msg->payload.prefix.address.un.ip6, address, VPP_IP6_ADDRESS_LEN); - - if(vapi_sw_interface_add_del_address(g_vapi_ctx_instance,msg,call_sw_interface_add_del_address,NULL)!=VAPI_OK){ - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - return ret; -} - -i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down) -{ - i32 ret = -1; - vapi_msg_sw_interface_set_flags *msg = vapi_alloc_sw_interface_set_flags(g_vapi_ctx_instance); - msg->payload.sw_if_index = sw_if_index; - msg->payload.flags = admin_up_down? IF_STATUS_API_FLAG_ADMIN_UP : 0; - - if(vapi_sw_interface_set_flags(g_vapi_ctx_instance,msg,call_sw_interface_set_flags,NULL)!=VAPI_OK){ - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - - return ret; -} - - -/** - * @brief Modify existing IPv4/IPv6 config on an interface. - */ -static int -interface_ipv46_config_modify(sr_session_ctx_t *session, const char *if_name, - sr_val_t *old_val, sr_val_t *new_val, bool is_ipv6) -{ - sr_xpath_ctx_t xpath_ctx = { 0, }; - char *addr_str = NULL; - uint8_t addr[16] = { 0, }; - uint8_t prefix = 0; - int rc = SR_ERR_OK; - - SRP_LOG_DBGMSG("Updating IP config on interface"); - - /* get old config to be deleted */ - if (SR_UINT8_T == old_val->type) { - prefix = old_val->data.uint8_val; - } else if (SR_STRING_T == old_val->type) { - prefix = netmask_to_prefix(old_val->data.string_val); - } else { - return SR_ERR_INVAL_ARG; - } - addr_str = sr_xpath_key_value((char*)old_val->xpath, "address", "ip", &xpath_ctx); - ip_addr_str_to_binary(addr_str, addr, is_ipv6); - sr_xpath_recover(&xpath_ctx); - - /* delete old IP config */ - rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* remove */); - if (SR_ERR_OK != rc) { - SRP_LOG_ERRMSG("Unable to remove old IP address config"); - return rc; - } - - /* update the config with the new value */ - if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) { - prefix = new_val->data.uint8_val; - } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) { - prefix = netmask_to_prefix(new_val->data.string_val); - } - - /* set new IP config */ - rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */); - if (SR_ERR_OK != rc) { - SRP_LOG_ERRMSG("Unable to remove old IP address config"); - return rc; - } - - return rc; -} - -/** - * @brief Callback to be called by any config change in subtrees "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address" - * or "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address". - */ -static int -ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, - uint32_t request_id, void *private_data) -{ - sr_change_iter_t *iter = NULL; - sr_change_oper_t op = SR_OP_CREATED; - sr_val_t *old_val = NULL; - sr_val_t *new_val = NULL; - sr_xpath_ctx_t xpath_ctx = { 0 }; - bool is_ipv6 = false, has_addr = false, has_prefix = false; - uint8_t addr[16] = { 0, }; - uint8_t prefix = 0; - char *node_name = NULL, *if_name = NULL; - int rc = SR_ERR_OK, op_rc = SR_ERR_OK; - - /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */ - if (SR_EV_DONE == event) { - return SR_ERR_OK; - } - - /* check whether we are handling ipv4 or ipv6 config */ - node_name = sr_xpath_node_idx((char*)xpath, 2, &xpath_ctx); - if (NULL != node_name && 0 == strcmp(node_name, "ipv6")) { - is_ipv6 = true; - } - sr_xpath_recover(&xpath_ctx); - - /* get changes iterator */ - rc = sr_get_changes_iter(session, xpath, &iter); - if (SR_ERR_OK != rc) { - // SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc)); - return rc; - } - - /* iterate over all changes */ - while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) && - (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) { - - if_name = strdup(sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx)); - sr_xpath_recover(&xpath_ctx); - - switch (op) { - case SR_OP_CREATED: - if (SR_LIST_T == new_val->type) { - /* create on list item - reset state vars */ - has_addr = has_prefix = false; - } else { - if (sr_xpath_node_name_eq(new_val->xpath, "ip")) { - ip_addr_str_to_binary(new_val->data.string_val, addr, is_ipv6); - has_addr = true; - } else if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) { - prefix = new_val->data.uint8_val; - has_prefix = true; - } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) { - prefix = netmask_to_prefix(new_val->data.string_val); - has_prefix = true; - } - if (has_addr && has_prefix) { - op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */); - } - } - break; - case SR_OP_MODIFIED: - op_rc = interface_ipv46_config_modify(session, if_name, old_val, new_val, is_ipv6); - break; - case SR_OP_DELETED: - if (SR_LIST_T == old_val->type) { - /* delete on list item - reset state vars */ - has_addr = has_prefix = false; - } else { - if (sr_xpath_node_name_eq(old_val->xpath, "ip")) { - ip_addr_str_to_binary(old_val->data.string_val, addr, is_ipv6); - has_addr = true; - } else if (sr_xpath_node_name_eq(old_val->xpath, "prefix-length")) { - prefix = old_val->data.uint8_val; - has_prefix = true; - } else if (sr_xpath_node_name_eq(old_val->xpath, "netmask")) { - prefix = netmask_to_prefix(old_val->data.string_val); - has_prefix = true; - } - if (has_addr && has_prefix) { - op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* !add */); - } - } - break; - default: - break; - } - if (SR_ERR_INVAL_ARG == op_rc) { - sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath); - } - free(if_name); - sr_free_val(old_val); - sr_free_val(new_val); - } - sr_free_change_iter(iter); - - return op_rc; -} - -/** - * @brief Callback to be called by any config change under "/ietf-interfaces:interfaces-state/interface" path. - * Does not provide any functionality, needed just to cover not supported config leaves. - */ -static int -ietf_interface_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, - uint32_t request_id, void *private_data) -{ - return SR_ERR_OK; -} - - -int ietf_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription){ - - int rc = SR_ERR_OK; - SRP_LOG_DBGMSG("Subscriging ietf."); - - // - rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface", ietf_interface_change_cb, - NULL, - 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription); - - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface\n"); - goto error; - } - - rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/enabled", ietf_interface_enable_disable_cb, - NULL, - 100, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/enabled\n"); - goto error; - } - - //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", ietf_interface_ipv46_address_change_cb, - rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces", ietf_interface_ipv46_address_change_cb, - NULL, - 99, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription); - - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address\n"); - goto error; - } - - //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", ietf_interface_ipv46_address_change_cb, - // NULL, - // 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription); - - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address\n"); - goto error; - } - - /* rc = sr_dp_get_items_subscribe(session, "/ietf-interfaces:interfaces-state", ietf_interface_state_cb, - NULL, SR_SUBSCR_CTX_REUSE, - subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces-state\n"); - goto error; - }*/ - - - SRP_LOG_INFMSG("ietf initialized successfully."); - return SR_ERR_OK; - - error: - SRP_LOG_ERRMSG("Error by initialization of the ietf."); - return rc; -} diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox b/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox deleted file mode 100644 index 978578039..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox +++ /dev/null @@ -1,211 +0,0 @@ -/** @mainpage About hICN sysrepo plugin -*This plugin serves as a data management agent. It provides yang models via -*NETCONF to allow the management of hicn-plugin which runs in VPP instance from out-of-box. - -*The following sections contain more details: -*- @subpage subp1 "hICN yang model" -*- @subpage subp2 "User Guide" -*- @subpage subp3 "Developer Guide" -*/ - -/** @page subp1 -*hicn.yang consists of one container for providing the state data (i.e., hicn-state). -*It consists of state, route, and face-ip-params -*nodes with the corresponding leaves. In the hicn model a variety of RPCs are provided -*to allow controller to communicate with the hicn-plugin as well as update the state -*data in hicn-state. You can install the yang model using the following bash script: - -``` -EXIT_CODE=0 -command -v sysrepoctl > /dev/null -if [ $? != 0 ]; then - echo "Could not find command \"sysrepoctl\"." - exit ${EXIT_CODE} -else -sysrepoctl --install path_to_hicn_yang_model -fi -``` - -*Here you can find different examples to run RPC in the yang-model. - -``` -<hicn-enable xmlns="urn:sysrepo:hicn"> - <prefix>b001::/64</prefix> -</hicn-enable> - -<hicn-disable xmlns="urn:sysrepo:hicn"> - <prefix>b001::/64</prefix> -</hicn-disable> -``` - */ - -/** @page subp2 - -*Firstly, verify the plugin and binary libraries are located correctly, then run -*the vpp through (service vpp start). Next, run the sysrepo plugin (sysrepo-plugind), -*for debug mode: sysrep-plugind -d -v 4 which -*runs with high verbosity. When the hicn sysrepo plugin is loaded, run the -*netopeer2-server which serves as NETCONF server. - - -*## Connect from netopeer2-cli - -*In order to connect through the netopeer client run the netopeer2-cli. Then, follow these steps: -``` -*- connect --host XXX --login XXX -*- get (you can get the configuration and operational data) -*- user-rpc (you can call one of the rpc proposed by hicn model but it needs an xml input) -``` - -*## Connect from OpenDaylight (ODL) controller - - -*In order to connect through the OpenDaylight follow these procedure: - -*- run karaf distribution (./opendayligh_installation_folder/bin/karaf) -*- install the required feature list in DOL (feature:install odl-netconf-server -* odl-netconf-connector odl-restconf-all odl-netconf-topology or -* odl-netconf-clustered-topology) -*- run a rest client program (e.g., postman or RESTClient) -*- mount the remote netopeer2-server to the OpenDaylight by the following REST API: - -*PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/hicn-node - -* with the following body -``` - <node xmlns="urn:TBD:params:xml:ns:yang:network-topology"> - <node-id>hicn-node</node-id> - <host xmlns="urn:opendaylight:netconf-node-topology">Remote_NETCONF_SERVER_IP</host> - <port xmlns="urn:opendaylight:netconf-node-topology">830</port> - <username xmlns="urn:opendaylight:netconf-node-topology">username</username> - <password xmlns="urn:opendaylight:netconf-node-topology">password</password> - <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only> - <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">1</keepalive-delay> - </node> -``` -*Note that the header files must be set to Content-Type: application/xml, Accept: application/xml. - -*- send the operation through the following REST API: - -*POST http://localhost:8181/restconf/operations/network-topology:network-topology/topology/topology-netconf/node/hicn-node/yang-ext:mount/ietf-netconf:edit-config - -*The body can be used the same as edit-config in netopeer2-cli. - -*## Connect from Network Services Orchestrator (NSO) - -*To connect NSO to the netopeer2-server, first, you need to write a NED package -*for your device. The procedure to create NED for hicn is explained in the following: - -*Place hicn.yang model in a folder called hicn-yang-model, and follow these steps: - -*- ncs-make-package --netconf-ned ./hicn-yang-model ./hicn-nso -*- cd hicn-nso/src; make -*- ncs-setup --ned-package ./hicn-nso --dest ./hicn-nso-project -*- cd hicn-nso-project -*- ncs -*- ncs_cli -C -u admin -*- configure -*- devices authgroups group authhicn default-map remote-name user_name remote-password password -*- devices device hicn address IP_device port 830 authgroup authhicn device-type netconf -*- state admin-state unlocked -*- commit -*- ssh fetch-host-keys - - -*At this point, we are able to connect to the remote device. - - - */ - - /** @page subp3 - -*This guide contains information intended for developers that need to extend/modify the hICN yang model. - -*# Adding configuration data -*In order to add configuration data, firstly it requires to update yang model and define the configuration paramters -*through a container and define the leaves. Once the yang model is updated in the sysrepo plugin you need to subscribe -*for ```sr_module_change_subscribe``` and provide the appropriate callback. -* -* -*# Adding new RPC -* -*In order to add RPC call, firstly it requires to update the yang model by new ```rpc``` statements and define the input to them. - - -*# Adding new operational data -* -*In order to add operational data, firstly it requires to add operational data in yang model by adding ```confg false``` to the container. -*Then, update the sysrepo plugin by the adding the ```sr_oper_get_items_subscribe```. - - Example: -I have a switch with two ports. I am going to write an RPC call to switch them on/off -, moreover I need to read operational data from each port. So, the following yang model can be proposed: - -``` -module switch { -namespace "urn:sysrepo:switch"; -prefix swtch; - -revision 2019-12-08{ - description "Initial revision."; -} - - -grouping status-reply{ - list port{ - key portid; - leaf portid { - description "the port id."; - type uint32; - } - leaf status { - description "the status of the port."; - type boolean; - } - -} -} - -rpc power { - description "Operation to power on/off switch."; - input { - leaf turned-on { - description "indicating on or off."; - type boolean; - default false; - } - } -} - - -container switch-state { - - config false; - description "operational data container for the switch."; - container status{ - uses status-reply; - } -``` -Afterwards, the following subscribes are required in the sysrepo plugin. - -``` -sr_rpc_subscribe(session, "/switch:power", callback, - session, 100,SR_SUBSCR_CTX_REUSE, subscription); - -``` - -session is the opened session with sysrepo, xpath is the path in the yang model, callback is the function -when RPC arrives, private context passed to the callback function, priprity which is set to 100 here indicates the priority if there re multiple RPCs, -options can alter the normal behaviour, and subscription is the subscribtion when initialize the connection towards the sysrepo - - -``` - rc = sr_oper_get_items_subscribe(session, "switch","/switch:switch-state/status", - callback, NULL, SR_SUBSCR_CTX_REUSE, - subscription); -``` -session is the opened session with sysrepo, xpath is the path in the yang model, callback is the function -when RPC arrives, private context passed to the callback which is NULL here, -options can alter the normal behaviour, and subscription is the subscribtion when initialize the connection towards the sysrepo - -*/
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c deleted file mode 100644 index 63685e10a..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (c) 2019-2020 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 hicn_model.c - * @brief This file contains implementations of the main calls - */ - -#define _GNU_SOURCE - -#include <inttypes.h> -#include <malloc.h> -#include <pthread.h> -#include <sched.h> -#include <stdio.h> -#include <string.h> -#include <sysrepo/xpath.h> -#include <unistd.h> -/* Hicn headers */ - -#include <hicn/util/ip_address.h> - -#include "../hicn_plugin.h" -#include "../hicn_vpp_comm.h" -#include "hicn_model.h" -#include "tlock.h" - -DEFINE_VAPI_MSG_IDS_HICN_API_JSON - -// Shared local variables between state and RPCs - -/** - * @brief this shared variable keeps the hicn state - */ -volatile hicn_state_t *hicn_state = NULL; -/** - * @brief this shared variable keeps hicn strategies - */ -volatile hicn_strategies_t *hicn_strategies = NULL; -/** - * @brief this shared variable keeps statistics of hicn faces - */ -volatile hicn_faces_t *hicn_faces = NULL; -/** - * @brief this shared variable keeps routes information in hicn - */ -volatile hicn_routes_t *hicn_routes = NULL; -/** - * @brief this shared variable is the link list to maintain all the faces (up to - * MAX_FACES) - */ -struct hicn_faces_s *fcurrent = NULL; -/** - * @brief this shared variable is the link list to maintain all the routes - */ -struct hicn_routes_s *rcurrent = NULL; - -static int init_buffer(void) { - hicn_state = memalign(MEM_ALIGN, sizeof(hicn_state_t)); - memset((hicn_state_t *)hicn_state, 0, sizeof(hicn_state_t)); - - hicn_strategies = memalign(MEM_ALIGN, sizeof(hicn_strategies_t)); - memset((hicn_strategies_t *)hicn_strategies, 0, sizeof(hicn_strategies_t)); - - hicn_faces = memalign(MEM_ALIGN, sizeof(hicn_faces_t)); - hicn_faces->next = memalign(MEM_ALIGN, sizeof(struct hicn_faces_s)); - fcurrent = hicn_faces->next; - - hicn_routes = memalign(MEM_ALIGN, sizeof(hicn_routes_t)); - hicn_routes->next = memalign(MEM_ALIGN, sizeof(struct hicn_routes_s)); - rcurrent = hicn_routes->next; - - int retval = -1; - ARG_CHECK5(retval, hicn_state, hicn_strategies, fcurrent, hicn_faces, - hicn_routes); - hicn_routes->nroute = 0; - hicn_faces->nface = 0; - retval = 0; - - return retval; -} - -static int init_face_pool(struct hicn_faces_s *head) { - for (int i = 0; i < MAX_FACE_POOL; i++) { - head->next = memalign(MEM_ALIGN, sizeof(struct hicn_faces_s)); - head = head->next; - } - SRP_LOG_DBGMSG("Face memory pool allocated\n"); - head->next = NULL; - return 0; -} - -static int init_route_pool(struct hicn_routes_s *head) { - for (int i = 0; i < MAX_ROUTE_POOL; i++) { - head->next = memalign(MEM_ALIGN, sizeof(struct hicn_routes_s)); - head = head->next; - } - SRP_LOG_DBGMSG("Route memory pool allocated\n"); - head->next = NULL; - return 0; -} - -/* VAPI CALLBACKS */ - -static vapi_error_e call_hicn_api_strategies_get( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_strategies_get_reply *reply) { - if (!reply->retval) { - SRP_LOG_DBGMSG("Successfully done"); - return VAPI_OK; - } else - return VAPI_EUSER; -} - -static vapi_error_e call_hicn_api_face_params_get( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_face_params_get_reply *reply) { - if (!reply->retval) { - if (callback_ctx != NULL) { - struct hicn_faces_s *tmp; - tmp = (struct hicn_faces_s *)callback_ctx; - tmp->face.intfc = reply->swif; - } - return VAPI_OK; - } else - return VAPI_EUSER; -} - -static vapi_error_e call_vapi_hicn_api_node_stats_get( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_node_stats_get_reply *reply) { - if (!reply->retval) { - hicn_state->pkts_processed = reply->pkts_processed; - hicn_state->pkts_interest_count = reply->pkts_interest_count; - hicn_state->pkts_data_count = reply->pkts_data_count; - hicn_state->pkts_from_cache_count = reply->pkts_from_cache_count; - hicn_state->pkts_no_pit_count = reply->pkts_no_pit_count; - hicn_state->pit_expired_count = reply->pit_expired_count; - hicn_state->cs_expired_count = reply->cs_expired_count; - hicn_state->cs_lru_count = reply->cs_lru_count; - hicn_state->pkts_drop_no_buf = reply->pkts_drop_no_buf; - hicn_state->interests_aggregated = reply->interests_aggregated; - hicn_state->interests_retx = reply->interests_retx; - hicn_state->pit_entries_count = reply->pit_entries_count; - hicn_state->cs_entries_count = reply->cs_entries_count; - hicn_state->cs_entries_ntw_count = reply->cs_entries_ntw_count; - return VAPI_OK; - } else - return VAPI_EUSER; -} - -static inline void state_update(sr_val_t *vals, struct lyd_node **parent, - sr_session_ctx_t *session) { - char buf[20]; - - sr_val_set_xpath(&vals[0], "/hicn:hicn-state/states/pkts_processed"); - vals[0].type = SR_UINT64_T; - vals[0].data.uint64_val = hicn_state->pkts_processed; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_processed); - *parent = - lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), - vals[0].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[1], "/hicn:hicn-state/states/pkts_interest_count"); - vals[1].type = SR_UINT64_T; - vals[1].data.uint64_val = hicn_state->pkts_interest_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_interest_count); - lyd_new_path(*parent, NULL, vals[1].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[2], "/hicn:hicn-state/states/pkts_data_count"); - vals[2].type = SR_UINT64_T; - vals[2].data.uint64_val = hicn_state->pkts_data_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_data_count); - lyd_new_path(*parent, NULL, vals[2].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[3], "/hicn:hicn-state/states/pkts_from_cache_count"); - vals[3].type = SR_UINT64_T; - vals[3].data.uint64_val = hicn_state->pkts_from_cache_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_from_cache_count); - lyd_new_path(*parent, NULL, vals[3].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[4], "/hicn:hicn-state/states/pkts_no_pit_count"); - vals[4].type = SR_UINT64_T; - vals[4].data.uint64_val = hicn_state->pkts_no_pit_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_no_pit_count); - lyd_new_path(*parent, NULL, vals[4].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[5], "/hicn:hicn-state/states/pit_expired_count"); - vals[5].type = SR_UINT64_T; - vals[5].data.uint64_val = hicn_state->pit_expired_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pit_expired_count); - lyd_new_path(*parent, NULL, vals[5].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[6], "/hicn:hicn-state/states/cs_expired_count"); - vals[6].type = SR_UINT64_T; - vals[6].data.uint64_val = hicn_state->cs_expired_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->cs_expired_count); - lyd_new_path(*parent, NULL, vals[6].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[7], "/hicn:hicn-state/states/cs_lru_count"); - vals[7].type = SR_UINT64_T; - vals[7].data.uint64_val = hicn_state->cs_lru_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->cs_lru_count); - lyd_new_path(*parent, NULL, vals[7].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[8], "/hicn:hicn-state/states/pkts_drop_no_buf"); - vals[8].type = SR_UINT64_T; - vals[8].data.uint64_val = hicn_state->pkts_drop_no_buf; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pkts_drop_no_buf); - lyd_new_path(*parent, NULL, vals[8].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[9], "/hicn:hicn-state/states/interests_aggregated"); - vals[9].type = SR_UINT64_T; - vals[9].data.uint64_val = hicn_state->interests_aggregated; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->interests_aggregated); - lyd_new_path(*parent, NULL, vals[9].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[10], "/hicn:hicn-state/states/interests_retx"); - vals[10].type = SR_UINT64_T; - vals[10].data.uint64_val = hicn_state->interests_retx; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->interests_retx); - lyd_new_path(*parent, NULL, vals[10].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[11], - "/hicn:hicn-state/states/interests_hash_collision"); - vals[11].type = SR_UINT64_T; - vals[11].data.uint64_val = hicn_state->interests_hash_collision; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->interests_hash_collision); - lyd_new_path(*parent, NULL, vals[11].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[12], "/hicn:hicn-state/states/pit_entries_count"); - vals[12].type = SR_UINT64_T; - vals[12].data.uint64_val = hicn_state->pit_entries_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->pit_entries_count); - lyd_new_path(*parent, NULL, vals[12].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[13], "/hicn:hicn-state/states/cs_entries_count"); - vals[13].type = SR_UINT64_T; - vals[13].data.uint64_val = hicn_state->cs_entries_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->cs_entries_count); - lyd_new_path(*parent, NULL, vals[13].xpath, buf, 0, 0); - - sr_val_set_xpath(&vals[14], "/hicn:hicn-state/states/cs_entries_ntw_count"); - vals[14].type = SR_UINT64_T; - vals[14].data.uint64_val = hicn_state->cs_entries_ntw_count; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, hicn_state->cs_entries_ntw_count); - lyd_new_path(*parent, NULL, vals[14].xpath, buf, 0, 0); -} - -static inline int routes_update(sr_val_t *vals, uint32_t nleaves, - struct lyd_node **parent, - sr_session_ctx_t *session) { - struct hicn_routes_s *temp = hicn_routes->next; - char buf[20]; - int route = 0; - for (int count = 0; count < nleaves; count++) { - sr_val_build_xpath(&vals[route], "%s[routeid='%d']/prefix", - "/hicn:hicn-state/routes/route", temp->route.route_id); - vals[route].type = SR_STRING_T; - - memset(buf, 0x00, 20); - if (temp->route.prefix.address.af == ADDRESS_IP4) { - struct sockaddr_in sa; - memcpy(&sa.sin_addr.s_addr, temp->route.prefix.address.un.ip4, - IPV4_ADDR_LEN); - inet_ntop(AF_INET, &(sa.sin_addr), buf, INET_ADDRSTRLEN); - vals[route].data.string_val = buf; - } else { - struct sockaddr_in6 sa; - memcpy(&sa.sin6_addr, temp->route.prefix.address.un.ip6, IPV6_ADDR_LEN); - inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN); - vals[route].data.string_val = buf; - } - - lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0); - - route++; - - sr_val_build_xpath(&vals[route], "%s[routeid='%d']/strategy_id", - "/hicn:hicn-state/routes/route", temp->route.route_id); - vals[route].type = SR_UINT32_T; - vals[route].data.uint32_val = temp->route.strategy_id; - memset(buf, 0x00, 20); - sprintf(buf, "%d", temp->route.strategy_id); - lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0); - - route++; - - temp = temp->next; - } - - SRP_LOG_DBGMSG("Routes state updated \n"); - return SR_ERR_OK; -} - -static inline int faces_update(sr_val_t *vals, uint32_t nleaves, - struct lyd_node **parent, - sr_session_ctx_t *session) { - struct hicn_faces_s *temp = hicn_faces->next; - char buf[20]; - int face = 0; - - for (int count = 0; count < nleaves; count++) { - vapi_msg_hicn_api_face_params_get *msg; - msg = vapi_alloc_hicn_api_face_params_get(g_vapi_ctx_instance); - - msg->payload.faceid = temp->face.faceid; - - if (vapi_hicn_api_face_params_get(g_vapi_ctx_instance, msg, - call_hicn_api_face_params_get, - (void *)temp) != VAPI_OK) { - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/intfc", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT32_T; - vals[face].data.uint32_val = temp->face.intfc; - memset(buf, 0x00, 20); - sprintf(buf, "%u", temp->face.intfc); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_packets", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.irx_packets; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.irx_packets); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_bytes", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.irx_bytes; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.irx_bytes); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_packets", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.itx_packets; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.itx_packets); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_bytes", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.itx_bytes; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.itx_bytes); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_packets", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.drx_packets; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.drx_packets); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_bytes", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.drx_bytes; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.drx_packets); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_packets", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.dtx_packets; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.dtx_packets); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_bytes", - "/hicn:hicn-state/faces/face", temp->face.faceid); - vals[face].type = SR_UINT64_T; - vals[face].data.uint64_val = temp->face.dtx_bytes; - memset(buf, 0x00, 20); - sprintf(buf, "%" PRIu64, temp->face.dtx_bytes); - lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0); - - face++; - - temp = temp->next; - } - SRP_LOG_DBGMSG("Faces state updated \n"); - return SR_ERR_OK; -} - -static int hicn_state_states_cb(sr_session_ctx_t *session, - const char *module_name, const char *path, - const char *request_xpath, uint32_t request_id, - struct lyd_node **parent, void *private_data) { - sr_val_t *vals; - int rc; - enum locks_name state; - state = lstate; - SRP_LOG_DBGMSG("Requesting state data"); - - rc = sr_new_values(NSTATE_LEAVES, &vals); - if (SR_ERR_OK != rc) { - return rc; - } - - tlock(state); - state_update(vals, parent, session); - tunlock(state); - - return SR_ERR_OK; -} - -static int hicn_state_route_cb(sr_session_ctx_t *session, - const char *module_name, const char *path, - const char *request_xpath, uint32_t request_id, - struct lyd_node **parent, void *private_data) { - sr_val_t *vals; - int rc; - enum locks_name route; - route = lroute; - uint32_t NROUTE_NODES = hicn_routes->nroute * ROUTES_CHILDREN; - - rc = sr_new_values(NROUTE_NODES, &vals); - if (SR_ERR_OK != rc) { - return rc; - } - - tlock(route); - routes_update(vals, NROUTE_NODES / ROUTES_CHILDREN, parent, session); - tunlock(route); - - return SR_ERR_OK; -} - -static int hicn_state_faces_cb(sr_session_ctx_t *session, - const char *module_name, const char *path, - const char *request_xpath, uint32_t request_id, - struct lyd_node **parent, void *private_data) { - sr_val_t *vals; - int rc; - enum locks_name faces; - faces = lfaces; - uint32_t NFACES_NODES = hicn_faces->nface * FACES_CHILDREN; - - rc = sr_new_values(NFACES_NODES, &vals); - if (SR_ERR_OK != rc) { - return rc; - } - - tlock(faces); - faces_update(vals, NFACES_NODES / FACES_CHILDREN, parent, session); - tunlock(faces); - - return SR_ERR_OK; -} - -static int hicn_strategies_get_cb(sr_session_ctx_t *session, const char *path, - const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, - sr_val_t **output, size_t *output_cnt, - void *private_data) { - SRP_LOG_DBGMSG("hicn strategies received successfully"); - vapi_msg_hicn_api_strategies_get *msg; - - msg = vapi_alloc_hicn_api_strategies_get(g_vapi_ctx_instance); - - if (vapi_hicn_api_strategies_get(g_vapi_ctx_instance, msg, - call_hicn_api_strategies_get, - NULL) != VAPI_OK) { - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - return SR_ERR_OK; -} - -static int hicn_face_params_get_cb(sr_session_ctx_t *session, const char *path, - const sr_val_t *input, - const size_t input_cnt, sr_event_t event, - uint32_t request_id, sr_val_t **output, - size_t *output_cnt, void *private_data) { - SRP_LOG_DBGMSG("hicn face ip params get received successfully"); - vapi_msg_hicn_api_face_params_get *msg; - - msg = vapi_alloc_hicn_api_face_params_get(g_vapi_ctx_instance); - - msg->payload.faceid = input[0].data.uint32_val; - - if (vapi_hicn_api_face_params_get(g_vapi_ctx_instance, msg, - call_hicn_api_face_params_get, - NULL) != VAPI_OK) { - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - return SR_ERR_OK; -} - -static vapi_error_e call_hicn_api_enable_disable( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_enable_disable_reply *reply) { - if (!reply->retval) { - SRP_LOG_DBGMSG("Successfully done"); - return VAPI_OK; - } else - return VAPI_EUSER; -} - -static int hicn_enable_cb(sr_session_ctx_t *session, const char *path, - const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, - sr_val_t **output, size_t *output_cnt, - void *private_data) { - SRP_LOG_DBGMSG("hicn enable received successfully"); - vapi_msg_hicn_api_enable_disable *msg; - - msg = vapi_alloc_hicn_api_enable_disable(g_vapi_ctx_instance); - - const char *delim = "/"; - if (input->type != SR_STRING_T) { - SRP_LOG_DBGMSG("Expected prefix of type string"); - return SR_ERR_OPERATION_FAILED; - } - char *token; - - /* get the first token */ - token = strtok(input->data.string_val, delim); - - /* if null the address is ipv4 else ipv6*/ - if (strrchr(token, ':') == NULL) { - struct sockaddr_in sa; - inet_pton(AF_INET, token, &(sa.sin_addr)); - unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr; - memcpy(&msg->payload.prefix.address.un.ip4[0], tmp, B32); - msg->payload.prefix.address.af = ADDRESS_IP4; - } else { - void *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, token, dst); - unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr; - memcpy(&msg->payload.prefix.address.un.ip6[0], tmp, B128); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - /* The second token is the prefix len*/ - token = strtok(NULL, delim); - - msg->payload.prefix.len = atoi(token); - msg->payload.enable_disable = 1; - - if (vapi_hicn_api_enable_disable(g_vapi_ctx_instance, msg, - call_hicn_api_enable_disable, - NULL) != VAPI_OK) { - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - return SR_ERR_OK; -} - -static int hicn_disable_cb(sr_session_ctx_t *session, const char *path, - const sr_val_t *input, const size_t input_cnt, - sr_event_t event, uint32_t request_id, - sr_val_t **output, size_t *output_cnt, - void *private_data) { - SRP_LOG_DBGMSG("hicn disable received successfully"); - vapi_msg_hicn_api_enable_disable *msg; - - msg = vapi_alloc_hicn_api_enable_disable(g_vapi_ctx_instance); - - const char *delim = "/"; - if (input->type != SR_STRING_T) { - SRP_LOG_DBGMSG("Expected prefix of type string"); - return SR_ERR_OPERATION_FAILED; - } - char *token; - - /* get the first token */ - token = strtok(input->data.string_val, delim); - - /* if null the address is ipv4 else ipv6*/ - if (strrchr(token, ':') == NULL) { - struct sockaddr_in sa; - inet_pton(AF_INET, token, &(sa.sin_addr)); - unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr; - memcpy(&msg->payload.prefix.address.un.ip4[0], tmp, B32); - msg->payload.prefix.address.af = ADDRESS_IP4; - } else { - void *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, token, dst); - unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr; - memcpy(&msg->payload.prefix.address.un.ip6[0], tmp, B128); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - /* The second token is the prefix len*/ - token = strtok(NULL, delim); - - msg->payload.prefix.len = atoi(token); - msg->payload.enable_disable = 0; - - if (vapi_hicn_api_enable_disable(g_vapi_ctx_instance, msg, - call_hicn_api_enable_disable, - NULL) != VAPI_OK) { - SRP_LOG_DBGMSG("Operation failed"); - return SR_ERR_OPERATION_FAILED; - } - - return SR_ERR_OK; -} - -static vapi_error_e hicn_api_routes_dump_cb( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_routes_details *reply) { - static int counter = 0; - - tlock(lroute); - if (reply != NULL) { - rcurrent->route.route_id = counter; - rcurrent->route.prefix = reply->prefix; - rcurrent->route.nfaces = reply->nfaces; - rcurrent->route.strategy_id = reply->strategy_id; - for (int cnt = 0; cnt < rcurrent->route.nfaces; cnt++) - rcurrent->route.faceids[cnt] = rcurrent->route.faceids[cnt]; - - counter++; - rcurrent = rcurrent->next; - - SRP_LOG_DBG("nfaces %d", reply->nfaces); - SRP_LOG_DBG("strategy_id %d", reply->strategy_id); - - } else { - SRP_LOG_DBGMSG("---------Routes------- \n"); - hicn_routes->nroute = counter; - counter = 0; - rcurrent = hicn_routes->next; - } - tunlock(lroute); - return SR_ERR_OK; -} - -static vapi_error_e hicn_api_face_stats_dump_cb( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_face_stats_details *reply) { - static int counter = 0; - - tlock(lfaces); - if (reply != NULL) { - fcurrent->face.faceid = reply->faceid; - fcurrent->face.intfc = 1; - fcurrent->face.irx_packets = reply->irx_packets; - fcurrent->face.irx_bytes = reply->irx_bytes; - fcurrent->face.itx_packets = reply->itx_packets; - fcurrent->face.itx_bytes = reply->itx_bytes; - fcurrent->face.drx_packets = reply->drx_packets; - fcurrent->face.drx_bytes = reply->drx_bytes; - fcurrent->face.dtx_packets = reply->dtx_packets; - fcurrent->face.dtx_bytes = reply->dtx_bytes; - counter++; - fcurrent = fcurrent->next; - SRP_LOG_DBG("faceid %d", reply->faceid); - SRP_LOG_DBG("drxB %d", reply->drx_bytes); - SRP_LOG_DBG("dtxB %d", reply->dtx_bytes); - - } else { - SRP_LOG_DBGMSG("---------Faces------- \n"); - hicn_faces->nface = counter; - counter = 0; - fcurrent = hicn_faces->next; - } - tunlock(lfaces); - return SR_ERR_OK; -} - -static void *state_thread(void *arg) { - // mapping can be retrieved by cpuinfo - int map = 0; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(map, &cpuset); - - // pin the thread to a core - if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) { - SRP_LOG_DBGMSG("Thread pining failed\n"); - exit(1); - } - - vapi_msg_hicn_api_node_stats_get *msg = NULL; - enum locks_name state; - state = lstate; - - while (true) { - tlock(state); - // dump faces - vapi_msg_hicn_api_face_stats_dump *fmsg; - fmsg = vapi_alloc_hicn_api_face_stats_dump(g_vapi_ctx_instance); - vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg, - hicn_api_face_stats_dump_cb, fcurrent); - - // dump routes - vapi_msg_hicn_api_routes_dump *rmsg; - rmsg = vapi_alloc_hicn_api_routes_dump(g_vapi_ctx_instance); - vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg, - hicn_api_routes_dump_cb, rcurrent); - - msg = vapi_alloc_hicn_api_node_stats_get(g_vapi_ctx_instance); - - if (vapi_hicn_api_node_stats_get(g_vapi_ctx_instance, msg, - call_vapi_hicn_api_node_stats_get, - NULL) != VAPI_OK) { - SRP_LOG_DBGMSG(" State operation failed"); - } - - tunlock(state); - sleep(1); - - SRP_LOG_DBGMSG("state cached"); - } - return NULL; -} - -int hicn_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription) { - int rc = SR_ERR_OK; - SRP_LOG_DBGMSG("Subscriging hicn."); - - // Initializing the locks - for (int i = 0; i < NLOCKS; i++) ticket_init(i, LOCK_INIT); - - // Initializing the buffer - rc = init_buffer(); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in initializing the buffers\n"); - goto error; - } - - SRP_LOG_DBGMSG("buffer initialized successfully."); - - rc = init_face_pool(fcurrent); - if (rc) { - SRP_LOG_DBGMSG("Problem in initializing the pools\n"); - goto error; - } - - rc = init_route_pool(rcurrent); - if (rc) { - SRP_LOG_DBGMSG("Problem in initializing the pools\n"); - goto error; - } - - SRP_LOG_DBGMSG("pools created successfully."); - - // Create state thread observation - pthread_t state_tid; - rc = pthread_create((pthread_t *)&state_tid, NULL, state_thread, NULL); - if (rc != 0) { - SRP_LOG_DBGMSG("Error making hicn state thread"); - return SR_ERR_OPERATION_FAILED; - } - SRP_LOG_DBGMSG("State thread created successfully."); - - // strategies subscriptions - - rc = sr_rpc_subscribe(session, "/hicn:strategies-get", hicn_strategies_get_cb, - session, 98, SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription strategies-get\n"); - goto error; - } - - // face ip subscriptions - - rc = sr_rpc_subscribe(session, "/hicn:face-params-get", - hicn_face_params_get_cb, session, 93, - SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription face-params-get\n"); - goto error; - } - - // hICN enable-disable subscriptions - - rc = sr_rpc_subscribe(session, "/hicn:hicn-enable", hicn_enable_cb, session, - 94, SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription hicn-enable\n"); - goto error; - } - - rc = sr_rpc_subscribe(session, "/hicn:hicn-disable", hicn_disable_cb, session, - 95, SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription hicn-enable\n"); - goto error; - } - - // subscribe as hicn state data provider - - rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/states", - hicn_state_states_cb, NULL, - SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/states\n"); - goto error; - } - - rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/routes", - hicn_state_route_cb, NULL, - SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/routes\n"); - goto error; - } - - rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/faces", - hicn_state_faces_cb, NULL, - SR_SUBSCR_CTX_REUSE, subscription); - if (rc != SR_ERR_OK) { - SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/faces\n"); - goto error; - } - - SRP_LOG_DBGMSG("hicn plugin initialized successfully.\n"); - return SR_ERR_OK; - -error: - SRP_LOG_ERRMSG("Error by initialization of the hicn plugin."); - sr_plugin_cleanup_cb(session, &g_vapi_ctx_instance); - return rc; -} diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h deleted file mode 100644 index 62fb15340..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -* Copyright (c) 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 hicn_model.h - * @brief This file contains main calls for hICN events coresponding to the hICN yang models - */ - -#ifndef __IETF_HICN_H__ -#define __IETF_HICN_H__ - -#include "../hicn_vpp_comm.h" -#include <vapi/hicn.api.vapi.h> - -/** - * @brief Align memory to one page boundary - */ -#define MEM_ALIGN 4096 - -/** - * @brief 32 bits = 4 bytes - */ -#define B32 4 -/** - * @brief 64bits = 8 bytes - */ -#define B64 8 -/** - * @brief 128 bits = 16 bytes - */ -#define B128 16 - -/** - * @brief set number of lock to 5 - */ -#define NLOCKS 5 - -/** - * @brief initialize all locks by 0, better to initialize by 0 :) - */ -#define LOCK_INIT 0 - -/** - * @brief enumeration for the locks - */ -enum locks_name {lstate, lstrategy, lstrategies, lroute, lfaces}; - - -// It is a coarse grain approach later can be changed to fine grained - - -/** - * @brief This indicates the number of leaves for the hICN state - */ -#define NSTATE_LEAVES 15 -/** - * @brief This indicates the number of leaves for strategy - */ -#define NSTRATEGY_LEAVES 1 -/** - * @brief This indicates the number of leaves for strategies - */ -#define NSTRATEGIES_LEAVES 2 -/** - * @brief This indicates the maximum faces which can be read as operational data - */ -#define MAX_FACE_POOL 100 -/** - * @brief This indicates the maximum routes which can be read as operational data - */ -#define MAX_ROUTE_POOL 100 -/** - * @brief This indicates the number of leaves for faces - */ -#define FACES_CHILDREN 9 /*this is the number of children of each leave in face except the key*/ -/** - * @brief This indicates the number of leaves for routes - */ -#define ROUTES_CHILDREN 2 /*this is the number of children of each leave in face except the key*/ - -typedef struct __attribute__ ((__packed__)) { - int32_t retval; - uint64_t pkts_processed; - uint64_t pkts_interest_count; - uint64_t pkts_data_count; - uint64_t pkts_from_cache_count; - uint64_t pkts_no_pit_count; - uint64_t pit_expired_count; - uint64_t cs_expired_count; - uint64_t cs_lru_count; - uint64_t pkts_drop_no_buf; - uint64_t interests_aggregated; - uint64_t interests_retx; - uint64_t interests_hash_collision; - uint64_t pit_entries_count; - uint64_t cs_entries_count; - uint64_t cs_entries_ntw_count; -} hicn_state_t; - - -typedef struct __attribute__ ((__packed__)) { - - uint8_t n_strategies; - uint32_t strategy_id[256]; - int32_t retval; -} hicn_strategies_t; - - -typedef struct __attribute__ ((__packed__)) { - uint32_t faceid; - uint32_t intfc; - uint64_t irx_packets; - uint64_t irx_bytes; - uint64_t itx_packets; - uint64_t itx_bytes; - uint64_t drx_packets; - uint64_t drx_bytes; - uint64_t dtx_packets; - uint64_t dtx_bytes; -} hicn_face_inf_t; - - -typedef struct __attribute__ ((__packed__)) { - u32 route_id; - vapi_type_prefix prefix; - u32 faceids[5]; - u8 nfaces; - u32 strategy_id; -} hicn_route_inf_t; - -/** - * @brief This is the link list to maintain the statistics of the faces - */ -struct hicn_faces_s{ - hicn_face_inf_t face; - struct hicn_faces_s * next; -}; - - -typedef struct __attribute__ ((__packed__)) { - uint32_t nface; - struct hicn_faces_s * next; -} hicn_faces_t; - -/** - * @brief This is the link list to maintain the route informations - */ -struct hicn_routes_s{ - hicn_route_inf_t route; - struct hicn_routes_s * next; -}; - - -typedef struct __attribute__ ((__packed__)) { - uint32_t nroute; - struct hicn_routes_s * next; -} hicn_routes_t; - -/** - * @brief This function subscribes the hICN evens consisting of all RPCs - * as well as operational data - */ -int hicn_subscribe_events(sr_session_ctx_t *session, - sr_subscription_ctx_t **subscription); - -#endif /* __IETF_HICN_H__ */ diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c deleted file mode 100644 index d27ae6492..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c +++ /dev/null @@ -1,21 +0,0 @@ -#include"tlock.h" - - -void ticket_init ( int Lock_Number , long int init ){ - -//__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST ); -//__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST ); -En[Lock_Number]=init; -De[Lock_Number]=init; -} - -void tlock(int Lock_Number ){ - - int my_ticket = __sync_fetch_and_add(&En[Lock_Number] , 1 ); - while ( my_ticket != De[ Lock_Number ] ) {}; - -} - -void tunlock(int Lock_Number ){ -De[Lock_Number]++; -} diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h deleted file mode 100644 index a871705a3..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 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 tlock.h - * @brief This file contains ticket lock APIs. - */ - -#ifndef __TLOCK_H__ -#define __TLOCK_H__ - - -/** - - * @brief limit the number of locks: it shoud be matched with the - * number of hicn-state leaves - */ -#define MAX_LOCK_SIZE 5 - -/** - * @brief Ticket lock counters - */ -volatile long int En[MAX_LOCK_SIZE] ; - -/** - * @brief Ticket lock counters - */ -volatile long int De[MAX_LOCK_SIZE] ; - - -/** - * @brief This function initialize the ticket lock - * @param Lock_Number describes the number of locks need to be initialized - * @param init describes the init number - */ -void ticket_init ( int Lock_Number , long int init ); -/** - * @brief this function acquire the lock - * Description of what the function does. This part may refer to the parameters - * @param Lock_Number pass the lock - */ -void tlock(int Lock_Number ); -/** - * @briefthis function release the lock - * @param Lock_Number lock number - - */ -void tunlock(int Lock_Number ); - -#endif /* __IETF_HICN_H__ */
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/README.md b/ctrl/sysrepo-plugins/hicn-plugin/test/README.md deleted file mode 100644 index a1c9bedff..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# test hICN sysrepo plugin - -Two simple tests are provided to verify the functionality of the plugin. In ```netconf-test``` you can find ```test.py``` which uses netconf-clinet library to send NETCONF command toward the sysrepo. This is the usage: -``` -python test.py host user password operation -``` -<b>host</b> indicates the host information. <b>user</b>, <b>password</b> are credentials to connect to the device. <b>Operation</b> can be one of the following: -``` -- route_dump - It receives the route operational data from vpp -- face_dump - It receives the face operational data from vpp -- face_add - It adds an hICN face in the vpp -- punt_add - It adds a punt in the vpp -- route_add - It adds route in the vpp -- face_dell - It deletes face from vpp -- route_del - It deletes route from vpp -- punt_del - It deletes punt from vpp -``` - -In the ```vapi-test``` you can find testing the VAPI for the communication between the hICN sysrepo plugin and vpp. This is the usage: - -``` -./test [route_add [4|6], punt_add [4|6], face_add [4|6], route_dump, face_dump] -``` -The definition for the argument is the same as the netconf-test except that here you can choose the test for IPV4 and IPV6. diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aface.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aface.xml deleted file mode 100644 index e1452f722..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aface.xml +++ /dev/null @@ -1,7 +0,0 @@ -<face-ip-add xmlns="urn:sysrepo:hicn"> - <lip4>192.168.20.10</lip4> - <lip6>-1</lip6> - <rip4>192.168.100.1</rip4> - <rip6>-1</rip6> - <swif>0</swif> -</face-ip-add> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/apunt.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/apunt.xml deleted file mode 100644 index b7fa8b741..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/apunt.xml +++ /dev/null @@ -1,6 +0,0 @@ -<punting-add xmlns="urn:sysrepo:hicn"> - <ip4>192.168.0.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <swif>0</swif> -</punting-add> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aroute.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aroute.xml deleted file mode 100644 index 9997452b9..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/aroute.xml +++ /dev/null @@ -1,13 +0,0 @@ -<route-nhops-add xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <face_ids0>0</face_ids0> - <face_ids1>0</face_ids1> - <face_ids2>0</face_ids2> - <face_ids3>0</face_ids3> - <face_ids4>0</face_ids4> - <face_ids5>0</face_ids5> - <face_ids6>0</face_ids6> - <n_faces>1</n_faces> -</route-nhops-add> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dface.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dface.xml deleted file mode 100644 index 07a9488a9..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dface.xml +++ /dev/null @@ -1,3 +0,0 @@ -<face-ip-del xmlns="urn:sysrepo:hicn"> - <faceid>0</faceid> -</face-ip-del> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dpunt.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dpunt.xml deleted file mode 100644 index 72d5c3c88..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/dpunt.xml +++ /dev/null @@ -1,6 +0,0 @@ -<punting-del xmlns="urn:sysrepo:hicn"> - <ip4>192.168.0.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <swif>0</swif> -</punting-del> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/droute.xml b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/droute.xml deleted file mode 100644 index ded28eecf..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/droute.xml +++ /dev/null @@ -1,6 +0,0 @@ -<route-nhops-del xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <faceid>0</faceid> -</route-nhops-del> diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/test.py b/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/test.py deleted file mode 100755 index 7c6163521..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/netconf-test/test.py +++ /dev/null @@ -1,66 +0,0 @@ -import sys -import xml.etree.ElementTree as ET -from netconf.client import connect_ssh - -def usage(): - print('usage: test.py host user password operation{route_dump, face_dump, face_add, route_add, punt_add, face_del, punt_del, route_del}') - -def test(host,user,password,operation): - with connect_ssh(host, 830, user, password) as session: - if (operation=='face_dump'): - config = session.get() - for root in config: - if root.tag=="{urn:sysrepo:hicn}hicn-state": - for entity in root: - if entity.tag=="{urn:sysrepo:hicn}faces": - print('Faces') - for face in entity: - for elem in face: - print(elem.tag +" : "+ elem.text) - elif (operation=='state_dump'): - config = session.get() - for root in config: - if root.tag=="{urn:sysrepo:hicn}hicn-state": - for entity in root: - if entity.tag=="{urn:sysrepo:hicn}states": - print('States') - for state in entity: - print(state.tag +" : "+ state.text) - elif (operation=='route_dump'): - config = session.get() - for root in config: - if root.tag=="{urn:sysrepo:hicn}hicn-state": - for entity in root: - if entity.tag=="{urn:sysrepo:hicn}routes": - print('Routes') - for route in entity: - for elem in route: - print(elem.tag +" : "+ elem.text) - elif(operation=='face_add'): - root = ET.parse('aface.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - elif(operation=='punt_add'): - root = ET.parse('apunt.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - elif(operation=='route_add'): - root = ET.parse('aroute.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - elif(operation=='face_del'): - root = ET.parse('dface.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - elif(operation=='punt_del'): - root = ET.parse('dpunt.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - elif(operation=='route_del'): - root = ET.parse('droute.xml').getroot() - session.send_rpc(ET.tostring(root, encoding='utf8').decode('utf8')) - else: - usage() - -if __name__ == '__main__': - if(len(sys.argv)<4): - usage() - else: - test(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4]) - - diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/Makefile b/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/Makefile deleted file mode 100755 index 8ab5d27de..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -main: - sudo gcc -g -o test test.c -lvapiclient diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c b/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c deleted file mode 100755 index f7b92c3c5..000000000 --- a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c +++ /dev/null @@ -1,290 +0,0 @@ -#include <vapi/vapi.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <inttypes.h> - -#include<vapi/hicn.api.vapi.h> - - -DEFINE_VAPI_MSG_IDS_HICN_API_JSON; - -vapi_ctx_t g_vapi_ctx_instance; - - -#define APP_NAME "test_hicn_plugin" -#define MAX_OUTSTANDING_REQUESTS 4 -#define RESPONSE_QUEUE_SIZE 2 - -vapi_ctx_t g_vapi_ctx_instance = NULL; - - -void usage(){ - printf("choose the test [route_add [4|6], punt_add [4|6], face_add [4|6], route_dump, face_dump]\n"); -} - -static vapi_error_e call_hicn_api_punting_add(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_punting_add_reply *reply){ -if(!reply->retval){ - printf("Successfully done"); - return VAPI_OK; - }else - return VAPI_EUSER; -} - -static vapi_error_e call_hicn_api_face_ip_add(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_face_ip_add_reply *reply){ -if(!reply->retval){ - printf("Successfully done"); - return VAPI_OK; - }else - return VAPI_EUSER; - -} - -static vapi_error_e call_hicn_api_route_nhops_add(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_hicn_api_route_nhops_add_reply *reply){ -if(!reply->retval){ - printf("Successfully done"); - return VAPI_OK; - }else - return VAPI_EUSER; -} - -static vapi_error_e -hicn_api_routes_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_routes_details *reply) -{ - - char buf[20]; - if (reply!=NULL){ - memset(buf, 0x00, 20); - if (reply->prefix.address.af==ADDRESS_IP4){ - struct sockaddr_in sa; - memcpy(&sa.sin_addr.s_addr, reply->prefix.address.un.ip4, 4); - inet_ntop(AF_INET, &(sa.sin_addr.s_addr), buf, INET_ADDRSTRLEN); - printf("Prefix:%s\n",buf); - }else{ - struct sockaddr_in6 sa; - memcpy(&sa.sin6_addr,reply->prefix.address.un.ip6,6); - inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN); - printf("Prefix:%s\n",buf); - } - }else - { - printf("---------Routes------- \n"); - } - return 0; - -} - - - -static vapi_error_e -hicn_api_face_stats_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_face_stats_details *reply) -{ - if (reply!=NULL){ - - printf("face_id:%d \n", reply->faceid); - printf("irx_packets:%" PRId64 "\n", reply->irx_packets); - printf("irx_bytes:%" PRId64 "\n", reply->irx_bytes); - printf("itx_packets:%" PRId64 "\n", reply->itx_packets); - printf("itx_bytes:%" PRId64 "\n", reply->itx_bytes); - printf("drx_packets:%" PRId64 "\n", reply->drx_packets); - printf("drx_bytes:%" PRId64 "\n", reply->drx_bytes); - printf("dtx_packets:%" PRId64 "\n", reply->dtx_packets); - printf("dtx_bytes:%" PRId64 "\n", reply->dtx_bytes); - - }else - { - printf("---------Facees------- \n"); - } - return 0; -} - - -int hicn_connect_vpp() -{ - - if (g_vapi_ctx_instance == NULL) - { - vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance); - rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, VAPI_MODE_BLOCKING, true); - if (rv != VAPI_OK) - { - vapi_ctx_free(g_vapi_ctx_instance); - return -1; - } - } - else - { - } - return 0; -} - -int hicn_disconnect_vpp() -{ - if (NULL != g_vapi_ctx_instance) - { - vapi_disconnect(g_vapi_ctx_instance); - vapi_ctx_free(g_vapi_ctx_instance); - g_vapi_ctx_instance = NULL; - } - return 0; -} - -int main(int argc, char **argv) -{ - - if (argc<2){ - usage(); - return 1; - } - - /* connect to vpp */ - int rc = hicn_connect_vpp(); - if (-1 == rc){ - perror("vpp connect error"); - return -1; - } - - if (!strcmp(argv[1],"route_add")){ - vapi_msg_hicn_api_route_nhops_add *msg; - msg = vapi_alloc_hicn_api_route_nhops_add(g_vapi_ctx_instance); - - if (!strcmp(argv[2],"4")){ - struct sockaddr_in sa; - inet_pton(AF_INET, "192.168.10.10", &(sa.sin_addr)); - unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr; - memcpy(&msg->payload.prefix.address.un.ip4[0],tmp,4); - msg->payload.prefix.address.af = ADDRESS_IP4; - }else{ - void *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, "2001::1", dst); - unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&msg->payload.prefix.address.un.ip6[0],tmp,16); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - msg->payload.prefix.len = 24; - msg->payload.face_ids[0] = 0; - msg->payload.face_ids[1] = 0; - msg->payload.face_ids[2] = 0; - msg->payload.face_ids[3] = 0; - msg->payload.face_ids[4] = 0; - msg->payload.face_ids[5] = 0; - msg->payload.face_ids[6] = 0; - msg->payload.n_faces = 1; - - if(vapi_hicn_api_route_nhops_add(g_vapi_ctx_instance,msg,call_hicn_api_route_nhops_add,NULL)!=VAPI_OK){ - perror("Operation failed"); - return -1; - } - }else if (!strcmp(argv[1],"face_add")){ - - vapi_msg_hicn_api_face_ip_add *fmsg; - fmsg = vapi_alloc_hicn_api_face_ip_add(g_vapi_ctx_instance); - - - if (!strcmp(argv[2],"4")){ - struct sockaddr_in sa; - inet_pton(AF_INET, "192.168.50.19", &(sa.sin_addr)); - unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr; - memcpy(&fmsg->payload.face.local_addr.un.ip4[0],tmp,4); - fmsg->payload.face.local_addr.af = ADDRESS_IP4; - - - inet_pton(AF_INET, "192.168.60.10", &(sa.sin_addr)); - tmp = (unsigned char *)&sa.sin_addr.s_addr; - memcpy(&fmsg->payload.face.remote_addr.un.ip4[0],tmp,4); - fmsg->payload.face.remote_addr.af = ADDRESS_IP4; - - }else{ - - void *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, "2001::1", dst); - unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&fmsg->payload.face.local_addr.un.ip6[0],tmp,16); - fmsg->payload.face.local_addr.af = ADDRESS_IP6; - - - inet_pton(AF_INET6, "3001::1", dst); - tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&fmsg->payload.face.remote_addr.un.ip6[0],tmp,16); - fmsg->payload.face.remote_addr.af = ADDRESS_IP6; - } - - fmsg->payload.face.swif = 0; // This is the idx number of interface - - if(vapi_hicn_api_face_ip_add(g_vapi_ctx_instance,fmsg,call_hicn_api_face_ip_add,NULL)!=VAPI_OK){ - perror("Operation failed"); - return -1; - } - }else if (!strcmp(argv[1],"route_dump")){ - // routes dump - vapi_msg_hicn_api_routes_dump *rmsg; - rmsg = vapi_alloc_hicn_api_routes_dump(g_vapi_ctx_instance); - vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg, hicn_api_routes_dump_cb, NULL); - - }else if (!strcmp(argv[1],"face_dump")){ - // faces dump - vapi_msg_hicn_api_face_stats_dump *fmsg; - fmsg = vapi_alloc_hicn_api_face_stats_dump(g_vapi_ctx_instance); - vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg, hicn_api_face_stats_dump_cb, NULL); - }else if (!strcmp(argv[1],"punt_add")){ - - vapi_msg_hicn_api_punting_add *pmsg; - - pmsg = vapi_alloc_hicn_api_punting_add(g_vapi_ctx_instance); - - pmsg->payload.type=IP_PUNT; - - if(!strcmp(argv[2],"4")){ - - struct sockaddr_in sa; - // store this IP address in sa: - inet_pton(AF_INET, "192.168.10.20", &(sa.sin_addr)); - unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr; - memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip4[0],tmp,4); - pmsg->payload.rule.ip.prefix.address.af = ADDRESS_IP4; - - - }else{ - - void *dst = malloc(sizeof(struct in6_addr)); - inet_pton(AF_INET6, "3001::1", dst); - unsigned char * tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip6[0],tmp,16); - pmsg->payload.rule.ip.prefix.address.af = ADDRESS_IP6; - } - - pmsg->payload.rule.ip.prefix.len = 24; - pmsg->payload.rule.ip.swif = 0; - - if (vapi_hicn_api_punting_add(g_vapi_ctx_instance, pmsg, call_hicn_api_punting_add, NULL)!=VAPI_OK){ - perror("Operation failed"); - return -1; - } - }else - { - usage(); - return 1; - } - - hicn_disconnect_vpp(); - - return rc; -} diff --git a/ctrl/sysrepo-plugins/yang/hicn/hicn.yang b/ctrl/sysrepo-plugins/yang/hicn/hicn.yang deleted file mode 100644 index 0514a7a2a..000000000 --- a/ctrl/sysrepo-plugins/yang/hicn/hicn.yang +++ /dev/null @@ -1,247 +0,0 @@ -module hicn { - namespace "urn:sysrepo:hicn"; - prefix hcn; - - import ietf-inet-types { - prefix inet; - } - - revision 2020-04-29{ - description "revised revision focus on telemetry."; - } - - /* new data types and grouping definition to forward the remote request toward hicn controler--to-->hicn */ - - typedef float { - type decimal64 { - fraction-digits 2; - } - } - - grouping states-reply { - - leaf pkts_processed { - description "ICN packets processed."; - type uint64; - } - - leaf pkts_interest_count { - description "PIT maximum size, otherwise -1 to assign default value."; - type uint64; - } - - leaf pkts_data_count { - description "CS maximum size, otherwise -1 to assign default value."; - type uint64; - } - - leaf pkts_from_cache_count { - description "Portion of CS reserved to application, otherwise -1 to assign default value."; - type uint64; - } - - leaf pkts_no_pit_count { - description "Default PIT entry lifetime, otherwise -1 to assign default value."; - type uint64; - } - - leaf pit_expired_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value."; - type uint64; - } - - leaf cs_expired_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf cs_lru_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf pkts_drop_no_buf { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf interests_aggregated { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf interests_retx { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf interests_hash_collision { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf pit_entries_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf cs_entries_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf cs_entries_ntw_count { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - } - - grouping face-stats-reply { - list face{ - key faceid; - leaf faceid { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint32; - } - - leaf intfc { - description "This is the idx number of the faceid."; - type uint32; - } - - leaf irx_packets { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf irx_bytes { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf itx_packets { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf itx_bytes { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - - leaf drx_packets { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf drx_bytes { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - leaf dtx_packets { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - - - leaf dtx_bytes { - description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; - type uint64; - } - } - } - - grouping route-reply { - - list route{ - key routeid; - leaf routeid { - description "the unique key for each item."; - type uint32; - } - leaf prefix { - description "IP address."; - type string; - - } - leaf strategy_id { - description "compile-time plugin features."; - type uint32; - } - } - } - - grouping strategies-reply { - leaf n_strategies { - description "Enable / disable ICN forwarder in VPP."; - type uint8; - } - leaf strategy_id { - description "Enable / disable ICN forwarder in VPP."; - type uint32; - } - - } - - typedef hicn-prefix { - description "hICN prefix."; - type inet:ip-prefix; - } - - - /* Hicn operational data */ - - container hicn-state { - - config false; - description "operational data container for the hicn."; - container faces{ - uses face-stats-reply; - } - container states{ - uses states-reply; - } - container routes{ - uses route-reply; - } - } - - - /* RPC Definitions */ - - rpc strategies-get { - description "Operation to get hicn strategies."; - } - - rpc face-params-get { - description "Operation to del hicn route."; - input { - leaf faceid { - description "Face to be retrieved ."; - type uint32; - } - } - } - - rpc hicn-enable { - description "Enable hicn on a gie prefix."; - input { - leaf prefix { - type hicn-prefix; - } - } - } - - rpc hicn-disable { - description "Disable hicn on a gie prefix."; - input { - leaf prefix { - type hicn-prefix; - } - } - } - -} diff --git a/ctrl/sysrepo-plugins/yang/hicn/rpc_call_samples.xml b/ctrl/sysrepo-plugins/yang/hicn/rpc_call_samples.xml deleted file mode 100644 index db79fd4ef..000000000 --- a/ctrl/sysrepo-plugins/yang/hicn/rpc_call_samples.xml +++ /dev/null @@ -1,78 +0,0 @@ -<node-params-get xmlns="urn:sysrepo:hicn"/> - -<node-stat-get xmlns="urn:sysrepo:hicn"/> - -<strategy-get xmlns="urn:sysrepo:hicn"> - <strategy_id>0</strategy_id> -</strategy-get> - -<strategies-get xmlns="urn:sysrepo:hicn"/> - - -<route-get xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>24</len> -</route-get> - -<route-del xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>30</len> -</route-del> - -<route-nhops-add xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <face_ids0>0</face_ids0> - <face_ids1>0</face_ids1> - <face_ids2>0</face_ids2> - <face_ids3>0</face_ids3> - <face_ids4>0</face_ids4> - <face_ids5>0</face_ids5> - <face_ids6>0</face_ids6> - <n_faces>1</n_faces> -</route-nhops-add> - -<route-nhops-del xmlns="urn:sysrepo:hicn"> - <ip4>192.168.1.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <faceid>0</faceid> -</route-nhops-del> - - -<face-ip-params-get xmlns="urn:sysrepo:hicn"> - <faceid>10</faceid> -</face-ip-params-get> - -<face-ip-add xmlns="urn:sysrepo:hicn"> - <lip4>192.168.1.10</lip4> - <lip6>-1</lip6> - <rip4>192.168.1.1</rip4> - <rip6>-1</rip6> - <swif>0</swif> -</face-ip-add> - - -<face-ip-del xmlns="urn:sysrepo:hicn"> - <faceid>0</faceid> -</face-ip-del> - -<punting-add xmlns="urn:sysrepo:hicn"> - <ip4>192.168.0.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <swif>0</swif> -</punting-add> - - -<punting-del xmlns="urn:sysrepo:hicn"> - <ip4>192.168.0.1</ip4> - <ip6>-1</ip6> - <len>24</len> - <swif>0</swif> -</punting-del> - -<face-stats-details xmlns="urn:sysrepo:hicn"/> diff --git a/ctrl/sysrepo-plugins/yang/hicn/sysrepo_startup.xml b/ctrl/sysrepo-plugins/yang/hicn/sysrepo_startup.xml deleted file mode 100644 index f88e13ea2..000000000 --- a/ctrl/sysrepo-plugins/yang/hicn/sysrepo_startup.xml +++ /dev/null @@ -1,11 +0,0 @@ -<hicn-conf xmlns="urn:sysrepo:hicn"> -<params> - <enable_disable>false</enable_disable> - <pit_max_size>-1</pit_max_size> - <cs_max_size>-1</cs_max_size> - <cs_reserved_app>-1</cs_reserved_app> - <pit_dflt_lifetime_sec>-1</pit_dflt_lifetime_sec> - <pit_max_lifetime_sec>-1</pit_max_lifetime_sec> - <pit_min_lifetime_sec>-1</pit_min_lifetime_sec> -</params> -</hicn-conf>
\ No newline at end of file diff --git a/ctrl/sysrepo-plugins/yang/ietf/iana-if-type@2014-05-08.yang b/ctrl/sysrepo-plugins/yang/ietf/iana-if-type@2014-05-08.yang deleted file mode 100644 index 4138ba46e..000000000 --- a/ctrl/sysrepo-plugins/yang/ietf/iana-if-type@2014-05-08.yang +++ /dev/null @@ -1,1704 +0,0 @@ -module iana-if-type { - - yang-version 1; - - namespace - "urn:ietf:params:xml:ns:yang:iana-if-type"; - - prefix ianaift; - - import ietf-interfaces { - prefix if; - } - - organization "IANA"; - - contact - " Internet Assigned Numbers Authority - - Postal: ICANN - 4676 Admiralty Way, Suite 330 - Marina del Rey, CA 90292 - - Tel: +1 310 823 9358 - <mailto:iana@iana.org>"; - - description - "This YANG module defines YANG identities for IANA-registered - interface types. - - This YANG module is maintained by IANA and reflects the - 'ifType definitions' registry. - - The latest revision of this YANG module can be obtained from - the IANA web site. - - Requests for new values should be made to IANA via - email (iana@iana.org). - - Copyright (c) 2014 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - Redistribution and use in source and binary forms, with or - without modification, is permitted pursuant to, and subject - to the license terms contained in, the Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - The initial version of this YANG module is part of RFC 7224; - see the RFC itself for full legal notices."; - - reference - "IANA 'ifType definitions' registry. - <http://www.iana.org/assignments/smi-numbers>"; - - - revision "2014-05-08" { - description "Initial revision."; - reference - "RFC 7224: IANA Interface Type YANG Module"; - - } - - - identity iana-interface-type { - base if:interface-type; - description - "This identity is used as a base for all interface types - defined in the 'ifType definitions' registry."; - } - - identity other { - base iana-interface-type; - } - - identity regular1822 { - base iana-interface-type; - } - - identity hdh1822 { - base iana-interface-type; - } - - identity ddnX25 { - base iana-interface-type; - } - - identity rfc877x25 { - base iana-interface-type; - reference - "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer"; - - } - - identity ethernetCsmacd { - base iana-interface-type; - description - "For all Ethernet-like interfaces, regardless of speed, - as per RFC 3635."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity iso88023Csmacd { - base iana-interface-type; - status deprecated; - description - "Deprecated via RFC 3635. - Use ethernetCsmacd(6) instead."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity iso88024TokenBus { - base iana-interface-type; - } - - identity iso88025TokenRing { - base iana-interface-type; - } - - identity iso88026Man { - base iana-interface-type; - } - - identity starLan { - base iana-interface-type; - status deprecated; - description - "Deprecated via RFC 3635. - Use ethernetCsmacd(6) instead."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity proteon10Mbit { - base iana-interface-type; - } - - identity proteon80Mbit { - base iana-interface-type; - } - - identity hyperchannel { - base iana-interface-type; - } - - identity fddi { - base iana-interface-type; - reference - "RFC 1512 - FDDI Management Information Base"; - - } - - identity lapb { - base iana-interface-type; - reference - "RFC 1381 - SNMP MIB Extension for X.25 LAPB"; - - } - - identity sdlc { - base iana-interface-type; - } - - identity ds1 { - base iana-interface-type; - description "DS1-MIB."; - reference - "RFC 4805 - Definitions of Managed Objects for the - DS1, J1, E1, DS2, and E2 Interface Types"; - - } - - identity e1 { - base iana-interface-type; - status obsolete; - description "Obsolete; see DS1-MIB."; - reference - "RFC 4805 - Definitions of Managed Objects for the - DS1, J1, E1, DS2, and E2 Interface Types"; - - } - - identity basicISDN { - base iana-interface-type; - description - "No longer used. See also RFC 2127."; - } - - identity primaryISDN { - base iana-interface-type; - description - "No longer used. See also RFC 2127."; - } - - identity propPointToPointSerial { - base iana-interface-type; - description "Proprietary serial."; - } - - identity ppp { - base iana-interface-type; - } - - identity softwareLoopback { - base iana-interface-type; - } - - identity eon { - base iana-interface-type; - description "CLNP over IP."; - } - - identity ethernet3Mbit { - base iana-interface-type; - } - - identity nsip { - base iana-interface-type; - description "XNS over IP."; - } - - identity slip { - base iana-interface-type; - description "Generic SLIP."; - } - - identity ultra { - base iana-interface-type; - description "Ultra Technologies."; - } - - identity ds3 { - base iana-interface-type; - description "DS3-MIB."; - reference - "RFC 3896 - Definitions of Managed Objects for the - DS3/E3 Interface Type"; - - } - - identity sip { - base iana-interface-type; - description "SMDS, coffee."; - reference - "RFC 1694 - Definitions of Managed Objects for SMDS - Interfaces using SMIv2"; - - } - - identity frameRelay { - base iana-interface-type; - description "DTE only."; - reference - "RFC 2115 - Management Information Base for Frame Relay - DTEs Using SMIv2"; - - } - - identity rs232 { - base iana-interface-type; - reference - "RFC 1659 - Definitions of Managed Objects for RS-232-like - Hardware Devices using SMIv2"; - - } - - identity para { - base iana-interface-type; - description "Parallel-port."; - reference - "RFC 1660 - Definitions of Managed Objects for - Parallel-printer-like Hardware Devices using - SMIv2"; - - } - - identity arcnet { - base iana-interface-type; - description "ARCnet."; - } - - identity arcnetPlus { - base iana-interface-type; - description "ARCnet Plus."; - } - - identity atm { - base iana-interface-type; - description "ATM cells."; - } - - identity miox25 { - base iana-interface-type; - reference - "RFC 1461 - SNMP MIB extension for Multiprotocol - Interconnect over X.25"; - - } - - identity sonet { - base iana-interface-type; - description "SONET or SDH."; - } - - identity x25ple { - base iana-interface-type; - reference - "RFC 2127 - ISDN Management Information Base using SMIv2"; - - } - - identity iso88022llc { - base iana-interface-type; - } - - identity localTalk { - base iana-interface-type; - } - - identity smdsDxi { - base iana-interface-type; - } - - identity frameRelayService { - base iana-interface-type; - description "FRNETSERV-MIB."; - reference - "RFC 2954 - Definitions of Managed Objects for Frame - Relay Service"; - - } - - identity v35 { - base iana-interface-type; - } - - identity hssi { - base iana-interface-type; - } - - identity hippi { - base iana-interface-type; - } - - identity modem { - base iana-interface-type; - description "Generic modem."; - } - - identity aal5 { - base iana-interface-type; - description "AAL5 over ATM."; - } - - identity sonetPath { - base iana-interface-type; - } - - identity sonetVT { - base iana-interface-type; - } - - identity smdsIcip { - base iana-interface-type; - description - "SMDS InterCarrier Interface."; - } - - identity propVirtual { - base iana-interface-type; - description - "Proprietary virtual/internal."; - reference - "RFC 2863 - The Interfaces Group MIB"; - - } - - identity propMultiplexor { - base iana-interface-type; - description - "Proprietary multiplexing."; - reference - "RFC 2863 - The Interfaces Group MIB"; - - } - - identity ieee80212 { - base iana-interface-type; - description "100BaseVG."; - } - - identity fibreChannel { - base iana-interface-type; - description "Fibre Channel."; - } - - identity hippiInterface { - base iana-interface-type; - description "HIPPI interfaces."; - } - - identity frameRelayInterconnect { - base iana-interface-type; - status obsolete; - description - "Obsolete; use either - frameRelay(32) or frameRelayService(44)."; - } - - identity aflane8023 { - base iana-interface-type; - description - "ATM Emulated LAN for 802.3."; - } - - identity aflane8025 { - base iana-interface-type; - description - "ATM Emulated LAN for 802.5."; - } - - identity cctEmul { - base iana-interface-type; - description "ATM Emulated circuit."; - } - - identity fastEther { - base iana-interface-type; - status deprecated; - description - "Obsoleted via RFC 3635. - ethernetCsmacd(6) should be used instead."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity isdn { - base iana-interface-type; - description "ISDN and X.25."; - reference - "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN - in the Packet Mode"; - - } - - identity v11 { - base iana-interface-type; - description "CCITT V.11/X.21."; - } - - identity v36 { - base iana-interface-type; - description "CCITT V.36."; - } - - identity g703at64k { - base iana-interface-type; - description "CCITT G703 at 64Kbps."; - } - - identity g703at2mb { - base iana-interface-type; - status obsolete; - description "Obsolete; see DS1-MIB."; - } - - identity qllc { - base iana-interface-type; - description "SNA QLLC."; - } - - identity fastEtherFX { - base iana-interface-type; - status deprecated; - description - "Obsoleted via RFC 3635. - ethernetCsmacd(6) should be used instead."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity channel { - base iana-interface-type; - description "Channel."; - } - - identity ieee80211 { - base iana-interface-type; - description "Radio spread spectrum."; - } - - identity ibm370parChan { - base iana-interface-type; - description - "IBM System 360/370 OEMI Channel."; - } - - identity escon { - base iana-interface-type; - description - "IBM Enterprise Systems Connection."; - } - - identity dlsw { - base iana-interface-type; - description "Data Link Switching."; - } - - identity isdns { - base iana-interface-type; - description "ISDN S/T interface."; - } - - identity isdnu { - base iana-interface-type; - description "ISDN U interface."; - } - - identity lapd { - base iana-interface-type; - description "Link Access Protocol D."; - } - - identity ipSwitch { - base iana-interface-type; - description "IP Switching Objects."; - } - - identity rsrb { - base iana-interface-type; - description - "Remote Source Route Bridging."; - } - - identity atmLogical { - base iana-interface-type; - description "ATM Logical Port."; - reference - "RFC 3606 - Definitions of Supplemental Managed Objects - for ATM Interface"; - - } - - identity ds0 { - base iana-interface-type; - description "Digital Signal Level 0."; - reference - "RFC 2494 - Definitions of Managed Objects for the DS0 - and DS0 Bundle Interface Type"; - - } - - identity ds0Bundle { - base iana-interface-type; - description - "Group of ds0s on the same ds1."; - reference - "RFC 2494 - Definitions of Managed Objects for the DS0 - and DS0 Bundle Interface Type"; - - } - - identity bsc { - base iana-interface-type; - description "Bisynchronous Protocol."; - } - - identity async { - base iana-interface-type; - description "Asynchronous Protocol."; - } - - identity cnr { - base iana-interface-type; - description "Combat Net Radio."; - } - - identity iso88025Dtr { - base iana-interface-type; - description "ISO 802.5r DTR."; - } - - identity eplrs { - base iana-interface-type; - description "Ext Pos Loc Report Sys."; - } - - identity arap { - base iana-interface-type; - description - "Appletalk Remote Access Protocol."; - } - - identity propCnls { - base iana-interface-type; - description - "Proprietary Connectionless Protocol."; - } - - identity hostPad { - base iana-interface-type; - description - "CCITT-ITU X.29 PAD Protocol."; - } - - identity termPad { - base iana-interface-type; - description - "CCITT-ITU X.3 PAD Facility."; - } - - identity frameRelayMPI { - base iana-interface-type; - description - "Multiproto Interconnect over FR."; - } - - identity x213 { - base iana-interface-type; - description "CCITT-ITU X213."; - } - - identity adsl { - base iana-interface-type; - description - "Asymmetric Digital Subscriber Loop."; - } - - identity radsl { - base iana-interface-type; - description - "Rate-Adapt. Digital Subscriber Loop."; - } - - identity sdsl { - base iana-interface-type; - description - "Symmetric Digital Subscriber Loop."; - } - - identity vdsl { - base iana-interface-type; - description - "Very H-Speed Digital Subscrib. Loop."; - } - - identity iso88025CRFPInt { - base iana-interface-type; - description "ISO 802.5 CRFP."; - } - - identity myrinet { - base iana-interface-type; - description "Myricom Myrinet."; - } - - identity voiceEM { - base iana-interface-type; - description - "Voice recEive and transMit."; - } - - identity voiceFXO { - base iana-interface-type; - description - "Voice Foreign Exchange Office."; - } - - identity voiceFXS { - base iana-interface-type; - description - "Voice Foreign Exchange Station."; - } - - identity voiceEncap { - base iana-interface-type; - description "Voice encapsulation."; - } - - identity voiceOverIp { - base iana-interface-type; - description - "Voice over IP encapsulation."; - } - - identity atmDxi { - base iana-interface-type; - description "ATM DXI."; - } - - identity atmFuni { - base iana-interface-type; - description "ATM FUNI."; - } - - identity atmIma { - base iana-interface-type; - description "ATM IMA."; - } - - identity pppMultilinkBundle { - base iana-interface-type; - description "PPP Multilink Bundle."; - } - - identity ipOverCdlc { - base iana-interface-type; - description "IBM ipOverCdlc."; - } - - identity ipOverClaw { - base iana-interface-type; - description - "IBM Common Link Access to Workstn."; - } - - identity stackToStack { - base iana-interface-type; - description "IBM stackToStack."; - } - - identity virtualIpAddress { - base iana-interface-type; - description "IBM VIPA."; - } - - identity mpc { - base iana-interface-type; - description - "IBM multi-protocol channel support."; - } - - identity ipOverAtm { - base iana-interface-type; - description "IBM ipOverAtm."; - reference - "RFC 2320 - Definitions of Managed Objects for Classical IP - and ARP Over ATM Using SMIv2 (IPOA-MIB)"; - - } - - identity iso88025Fiber { - base iana-interface-type; - description - "ISO 802.5j Fiber Token Ring."; - } - - identity tdlc { - base iana-interface-type; - description - "IBM twinaxial data link control."; - } - - identity gigabitEthernet { - base iana-interface-type; - status deprecated; - description - "Obsoleted via RFC 3635. - ethernetCsmacd(6) should be used instead."; - reference - "RFC 3635 - Definitions of Managed Objects for the - Ethernet-like Interface Types"; - - } - - identity hdlc { - base iana-interface-type; - description "HDLC."; - } - - identity lapf { - base iana-interface-type; - description "LAP F."; - } - - identity v37 { - base iana-interface-type; - description "V.37."; - } - - identity x25mlp { - base iana-interface-type; - description "Multi-Link Protocol."; - } - - identity x25huntGroup { - base iana-interface-type; - description "X25 Hunt Group."; - } - - identity transpHdlc { - base iana-interface-type; - description "Transp HDLC."; - } - - identity interleave { - base iana-interface-type; - description "Interleave channel."; - } - - identity fast { - base iana-interface-type; - description "Fast channel."; - } - - identity ip { - base iana-interface-type; - description - "IP (for APPN HPR in IP networks)."; - } - - identity docsCableMaclayer { - base iana-interface-type; - description "CATV Mac Layer."; - } - - identity docsCableDownstream { - base iana-interface-type; - description - "CATV Downstream interface."; - } - - identity docsCableUpstream { - base iana-interface-type; - description "CATV Upstream interface."; - } - - identity a12MppSwitch { - base iana-interface-type; - description - "Avalon Parallel Processor."; - } - - identity tunnel { - base iana-interface-type; - description "Encapsulation interface."; - } - - identity coffee { - base iana-interface-type; - description "Coffee pot."; - reference - "RFC 2325 - Coffee MIB"; - - } - - identity ces { - base iana-interface-type; - description - "Circuit Emulation Service."; - } - - identity atmSubInterface { - base iana-interface-type; - description "ATM Sub Interface."; - } - - identity l2vlan { - base iana-interface-type; - description - "Layer 2 Virtual LAN using 802.1Q."; - } - - identity l3ipvlan { - base iana-interface-type; - description - "Layer 3 Virtual LAN using IP."; - } - - identity l3ipxvlan { - base iana-interface-type; - description - "Layer 3 Virtual LAN using IPX."; - } - - identity digitalPowerline { - base iana-interface-type; - description "IP over Power Lines."; - } - - identity mediaMailOverIp { - base iana-interface-type; - description "Multimedia Mail over IP."; - } - - identity dtm { - base iana-interface-type; - description - "Dynamic synchronous Transfer Mode."; - } - - identity dcn { - base iana-interface-type; - description - "Data Communications Network."; - } - - identity ipForward { - base iana-interface-type; - description "IP Forwarding Interface."; - } - - identity msdsl { - base iana-interface-type; - description - "Multi-rate Symmetric DSL."; - } - - identity ieee1394 { - base iana-interface-type; - description - "IEEE1394 High Performance Serial Bus."; - } - - identity if-gsn { - base iana-interface-type; - description "HIPPI-6400."; - } - - identity dvbRccMacLayer { - base iana-interface-type; - description "DVB-RCC MAC Layer."; - } - - identity dvbRccDownstream { - base iana-interface-type; - description - "DVB-RCC Downstream Channel."; - } - - identity dvbRccUpstream { - base iana-interface-type; - description - "DVB-RCC Upstream Channel."; - } - - identity atmVirtual { - base iana-interface-type; - description "ATM Virtual Interface."; - } - - identity mplsTunnel { - base iana-interface-type; - description - "MPLS Tunnel Virtual Interface."; - } - - identity srp { - base iana-interface-type; - description "Spatial Reuse Protocol."; - } - - identity voiceOverAtm { - base iana-interface-type; - description "Voice over ATM."; - } - - identity voiceOverFrameRelay { - base iana-interface-type; - description "Voice Over Frame Relay."; - } - - identity idsl { - base iana-interface-type; - description - "Digital Subscriber Loop over ISDN."; - } - - identity compositeLink { - base iana-interface-type; - description - "Avici Composite Link Interface."; - } - - identity ss7SigLink { - base iana-interface-type; - description "SS7 Signaling Link."; - } - - identity propWirelessP2P { - base iana-interface-type; - description - "Prop. P2P wireless interface."; - } - - identity frForward { - base iana-interface-type; - description "Frame Forward Interface."; - } - - identity rfc1483 { - base iana-interface-type; - description - "Multiprotocol over ATM AAL5."; - reference - "RFC 1483 - Multiprotocol Encapsulation over ATM - Adaptation Layer 5"; - - } - - identity usb { - base iana-interface-type; - description "USB Interface."; - } - - identity ieee8023adLag { - base iana-interface-type; - description - "IEEE 802.3ad Link Aggregate."; - } - - identity bgppolicyaccounting { - base iana-interface-type; - description "BGP Policy Accounting."; - } - - identity frf16MfrBundle { - base iana-interface-type; - description - "FRF.16 Multilink Frame Relay."; - } - - identity h323Gatekeeper { - base iana-interface-type; - description "H323 Gatekeeper."; - } - - identity h323Proxy { - base iana-interface-type; - description - "H323 Voice and Video Proxy."; - } - - identity mpls { - base iana-interface-type; - description "MPLS."; - } - - identity mfSigLink { - base iana-interface-type; - description - "Multi-frequency signaling link."; - } - - identity hdsl2 { - base iana-interface-type; - description - "High Bit-Rate DSL - 2nd generation."; - } - - identity shdsl { - base iana-interface-type; - description "Multirate HDSL2."; - } - - identity ds1FDL { - base iana-interface-type; - description - "Facility Data Link (4Kbps) on a DS1."; - } - - identity pos { - base iana-interface-type; - description - "Packet over SONET/SDH Interface."; - } - - identity dvbAsiIn { - base iana-interface-type; - description "DVB-ASI Input."; - } - - identity dvbAsiOut { - base iana-interface-type; - description "DVB-ASI Output."; - } - - identity plc { - base iana-interface-type; - description - "Power Line Communications."; - } - - identity nfas { - base iana-interface-type; - description - "Non-Facility Associated Signaling."; - } - - identity tr008 { - base iana-interface-type; - description "TR008."; - } - - identity gr303RDT { - base iana-interface-type; - description "Remote Digital Terminal."; - } - - identity gr303IDT { - base iana-interface-type; - description - "Integrated Digital Terminal."; - } - - identity isup { - base iana-interface-type; - description "ISUP."; - } - - identity propDocsWirelessMaclayer { - base iana-interface-type; - description - "Cisco proprietary Maclayer."; - } - - identity propDocsWirelessDownstream { - base iana-interface-type; - description - "Cisco proprietary Downstream."; - } - - identity propDocsWirelessUpstream { - base iana-interface-type; - description - "Cisco proprietary Upstream."; - } - - identity hiperlan2 { - base iana-interface-type; - description - "HIPERLAN Type 2 Radio Interface."; - } - - identity propBWAp2Mp { - base iana-interface-type; - description - "PropBroadbandWirelessAccesspt2Multipt (use of this value - for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f - is deprecated, and ieee80216WMAN(237) should be used - instead)."; - } - - identity sonetOverheadChannel { - base iana-interface-type; - description "SONET Overhead Channel."; - } - - identity digitalWrapperOverheadChannel { - base iana-interface-type; - description "Digital Wrapper."; - } - - identity aal2 { - base iana-interface-type; - description "ATM adaptation layer 2."; - } - - identity radioMAC { - base iana-interface-type; - description - "MAC layer over radio links."; - } - - identity atmRadio { - base iana-interface-type; - description "ATM over radio links."; - } - - identity imt { - base iana-interface-type; - description "Inter-Machine Trunks."; - } - - identity mvl { - base iana-interface-type; - description - "Multiple Virtual Lines DSL."; - } - - identity reachDSL { - base iana-interface-type; - description "Long Reach DSL."; - } - - identity frDlciEndPt { - base iana-interface-type; - description - "Frame Relay DLCI End Point."; - } - - identity atmVciEndPt { - base iana-interface-type; - description "ATM VCI End Point."; - } - - identity opticalChannel { - base iana-interface-type; - description "Optical Channel."; - } - - identity opticalTransport { - base iana-interface-type; - description "Optical Transport."; - } - - identity propAtm { - base iana-interface-type; - description "Proprietary ATM."; - } - - identity voiceOverCable { - base iana-interface-type; - description - "Voice Over Cable Interface."; - } - - identity infiniband { - base iana-interface-type; - description "Infiniband."; - } - - identity teLink { - base iana-interface-type; - description "TE Link."; - } - - identity q2931 { - base iana-interface-type; - description "Q.2931."; - } - - identity virtualTg { - base iana-interface-type; - description "Virtual Trunk Group."; - } - - identity sipTg { - base iana-interface-type; - description "SIP Trunk Group."; - } - - identity sipSig { - base iana-interface-type; - description "SIP Signaling."; - } - - identity docsCableUpstreamChannel { - base iana-interface-type; - description "CATV Upstream Channel."; - } - - identity econet { - base iana-interface-type; - description "Acorn Econet."; - } - - identity pon155 { - base iana-interface-type; - description - "FSAN 155Mb Symetrical PON interface."; - } - - identity pon622 { - base iana-interface-type; - description - "FSAN 622Mb Symetrical PON interface."; - } - - identity bridge { - base iana-interface-type; - description - "Transparent bridge interface."; - } - - identity linegroup { - base iana-interface-type; - description - "Interface common to multiple lines."; - } - - identity voiceEMFGD { - base iana-interface-type; - description - "Voice E&M Feature Group D."; - } - - identity voiceFGDEANA { - base iana-interface-type; - description - "Voice FGD Exchange Access North American."; - } - - identity voiceDID { - base iana-interface-type; - description - "Voice Direct Inward Dialing."; - } - - identity mpegTransport { - base iana-interface-type; - description - "MPEG transport interface."; - } - - identity sixToFour { - base iana-interface-type; - status deprecated; - description - "6to4 interface (DEPRECATED)."; - reference - "RFC 4087 - IP Tunnel MIB"; - - } - - identity gtp { - base iana-interface-type; - description - "GTP (GPRS Tunneling Protocol)."; - } - - identity pdnEtherLoop1 { - base iana-interface-type; - description "Paradyne EtherLoop 1."; - } - - identity pdnEtherLoop2 { - base iana-interface-type; - description "Paradyne EtherLoop 2."; - } - - identity opticalChannelGroup { - base iana-interface-type; - description "Optical Channel Group."; - } - - identity homepna { - base iana-interface-type; - description "HomePNA ITU-T G.989."; - } - - identity gfp { - base iana-interface-type; - description - "Generic Framing Procedure (GFP)."; - } - - identity ciscoISLvlan { - base iana-interface-type; - description - "Layer 2 Virtual LAN using Cisco ISL."; - } - - identity actelisMetaLOOP { - base iana-interface-type; - description - "Acteleis proprietary MetaLOOP High Speed Link."; - } - - identity fcipLink { - base iana-interface-type; - description "FCIP Link."; - } - - identity rpr { - base iana-interface-type; - description - "Resilient Packet Ring Interface Type."; - } - - identity qam { - base iana-interface-type; - description "RF Qam Interface."; - } - - identity lmp { - base iana-interface-type; - description - "Link Management Protocol."; - reference - "RFC 4327 - Link Management Protocol (LMP) Management - Information Base (MIB)"; - - } - - identity cblVectaStar { - base iana-interface-type; - description - "Cambridge Broadband Networks Limited VectaStar."; - } - - identity docsCableMCmtsDownstream { - base iana-interface-type; - description - "CATV Modular CMTS Downstream Interface."; - } - - identity adsl2 { - base iana-interface-type; - status deprecated; - description - "Asymmetric Digital Subscriber Loop Version 2 - (DEPRECATED/OBSOLETED - please use adsl2plus(238) - instead)."; - reference - "RFC 4706 - Definitions of Managed Objects for Asymmetric - Digital Subscriber Line 2 (ADSL2)"; - - } - - identity macSecControlledIF { - base iana-interface-type; - description "MACSecControlled."; - } - - identity macSecUncontrolledIF { - base iana-interface-type; - description "MACSecUncontrolled."; - } - - identity aviciOpticalEther { - base iana-interface-type; - description - "Avici Optical Ethernet Aggregate."; - } - - identity atmbond { - base iana-interface-type; - description "atmbond."; - } - - identity voiceFGDOS { - base iana-interface-type; - description - "Voice FGD Operator Services."; - } - - identity mocaVersion1 { - base iana-interface-type; - description - "MultiMedia over Coax Alliance (MoCA) Interface - as documented in information provided privately to IANA."; - } - - identity ieee80216WMAN { - base iana-interface-type; - description - "IEEE 802.16 WMAN interface."; - } - - identity adsl2plus { - base iana-interface-type; - description - "Asymmetric Digital Subscriber Loop Version 2 - - Version 2 Plus and all variants."; - } - - identity dvbRcsMacLayer { - base iana-interface-type; - description "DVB-RCS MAC Layer."; - reference - "RFC 5728 - The SatLabs Group DVB-RCS MIB"; - - } - - identity dvbTdm { - base iana-interface-type; - description "DVB Satellite TDM."; - reference - "RFC 5728 - The SatLabs Group DVB-RCS MIB"; - - } - - identity dvbRcsTdma { - base iana-interface-type; - description "DVB-RCS TDMA."; - reference - "RFC 5728 - The SatLabs Group DVB-RCS MIB"; - - } - - identity x86Laps { - base iana-interface-type; - description - "LAPS based on ITU-T X.86/Y.1323."; - } - - identity wwanPP { - base iana-interface-type; - description "3GPP WWAN."; - } - - identity wwanPP2 { - base iana-interface-type; - description "3GPP2 WWAN."; - } - - identity voiceEBS { - base iana-interface-type; - description - "Voice P-phone EBS physical interface."; - } - - identity ifPwType { - base iana-interface-type; - description - "Pseudowire interface type."; - reference - "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)"; - - } - - identity ilan { - base iana-interface-type; - description - "Internal LAN on a bridge per IEEE 802.1ap."; - } - - identity pip { - base iana-interface-type; - description - "Provider Instance Port on a bridge per IEEE 802.1ah PBB."; - } - - identity aluELP { - base iana-interface-type; - description - "Alcatel-Lucent Ethernet Link Protection."; - } - - identity gpon { - base iana-interface-type; - description - "Gigabit-capable passive optical networks (G-PON) as per - ITU-T G.948."; - } - - identity vdsl2 { - base iana-interface-type; - description - "Very high speed digital subscriber line Version 2 - (as per ITU-T Recommendation G.993.2)."; - reference - "RFC 5650 - Definitions of Managed Objects for Very High - Speed Digital Subscriber Line 2 (VDSL2)"; - - } - - identity capwapDot11Profile { - base iana-interface-type; - description "WLAN Profile Interface."; - reference - "RFC 5834 - Control and Provisioning of Wireless Access - Points (CAPWAP) Protocol Binding MIB for - IEEE 802.11"; - - } - - identity capwapDot11Bss { - base iana-interface-type; - description "WLAN BSS Interface."; - reference - "RFC 5834 - Control and Provisioning of Wireless Access - Points (CAPWAP) Protocol Binding MIB for - IEEE 802.11"; - - } - - identity capwapWtpVirtualRadio { - base iana-interface-type; - description - "WTP Virtual Radio Interface."; - reference - "RFC 5833 - Control and Provisioning of Wireless Access - Points (CAPWAP) Protocol Base MIB"; - - } - - identity bits { - base iana-interface-type; - description "bitsport."; - } - - identity docsCableUpstreamRfPort { - base iana-interface-type; - description - "DOCSIS CATV Upstream RF Port."; - } - - identity cableDownstreamRfPort { - base iana-interface-type; - description "CATV downstream RF Port."; - } - - identity vmwareVirtualNic { - base iana-interface-type; - description - "VMware Virtual Network Interface."; - } - - identity ieee802154 { - base iana-interface-type; - description - "IEEE 802.15.4 WPAN interface."; - reference - "IEEE 802.15.4-2006"; - - } - - identity otnOdu { - base iana-interface-type; - description "OTN Optical Data Unit."; - } - - identity otnOtu { - base iana-interface-type; - description - "OTN Optical channel Transport Unit."; - } - - identity ifVfiType { - base iana-interface-type; - description - "VPLS Forwarding Instance Interface Type."; - } - - identity g9981 { - base iana-interface-type; - description - "G.998.1 bonded interface."; - } - - identity g9982 { - base iana-interface-type; - description - "G.998.2 bonded interface."; - } - - identity g9983 { - base iana-interface-type; - description - "G.998.3 bonded interface."; - } - - identity aluEpon { - base iana-interface-type; - description - "Ethernet Passive Optical Networks (E-PON)."; - } - - identity aluEponOnu { - base iana-interface-type; - description - "EPON Optical Network Unit."; - } - - identity aluEponPhysicalUni { - base iana-interface-type; - description - "EPON physical User to Network interface."; - } - - identity aluEponLogicalLink { - base iana-interface-type; - description - "The emulation of a point-to-point link over the EPON - layer."; - } - - identity aluGponOnu { - base iana-interface-type; - description - "GPON Optical Network Unit."; - reference - "ITU-T G.984.2"; - - } - - identity aluGponPhysicalUni { - base iana-interface-type; - description - "GPON physical User to Network interface."; - reference - "ITU-T G.984.2"; - - } - - identity vmwareNicTeam { - base iana-interface-type; - description "VMware NIC Team."; - } - } // module iana-if-type diff --git a/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang b/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang deleted file mode 100644 index f66c205ce..000000000 --- a/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang +++ /dev/null @@ -1,1123 +0,0 @@ -module ietf-interfaces { - yang-version 1.1; - namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; - prefix if; - - import ietf-yang-types { - prefix yang; - } - - organization - "IETF NETMOD (Network Modeling) Working Group"; - - contact - "WG Web: <https://datatracker.ietf.org/wg/netmod/> - WG List: <mailto:netmod@ietf.org> - - Editor: Martin Bjorklund - <mailto:mbj@tail-f.com>"; - - description - "This module contains a collection of YANG definitions for - managing network interfaces. - - Copyright (c) 2018 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - Redistribution and use in source and binary forms, with or - without modification, is permitted pursuant to, and subject - to the license terms contained in, the Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (https://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 8343; see - the RFC itself for full legal notices."; - - revision 2018-02-20 { - description - "Updated to support NMDA."; - reference - "RFC 8343: A YANG Data Model for Interface Management"; - } - - revision 2014-05-08 { - description - "Initial revision."; - reference - "RFC 7223: A YANG Data Model for Interface Management"; - } - - /* - * Typedefs - */ - - typedef interface-ref { - type leafref { - path "/if:interfaces/if:interface/if:name"; - } - description - "This type is used by data models that need to reference - interfaces."; - } - - /* - * Identities - */ - - identity interface-type { - description - "Base identity from which specific interface types are - derived."; - } - - /* - * Features - */ - - feature arbitrary-names { - description - "This feature indicates that the device allows user-controlled - interfaces to be named arbitrarily."; - } - feature pre-provisioning { - description - "This feature indicates that the device supports - pre-provisioning of interface configuration, i.e., it is - possible to configure an interface whose physical interface - hardware is not present on the device."; - } - feature if-mib { - description - "This feature indicates that the device implements - the IF-MIB."; - reference - "RFC 2863: The Interfaces Group MIB"; - } - - /* - * Data nodes - */ - - container interfaces { - description - "Interface parameters."; - - list interface { - key "name"; - - description - "The list of interfaces on the device. - - The status of an interface is available in this list in the - operational state. If the configuration of a - system-controlled interface cannot be used by the system - (e.g., the interface hardware present does not match the - interface type), then the configuration is not applied to - the system-controlled interface shown in the operational - state. If the configuration of a user-controlled interface - cannot be used by the system, the configured interface is - not instantiated in the operational state. - - System-controlled interfaces created by the system are - always present in this list in the operational state, - whether or not they are configured."; - - leaf name { - type string; - description - "The name of the interface. - - A device MAY restrict the allowed values for this leaf, - possibly depending on the type of the interface. - For system-controlled interfaces, this leaf is the - device-specific name of the interface. - - If a client tries to create configuration for a - system-controlled interface that is not present in the - operational state, the server MAY reject the request if - the implementation does not support pre-provisioning of - interfaces or if the name refers to an interface that can - never exist in the system. A Network Configuration - Protocol (NETCONF) server MUST reply with an rpc-error - with the error-tag 'invalid-value' in this case. - - If the device supports pre-provisioning of interface - configuration, the 'pre-provisioning' feature is - advertised. - - If the device allows arbitrarily named user-controlled - interfaces, the 'arbitrary-names' feature is advertised. - - When a configured user-controlled interface is created by - the system, it is instantiated with the same name in the - operational state. - - A server implementation MAY map this leaf to the ifName - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and ifName. The definition of - such a mechanism is outside the scope of this document."; - reference - "RFC 2863: The Interfaces Group MIB - ifName"; - } - - leaf description { - type string; - description - "A textual description of the interface. - - A server implementation MAY map this leaf to the ifAlias - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and ifAlias. The definition of - such a mechanism is outside the scope of this document. - - Since ifAlias is defined to be stored in non-volatile - storage, the MIB implementation MUST map ifAlias to the - value of 'description' in the persistently stored - configuration."; - reference - "RFC 2863: The Interfaces Group MIB - ifAlias"; - } - - leaf type { - type identityref { - base interface-type; - } - mandatory true; - description - "The type of the interface. - - When an interface entry is created, a server MAY - initialize the type leaf with a valid value, e.g., if it - is possible to derive the type from the name of the - interface. - - If a client tries to set the type of an interface to a - value that can never be used by the system, e.g., if the - type is not supported or if the type does not match the - name of the interface, the server MUST reject the request. - A NETCONF server MUST reply with an rpc-error with the - error-tag 'invalid-value' in this case."; - reference - "RFC 2863: The Interfaces Group MIB - ifType"; - } - - leaf enabled { - type boolean; - default "true"; - description - "This leaf contains the configured, desired state of the - interface. - - Systems that implement the IF-MIB use the value of this - leaf in the intended configuration to set - IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry - has been initialized, as described in RFC 2863. - - Changes in this leaf in the intended configuration are - reflected in ifAdminStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; - } - - leaf link-up-down-trap-enable { - if-feature if-mib; - type enumeration { - enum enabled { - value 1; - description - "The device will generate linkUp/linkDown SNMP - notifications for this interface."; - } - enum disabled { - value 2; - description - "The device will not generate linkUp/linkDown SNMP - notifications for this interface."; - } - } - description - "Controls whether linkUp/linkDown SNMP notifications - should be generated for this interface. - - If this node is not configured, the value 'enabled' is - operationally used by the server for interfaces that do - not operate on top of any other interface (i.e., there are - no 'lower-layer-if' entries), and 'disabled' otherwise."; - reference - "RFC 2863: The Interfaces Group MIB - - ifLinkUpDownTrapEnable"; - } - - leaf admin-status { - if-feature if-mib; - type enumeration { - enum up { - value 1; - description - "Ready to pass packets."; - } - enum down { - value 2; - description - "Not ready to pass packets and not in some test mode."; - } - enum testing { - value 3; - description - "In some test mode."; - } - } - config false; - mandatory true; - description - "The desired state of the interface. - - This leaf has the same read semantics as ifAdminStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; - } - - leaf oper-status { - type enumeration { - enum up { - value 1; - description - "Ready to pass packets."; - } - enum down { - value 2; - - description - "The interface does not pass any packets."; - } - enum testing { - value 3; - description - "In some test mode. No operational packets can - be passed."; - } - enum unknown { - value 4; - description - "Status cannot be determined for some reason."; - } - enum dormant { - value 5; - description - "Waiting for some external event."; - } - enum not-present { - value 6; - description - "Some component (typically hardware) is missing."; - } - enum lower-layer-down { - value 7; - description - "Down due to state of lower-layer interface(s)."; - } - } - config false; - mandatory true; - description - "The current operational state of the interface. - - This leaf has the same semantics as ifOperStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifOperStatus"; - } - - leaf last-change { - type yang:date-and-time; - config false; - description - "The time the interface entered its current operational - state. If the current state was entered prior to the - last re-initialization of the local network management - subsystem, then this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifLastChange"; - } - - leaf if-index { - if-feature if-mib; - type int32 { - range "1..2147483647"; - } - config false; - mandatory true; - description - "The ifIndex value for the ifEntry represented by this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifIndex"; - } - - leaf phys-address { - type yang:phys-address; - config false; - description - "The interface's address at its protocol sub-layer. For - example, for an 802.x interface, this object normally - contains a Media Access Control (MAC) address. The - interface's media-specific modules must define the bit - and byte ordering and the format of the value of this - object. For interfaces that do not have such an address - (e.g., a serial line), this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; - } - - leaf-list higher-layer-if { - type interface-ref; - config false; - description - "A list of references to interfaces layered on top of this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - } - - leaf-list lower-layer-if { - type interface-ref; - config false; - - description - "A list of references to interfaces layered underneath this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - } - - leaf speed { - type yang:gauge64; - units "bits/second"; - config false; - description - "An estimate of the interface's current bandwidth in bits - per second. For interfaces that do not vary in - bandwidth or for those where no accurate estimation can - be made, this node should contain the nominal bandwidth. - For interfaces that have no concept of bandwidth, this - node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - - ifSpeed, ifHighSpeed"; - } - - container statistics { - config false; - description - "A collection of interface-related statistics objects."; - - leaf discontinuity-time { - type yang:date-and-time; - mandatory true; - description - "The time on the most recent occasion at which any one or - more of this interface's counters suffered a - discontinuity. If no such discontinuities have occurred - since the last re-initialization of the local management - subsystem, then this node contains the time the local - management subsystem re-initialized itself."; - } - - leaf in-octets { - type yang:counter64; - description - "The total number of octets received on the interface, - including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; - } - - leaf in-unicast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were not addressed to a - multicast or broadcast address at this sub-layer. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; - } - - leaf in-broadcast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a broadcast - address at this sub-layer. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInBroadcastPkts"; - } - - leaf in-multicast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a multicast - address at this sub-layer. For a MAC-layer protocol, - this includes both Group and Functional addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInMulticastPkts"; - } - - leaf in-discards { - type yang:counter32; - description - "The number of inbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being deliverable to a higher-layer - protocol. One possible reason for discarding such a - packet could be to free up buffer space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInDiscards"; - } - - leaf in-errors { - type yang:counter32; - description - "For packet-oriented interfaces, the number of inbound - packets that contained errors preventing them from being - deliverable to a higher-layer protocol. For character- - oriented or fixed-length interfaces, the number of - inbound transmission units that contained errors - preventing them from being deliverable to a higher-layer - protocol. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInErrors"; - } - - leaf in-unknown-protos { - type yang:counter32; - - description - "For packet-oriented interfaces, the number of packets - received via the interface that were discarded because - of an unknown or unsupported protocol. For - character-oriented or fixed-length interfaces that - support protocol multiplexing, the number of - transmission units received via the interface that were - discarded because of an unknown or unsupported protocol. - For any interface that does not support protocol - multiplexing, this counter is not present. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; - } - - leaf out-octets { - type yang:counter64; - description - "The total number of octets transmitted out of the - interface, including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; - } - - leaf out-unicast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted and that were not addressed - to a multicast or broadcast address at this sub-layer, - including those that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; - } - - leaf out-broadcast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted and that were addressed to a - broadcast address at this sub-layer, including those - that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutBroadcastPkts"; - } - - leaf out-multicast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted and that were addressed to a - multicast address at this sub-layer, including those - that were discarded or not sent. For a MAC-layer - protocol, this includes both Group and Functional - addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutMulticastPkts"; - } - - leaf out-discards { - type yang:counter32; - description - "The number of outbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being transmitted. One possible reason - for discarding such a packet could be to free up buffer - space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; - } - - leaf out-errors { - type yang:counter32; - description - "For packet-oriented interfaces, the number of outbound - packets that could not be transmitted because of errors. - For character-oriented or fixed-length interfaces, the - number of outbound transmission units that could not be - transmitted because of errors. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutErrors"; - } - } - - } - } - - /* - * Legacy typedefs - */ - - typedef interface-state-ref { - type leafref { - path "/if:interfaces-state/if:interface/if:name"; - } - status deprecated; - description - "This type is used by data models that need to reference - the operationally present interfaces."; - } - - /* - * Legacy operational state data nodes - */ - - container interfaces-state { - config false; - status deprecated; - description - "Data nodes for the operational state of interfaces."; - - list interface { - key "name"; - status deprecated; - - description - "The list of interfaces on the device. - - System-controlled interfaces created by the system are - always present in this list, whether or not they are - configured."; - - leaf name { - type string; - status deprecated; - description - "The name of the interface. - - A server implementation MAY map this leaf to the ifName - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and ifName. The definition of - such a mechanism is outside the scope of this document."; - reference - "RFC 2863: The Interfaces Group MIB - ifName"; - } - - leaf type { - type identityref { - base interface-type; - } - mandatory true; - status deprecated; - description - "The type of the interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifType"; - } - - leaf admin-status { - if-feature if-mib; - type enumeration { - enum up { - value 1; - description - "Ready to pass packets."; - } - enum down { - value 2; - description - "Not ready to pass packets and not in some test mode."; - } - enum testing { - value 3; - description - "In some test mode."; - } - } - mandatory true; - status deprecated; - description - "The desired state of the interface. - - This leaf has the same read semantics as ifAdminStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; - } - - leaf oper-status { - type enumeration { - enum up { - value 1; - description - "Ready to pass packets."; - } - enum down { - value 2; - description - "The interface does not pass any packets."; - } - enum testing { - value 3; - description - "In some test mode. No operational packets can - be passed."; - } - enum unknown { - value 4; - description - "Status cannot be determined for some reason."; - } - enum dormant { - value 5; - description - "Waiting for some external event."; - } - enum not-present { - value 6; - description - "Some component (typically hardware) is missing."; - } - enum lower-layer-down { - value 7; - description - "Down due to state of lower-layer interface(s)."; - } - } - mandatory true; - status deprecated; - description - "The current operational state of the interface. - - This leaf has the same semantics as ifOperStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifOperStatus"; - } - - leaf last-change { - type yang:date-and-time; - status deprecated; - description - "The time the interface entered its current operational - state. If the current state was entered prior to the - last re-initialization of the local network management - subsystem, then this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifLastChange"; - } - - leaf if-index { - if-feature if-mib; - type int32 { - range "1..2147483647"; - } - mandatory true; - status deprecated; - description - "The ifIndex value for the ifEntry represented by this - interface."; - - reference - "RFC 2863: The Interfaces Group MIB - ifIndex"; - } - - leaf phys-address { - type yang:phys-address; - status deprecated; - description - "The interface's address at its protocol sub-layer. For - example, for an 802.x interface, this object normally - contains a Media Access Control (MAC) address. The - interface's media-specific modules must define the bit - and byte ordering and the format of the value of this - object. For interfaces that do not have such an address - (e.g., a serial line), this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; - } - - leaf-list higher-layer-if { - type interface-state-ref; - status deprecated; - description - "A list of references to interfaces layered on top of this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - } - - leaf-list lower-layer-if { - type interface-state-ref; - status deprecated; - description - "A list of references to interfaces layered underneath this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - } - - leaf speed { - type yang:gauge64; - units "bits/second"; - status deprecated; - description - "An estimate of the interface's current bandwidth in bits - per second. For interfaces that do not vary in - bandwidth or for those where no accurate estimation can - - be made, this node should contain the nominal bandwidth. - For interfaces that have no concept of bandwidth, this - node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - - ifSpeed, ifHighSpeed"; - } - - container statistics { - status deprecated; - description - "A collection of interface-related statistics objects."; - - leaf discontinuity-time { - type yang:date-and-time; - mandatory true; - status deprecated; - description - "The time on the most recent occasion at which any one or - more of this interface's counters suffered a - discontinuity. If no such discontinuities have occurred - since the last re-initialization of the local management - subsystem, then this node contains the time the local - management subsystem re-initialized itself."; - } - - leaf in-octets { - type yang:counter64; - status deprecated; - description - "The total number of octets received on the interface, - including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; - } - - leaf in-unicast-pkts { - type yang:counter64; - status deprecated; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were not addressed to a - multicast or broadcast address at this sub-layer. - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; - } - - leaf in-broadcast-pkts { - type yang:counter64; - status deprecated; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a broadcast - address at this sub-layer. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInBroadcastPkts"; - } - - leaf in-multicast-pkts { - type yang:counter64; - status deprecated; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a multicast - address at this sub-layer. For a MAC-layer protocol, - this includes both Group and Functional addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInMulticastPkts"; - } - - leaf in-discards { - type yang:counter32; - status deprecated; - - description - "The number of inbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being deliverable to a higher-layer - protocol. One possible reason for discarding such a - packet could be to free up buffer space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInDiscards"; - } - - leaf in-errors { - type yang:counter32; - status deprecated; - description - "For packet-oriented interfaces, the number of inbound - packets that contained errors preventing them from being - deliverable to a higher-layer protocol. For character- - oriented or fixed-length interfaces, the number of - inbound transmission units that contained errors - preventing them from being deliverable to a higher-layer - protocol. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInErrors"; - } - - leaf in-unknown-protos { - type yang:counter32; - status deprecated; - description - "For packet-oriented interfaces, the number of packets - received via the interface that were discarded because - of an unknown or unsupported protocol. For - character-oriented or fixed-length interfaces that - support protocol multiplexing, the number of - transmission units received via the interface that were - discarded because of an unknown or unsupported protocol. - For any interface that does not support protocol - multiplexing, this counter is not present. - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; - } - - leaf out-octets { - type yang:counter64; - status deprecated; - description - "The total number of octets transmitted out of the - interface, including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; - } - - leaf out-unicast-pkts { - type yang:counter64; - status deprecated; - description - "The total number of packets that higher-level protocols - requested be transmitted and that were not addressed - to a multicast or broadcast address at this sub-layer, - including those that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; - } - - leaf out-broadcast-pkts { - type yang:counter64; - status deprecated; - - description - "The total number of packets that higher-level protocols - requested be transmitted and that were addressed to a - broadcast address at this sub-layer, including those - that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutBroadcastPkts"; - } - - leaf out-multicast-pkts { - type yang:counter64; - status deprecated; - description - "The total number of packets that higher-level protocols - requested be transmitted and that were addressed to a - multicast address at this sub-layer, including those - that were discarded or not sent. For a MAC-layer - protocol, this includes both Group and Functional - addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutMulticastPkts"; - } - - leaf out-discards { - type yang:counter32; - status deprecated; - description - "The number of outbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being transmitted. One possible reason - for discarding such a packet could be to free up buffer - space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; - } - - leaf out-errors { - type yang:counter32; - status deprecated; - description - "For packet-oriented interfaces, the number of outbound - packets that could not be transmitted because of errors. - For character-oriented or fixed-length interfaces, the - number of outbound transmission units that could not be - transmitted because of errors. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutErrors"; - } - } - } - } -} diff --git a/ctrl/sysrepo-plugins/yang/ietf/ietf-ip@2014-06-16.yang b/ctrl/sysrepo-plugins/yang/ietf/ietf-ip@2014-06-16.yang deleted file mode 100644 index 79606cc07..000000000 --- a/ctrl/sysrepo-plugins/yang/ietf/ietf-ip@2014-06-16.yang +++ /dev/null @@ -1,742 +0,0 @@ -module ietf-ip { - - yang-version 1; - - namespace - "urn:ietf:params:xml:ns:yang:ietf-ip"; - - prefix ip; - - import ietf-interfaces { - prefix if; - } - import ietf-inet-types { - prefix inet; - } - import ietf-yang-types { - prefix yang; - } - - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - - contact - "WG Web: <http://tools.ietf.org/wg/netmod/> - WG List: <mailto:netmod@ietf.org> - - WG Chair: Thomas Nadeau - <mailto:tnadeau@lucidvision.com> - - WG Chair: Juergen Schoenwaelder - <mailto:j.schoenwaelder@jacobs-university.de> - - Editor: Martin Bjorklund - <mailto:mbj@tail-f.com>"; - - description - "This module contains a collection of YANG definitions for - configuring IP implementations. - - Copyright (c) 2014 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - Redistribution and use in source and binary forms, with or - without modification, is permitted pursuant to, and subject - to the license terms contained in, the Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 7277; see - the RFC itself for full legal notices."; - - revision "2014-06-16" { - description "Initial revision."; - reference - "RFC 7277: A YANG Data Model for IP Management"; - - } - - - feature ipv4-non-contiguous-netmasks { - description - "Indicates support for configuring non-contiguous - subnet masks."; - } - - feature ipv6-privacy-autoconf { - description - "Indicates support for Privacy Extensions for Stateless Address - Autoconfiguration in IPv6."; - reference - "RFC 4941: Privacy Extensions for Stateless Address - Autoconfiguration in IPv6"; - - } - - typedef ip-address-origin { - type enumeration { - enum "other" { - value 0; - description - "None of the following."; - } - enum "static" { - value 1; - description - "Indicates that the address has been statically - configured - for example, using NETCONF or a Command Line - Interface."; - } - enum "dhcp" { - value 2; - description - "Indicates an address that has been assigned to this - system by a DHCP server."; - } - enum "link-layer" { - value 3; - description - "Indicates an address created by IPv6 stateless - autoconfiguration that embeds a link-layer address in its - interface identifier."; - } - enum "random" { - value 4; - description - "Indicates an address chosen by the system at - - random, e.g., an IPv4 address within 169.254/16, an - RFC 4941 temporary address, or an RFC 7217 semantically - opaque address."; - reference - "RFC 4941: Privacy Extensions for Stateless Address - Autoconfiguration in IPv6 - RFC 7217: A Method for Generating Semantically Opaque - Interface Identifiers with IPv6 Stateless - Address Autoconfiguration (SLAAC)"; - - } - } - description - "The origin of an address."; - } - - typedef neighbor-origin { - type enumeration { - enum "other" { - value 0; - description - "None of the following."; - } - enum "static" { - value 1; - description - "Indicates that the mapping has been statically - configured - for example, using NETCONF or a Command Line - Interface."; - } - enum "dynamic" { - value 2; - description - "Indicates that the mapping has been dynamically resolved - using, e.g., IPv4 ARP or the IPv6 Neighbor Discovery - protocol."; - } - } - description - "The origin of a neighbor entry."; - } - - augment /if:interfaces/if:interface { - description - "Parameters for configuring IP on interfaces. - - If an interface is not capable of running IP, the server - must not allow the client to configure these parameters."; - container ipv4 { - presence - "Enables IPv4 unless the 'enabled' leaf - (which defaults to 'true') is set to 'false'"; - description - "Parameters for the IPv4 address family."; - leaf enabled { - type boolean; - default 'true'; - description - "Controls whether IPv4 is enabled or disabled on this - interface. When IPv4 is enabled, this interface is - connected to an IPv4 stack, and the interface can send - and receive IPv4 packets."; - } - - leaf forwarding { - type boolean; - default 'false'; - description - "Controls IPv4 packet forwarding of datagrams received by, - but not addressed to, this interface. IPv4 routers - forward datagrams. IPv4 hosts do not (except those - source-routed via the host)."; - } - - leaf mtu { - type uint16 { - range "68..max"; - } - units "octets"; - description - "The size, in octets, of the largest IPv4 packet that the - interface will send and receive. - - The server may restrict the allowed values for this leaf, - depending on the interface's type. - - If this leaf is not configured, the operationally used MTU - depends on the interface's type."; - reference - "RFC 791: Internet Protocol"; - - } - - list address { - key "ip"; - description - "The list of configured IPv4 addresses on the interface."; - leaf ip { - type inet:ipv4-address-no-zone; - description - "The IPv4 address on the interface."; - } - - choice subnet { - mandatory true; - description - "The subnet can be specified as a prefix-length, or, - if the server supports non-contiguous netmasks, as - a netmask."; - leaf prefix-length { - type uint8 { - range "0..32"; - } - description - "The length of the subnet prefix."; - } - leaf netmask { - if-feature ipv4-non-contiguous-netmasks; - type yang:dotted-quad; - description - "The subnet specified as a netmask."; - } - } // choice subnet - } // list address - - list neighbor { - key "ip"; - description - "A list of mappings from IPv4 addresses to - link-layer addresses. - - Entries in this list are used as static entries in the - ARP Cache."; - reference - "RFC 826: An Ethernet Address Resolution Protocol"; - - leaf ip { - type inet:ipv4-address-no-zone; - description - "The IPv4 address of the neighbor node."; - } - - leaf link-layer-address { - type yang:phys-address; - mandatory true; - description - "The link-layer address of the neighbor node."; - } - } // list neighbor - } // container ipv4 - - container ipv6 { - presence - "Enables IPv6 unless the 'enabled' leaf - (which defaults to 'true') is set to 'false'"; - description - "Parameters for the IPv6 address family."; - leaf enabled { - type boolean; - default 'true'; - description - "Controls whether IPv6 is enabled or disabled on this - interface. When IPv6 is enabled, this interface is - connected to an IPv6 stack, and the interface can send - and receive IPv6 packets."; - } - - leaf forwarding { - type boolean; - default 'false'; - description - "Controls IPv6 packet forwarding of datagrams received by, - but not addressed to, this interface. IPv6 routers - forward datagrams. IPv6 hosts do not (except those - source-routed via the host)."; - reference - "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) - Section 6.2.1, IsRouter"; - - } - - leaf mtu { - type uint32 { - range "1280..max"; - } - units "octets"; - description - "The size, in octets, of the largest IPv6 packet that the - interface will send and receive. - - The server may restrict the allowed values for this leaf, - depending on the interface's type. - - If this leaf is not configured, the operationally used MTU - depends on the interface's type."; - reference - "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification - Section 5"; - - } - - list address { - key "ip"; - description - "The list of configured IPv6 addresses on the interface."; - leaf ip { - type inet:ipv6-address-no-zone; - description - "The IPv6 address on the interface."; - } - - leaf prefix-length { - type uint8 { - range "0..128"; - } - mandatory true; - description - "The length of the subnet prefix."; - } - } // list address - - list neighbor { - key "ip"; - description - "A list of mappings from IPv6 addresses to - link-layer addresses. - - Entries in this list are used as static entries in the - Neighbor Cache."; - reference - "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; - - leaf ip { - type inet:ipv6-address-no-zone; - description - "The IPv6 address of the neighbor node."; - } - - leaf link-layer-address { - type yang:phys-address; - mandatory true; - description - "The link-layer address of the neighbor node."; - } - } // list neighbor - - leaf dup-addr-detect-transmits { - type uint32; - default '1'; - description - "The number of consecutive Neighbor Solicitation messages - sent while performing Duplicate Address Detection on a - tentative address. A value of zero indicates that - Duplicate Address Detection is not performed on - tentative addresses. A value of one indicates a single - transmission with no follow-up retransmissions."; - reference - "RFC 4862: IPv6 Stateless Address Autoconfiguration"; - - } - - container autoconf { - description - "Parameters to control the autoconfiguration of IPv6 - addresses, as described in RFC 4862."; - reference - "RFC 4862: IPv6 Stateless Address Autoconfiguration"; - - leaf create-global-addresses { - type boolean; - default 'true'; - description - "If enabled, the host creates global addresses as - described in RFC 4862."; - reference - "RFC 4862: IPv6 Stateless Address Autoconfiguration - Section 5.5"; - - } - - leaf create-temporary-addresses { - if-feature ipv6-privacy-autoconf; - type boolean; - default 'false'; - description - "If enabled, the host creates temporary addresses as - described in RFC 4941."; - reference - "RFC 4941: Privacy Extensions for Stateless Address - Autoconfiguration in IPv6"; - - } - - leaf temporary-valid-lifetime { - if-feature ipv6-privacy-autoconf; - type uint32; - units "seconds"; - default '604800'; - description - "The time period during which the temporary address - is valid."; - reference - "RFC 4941: Privacy Extensions for Stateless Address - Autoconfiguration in IPv6 - - TEMP_VALID_LIFETIME"; - - } - - leaf temporary-preferred-lifetime { - if-feature ipv6-privacy-autoconf; - type uint32; - units "seconds"; - default '86400'; - description - "The time period during which the temporary address is - preferred."; - reference - "RFC 4941: Privacy Extensions for Stateless Address - Autoconfiguration in IPv6 - - TEMP_PREFERRED_LIFETIME"; - - } - } // container autoconf - } // container ipv6 - } - - augment /if:interfaces-state/if:interface { - description - "Data nodes for the operational state of IP on interfaces."; - container ipv4 { - presence - "Present if IPv4 is enabled on this interface"; - config false; - description - "Interface-specific parameters for the IPv4 address family."; - leaf forwarding { - type boolean; - description - "Indicates whether IPv4 packet forwarding is enabled or - disabled on this interface."; - } - - leaf mtu { - type uint16 { - range "68..max"; - } - units "octets"; - description - "The size, in octets, of the largest IPv4 packet that the - interface will send and receive."; - reference - "RFC 791: Internet Protocol"; - - } - - list address { - key "ip"; - description - "The list of IPv4 addresses on the interface."; - leaf ip { - type inet:ipv4-address-no-zone; - description - "The IPv4 address on the interface."; - } - - choice subnet { - description - "The subnet can be specified as a prefix-length, or, - if the server supports non-contiguous netmasks, as - a netmask."; - leaf prefix-length { - type uint8 { - range "0..32"; - } - description - "The length of the subnet prefix."; - } - leaf netmask { - if-feature ipv4-non-contiguous-netmasks; - type yang:dotted-quad; - description - "The subnet specified as a netmask."; - } - } // choice subnet - - leaf origin { - type ip-address-origin; - description - "The origin of this address."; - } - } // list address - - list neighbor { - key "ip"; - description - "A list of mappings from IPv4 addresses to - link-layer addresses. - - This list represents the ARP Cache."; - reference - "RFC 826: An Ethernet Address Resolution Protocol"; - - leaf ip { - type inet:ipv4-address-no-zone; - description - "The IPv4 address of the neighbor node."; - } - - leaf link-layer-address { - type yang:phys-address; - description - "The link-layer address of the neighbor node."; - } - - leaf origin { - type neighbor-origin; - description - "The origin of this neighbor entry."; - } - } // list neighbor - } // container ipv4 - - container ipv6 { - presence - "Present if IPv6 is enabled on this interface"; - config false; - description - "Parameters for the IPv6 address family."; - leaf forwarding { - type boolean; - default 'false'; - description - "Indicates whether IPv6 packet forwarding is enabled or - disabled on this interface."; - reference - "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) - Section 6.2.1, IsRouter"; - - } - - leaf mtu { - type uint32 { - range "1280..max"; - } - units "octets"; - description - "The size, in octets, of the largest IPv6 packet that the - interface will send and receive."; - reference - "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification - Section 5"; - - } - - list address { - key "ip"; - description - "The list of IPv6 addresses on the interface."; - leaf ip { - type inet:ipv6-address-no-zone; - description - "The IPv6 address on the interface."; - } - - leaf prefix-length { - type uint8 { - range "0..128"; - } - mandatory true; - description - "The length of the subnet prefix."; - } - - leaf origin { - type ip-address-origin; - description - "The origin of this address."; - } - - leaf status { - type enumeration { - enum "preferred" { - value 0; - description - "This is a valid address that can appear as the - destination or source address of a packet."; - } - enum "deprecated" { - value 1; - description - "This is a valid but deprecated address that should - no longer be used as a source address in new - communications, but packets addressed to such an - address are processed as expected."; - } - enum "invalid" { - value 2; - description - "This isn't a valid address, and it shouldn't appear - as the destination or source address of a packet."; - } - enum "inaccessible" { - value 3; - description - "The address is not accessible because the interface - to which this address is assigned is not - operational."; - } - enum "unknown" { - value 4; - description - "The status cannot be determined for some reason."; - } - enum "tentative" { - value 5; - description - "The uniqueness of the address on the link is being - verified. Addresses in this state should not be - used for general communication and should only be - used to determine the uniqueness of the address."; - } - enum "duplicate" { - value 6; - description - "The address has been determined to be non-unique on - the link and so must not be used."; - } - enum "optimistic" { - value 7; - description - "The address is available for use, subject to - restrictions, while its uniqueness on a link is - being verified."; - } - } - description - "The status of an address. Most of the states correspond - to states from the IPv6 Stateless Address - Autoconfiguration protocol."; - reference - "RFC 4293: Management Information Base for the - Internet Protocol (IP) - - IpAddressStatusTC - RFC 4862: IPv6 Stateless Address Autoconfiguration"; - - } - } // list address - - list neighbor { - key "ip"; - description - "A list of mappings from IPv6 addresses to - link-layer addresses. - - This list represents the Neighbor Cache."; - reference - "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; - - leaf ip { - type inet:ipv6-address-no-zone; - description - "The IPv6 address of the neighbor node."; - } - - leaf link-layer-address { - type yang:phys-address; - description - "The link-layer address of the neighbor node."; - } - - leaf origin { - type neighbor-origin; - description - "The origin of this neighbor entry."; - } - - leaf is-router { - type empty; - description - "Indicates that the neighbor node acts as a router."; - } - - leaf state { - type enumeration { - enum "incomplete" { - value 0; - description - "Address resolution is in progress, and the link-layer - address of the neighbor has not yet been - determined."; - } - enum "reachable" { - value 1; - description - "Roughly speaking, the neighbor is known to have been - reachable recently (within tens of seconds ago)."; - } - enum "stale" { - value 2; - description - "The neighbor is no longer known to be reachable, but - until traffic is sent to the neighbor no attempt - should be made to verify its reachability."; - } - enum "delay" { - value 3; - description - "The neighbor is no longer known to be reachable, and - traffic has recently been sent to the neighbor. - Rather than probe the neighbor immediately, however, - delay sending probes for a short while in order to - give upper-layer protocols a chance to provide - reachability confirmation."; - } - enum "probe" { - value 4; - description - "The neighbor is no longer known to be reachable, and - unicast Neighbor Solicitation probes are being sent - to verify reachability."; - } - } - description - "The Neighbor Unreachability Detection state of this - entry."; - reference - "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) - Section 7.3.2"; - - } - } // list neighbor - } // container ipv6 - } - } // module ietf-ip diff --git a/ctrl/sysrepo-plugins/yang/ietf/ietf-yang-types@2013-07-15.yang b/ctrl/sysrepo-plugins/yang/ietf/ietf-yang-types@2013-07-15.yang deleted file mode 100644 index ee58fa3ab..000000000 --- a/ctrl/sysrepo-plugins/yang/ietf/ietf-yang-types@2013-07-15.yang +++ /dev/null @@ -1,474 +0,0 @@ -module ietf-yang-types { - - namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; - prefix "yang"; - - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - - contact - "WG Web: <http://tools.ietf.org/wg/netmod/> - WG List: <mailto:netmod@ietf.org> - - WG Chair: David Kessens - <mailto:david.kessens@nsn.com> - - WG Chair: Juergen Schoenwaelder - <mailto:j.schoenwaelder@jacobs-university.de> - - Editor: Juergen Schoenwaelder - <mailto:j.schoenwaelder@jacobs-university.de>"; - - description - "This module contains a collection of generally useful derived - YANG data types. - - Copyright (c) 2013 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - Redistribution and use in source and binary forms, with or - without modification, is permitted pursuant to, and subject - to the license terms contained in, the Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 6991; see - the RFC itself for full legal notices."; - - revision 2013-07-15 { - description - "This revision adds the following new data types: - - yang-identifier - - hex-string - - uuid - - dotted-quad"; - reference - "RFC 6991: Common YANG Data Types"; - } - - revision 2010-09-24 { - description - "Initial revision."; - reference - "RFC 6021: Common YANG Data Types"; - } - - /*** collection of counter and gauge types ***/ - - typedef counter32 { - type uint32; - description - "The counter32 type represents a non-negative integer - that monotonically increases until it reaches a - maximum value of 2^32-1 (4294967295 decimal), when it - wraps around and starts increasing again from zero. - - Counters have no defined 'initial' value, and thus, a - single value of a counter has (in general) no information - content. Discontinuities in the monotonically increasing - value normally occur at re-initialization of the - management system, and at other times as specified in the - description of a schema node using this type. If such - other times can occur, for example, the creation of - a schema node of type counter32 at times other than - re-initialization, then a corresponding schema node - should be defined, with an appropriate type, to indicate - the last discontinuity. - - The counter32 type should not be used for configuration - schema nodes. A default statement SHOULD NOT be used in - combination with the type counter32. - - In the value set and its semantics, this type is equivalent - to the Counter32 type of the SMIv2."; - reference - "RFC 2578: Structure of Management Information Version 2 - (SMIv2)"; - } - - typedef zero-based-counter32 { - type yang:counter32; - default "0"; - description - "The zero-based-counter32 type represents a counter32 - that has the defined 'initial' value zero. - - A schema node of this type will be set to zero (0) on creation - and will thereafter increase monotonically until it reaches - a maximum value of 2^32-1 (4294967295 decimal), when it - wraps around and starts increasing again from zero. - - Provided that an application discovers a new schema node - of this type within the minimum time to wrap, it can use the - 'initial' value as a delta. It is important for a management - station to be aware of this minimum time and the actual time - between polls, and to discard data if the actual time is too - long or there is no defined minimum time. - - In the value set and its semantics, this type is equivalent - to the ZeroBasedCounter32 textual convention of the SMIv2."; - reference - "RFC 4502: Remote Network Monitoring Management Information - Base Version 2"; - } - - typedef counter64 { - type uint64; - description - "The counter64 type represents a non-negative integer - that monotonically increases until it reaches a - maximum value of 2^64-1 (18446744073709551615 decimal), - when it wraps around and starts increasing again from zero. - - Counters have no defined 'initial' value, and thus, a - single value of a counter has (in general) no information - content. Discontinuities in the monotonically increasing - value normally occur at re-initialization of the - management system, and at other times as specified in the - description of a schema node using this type. If such - other times can occur, for example, the creation of - a schema node of type counter64 at times other than - re-initialization, then a corresponding schema node - should be defined, with an appropriate type, to indicate - the last discontinuity. - - The counter64 type should not be used for configuration - schema nodes. A default statement SHOULD NOT be used in - combination with the type counter64. - - In the value set and its semantics, this type is equivalent - to the Counter64 type of the SMIv2."; - reference - "RFC 2578: Structure of Management Information Version 2 - (SMIv2)"; - } - - typedef zero-based-counter64 { - type yang:counter64; - default "0"; - description - "The zero-based-counter64 type represents a counter64 that - has the defined 'initial' value zero. - - A schema node of this type will be set to zero (0) on creation - and will thereafter increase monotonically until it reaches - a maximum value of 2^64-1 (18446744073709551615 decimal), - when it wraps around and starts increasing again from zero. - - Provided that an application discovers a new schema node - of this type within the minimum time to wrap, it can use the - 'initial' value as a delta. It is important for a management - station to be aware of this minimum time and the actual time - between polls, and to discard data if the actual time is too - long or there is no defined minimum time. - - In the value set and its semantics, this type is equivalent - to the ZeroBasedCounter64 textual convention of the SMIv2."; - reference - "RFC 2856: Textual Conventions for Additional High Capacity - Data Types"; - } - - typedef gauge32 { - type uint32; - description - "The gauge32 type represents a non-negative integer, which - may increase or decrease, but shall never exceed a maximum - value, nor fall below a minimum value. The maximum value - cannot be greater than 2^32-1 (4294967295 decimal), and - the minimum value cannot be smaller than 0. The value of - a gauge32 has its maximum value whenever the information - being modeled is greater than or equal to its maximum - value, and has its minimum value whenever the information - being modeled is smaller than or equal to its minimum value. - If the information being modeled subsequently decreases - below (increases above) the maximum (minimum) value, the - gauge32 also decreases (increases). - - In the value set and its semantics, this type is equivalent - to the Gauge32 type of the SMIv2."; - reference - "RFC 2578: Structure of Management Information Version 2 - (SMIv2)"; - } - - typedef gauge64 { - type uint64; - description - "The gauge64 type represents a non-negative integer, which - may increase or decrease, but shall never exceed a maximum - value, nor fall below a minimum value. The maximum value - cannot be greater than 2^64-1 (18446744073709551615), and - the minimum value cannot be smaller than 0. The value of - a gauge64 has its maximum value whenever the information - being modeled is greater than or equal to its maximum - value, and has its minimum value whenever the information - being modeled is smaller than or equal to its minimum value. - If the information being modeled subsequently decreases - below (increases above) the maximum (minimum) value, the - gauge64 also decreases (increases). - - In the value set and its semantics, this type is equivalent - to the CounterBasedGauge64 SMIv2 textual convention defined - in RFC 2856"; - reference - "RFC 2856: Textual Conventions for Additional High Capacity - Data Types"; - } - - /*** collection of identifier-related types ***/ - - typedef object-identifier { - type string { - pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' - + '(\.(0|([1-9]\d*)))*'; - } - description - "The object-identifier type represents administratively - assigned names in a registration-hierarchical-name tree. - - Values of this type are denoted as a sequence of numerical - non-negative sub-identifier values. Each sub-identifier - value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers - are separated by single dots and without any intermediate - whitespace. - - The ASN.1 standard restricts the value space of the first - sub-identifier to 0, 1, or 2. Furthermore, the value space - of the second sub-identifier is restricted to the range - 0 to 39 if the first sub-identifier is 0 or 1. Finally, - the ASN.1 standard requires that an object identifier - has always at least two sub-identifiers. The pattern - captures these restrictions. - - Although the number of sub-identifiers is not limited, - module designers should realize that there may be - implementations that stick with the SMIv2 limit of 128 - sub-identifiers. - - This type is a superset of the SMIv2 OBJECT IDENTIFIER type - since it is not restricted to 128 sub-identifiers. Hence, - this type SHOULD NOT be used to represent the SMIv2 OBJECT - IDENTIFIER type; the object-identifier-128 type SHOULD be - used instead."; - reference - "ISO9834-1: Information technology -- Open Systems - Interconnection -- Procedures for the operation of OSI - Registration Authorities: General procedures and top - arcs of the ASN.1 Object Identifier tree"; - } - - typedef object-identifier-128 { - type object-identifier { - pattern '\d*(\.\d*){1,127}'; - } - description - "This type represents object-identifiers restricted to 128 - sub-identifiers. - - In the value set and its semantics, this type is equivalent - to the OBJECT IDENTIFIER type of the SMIv2."; - reference - "RFC 2578: Structure of Management Information Version 2 - (SMIv2)"; - } - - typedef yang-identifier { - type string { - length "1..max"; - pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; - pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; - } - description - "A YANG identifier string as defined by the 'identifier' - rule in Section 12 of RFC 6020. An identifier must - start with an alphabetic character or an underscore - followed by an arbitrary sequence of alphabetic or - numeric characters, underscores, hyphens, or dots. - - A YANG identifier MUST NOT start with any possible - combination of the lowercase or uppercase character - sequence 'xml'."; - reference - "RFC 6020: YANG - A Data Modeling Language for the Network - Configuration Protocol (NETCONF)"; - } - - /*** collection of types related to date and time***/ - - typedef date-and-time { - type string { - pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' - + '(Z|[\+\-]\d{2}:\d{2})'; - } - description - "The date-and-time type is a profile of the ISO 8601 - standard for representation of dates and times using the - Gregorian calendar. The profile is defined by the - date-time production in Section 5.6 of RFC 3339. - - The date-and-time type is compatible with the dateTime XML - schema type with the following notable exceptions: - - (a) The date-and-time type does not allow negative years. - - (b) The date-and-time time-offset -00:00 indicates an unknown - time zone (see RFC 3339) while -00:00 and +00:00 and Z - all represent the same time zone in dateTime. - - (c) The canonical format (see below) of data-and-time values - differs from the canonical format used by the dateTime XML - schema type, which requires all times to be in UTC using - the time-offset 'Z'. - - This type is not equivalent to the DateAndTime textual - convention of the SMIv2 since RFC 3339 uses a different - separator between full-date and full-time and provides - higher resolution of time-secfrac. - - The canonical format for date-and-time values with a known time - zone uses a numeric time zone offset that is calculated using - the device's configured known offset to UTC time. A change of - the device's offset to UTC time will cause date-and-time values - to change accordingly. Such changes might happen periodically - in case a server follows automatically daylight saving time - (DST) time zone offset changes. The canonical format for - date-and-time values with an unknown time zone (usually - referring to the notion of local time) uses the time-offset - -00:00."; - reference - "RFC 3339: Date and Time on the Internet: Timestamps - RFC 2579: Textual Conventions for SMIv2 - XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; - } - - typedef timeticks { - type uint32; - description - "The timeticks type represents a non-negative integer that - represents the time, modulo 2^32 (4294967296 decimal), in - hundredths of a second between two epochs. When a schema - node is defined that uses this type, the description of - the schema node identifies both of the reference epochs. - - In the value set and its semantics, this type is equivalent - to the TimeTicks type of the SMIv2."; - reference - "RFC 2578: Structure of Management Information Version 2 - (SMIv2)"; - } - - typedef timestamp { - type yang:timeticks; - description - "The timestamp type represents the value of an associated - timeticks schema node at which a specific occurrence - happened. The specific occurrence must be defined in the - description of any schema node defined using this type. When - the specific occurrence occurred prior to the last time the - associated timeticks attribute was zero, then the timestamp - value is zero. Note that this requires all timestamp values - to be reset to zero when the value of the associated timeticks - attribute reaches 497+ days and wraps around to zero. - - The associated timeticks schema node must be specified - in the description of any schema node using this type. - - In the value set and its semantics, this type is equivalent - to the TimeStamp textual convention of the SMIv2."; - reference - "RFC 2579: Textual Conventions for SMIv2"; - } - - /*** collection of generic address types ***/ - - typedef phys-address { - type string { - pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; - } - - description - "Represents media- or physical-level addresses represented - as a sequence octets, each octet represented by two hexadecimal - numbers. Octets are separated by colons. The canonical - representation uses lowercase characters. - - In the value set and its semantics, this type is equivalent - to the PhysAddress textual convention of the SMIv2."; - reference - "RFC 2579: Textual Conventions for SMIv2"; - } - - typedef mac-address { - type string { - pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; - } - description - "The mac-address type represents an IEEE 802 MAC address. - The canonical representation uses lowercase characters. - - In the value set and its semantics, this type is equivalent - to the MacAddress textual convention of the SMIv2."; - reference - "IEEE 802: IEEE Standard for Local and Metropolitan Area - Networks: Overview and Architecture - RFC 2579: Textual Conventions for SMIv2"; - } - - /*** collection of XML-specific types ***/ - - typedef xpath1.0 { - type string; - description - "This type represents an XPATH 1.0 expression. - - When a schema node is defined that uses this type, the - description of the schema node MUST specify the XPath - context in which the XPath expression is evaluated."; - reference - "XPATH: XML Path Language (XPath) Version 1.0"; - } - - /*** collection of string types ***/ - - typedef hex-string { - type string { - pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; - } - description - "A hexadecimal string with octets represented as hex digits - separated by colons. The canonical representation uses - lowercase characters."; - } - - typedef uuid { - type string { - pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' - + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; - } - description - "A Universally Unique IDentifier in the string representation - defined in RFC 4122. The canonical representation uses - lowercase characters. - - The following is an example of a UUID in string representation: - f81d4fae-7dec-11d0-a765-00a0c91e6bf6 - "; - reference - "RFC 4122: A Universally Unique IDentifier (UUID) URN - Namespace"; - } - - typedef dotted-quad { - type string { - pattern - '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' - + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; - } - description - "An unsigned 32-bit number expressed in the dotted-quad - notation, i.e., four octets written as decimal numbers - and separated with the '.' (full stop) character."; - } -} |