aboutsummaryrefslogtreecommitdiffstats
path: root/src/scvpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/scvpp')
-rw-r--r--src/scvpp/CMakeLists.txt66
-rw-r--r--src/scvpp/inc/scvpp/comm.h (renamed from src/scvpp/src/sc_vpp_comm.h)107
-rw-r--r--src/scvpp/inc/scvpp/interface.h69
-rw-r--r--src/scvpp/inc/scvpp/ip.h77
-rw-r--r--src/scvpp/inc/scvpp/nat.h (renamed from src/scvpp/src/sc_vpp_nat.h)0
-rw-r--r--src/scvpp/inc/scvpp/v3po.h54
-rw-r--r--src/scvpp/src/CMakeLists.txt57
-rw-r--r--src/scvpp/src/comm.c (renamed from src/scvpp/src/sc_vpp_comm.c)22
-rw-r--r--src/scvpp/src/interface.c176
-rw-r--r--src/scvpp/src/ip.c (renamed from src/scvpp/src/sc_vpp_ip.c)185
-rw-r--r--src/scvpp/src/nat.c (renamed from src/scvpp/src/sc_vpp_nat.c)133
-rw-r--r--src/scvpp/src/sc_vpp_interface.c252
-rw-r--r--src/scvpp/src/sc_vpp_interface.h61
-rw-r--r--src/scvpp/src/sc_vpp_ip.h36
-rw-r--r--src/scvpp/src/sc_vpp_v3po.h26
-rw-r--r--src/scvpp/src/v3po.c (renamed from src/scvpp/src/sc_vpp_v3po.c)66
-rw-r--r--src/scvpp/tests/CMakeLists.txt37
-rw-r--r--src/scvpp/tests/scvpp_iface_test.c130
-rw-r--r--src/scvpp/tests/scvpp_ip_test.c184
-rw-r--r--src/scvpp/tests/scvpp_nat_test.c51
-rw-r--r--src/scvpp/tests/scvpp_test.c160
-rw-r--r--src/scvpp/tests/scvpp_test.h (renamed from src/scvpp/tests/scvpp_nat_test.h)17
22 files changed, 1164 insertions, 802 deletions
diff --git a/src/scvpp/CMakeLists.txt b/src/scvpp/CMakeLists.txt
index 2dc42d6..8d04085 100644
--- a/src/scvpp/CMakeLists.txt
+++ b/src/scvpp/CMakeLists.txt
@@ -16,8 +16,57 @@
cmake_minimum_required(VERSION 2.8)
project(scvpp)
-# DEPENDENCIES
-##############
+# COMPILER & LINKER
+###################
+
+# scvpp sources
+set(SCVPP_SOURCES
+ src/comm.c
+ src/interface.c
+ src/ip.c
+ src/v3po.c
+ src/nat.c
+)
+
+# scvpp public headers
+set(SCVPP_HEADERS
+ inc/scvpp/comm.h
+ inc/scvpp/interface.h
+ inc/scvpp/ip.h
+ inc/scvpp/v3po.h
+ inc/scvpp/nat.h
+)
+
+#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR
+include(GNUInstallDirs)
+
+# Generate a compile_commands.json with compile options
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
+
+#set compiler and linker flags
+set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2")
+set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}")
+set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}")
+#NDEBUG to skip assert checks
+set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}")
+
+# libraries to link with
+set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl)
+
+# build instructions
+add_library(scvpp SHARED ${SCVPP_SOURCES})
+add_library(scvpp_a ${SCVPP_SOURCES})
+
+# linker instructions
+target_link_libraries(scvpp ${LINK_LIBRARIES})
+target_link_libraries(scvpp_a ${LINK_LIBRARIES})
+
+# to build shared and static library for scvpp, include project private directory inc before installing header file
+target_include_directories(scvpp PRIVATE inc)
+target_include_directories(scvpp_a PRIVATE inc)
+
+# TESTING
+#########
# enable testing if requested and possible
SET(ENABLE_TESTS 1 CACHE BOOL "Enable unit tests.")
@@ -32,16 +81,13 @@ if(ENABLE_TESTS)
endif(CMOCKA_FOUND)
endif(ENABLE_TESTS)
-# COMPILER & LINKER & INSTALL
-#############################
-
-#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR
-include(GNUInstallDirs)
-add_subdirectory(src)
+# INSTALL
+#########
-# MORE INSTALL
-##############
+# install rules
+install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/scvpp)
find_package(PkgConfig QUIET) #QUIET disables message if not found
if(PKG_CONFIG_FOUND)
diff --git a/src/scvpp/src/sc_vpp_comm.h b/src/scvpp/inc/scvpp/comm.h
index eeeaaf9..9a27517 100644
--- a/src/scvpp/src/sc_vpp_comm.h
+++ b/src/scvpp/inc/scvpp/comm.h
@@ -23,22 +23,30 @@
#include <vapi/vapi_common.h>
#include <vapi/vpe.api.vapi.h>
+typedef enum {
+ SCVPP_OK = 0, /* Success */
+ SCVPP_EINVAL, /* Invalid value encountered */
+ SCVPP_EAGAIN, /* Operation would block */
+ SCVPP_ENOTSUP, /* Operation not supported */
+ SCVPP_ENOMEM, /* Out of memory */
+ SCVPP_NOT_FOUND, /* Required element can not be found */
+} scvpp_error_e;
+
// Use VAPI macros to define symbols
DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
-#define VPP_INTFC_NAME_LEN 64
-#define VPP_TAPV2_NAME_LEN VPP_INTFC_NAME_LEN
-#define VPP_IP4_ADDRESS_LEN 4
-#define VPP_IP6_ADDRESS_LEN 16
-#define VPP_IP4_ADDRESS_STRING_LEN 16
-#define VPP_IP4_PREFIX_STRING_LEN 19
#define VPP_IP4_HOST_PREFIX_LEN 32
-#define VPP_IP6_ADDRESS_STRING_LEN 46
-#define VPP_MAC_ADDRESS_LEN 8
-#define VPP_TAG_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_PROFILE_NAME_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_PSK_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_ID_LEN 32
+#define VPP_INTFC_NAME_LEN 64 /* Interface name max length */
+#define VPP_IP4_ADDRESS_LEN 4 /* IPv4 length in VPP format */
+#define VPP_IP6_ADDRESS_LEN 16 /* IPv6 length in VPP format */
+#define VPP_MAC_ADDRESS_LEN 8 /* MAC length in VPP format */
+/* IPv4 and IPv6 length in string format */
+#define VPP_IP4_ADDRESS_STRING_LEN INET_ADDRSTRLEN //16, include '\0'
+#define VPP_IP6_ADDRESS_STRING_LEN INET6_ADDRSTRLEN //46, include '\0'
+#define VPP_IP4_PREFIX_STRING_LEN \
+ INET_ADDRSTRLEN + sizeof('/') + 2 // include '\0'
+#define VPP_IP6_PREFIX_STRING_LEN \
+ INET6_ADDRSTRLEN + sizeof('/') + 3 // include '\0'
/**********************************MACROS**********************************/
#define ARG_CHECK(retval, arg) \
@@ -86,9 +94,10 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
vapi_payload_##api_name##_reply * reply) \
{ \
UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \
+ vapi_payload_##api_name##_reply * passed; \
if (caller_ctx) \
{ \
- vapi_payload_##api_name##_reply * passed = (vapi_payload_##api_name##_reply *)caller_ctx; \
+ passed = (vapi_payload_##api_name##_reply *)caller_ctx; \
*passed = *reply; \
} \
return VAPI_OK; \
@@ -104,13 +113,81 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
else \
{ \
while (VAPI_EAGAIN == (rv = call_code)); \
- rv = vapi_dispatch (g_vapi_ctx_instance); \
+ if (rv != VAPI_OK) { /* try once more to get reply */ \
+ rv = vapi_dispatch (g_vapi_ctx); \
+ } \
} \
} \
while (0)
#define VAPI_CALL(call_code) VAPI_CALL_MODE(call_code, g_vapi_mode)
+struct elt {
+ void *data; //vapi_payload structure
+ struct elt *next;
+ int id; //id of the stack element to count total nb of elements
+};
+
+static inline int push(struct elt **stack, void *data, int length)
+{
+ struct elt *el;
+
+ //new stack node
+ el = malloc(sizeof(struct elt));
+ if (!el)
+ return -ENOMEM;
+ el->data = malloc(length);
+ if (!el->data)
+ return -ENOMEM;
+
+ memcpy(el->data, data, length);
+ if (*stack)
+ el->id = (*stack)->id++;
+ else
+ el->id = 0;
+ el->next = *stack; //point to old value of stack
+ *stack = el; //el is new stack head
+
+ return 0;
+}
+
+static inline void * pop(struct elt **stack)
+{
+ struct elt *prev;
+ void *data;
+
+ if (!(*stack))
+ return NULL;
+
+ data = (*stack)->data; //get data at stack head
+ prev = *stack; //save stack to free memory later
+ *stack = (*stack)->next; //new stack
+
+ free(prev);
+ prev = NULL;
+
+ return data;
+}
+
+#define VAPI_DUMP_LIST_CB(api_name) \
+static vapi_error_e \
+api_name##_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, \
+ vapi_payload_##api_name##_details *reply) \
+{ \
+ UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \
+ struct elt **stackp; \
+ ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply); \
+ \
+ stackp = (struct elt**) caller_ctx; \
+ push(stackp, reply, sizeof(*reply)); \
+ \
+ return VAPI_OK; \
+}
+
+#define foreach_stack_elt(stack) \
+ for(void *data = pop(&stack); data != NULL ; data = pop(&stack))
+//for(void *data = pop(&stack); stack != NULL ; data = pop(&stack)) // No!!
+
int sc_aton(const char *cp, u8 * buf, size_t length);
char * sc_ntoa(const u8 * buf);
@@ -126,7 +203,7 @@ uint32_t hardntohlu32(uint8_t host[4]);
* VPP
*/
-extern vapi_ctx_t g_vapi_ctx_instance;
+extern vapi_ctx_t g_vapi_ctx;
extern vapi_mode_e g_vapi_mode;
int sc_connect_vpp();
diff --git a/src/scvpp/inc/scvpp/interface.h b/src/scvpp/inc/scvpp/interface.h
new file mode 100644
index 0000000..86cd185
--- /dev/null
+++ b/src/scvpp/inc/scvpp/interface.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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 __BAPI_INTERFACE_H__
+#define __BAPI_INTERFACE_H__
+
+#include <vapi/interface.api.vapi.h>
+#include <scvpp/comm.h>
+
+typedef vapi_payload_sw_interface_details sw_interface_dump_t;
+
+/**
+ * @brief Change an interface state
+ * @param interface_name - name of target interface
+ * @param enable - true=state up, false=state down
+ * @return 0 for success, else negative SCVPP error code
+ */
+int interface_enable(const char *interface_name, const bool enable);
+
+/**
+ * @brief Dump details about all existing interfaces
+ * @return stack structure containing all interfaces or NULL if empty
+ */
+extern struct elt * interface_dump_all();
+
+
+/**
+ * @brief Dump details about a specific interface
+ * @param details - where answer will be written
+ * @param interface_name - name of the interface to dump
+ * @return 0 for success or negative SCVPP error code
+ */
+extern int interface_dump_iface(sw_interface_dump_t *details,
+ const char *interface_name);
+
+/*
+ * Library internal helper functions. Symbols should not be exported eventually
+ */
+
+/*
+ * @brief Get VPP internal index for an interface
+ * @param interface_name - name of the interface to get id from
+ * @param sw_if_index - pointer to interface index to be returned
+ * @return 0 upon success or negative SCVPP error code
+ */
+extern int get_interface_id(const char *interface_name, uint32_t *sw_if_index);
+
+/* @brief Get interface name from an interface ID. This is a super expensive
+ * operation !!! Avoid using it.
+ * @param interface_name - pointer to string holding returned interface name
+ * @param sw_if_index - interface index provided
+ * @return 0 upon success or negative SCVPP error code
+ */
+extern int get_interface_name(char *interface_name, uint32_t sw_if_index);
+
+#endif /* __BAPI_INTERFACE_H__ */
diff --git a/src/scvpp/inc/scvpp/ip.h b/src/scvpp/inc/scvpp/ip.h
new file mode 100644
index 0000000..f8805b3
--- /dev/null
+++ b/src/scvpp/inc/scvpp/ip.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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 __BAPI_IP_H__
+#define __BAPI_IP_H__
+
+#include <vapi/interface.api.vapi.h>
+#include <vapi/ip.api.vapi.h>
+
+typedef vapi_payload_ip_fib_details fib_dump_t;
+
+/*
+ * @brief Dump IPv4/IPv6 address from an interface.
+ * @param interface_name - name of the interface to get ip from.
+ * @param ip_addr - where dump will store IP. If IP not found, returns 0.0.0.0
+ * @param prefix_len - pointer where dump will store prefix
+ * @param is_ipv6 - true = IPv6, false = IPv4
+ * @return 0 on success, or nergative SCVPP error code
+ */
+extern int ipv46_address_dump(const char *interface_name, char *ip_addr,
+ u8 *prefix_len, bool is_ipv6);
+
+/**
+ * @brief Add or remove IPv4/IPv6 address to/from an interface.
+ * @param interface_name - name of interface to configure
+ * @param addr - address to add
+ * @param prefix_len - prefix length of interface
+ * @param is_ipv6 - true if ipv6, false otherwise
+ * @param add - true to add, false to remove
+ */
+extern int ipv46_config_add_remove(const char *interface_name, const char *addr,
+ uint8_t prefix_len, bool is_ipv6, bool add);
+
+/*
+ * TODO should add a field is_ipv6 because it only do ipv4 now
+ * @brief Add or remove an IP route
+ * @param dst_address - subnet IP you wish to route
+ * @param dst_address_length - prefix length for subnet you wish to route
+ * @param next_address - Next hop IP (can use next_hop_interface instead)
+ * @param is_add - true to add, false to remove
+ * @param table_id - id of the tab in FIB
+ * @param next_hop_interface - Next hop interface (can use next_address instead)
+ */
+extern int
+ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
+ const char* next_address, u8 is_add, u32 table_id,
+ const char *next_hop_interface);
+
+/**
+ * @brief Dump all FIB tables entries
+ * @return stacked answers on success, or NULL on failure
+ */
+extern struct elt* ipv4_fib_dump_all();
+
+/*
+ * @brief Dump information about a prefix, based on fib_dump_all
+ * @param prefix_xpath - prefix to look for in FIB
+ * @param reply - FIB entry dump replied
+ * @return SCVPP_OK if prefix found or SCVPP_NOT_FOUND
+ */
+extern int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply);
+
+#endif /* __BAPI_IP_H__ */
diff --git a/src/scvpp/src/sc_vpp_nat.h b/src/scvpp/inc/scvpp/nat.h
index 40e727e..40e727e 100644
--- a/src/scvpp/src/sc_vpp_nat.h
+++ b/src/scvpp/inc/scvpp/nat.h
diff --git a/src/scvpp/inc/scvpp/v3po.h b/src/scvpp/inc/scvpp/v3po.h
new file mode 100644
index 0000000..f876ab4
--- /dev/null
+++ b/src/scvpp/inc/scvpp/v3po.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 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 _V3PO__INTERFACE_H__
+#define _V3PO__INTERFACE_H__
+
+#include <vapi/tapv2.api.vapi.h>
+#include <vapi/l2.api.vapi.h>
+
+/**
+ * V3PO defines operations for specific interfaces used by VPP like:
+ * - tapv2
+ */
+
+/* tapv2 */
+
+typedef vapi_payload_tap_create_v2 tapv2_create_t;
+typedef vapi_payload_sw_interface_tap_v2_details tapv2_dump_t;
+
+/**
+ * TODO problem: vapi_payload_sw_interface_tap_v2_details reply is NULL
+ * @brief Dump information about a tap interface
+ * @param dump - where dump information will be stored
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int dump_tapv2(tapv2_dump_t *dump);
+
+/**
+ * @brief Create a tapv2 interface
+ * @param query - required structure for the creation of a VPP tapv2 interface
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int create_tapv2(tapv2_create_t *query);
+
+/**
+ * @brief Delete a tapv2 interface
+ * @param interface_name - name of the interface to delete
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int delete_tapv2(char *interface_name);
+
+#endif /* __V3PO_INTERFACE_H__ */
diff --git a/src/scvpp/src/CMakeLists.txt b/src/scvpp/src/CMakeLists.txt
deleted file mode 100644
index 71a891f..0000000
--- a/src/scvpp/src/CMakeLists.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (c) 2018 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.
-#
-
-# scvpp sources
-set(SCVPP_SOURCES
- sc_vpp_comm.c
- sc_vpp_interface.c
- sc_vpp_ip.c
- sc_vpp_v3po.c
- sc_vpp_nat.c
-)
-
-# scvpp public headers
-set(SCVPP_HEADERS
- sc_vpp_comm.h
- sc_vpp_interface.h
- sc_vpp_ip.h
- sc_vpp_v3po.h
- sc_vpp_nat.h
-)
-
-# Generate a compile_commands.json with compile options
-set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
-
-#set compiler and linker flags
-set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2")
-set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}")
-set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}")
-#NDEBUG to skip assert checks
-set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}")
-
-# libraries to link with
-set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl)
-
-# build instructions
-add_library(scvpp SHARED ${SCVPP_SOURCES})
-add_library(scvpp_a ${SCVPP_SOURCES})
-
-# linker instructions
-target_link_libraries(scvpp ${LINK_LIBRARIES})
-target_link_libraries(scvpp_a ${LINK_LIBRARIES})
-
-# install rules
-install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/scvpp/src/sc_vpp_comm.c b/src/scvpp/src/comm.c
index cd0b035..a065b58 100644
--- a/src/scvpp/src/sc_vpp_comm.c
+++ b/src/scvpp/src/comm.c
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
+#include <scvpp/comm.h>
#include <assert.h>
#include <string.h>
@@ -24,21 +24,21 @@
#define MAX_OUTSTANDING_REQUESTS 4
#define RESPONSE_QUEUE_SIZE 2
-vapi_ctx_t g_vapi_ctx_instance = NULL;
+vapi_ctx_t g_vapi_ctx = NULL;
vapi_mode_e g_vapi_mode = VAPI_MODE_NONBLOCKING;
int sc_connect_vpp()
{
- if (g_vapi_ctx_instance == NULL)
+ if (g_vapi_ctx == NULL)
{
- vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
- rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL,
+ vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx);
+ rv = vapi_connect(g_vapi_ctx, APP_NAME, NULL,
MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
VAPI_MODE_BLOCKING, true);
if (rv != VAPI_OK)
{
- vapi_ctx_free(g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
+ vapi_ctx_free(g_vapi_ctx);
+ g_vapi_ctx = NULL;
return -1;
}
}
@@ -48,11 +48,11 @@ int sc_connect_vpp()
int sc_disconnect_vpp()
{
- if (NULL != g_vapi_ctx_instance)
+ if (NULL != g_vapi_ctx)
{
- vapi_disconnect(g_vapi_ctx_instance);
- vapi_ctx_free(g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
+ vapi_disconnect(g_vapi_ctx);
+ vapi_ctx_free(g_vapi_ctx);
+ g_vapi_ctx = NULL;
}
return 0;
}
diff --git a/src/scvpp/src/interface.c b/src/scvpp/src/interface.c
new file mode 100644
index 0000000..53cea1c
--- /dev/null
+++ b/src/scvpp/src/interface.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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 <stdbool.h>
+
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+
+// Use VAPI macros to define symbols
+DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
+
+static vapi_error_e
+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)
+{
+ UNUSED(rv); UNUSED(ctx); UNUSED(is_last);
+
+ vapi_payload_sw_interface_details *passed;
+
+ ARG_CHECK2(VAPI_EINVAL, callback_ctx, reply);
+
+ //copy
+ passed = (vapi_payload_sw_interface_details *) callback_ctx;
+ *passed = *reply;
+
+ return VAPI_OK;
+}
+
+static vapi_error_e
+bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details,
+ const char *iface_name)
+{
+ vapi_msg_sw_interface_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_sw_interface_dump(g_vapi_ctx);
+ assert(NULL != mp);
+
+ /* Dump a specific interfaces */
+ mp->payload.name_filter_valid = true;
+ strncpy((char *)mp->payload.name_filter, iface_name, VPP_INTFC_NAME_LEN);
+
+ VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp,
+ sw_interface_dump_cb, details));
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ return rv;
+}
+
+int get_interface_id(const char *if_name, uint32_t *sw_if_index)
+{
+ vapi_payload_sw_interface_details details = {0};
+ vapi_error_e rv;
+
+ ARG_CHECK2(-SCVPP_EINVAL, if_name, sw_if_index);
+
+ rv = bin_api_sw_interface_dump(&details, if_name);
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ if (strncmp(if_name, (char*) details.interface_name, VPP_INTFC_NAME_LEN)
+ != 0)
+ return -SCVPP_NOT_FOUND;
+
+ *sw_if_index = details.sw_if_index;
+
+ return 0;
+}
+
+/*
+ * dump only a specific interface
+ */
+int interface_dump_iface(sw_interface_dump_t *details, const char *iface_name)
+{
+ vapi_error_e rv;
+
+ rv = bin_api_sw_interface_dump(details, iface_name);
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ if (strncmp(iface_name, (char*) details->interface_name, VPP_INTFC_NAME_LEN)
+ != 0)
+ return -SCVPP_NOT_FOUND;
+
+ return SCVPP_OK;
+}
+
+VAPI_DUMP_LIST_CB(sw_interface)
+
+struct elt* interface_dump_all()
+{
+ struct elt* stack = NULL;
+ vapi_msg_sw_interface_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_sw_interface_dump(g_vapi_ctx);
+
+ /* Dump all */
+ mp->payload.name_filter_valid = false;
+ memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter));
+
+ VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp, sw_interface_all_cb,
+ &stack));
+ if (VAPI_OK != rv)
+ return NULL;
+
+ return stack;
+}
+
+VAPI_RETVAL_CB(sw_interface_set_flags);
+
+int interface_enable(const char *interface_name, const bool enable)
+{
+ vapi_msg_sw_interface_set_flags *mp;
+ uint32_t sw_if_index;
+ vapi_error_e rv;
+ int rc;
+
+ ARG_CHECK(-SCVPP_EINVAL, interface_name);
+
+ rc = get_interface_id(interface_name, &sw_if_index);
+ if (rc != 0)
+ return -SCVPP_NOT_FOUND;
+
+ mp = vapi_alloc_sw_interface_set_flags(g_vapi_ctx);
+ assert(NULL != mp);
+ mp->payload.sw_if_index = sw_if_index;
+ mp->payload.admin_up_down = enable;
+
+ VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx, mp,
+ sw_interface_set_flags_cb, NULL));
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
+
+ return 0;
+}
+
+int get_interface_name(char *interface_name, uint32_t sw_if_index)
+{
+ struct elt *stack= NULL;
+ sw_interface_dump_t *dump;
+ int rc = -SCVPP_NOT_FOUND;
+
+ stack = interface_dump_all();
+ if (!stack)
+ return -SCVPP_NOT_FOUND;
+
+ foreach_stack_elt(stack) {
+ dump = (sw_interface_dump_t *) data;
+
+ if (dump->sw_if_index == sw_if_index) {
+ strncpy(interface_name, (char *)dump->interface_name, VPP_INTFC_NAME_LEN);
+ rc = SCVPP_OK;
+ }
+
+ free(dump);
+ }
+
+ return rc;
+}
diff --git a/src/scvpp/src/sc_vpp_ip.c b/src/scvpp/src/ip.c
index 0dfd108..2dc991c 100644
--- a/src/scvpp/src/sc_vpp_ip.c
+++ b/src/scvpp/src/ip.c
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
-#include "sc_vpp_ip.h"
-
-#include "sc_vpp_interface.h"
+#include <scvpp/comm.h>
+#include <scvpp/ip.h>
+#include <scvpp/interface.h>
#include <assert.h>
+#include <stdio.h>
// Use VAPI macros to define symbols
DEFINE_VAPI_MSG_IDS_IP_API_JSON
@@ -36,7 +36,7 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6,
ARG_CHECK(VAPI_EINVAL, ip_address);
- mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance);
+ mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx);
assert(NULL != mp);
mp->payload.sw_if_index = sw_if_index;
@@ -44,10 +44,10 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6,
mp->payload.is_ipv6 = is_ipv6;
mp->payload.del_all = del_all;
mp->payload.address_length = address_length;
- if (sc_aton(ip_address, mp->payload.address, sizeof(mp->payload.address)))
+ if (sc_aton(ip_address, mp->payload.address, VPP_IP4_ADDRESS_LEN))
return VAPI_EINVAL;
- VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx, mp,
sw_interface_add_del_address_cb, NULL));
return rv;
@@ -59,38 +59,41 @@ static vapi_error_e
bin_api_ip_add_del_route(vapi_payload_ip_add_del_route_reply * reply,
const char* dst_address, uint8_t dst_address_length,
const char* next_hop, uint8_t is_add,
- uint32_t table_id, const char *interface_name)
+ uint32_t table_id, const char *next_interface)
{
- sw_interface_details_query_t query = {0};
vapi_msg_ip_add_del_route *mp;
+ uint32_t sw_if_index;
+ vapi_error_e rv ;
+ int rc;
- ARG_CHECK4(VAPI_EINVAL, reply, dst_address, next_hop, interface_name);
-
- sw_interface_details_query_set_name(&query, interface_name);
+ ARG_CHECK2(VAPI_EINVAL, reply, dst_address);
- if (!get_interface_id(&query))
+ //Require interface or next hop IP or both
+ if (!next_interface && !next_hop)
return VAPI_EINVAL;
- mp = vapi_alloc_ip_add_del_route (g_vapi_ctx_instance, 1);
+ mp = vapi_alloc_ip_add_del_route(g_vapi_ctx, 1);
assert(NULL != mp);
- //ip route add 2.2.2.2/24 via 5.5.5.5
- //show ip fib table 0 2.2.2.0/24 detail
+ if (next_interface) {
+ rc = get_interface_id(next_interface, &sw_if_index);
+ if (rc < 0)
+ return VAPI_EINVAL;
+ }
mp->payload.is_add = is_add;
- mp->payload.dst_address_length = dst_address_length;
mp->payload.table_id = table_id;
- mp->payload.next_hop_sw_if_index = query.sw_interface_details.sw_if_index;
-
- if (sc_aton(dst_address, mp->payload.dst_address,
- sizeof(mp->payload.dst_address)))
- return VAPI_EINVAL;
- if (sc_aton(next_hop, mp->payload.next_hop_address,
- sizeof(mp->payload.next_hop_address)))
- return VAPI_EINVAL;
+ mp->payload.is_ipv6 = false;
+ mp->payload.is_local = false;
+ sc_aton(dst_address, mp->payload.dst_address, VPP_IP4_ADDRESS_LEN);
+ mp->payload.dst_address_length = dst_address_length;
+ if (next_interface) //interface is not mandatory
+ mp->payload.next_hop_sw_if_index = sw_if_index;
+ if (next_hop) //next hop ip is not mandatory
+ sc_aton(next_hop, mp->payload.next_hop_address, VPP_IP4_ADDRESS_LEN);
- vapi_error_e rv ;
- VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx_instance, mp, ip_add_del_route_cb, reply));
+ VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx, mp,
+ ip_add_del_route_cb, reply));
return rv;
}
@@ -100,12 +103,13 @@ ip_address_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv,
bool is_last, vapi_payload_ip_address_details *reply)
{
UNUSED(rv);
+ vapi_payload_ip_address_details *passed;
+
ARG_CHECK3(VAPI_EINVAL, ctx, callback_ctx, reply);
//copy dump reply in callback context
- if (!is_last && callback_ctx) {
- vapi_payload_ip_address_details *passed =
- (vapi_payload_ip_address_details *) callback_ctx;
+ if (!is_last) {
+ passed = (vapi_payload_ip_address_details *) callback_ctx;
*passed = *reply;
}
@@ -119,11 +123,13 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6,
vapi_msg_ip_address_dump *mp;
vapi_error_e rv;
- mp = vapi_alloc_ip_address_dump(g_vapi_ctx_instance);
+ mp = vapi_alloc_ip_address_dump(g_vapi_ctx);
+ assert(mp != NULL);
+
mp->payload.sw_if_index = sw_if_index;
mp->payload.is_ipv6 = is_ipv6;
- VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx_instance, mp, ip_address_dump_cb,
+ VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx, mp, ip_address_dump_cb,
dctx));
if (rv != VAPI_OK)
return rv;
@@ -131,64 +137,112 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6,
return VAPI_OK;
}
-/*
- * @brief Dump IPv4/IPv6 address from an interface.
- * @param interface_name Name of the interface to dump.
- * @param ip_addr pointer where dump will store IP.
- * @param prefix_len pointer where dump will store prefix
- */
+///VAPI_DUMP_LIST_CB(ip_fib); can not be used because of path flexible array
+
+static vapi_error_e
+ip_fib_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_fib_details *reply)
+{
+ UNUSED(ctx); UNUSED(rv); UNUSED(is_last);
+ struct elt **stackp;
+ ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply);
+
+ stackp = (struct elt**) caller_ctx;
+ push(stackp, reply, sizeof(*reply)+reply->count*sizeof(vapi_type_fib_path));
+
+ return VAPI_OK;
+}
+
+struct elt* ipv4_fib_dump_all()
+{
+ struct elt *stack = NULL;
+ vapi_msg_ip_fib_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_ip_fib_dump(g_vapi_ctx);
+ assert(mp != NULL);
+
+ VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx, mp, ip_fib_all_cb, &stack));
+ if(VAPI_OK != rv)
+ return NULL;
+
+ return stack;
+}
+
+int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply)
+{
+ struct elt *stack = NULL;
+ char prefix[VPP_IP4_PREFIX_STRING_LEN];
+ fib_dump_t *dump;
+ int rc = -SCVPP_NOT_FOUND;
+
+ stack = ipv4_fib_dump_all();
+ if (!stack)
+ return rc;
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (rc == -SCVPP_NOT_FOUND) {
+ snprintf(prefix, VPP_IP4_PREFIX_STRING_LEN, "%s/%u",
+ sc_ntoa(dump->address), dump->address_length);
+ if (!strncmp(prefix_xpath, prefix, VPP_IP4_PREFIX_STRING_LEN)) {
+ *reply = dump;
+ rc = SCVPP_OK;
+ continue;
+ }
+ }
+
+ free(dump);
+ }
+
+ return rc;
+}
+
int ipv46_address_dump(const char *interface_name, char *ip_addr,
u8 *prefix_len, bool is_ipv6)
{
vapi_payload_ip_address_details dctx = {0};
- sw_interface_details_query_t query = {0};
+ uint32_t sw_if_index;
vapi_error_e rv;
+ int rc;
- sw_interface_details_query_set_name(&query, interface_name);
-
- if (!get_interface_id(&query))
- return -EINVAL;
+ rc = get_interface_id(interface_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
- rv = bin_api_ip_address_dump(query.sw_interface_details.sw_if_index, is_ipv6, &dctx);
+ rv = bin_api_ip_address_dump(sw_if_index, is_ipv6, &dctx);
if (rv != VAPI_OK)
- return -EAGAIN;
+ return -SCVPP_EINVAL;
strcpy(ip_addr, sc_ntoa(dctx.ip)); //IP string
*prefix_len = dctx.prefix_length; //prefix length
- return 0;
+ return SCVPP_OK;
}
-/**
- * @brief Add or remove IPv4/IPv6 address to/from an interface.
- */
int ipv46_config_add_remove(const char *if_name, const char *addr,
uint8_t prefix, bool is_ipv6, bool add)
{
vapi_error_e rv;
+ uint32_t sw_if_index;
int rc;
ARG_CHECK2(-1, if_name, addr);
- /* get interface index */
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, if_name);
- rc = get_interface_id(&query);
- if (!rc)
- return -EINVAL;
+ rc = get_interface_id(if_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
/* add del addr */
- rv = bin_api_sw_interface_add_del_address(query.sw_interface_details.sw_if_index,
- add, is_ipv6, 0, prefix, addr);
+ rv = bin_api_sw_interface_add_del_address(sw_if_index, add, is_ipv6, 0,
+ prefix, addr);
if (rv != VAPI_OK)
- return -EINVAL;
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
-/*
- * @brief Add or remove an IP route
- */
int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
const char* next_address, u8 is_add,
u32 table_id, const char *interface)
@@ -198,9 +252,8 @@ int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
rv = bin_api_ip_add_del_route(&reply, dst_address, dst_address_length,
next_address, is_add, table_id, interface);
- if (VAPI_OK != rv || reply.retval > 0) {
- return -EINVAL;
- }
+ if (VAPI_OK != rv || reply.retval > 0)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
diff --git a/src/scvpp/src/sc_vpp_nat.c b/src/scvpp/src/nat.c
index e4bf2b7..17ace64 100644
--- a/src/scvpp/src/sc_vpp_nat.c
+++ b/src/scvpp/src/nat.c
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
-#include "sc_vpp_nat.h"
+#include <scvpp/comm.h>
+#include <scvpp/nat.h>
#include <assert.h>
#include <stdbool.h>
@@ -28,8 +28,7 @@ nat44_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
vapi_error_e rv, bool is_last,
vapi_payload_nat44_interface_details *reply)
{
- UNUSED(ctx);
- UNUSED(rv);
+ UNUSED(ctx); UNUSED(rv);
vapi_payload_nat44_interface_details *dctx = callback_ctx;
assert(dctx);
@@ -56,10 +55,10 @@ bin_api_nat44_interface_dump(vapi_payload_nat44_interface_details *reply)
ARG_CHECK(VAPI_EINVAL, reply);
- mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx);
assert(NULL != mp);
- VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx, mp,
nat44_interface_dump_cb, reply));
return rv;
@@ -76,12 +75,12 @@ bin_api_nat44_add_del_interface_addr(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx, mp,
nat44_add_del_interface_addr_cb,
NULL));
@@ -99,13 +98,13 @@ bin_api_nat44_add_del_addr_range(
ARG_CHECK(VAPI_EINVAL, range);
- mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *range;
- VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx, mp,
nat44_add_del_address_range_cb,
NULL));
@@ -123,13 +122,12 @@ bin_api_nat44_add_del_static_mapping(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx_instance);
-
+ mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx, mp,
nat44_add_del_static_mapping_cb,
NULL));
@@ -140,8 +138,7 @@ static vapi_error_e nat44_static_mapping_dump_cb(
struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv,
bool is_last,vapi_payload_nat44_static_mapping_details *reply)
{
- UNUSED(rv);
- UNUSED(ctx);
+ UNUSED(rv); UNUSED(ctx);
vapi_payload_nat44_static_mapping_details *dctx = callback_ctx;
assert(dctx);
@@ -166,10 +163,10 @@ bin_api_nat44_static_mapping_dump(
ARG_CHECK(VAPI_EINVAL, reply);
- msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx_instance);
+ msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx);
assert(NULL != msg);
- VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx_instance, msg,
+ VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx, msg,
nat44_static_mapping_dump_cb,
reply));
@@ -186,13 +183,13 @@ static vapi_error_e bin_api_nat44_forwarding_enable_disable(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
VAPI_CALL(vapi_nat44_forwarding_enable_disable(
- g_vapi_ctx_instance, mp, nat44_forwarding_enable_disable_cb, NULL));
+ g_vapi_ctx, mp, nat44_forwarding_enable_disable_cb, NULL));
return rv;
}
@@ -207,113 +204,91 @@ bin_api_nat_set_workers(const vapi_payload_nat_set_workers *msg)
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat_set_workers(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat_set_workers(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx_instance, mp, nat_set_workers_cb,
- NULL));
+ VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx, mp, nat_set_workers_cb, NULL));
return rv;
}
int nat44_interface_dump(nat44_interface_details_t *reply)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_interface_dump(reply);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_interface_dump(reply);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_interface_addr(const nat44_add_del_interface_addr_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_interface_addr(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_interface_addr(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_addr_range(const nat44_add_del_address_range_t *range)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_addr_range(range);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_addr_range(range);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_static_mapping(const nat44_add_del_static_mapping_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_static_mapping(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_static_mapping(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_static_mapping_dump(nat44_static_mapping_details_t *reply)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_static_mapping_dump(reply);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_static_mapping_dump(reply);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
-int nat44_forwarding_enable_disable(
- const nat44_forwarding_enable_disable_t *msg)
+int
+nat44_forwarding_enable_disable(const nat44_forwarding_enable_disable_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_forwarding_enable_disable(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_forwarding_enable_disable(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
return 0;
}
int nat_set_workers(const nat_set_workers_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat_set_workers(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat_set_workers(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
diff --git a/src/scvpp/src/sc_vpp_interface.c b/src/scvpp/src/sc_vpp_interface.c
deleted file mode 100644
index bc5befc..0000000
--- a/src/scvpp/src/sc_vpp_interface.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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 <stdbool.h>
-
-#include <vapi/l2.api.vapi.h>
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-
-
-// Use VAPI macros to define symbols
-DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
-DEFINE_VAPI_MSG_IDS_L2_API_JSON;
-
-void sw_interface_details_query_set_name(sw_interface_details_query_t * query,
- const char * interface_name)
-{
- assert(query && interface_name);
-
- memset(query, 0, sizeof(*query));
-
- strncpy((char*) query->sw_interface_details.interface_name, interface_name,
- sizeof(query->sw_interface_details.interface_name));
-}
-
-static vapi_error_e
-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)
-{
- UNUSED(rv); UNUSED(ctx); UNUSED(is_last);
-
- vapi_payload_sw_interface_details *passed;
-
- ARG_CHECK(-EINVAL, callback_ctx);
-
- passed = (vapi_payload_sw_interface_details *) callback_ctx;
-
- //Interface is found if index of query equals index of reply
- if (passed->sw_if_index != reply->sw_if_index)
- return -EINVAL;
-
- //copy
- *passed = *reply;
-
- return VAPI_OK;
-}
-
-static vapi_error_e
-bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details)
-{
- vapi_msg_sw_interface_dump *mp;
- vapi_error_e rv;
-
- mp = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- mp->payload.name_filter_valid = 0;
- memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter));
- assert(NULL != mp);
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, sw_interface_dump_cb, details));
- if (!rv)
- return -EINVAL;
-
- return rv;
-}
-
-static vapi_error_e
-interface_dump_all_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- UNUSED(ctx); UNUSED(rv);
- dump_all_ctx *dctx = callback_ctx;
-
- if (is_last)
- return VAPI_OK;
-
- if(dctx->capacity == 0 && dctx->intfcArray == NULL) {
- dctx->capacity = 10;
- dctx->intfcArray = (vpp_interface_t*)malloc( sizeof(vpp_interface_t)*dctx->capacity );
- }
- if(dctx->num_ifs >= dctx->capacity-1) {
- dctx->capacity += 10;
- dctx->intfcArray = (vpp_interface_t*)realloc(dctx->intfcArray, sizeof(vpp_interface_t)*dctx->capacity );
- }
-
- vpp_interface_t * iface = &dctx->intfcArray[dctx->num_ifs];
-
- iface->sw_if_index = reply->sw_if_index;
- strncpy(iface->interface_name, (char*) reply->interface_name,
- VPP_INTFC_NAME_LEN);
- iface->l2_address_length = reply->l2_address_length;
- memcpy(iface->l2_address, reply->l2_address, reply->l2_address_length );
- iface->link_speed = reply->link_speed;
-
- iface->link_mtu = reply->link_mtu;
- iface->admin_up_down = reply->admin_up_down;
- iface->link_up_down = reply->link_up_down;
-
- dctx->num_ifs += 1;
-
- return VAPI_OK;
-}
-
-int interface_dump_all(dump_all_ctx * dctx)
-{
- vapi_msg_sw_interface_dump *dump;
- vapi_error_e rv;
-
- ARG_CHECK(-1, dctx);
-
- if(dctx == NULL)
- return -1;
-
- dctx->intfcArray = NULL;
- dctx->capacity = 0;
- dctx->num_ifs = 0;
-
- dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- dump->payload.name_filter_valid = 0;
- memset(dump->payload.name_filter, 0, sizeof(dump->payload.name_filter));
- while (VAPI_EAGAIN ==
- (rv =
- vapi_sw_interface_dump(g_vapi_ctx_instance, dump, interface_dump_all_cb,
- dctx)));
-
- return dctx->num_ifs;
-}
-
-static vapi_error_e
-get_interface_id_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- UNUSED(ctx); UNUSED(rv);
-
- sw_interface_details_query_t *dctx = callback_ctx;
- assert(dctx);
-
- if (!dctx->interface_found)
- {
- if (is_last)
- {
- assert(NULL == reply);
- }
- else
- {
- assert(NULL != reply);
-
- if (0 == strcmp((const char*)dctx->sw_interface_details.interface_name,
- (const char*)reply->interface_name))
- {
- dctx->interface_found = true;
- dctx->sw_interface_details = *reply;
- }
- }
- }
-
- return VAPI_OK;
-}
-
-// return error code instead of boolean
-int get_interface_id(sw_interface_details_query_t * sw_interface_details_query)
-{
- vapi_error_e rv;
-
- ARG_CHECK(false, sw_interface_details_query);
-
- sw_interface_details_query->interface_found = false;
-
- vapi_msg_sw_interface_dump *mp = vapi_alloc_sw_interface_dump (g_vapi_ctx_instance);
- assert(NULL != mp);
-
- mp->payload.name_filter_valid = true;
- memcpy(mp->payload.name_filter, sw_interface_details_query->sw_interface_details.interface_name,
- sizeof(mp->payload.name_filter));
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, get_interface_id_cb, sw_interface_details_query));
- if (VAPI_OK != rv)
- return false;
-
- return sw_interface_details_query->interface_found;
-}
-
-int get_interface_name(sw_interface_details_query_t *query)
-{
- vapi_error_e rv;
-
- ARG_CHECK(-EINVAL, query);
-
- query->interface_found = false;
-
- rv = bin_api_sw_interface_dump(&query->sw_interface_details);
- if (rv == VAPI_OK)
- query->interface_found = true;
-
- return query->interface_found;
-}
-
-VAPI_RETVAL_CB(sw_interface_set_flags);
-
-static vapi_error_e
-bin_api_sw_interface_set_flags(uint32_t if_index, uint8_t up)
-{
- vapi_msg_sw_interface_set_flags *mp = vapi_alloc_sw_interface_set_flags (g_vapi_ctx_instance);
- assert(NULL != mp);
-
- mp->payload.sw_if_index = if_index;
- mp->payload.admin_up_down = up;
-
- vapi_error_e rv;
- VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx_instance, mp, sw_interface_set_flags_cb, NULL));
-
- return rv;
-}
-
-int interface_enable(const char *interface_name, const bool enable)
-{
- ARG_CHECK(-1, interface_name);
-
- int rc = 0;
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, interface_name);
-
- rc = get_interface_id(&query);
- if (!rc)
- return -1;
-
- rc = bin_api_sw_interface_set_flags(query.sw_interface_details.sw_if_index,
- enable);
- if (VAPI_OK != rc)
- return -1;
-
- return 0;
-}
diff --git a/src/scvpp/src/sc_vpp_interface.h b/src/scvpp/src/sc_vpp_interface.h
deleted file mode 100644
index 32b61bc..0000000
--- a/src/scvpp/src/sc_vpp_interface.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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 __BAPI_INTERFACE_H__
-#define __BAPI_INTERFACE_H__
-
-#include <vapi/interface.api.vapi.h>
-
-int interface_enable(const char *interface_name, const bool enable);
-
-//TODO remove the following structures ASAP
-typedef struct {
- bool interface_found;
- vapi_payload_sw_interface_details sw_interface_details;
-} sw_interface_details_query_t;
-
-typedef struct _vpp_interface_t
-{
- u32 sw_if_index;
- char interface_name[VPP_INTFC_NAME_LEN];
- u8 l2_address[VPP_MAC_ADDRESS_LEN];
- u32 l2_address_length;
- u64 link_speed;
- u16 link_mtu;
- u8 admin_up_down;
- u8 link_up_down;
-} vpp_interface_t;
-
-typedef struct _dump_all_ctx
-{
- int num_ifs;
- int capacity;
- vpp_interface_t * intfcArray;
-} dump_all_ctx;
-
-/* return the number of interfaces or a negative error code */
-extern int interface_dump_all(dump_all_ctx * dctx);
-
-extern void sw_interface_details_query_set_name(sw_interface_details_query_t * query,
- const char * interface_name);
-
-//input - sw_interface_details_query shall contain interface_name
-extern int get_interface_id(sw_interface_details_query_t * sw_interface_details_query);
-
-//input - sw_interface_details_query shall contain sw_if_index
-extern int get_interface_name(sw_interface_details_query_t * sw_interface_details_query);
-
-#endif /* __BAPI_INTERFACE_H__ */
diff --git a/src/scvpp/src/sc_vpp_ip.h b/src/scvpp/src/sc_vpp_ip.h
deleted file mode 100644
index a9f19d4..0000000
--- a/src/scvpp/src/sc_vpp_ip.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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 __BAPI_IP_H__
-#define __BAPI_IP_H__
-
-#include <vapi/interface.api.vapi.h>
-#include <vapi/ip.api.vapi.h>
-
-/* If no IP has been found ip_addr will be "0.0.0.0" */
-extern int ipv46_address_dump(const char *interface_name, char *ip_addr,
- u8 *prefix_len, bool is_ipv6);
-
-extern int ipv46_config_add_remove(const char *if_name, const char *addr,
- uint8_t prefix, bool is_ipv6, bool add);
-
-extern int
-ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
- const char* next_address, u8 is_add, u32 table_id,
- const char *interface);
-
-#endif /* __BAPI_IP_H__ */
diff --git a/src/scvpp/src/sc_vpp_v3po.h b/src/scvpp/src/sc_vpp_v3po.h
deleted file mode 100644
index 9c13569..0000000
--- a/src/scvpp/src/sc_vpp_v3po.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2016 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 _V3PO__INTERFACE_H__
-#define _V3PO__INTERFACE_H__
-
-#include <vapi/tapv2.api.vapi.h>
-
-typedef vapi_payload_tap_create_v2 tapv2_create_t;
-
-int create_tapv2(tapv2_create_t *query);
-int delete_tapv2(char *iface_name);
-
-#endif /* __V3PO_INTERFACE_H__ */
diff --git a/src/scvpp/src/sc_vpp_v3po.c b/src/scvpp/src/v3po.c
index d312331..f0a41c5 100644
--- a/src/scvpp/src/sc_vpp_v3po.c
+++ b/src/scvpp/src/v3po.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
* 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:
@@ -15,35 +17,18 @@
#include <assert.h>
-#include "sc_vpp_comm.h"
-#include "sc_vpp_v3po.h"
-#include "sc_vpp_interface.h"
+#include <scvpp/comm.h>
+#include <scvpp/v3po.h>
+#include <scvpp/interface.h>
+
+// Use VAPI macros to define symbols
+DEFINE_VAPI_MSG_IDS_L2_API_JSON;
+DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON
/*
* tap-v2 interfaces
*/
-DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON
-
-// Dump tapv2
-
-//typedef struct __attribute__ ((__packed__)) {
-// u32 sw_if_index;
-// u32 id;
-// u8 dev_name[64];
-// u16 tx_ring_sz;
-// u16 rx_ring_sz;
-// u8 host_mac_addr[6];
-// u8 host_if_name[64];
-// u8 host_namespace[64];
-// u8 host_bridge[64];
-// u8 host_ip4_addr[4];
-// u8 host_ip4_prefix_len;
-// u8 host_ip6_addr[16];
-// u8 host_ip6_prefix_len;
-// u32 tap_flags;
-//} vapi_payload_sw_interface_tap_v2_details;
-
// Delete tapv2
VAPI_RETVAL_CB(tap_delete_v2);
@@ -53,35 +38,33 @@ static vapi_error_e bin_api_delete_tapv2(u32 sw_if_index)
vapi_msg_tap_delete_v2 *mp;
vapi_error_e rv;
- mp = vapi_alloc_tap_delete_v2(g_vapi_ctx_instance);
+ mp = vapi_alloc_tap_delete_v2(g_vapi_ctx);
assert(NULL != mp);
mp->payload.sw_if_index = sw_if_index;
- VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx_instance, mp, tap_delete_v2_cb,
- NULL));
+ VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx, mp, tap_delete_v2_cb, NULL));
if (rv != VAPI_OK)
- return -EAGAIN;
+ return -rv;
- return rv;
+ return VAPI_OK;
}
int delete_tapv2(char *iface_name)
{
+ uint32_t sw_if_index;
+ vapi_error_e rv;
int rc;
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, iface_name);
+ rc = get_interface_id(iface_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
- rc = get_interface_id(&query);
- if (!rc)
- return -1;
+ rv = bin_api_delete_tapv2(sw_if_index);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- rc = bin_api_delete_tapv2(query.sw_interface_details.sw_if_index);
- if (VAPI_OK != rc)
- return -1;
-
- return 0;
+ return SCVPP_OK;
}
// Create tapv2
@@ -93,13 +76,12 @@ int create_tapv2(tapv2_create_t *query)
vapi_msg_tap_create_v2 *mp;
vapi_error_e rv;
- mp = vapi_alloc_tap_create_v2(g_vapi_ctx_instance);
+ mp = vapi_alloc_tap_create_v2(g_vapi_ctx);
assert(NULL != mp);
memcpy(&mp->payload, query, sizeof(tapv2_create_t));
- VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx_instance, mp, tap_create_v2_cb,
- NULL));
+ VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx, mp, tap_create_v2_cb, NULL));
if (rv != VAPI_OK)
return -EAGAIN;
diff --git a/src/scvpp/tests/CMakeLists.txt b/src/scvpp/tests/CMakeLists.txt
index 3153fe0..2b6de4a 100644
--- a/src/scvpp/tests/CMakeLists.txt
+++ b/src/scvpp/tests/CMakeLists.txt
@@ -18,24 +18,23 @@ include_directories ("${PROJECT_SOURCE_DIR}/src")
# check whether valgrind is installed
find_program(valgrind_FOUND valgrind)
-# macro for adding of an unit test
-macro(ADD_UNIT_TEST TEST_NAME)
- set(TEST_SRC
- ${TEST_NAME}.c
- scvpp_nat_test.c
- )
- add_executable(${TEST_NAME} ${TEST_SRC})
- target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARIES} scvpp_a)
- add_test(${TEST_NAME} ${TEST_NAME})
+set(TEST_SRC
+ scvpp_test.h
+ scvpp_test.c
+ scvpp_iface_test.c
+ scvpp_ip_test.c
+ scvpp_nat_test.c
+)
- if(valgrind_FOUND)
- add_test(${TEST_NAME}_valgrind valgrind
- --error-exitcode=1 --read-var-info=yes
- --leak-check=full --show-leak-kinds=all
- ./${TEST_NAME}
- )
- endif(valgrind_FOUND)
-endmacro(ADD_UNIT_TEST)
+add_executable(scvpp_test ${TEST_SRC})
+target_link_libraries(scvpp_test ${CMOCKA_LIBRARIES} scvpp_a)
+target_include_directories(scvpp_test PRIVATE ../inc)
+add_test(scvpp_test scvpp_test)
-# add individual unit-tests
-ADD_UNIT_TEST(scvpp_test)
+if(valgrind_FOUND)
+ add_test(${TEST_NAME}_valgrind valgrind
+ --error-exitcode=1 --read-var-info=yes
+ --leak-check=full --show-leak-kinds=all
+ ./${TEST_NAME}
+ )
+endif(valgrind_FOUND)
diff --git a/src/scvpp/tests/scvpp_iface_test.c b/src/scvpp/tests/scvpp_iface_test.c
new file mode 100644
index 0000000..6a96694
--- /dev/null
+++ b/src/scvpp/tests/scvpp_iface_test.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016 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 <unistd.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <cmocka.h>
+
+#include "scvpp_test.h"
+
+#include <scvpp/interface.h>
+#include <scvpp/v3po.h>
+
+static void test_enable_disable(void **state)
+{
+ UNUSED(state);
+ sw_interface_dump_t dump = {0};
+ int rc;
+
+ rc = interface_enable("tap0", 1);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = interface_dump_iface(&dump, "tap0");
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_int_equal(dump.admin_up_down, true);
+
+ rc = interface_enable("tap0", 0);
+ assert_int_equal(rc, SCVPP_OK);
+}
+
+static void test_create_tapv2(void **state)
+{
+ UNUSED(state);
+ tapv2_create_t query = {0};
+ sw_interface_dump_t dump = {0};
+ int rc;
+
+ query.id = 1;
+ query.use_random_mac = 1;
+
+ rc = create_tapv2(&query);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = interface_dump_iface(&dump, "tap1");
+ assert_int_equal(rc, SCVPP_OK);
+}
+
+static int teardown_tapv2(void **state)
+{
+ UNUSED(state);
+ return delete_tapv2("tap1");
+}
+
+static void test_dump_iface_all(void **state)
+{
+ UNUSED(state);
+ struct elt *stack = NULL;
+ sw_interface_dump_t *dump;
+ bool exist = false;
+
+ stack = interface_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (sw_interface_dump_t *) data;
+ if (!strncmp((char*) dump->interface_name, "tap0", VPP_INTFC_NAME_LEN))
+ exist = true;
+ free(dump);
+ }
+ assert_true(exist);
+}
+
+static void test_dump_iface_exist(void **state)
+{
+ UNUSED(state);
+ vapi_payload_sw_interface_details details = {0};
+ int rc;
+
+ rc = interface_dump_iface(&details, "local0");
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_string_equal(details.interface_name, "local0");
+}
+
+static void test_dump_iface_unexist(void **state)
+{
+ UNUSED(state);
+ vapi_payload_sw_interface_details details = {0};
+ int rc;
+
+ rc = interface_dump_iface(&details, "unexisting");
+ assert_int_equal(rc, -SCVPP_NOT_FOUND);
+}
+
+static void test_get_interface_name(void **state)
+{
+ UNUSED(state);
+ char interface_name[VPP_INTFC_NAME_LEN];
+ uint32_t tap0_if_index;
+ int rc;
+
+ rc = get_interface_id("tap0", &tap0_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = get_interface_name(interface_name, tap0_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_string_equal(interface_name, "tap0");
+}
+
+const struct CMUnitTest iface_tests[IFACE_TEST_SIZE] = {
+ cmocka_unit_test_teardown(test_create_tapv2, teardown_tapv2),
+ cmocka_unit_test(test_enable_disable),
+ cmocka_unit_test(test_dump_iface_all),
+ cmocka_unit_test(test_dump_iface_exist),
+ cmocka_unit_test(test_dump_iface_unexist),
+ cmocka_unit_test(test_get_interface_name),
+};
diff --git a/src/scvpp/tests/scvpp_ip_test.c b/src/scvpp/tests/scvpp_ip_test.c
new file mode 100644
index 0000000..5e28123
--- /dev/null
+++ b/src/scvpp/tests/scvpp_ip_test.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2019 Cisco
+ *
+ * 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 <unistd.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <cmocka.h>
+
+#include "scvpp_test.h"
+
+#include <scvpp/ip.h>
+#include <scvpp/interface.h>
+#include <scvpp/comm.h>
+
+static void test_add_remove_ipv4(void **state)
+{
+ UNUSED(state);
+ const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
+ char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
+ u8 prefix_q = 24;
+ u8 prefix_r;
+ int rc;
+
+ //add ipv4 on tap0
+ rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //dump ipv4 on tap0 and check if it mach
+ rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
+ assert_int_equal(rc, SCVPP_OK);
+ assert_string_equal(ip_q, ip_r);
+ assert_int_equal(prefix_q, prefix_r);
+
+ //remove ipv4 on tap0
+ rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //dump ipv4 after removal and check if equals 0.0.0.0
+ rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
+ assert_int_equal(rc, SCVPP_OK);
+ assert_string_equal(ip_r, "0.0.0.0");
+}
+
+static void test_ipv4_add_del_route_no_iface(void **state)
+{
+ UNUSED(state);
+ int rc;
+ char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0";
+ uint8_t prefix_len = 24;
+ char next_hop[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.100";
+ uint32_t table_id = 0;
+ fib_dump_t *dump;
+ struct elt *stack;
+ bool route_found = false;
+
+ /* Must fail, can not have both interface and next hop IP null */
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true,
+ table_id, NULL);
+ assert_int_equal(rc, -SCVPP_EINVAL);
+
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, true,
+ table_id, NULL);
+ assert_int_equal(rc, SCVPP_OK);
+
+ /* Dump all FIB routes and check if we find ours */
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ assert_int_equal(dump->table_id, table_id);
+ assert_int_equal(dump->count, 1);
+ assert_string_equal(sc_ntoa(dump->path[0].next_hop), next_hop);
+ }
+ free(dump);
+ }
+ assert_true(route_found);
+
+ /* Delete previously set route */
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, false,
+ table_id, NULL);
+ assert_int_equal(rc, SCVPP_OK);
+
+ /* Check our route has been deleted */
+ route_found = false;
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ }
+ free(dump);
+ }
+ assert_false(route_found);
+}
+
+static void test_ipv4_add_del_route_no_next_hop_ip(void **state)
+{
+ UNUSED(state);
+ int rc;
+ char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0";
+ uint8_t prefix_len = 24;
+ char interface[VPP_IP4_ADDRESS_STRING_LEN] = "tap0";
+ uint32_t table_id = 0;
+ uint32_t sw_if_index;
+ fib_dump_t *dump;
+ struct elt *stack;
+ bool route_found = false;
+
+ //Add a new route
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true,
+ table_id, interface);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //Dump all FIB routes and check we find ours
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+
+ rc = get_interface_id(interface, &sw_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ assert_int_equal(dump->table_id, table_id);
+ assert_int_equal(dump->count, 1);
+ assert_int_equal(dump->path[0].sw_if_index, sw_if_index);
+ }
+ free(dump);
+ }
+ assert_true(route_found);
+
+ //Delete route
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, false,
+ table_id, interface);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //Check our route has been deleted
+ route_found = false;
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ }
+ free(dump);
+ }
+ assert_false(route_found);
+}
+
+
+const struct CMUnitTest ip_tests[IP_TEST_SIZE] = {
+ cmocka_unit_test(test_add_remove_ipv4),
+ cmocka_unit_test(test_ipv4_add_del_route_no_next_hop_ip),
+ cmocka_unit_test(test_ipv4_add_del_route_no_iface),
+};
diff --git a/src/scvpp/tests/scvpp_nat_test.c b/src/scvpp/tests/scvpp_nat_test.c
index fae9615..044102e 100644
--- a/src/scvpp/tests/scvpp_nat_test.c
+++ b/src/scvpp/tests/scvpp_nat_test.c
@@ -20,36 +20,37 @@
#include <setjmp.h>
#include <cmocka.h>
-#include "scvpp_nat_test.h"
-#include "sc_vpp_comm.h"
-#include "sc_vpp_nat.h"
+#include "scvpp_test.h"
-void test_nat44_static_mapping(__attribute__((unused)) void **state)
+#include <scvpp/comm.h>
+#include <scvpp/nat.h>
+
+
+void test_nat44_static_mapping(void **state)
{
+ UNUSED(state);
nat44_add_del_static_mapping_t map = {0};
nat44_static_mapping_details_t dump = {0};
u8 empty_ip[4] = {0};
+ int rc;
/*Configure the static mapping
Alternative to this CLI command:
nat44 add static mapping local 172.168.0.1 external 172.168.8.5
*/
-
sc_aton("172.168.0.1", map.local_ip_address,
sizeof(map.local_ip_address));
-
sc_aton("172.168.8.5", map.external_ip_address,
sizeof(map.external_ip_address));
-
map.addr_only = 1;
-
map.external_sw_if_index = ~0;
-
map.is_add = 1;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, map.addr_only);
@@ -62,11 +63,13 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state)
/* Remove previous config*/
map.is_add = 0;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
memset(&dump, 0, sizeof(dump));
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, 0);
@@ -77,14 +80,16 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state)
sizeof(dump.external_ip_address));
}
-void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
+void test_nat44_static_mapping_with_ports(void **state)
{
+ UNUSED(state);
nat44_add_del_static_mapping_t map = {0};
nat44_static_mapping_details_t dump = {0};
nat44_add_del_address_range_t range = {0};
u8 empty_ip[4] = {0};
const u16 lport = 77;
const u16 eport = 88;
+ int rc;
/*Configure address pool
Alternative to this CLI:
@@ -98,7 +103,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
range.is_add = 1;
- nat44_add_del_addr_range(&range);
+ rc = nat44_add_del_addr_range(&range);
+ assert_int_equal(rc, SCVPP_OK);
/*Configure NAT with ports
Alternative to this CLI:
@@ -122,9 +128,11 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
map.is_add = 1;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, map.addr_only);
@@ -142,11 +150,13 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
map.is_add = 0;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
memset(&dump, 0, sizeof(dump));
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, 0);
@@ -162,7 +172,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
range.is_add = 0;
- nat44_add_del_addr_range(&range);
+ rc = nat44_add_del_addr_range(&range);
+ assert_int_equal(rc, SCVPP_OK);
}
const struct CMUnitTest nat_tests[] = {
diff --git a/src/scvpp/tests/scvpp_test.c b/src/scvpp/tests/scvpp_test.c
index cc23e43..f6e99a0 100644
--- a/src/scvpp/tests/scvpp_test.c
+++ b/src/scvpp/tests/scvpp_test.c
@@ -14,89 +14,19 @@
*/
#include <stdlib.h>
-#include <stdio.h>
#include <unistd.h>
+#include <stdio.h>
#include <setjmp.h>
-#include <cmocka.h>
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
-#include "sc_vpp_v3po.h"
-#include "scvpp_nat_test.h"
-
-//TODO Check with future function get_interface_state
-static void test_enable_disable(void **state)
-{
- int rc;
-
- rc = interface_enable("tap0", 1);
- assert_int_equal(rc, 0);
-
- rc = interface_enable("tap0", 0);
- assert_int_equal(rc, 0);
-}
-
-//TODO would need to make sure tap0 is index 1
-//TODO delete eventually because get_interface_id will not be extern
-static void test_name2index(void **state)
-{
- int rc;
- const char iface_name[] = "tap0";
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, iface_name);
-
- rc = get_interface_id(&query);
- assert_int_equal(rc, 1);
-
- assert_string_equal(iface_name, query.sw_interface_details.interface_name);
- assert_int_equal(query.sw_interface_details.sw_if_index, 1);
-}
-
-static void test_add_ipv4(void **state)
-{
- const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
- char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
- u8 prefix_q = 24;
- u8 prefix_r;
- int rc;
-
- //add ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
- assert_int_equal(rc, 0);
-
- rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
- assert_int_equal(rc, 0);
-
- assert_string_equal(ip_q, ip_r);
- assert_int_equal(prefix_q, prefix_r);
-}
-
-static void test_remove_ipv4(void **state)
-{
- const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
- char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
- u8 prefix_q = 24;
- u8 prefix_r;
- int rc;
-
- //add ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
- assert_int_equal(rc, 0);
- //remove ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false);
- assert_int_equal(rc, 0);
-
- //dump ipv4
- rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
- assert_int_equal(rc, 0);
+#include <scvpp/comm.h>
+#include <scvpp/v3po.h>
- assert_string_equal(ip_r, "0.0.0.0");
-}
+#include "scvpp_test.h"
+/* test "AAA.BBB.CCC.DDD" -> {A, B, C, D} */
static void test_sc_ntoa(void **state)
{
+ UNUSED(state);
u8 buf[4] = {192, 168, 100, 44};
char *res;
@@ -104,52 +34,76 @@ static void test_sc_ntoa(void **state)
assert_string_equal(res, "192.168.100.44");
}
-static void test_create_tapv2(void **state)
+/* test {A, B, C, D} -> "AAA.BBB.CCC.DDD" */
+static void test_sc_aton(void **state)
{
- tapv2_create_t query = {0};
+ UNUSED(state);
+ char ip[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.44";
+ uint8_t buf[4];
int rc;
- query.id = 1;
- query.use_random_mac = 1;
-
- rc = create_tapv2(&query);
+ rc = sc_aton(ip, buf, VPP_IP4_ADDRESS_LEN);
assert_int_equal(rc, 0);
- //TODO dump_tav2 and compare values
-
- rc = delete_tapv2("tap1");
- assert_int_equal(rc, 0);
+ assert_int_equal(buf[0], 192);
+ assert_int_equal(buf[1], 168);
+ assert_int_equal(buf[2], 100);
+ assert_int_equal(buf[3], 44);
}
-int main()
+static int setup(void **state)
{
+ UNUSED(state);
tapv2_create_t query = {0};
- const struct CMUnitTest tests[] = {
- cmocka_unit_test_setup_teardown(test_enable_disable, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_name2index, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_add_ipv4, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_remove_ipv4, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_sc_ntoa, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_create_tapv2, NULL, NULL),
- };
- if (sc_connect_vpp() != 0)
+ if (sc_connect_vpp() != 0) {
fprintf(stderr, "Error connecting to VPP\n");
+ return -1;
+ }
/* Create interface tap0 to test several functions */
query.id = 0;
query.use_random_mac = 1;
- if (create_tapv2(&query) != 0)
+ if (create_tapv2(&query) != 0) {
fprintf(stderr, "Error creating tap0\n");
+ return -1;
+ }
- cmocka_run_group_tests(tests, NULL, NULL);
-
- print_message("\nNAT Tests\n");
- cmocka_run_group_tests(nat_tests, NULL, NULL);
+ return 0;
+}
+static int teardown(void **state)
+{
+ UNUSED(state);
/* Delete tap0 */
- if (delete_tapv2("tap0") != 0)
+ if (delete_tapv2("tap0") != 0) {
fprintf(stderr, "Failed deleting tap0\n");
+ return -1;
+ }
+
+ sc_disconnect_vpp();
+
+ return 0;
+}
+
+/* return code for scvpp-test binary is the number of failed test */
+int main()
+{
+ int rc = 0;
+
+ const struct CMUnitTest common_tests[] = {
+ cmocka_unit_test(test_sc_ntoa),
+ cmocka_unit_test(test_sc_aton),
+ };
+
+ print_message("Common tests\n");
+ rc |= cmocka_run_group_tests(common_tests, NULL, NULL);
+ print_message("Interface tests\n");
+ rc |= cmocka_run_group_tests(iface_tests, setup, teardown);
+ print_message("IP tests\n");
+ rc |= cmocka_run_group_tests(ip_tests, setup, teardown);
+ print_message("NAT tests\n");
+ rc |= cmocka_run_group_tests(nat_tests, setup, teardown);
- return sc_disconnect_vpp();
+ return rc;
}
diff --git a/src/scvpp/tests/scvpp_nat_test.h b/src/scvpp/tests/scvpp_test.h
index 8a22f87..28bd514 100644
--- a/src/scvpp/tests/scvpp_nat_test.h
+++ b/src/scvpp/tests/scvpp_test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 PANTHEON.tech.
+ * Copyright (c) 2019 Cisco
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,18 @@
* limitations under the License.
*/
-/* inclusion guard */
-#ifndef __SCVPP_NAT_TEST_H__
-#define __SCVPP_NAT_TEST_H__
+#ifndef __SCVPP_TEST_H
+#define __SCVPP_TEST_H__
+
+#include <cmocka.h>
+
+#define IFACE_TEST_SIZE 6
+extern const struct CMUnitTest iface_tests[IFACE_TEST_SIZE];
+
+#define IP_TEST_SIZE 3
+extern const struct CMUnitTest ip_tests[IP_TEST_SIZE];
#define NAT_TEST_SIZE 2
extern const struct CMUnitTest nat_tests[NAT_TEST_SIZE];
-#endif /* __SCVPP_NAT_TEST_H__ */
+#endif /* __SCVPP_TEST_H__ */