From 3e949f72778dd076fffecd7da2fb83cbb1ccb428 Mon Sep 17 00:00:00 2001 From: Alberto Compagno Date: Tue, 19 Nov 2019 17:57:20 +0000 Subject: [HICN-398] Added face create/delete/list and listener list on libctrl for hicn-plugin Listener list returns the list of interfaces and their ip addresses Signed-off-by: Alberto Compagno Change-Id: I2582cf29d4f1f60964766d47ad8d6dc64504fd62 --- ctrl/libhicnctrl/CMakeLists.txt | 1 + ctrl/libhicnctrl/includes/hicn/ctrl/api.h | 8 +- ctrl/libhicnctrl/includes/hicn/ctrl/face.h | 4 +- ctrl/libhicnctrl/src/CMakeLists.txt | 1 + ctrl/libhicnctrl/src/api.c | 10 +- ctrl/libhicnctrl/src/cli.c | 6 +- ctrl/libhicnctrl/src/face.c | 2 +- ctrl/libhicnctrl/src/hicn_plugin_api.c | 565 ++++++++++++++++++++++++++--- ctrl/libhicnctrl/src/util/hash.h | 3 +- 9 files changed, 529 insertions(+), 71 deletions(-) (limited to 'ctrl') diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt index 43d120473..59620088e 100644 --- a/ctrl/libhicnctrl/CMakeLists.txt +++ b/ctrl/libhicnctrl/CMakeLists.txt @@ -58,6 +58,7 @@ else() ${HICNPLUGIN_INCLUDE_DIRS}) set(HICN_LIBRARIES ${HICNPLUGIN_LIBRARIES}) + set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs") list(APPEND DEPENDENCIES hicn_plugin diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h index eba80bdb3..068b3eb08 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h @@ -139,7 +139,7 @@ typedef struct hc_data_s { * 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); +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. @@ -382,7 +382,11 @@ int hc_sock_reset(hc_sock_t *s); #define NULLTERM 1 #endif -#define INTERFACE_LEN IFNAMSIZ +#ifdef HICN_VPP_PLUGIN + #define INTERFACE_LEN 64 +#else + #define INTERFACE_LEN IFNAMSIZ +#endif #define MAXSZ_HC_NAME_ SYMBOLIC_NAME_LEN #define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h index f0a8045de..12bf3afa6 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h @@ -34,7 +34,7 @@ #include -typedef unsigned int hash_t; +//typedef unsigned int hash_t; //incompatible with vpp /* Netdevice type */ @@ -192,7 +192,7 @@ 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); -hash_t face_hash(const face_t * face); +unsigned int face_hash(const face_t * face); size_t face_snprintf(char * s, size_t size, const face_t * face); diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt index 14c204dda..42fe3d543 100644 --- a/ctrl/libhicnctrl/src/CMakeLists.txt +++ b/ctrl/libhicnctrl/src/CMakeLists.txt @@ -87,5 +87,6 @@ if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android" AND NOT COMPILE_FOR_IOS) COMPONENT ${LIBHICNCTRL_COMPONENT} INCLUDE_DIRS ${INCLUDE_DIRS} DEFINITIONS ${COMPILER_DEFINITIONS} + LINK_FLAGS ${LINK_FLAGS} ) endif () diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c index ea4ed69c2..f7efd6b44 100644 --- a/ctrl/libhicnctrl/src/api.c +++ b/ctrl/libhicnctrl/src/api.c @@ -303,7 +303,7 @@ typedef struct hc_msg_s { ******************************************************************************/ hc_data_t * -hc_data_create(size_t in_element_size, size_t out_element_size) +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) @@ -317,7 +317,7 @@ hc_data_create(size_t in_element_size, size_t out_element_size) 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 = NULL; + data->complete_cb = complete_cb; data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); if (!data->buffer) @@ -851,7 +851,7 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len, //hc_sock_reset(s); /* XXX data will at least store the result (complete) */ - hc_data_t * data = hc_data_create(params->size_in, params->size_out); + 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; @@ -2398,7 +2398,7 @@ hc_face_list(hc_sock_t * s, hc_data_t ** pdata) return -1; } - hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t)); + 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."); @@ -2795,7 +2795,7 @@ hc_strategy_list(hc_sock_t * s, hc_data_t ** data) { int rc; - *data = hc_data_create(0, sizeof(hc_strategy_t)); + *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); diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c index 879454c3a..fc81139d6 100644 --- a/ctrl/libhicnctrl/src/cli.c +++ b/ctrl/libhicnctrl/src/cli.c @@ -401,7 +401,8 @@ parse_options(int argc, char *argv[], hc_command_t * command) goto ERR_PARAM; command->face.face.remote_port = atoi(argv[optind++]); if (argc != optind) { - netdevice_set_name(&command->face.face.netdevice, argv[optind++]); + //netdevice_set_name(&command->face.face.netdevice, argv[optind++]); + command->face.face.netdevice.index = atoi(argv[optind++]); } break; @@ -439,7 +440,8 @@ parse_options(int argc, char *argv[], hc_command_t * command) 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++]); + //netdevice_set_name(&command->face.face.netdevice, argv[optind++]); } } break; diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c index 0e25890da..e617ff8a4 100644 --- a/ctrl/libhicnctrl/src/face.c +++ b/ctrl/libhicnctrl/src/face.c @@ -356,7 +356,7 @@ face_cmp(const face_t * f1, const face_t * f2) return 0; } -hash_t +unsigned int face_hash(const face_t * face) { /* Assuming the unused part of the struct is set to zero */ diff --git a/ctrl/libhicnctrl/src/hicn_plugin_api.c b/ctrl/libhicnctrl/src/hicn_plugin_api.c index 7dbd88771..7d2a4b4b4 100644 --- a/ctrl/libhicnctrl/src/hicn_plugin_api.c +++ b/ctrl/libhicnctrl/src/hicn_plugin_api.c @@ -32,19 +32,30 @@ #include #include #include +#include +#include #include #include +#include +#include #define APP_NAME "hicn_plugin" #define MAX_OUTSTANDING_REQUESTS 4 #define RESPONSE_QUEUE_SIZE 2 +// #define vl_typedefs +// #include +// #undef vl_typedefs + DEFINE_VAPI_MSG_IDS_HICN_API_JSON +DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON +DEFINE_VAPI_MSG_IDS_IP_API_JSON /* * Internal state associated to a pending request */ typedef struct { + vapi_ctx_t g_vapi_ctx_instance; int seq; // Reusing the buffer of data to hold both the unparsed response from the // forwarder and the result of the parsing @@ -104,13 +115,14 @@ void hc_sock_request_free(hc_sock_request_t *request) { free(request); } _(hicn_api_node_params_set_reply) \ _(hicn_api_node_params_get_reply) \ _(hicn_api_node_stats_get_reply) \ - _(hicn_api_face_ip_add) \ - _(hicn_api_face_ip_add_reply) \ - _(hicn_api_face_ip_del) \ - _(hicn_api_face_ip_del_reply) \ - _(hicn_api_face_ip_params_get) \ + _(hicn_api_face_add) \ + _(hicn_api_face_add_reply) \ + _(hicn_api_face_del) \ + _(hicn_api_face_del_reply) \ + _(hicn_api_face_get) \ + _(hicn_api_faces_details) \ _(hicn_api_face_stats_details) \ - _(hicn_api_face_ip_params_get_reply) \ + _(hicn_api_face_get_reply) \ _(hicn_api_route_nhops_add) \ _(hicn_api_route_nhops_add_reply) \ _(hicn_api_route_del) \ @@ -136,7 +148,10 @@ typedef union { #undef _ } hc_msg_payload_t; -#define IS_DUMP_MSG(a) (a == vapi_msg_id_hicn_api_face_stats_dump || a == vapi_msg_id_hicn_api_routes_dump) +#define IS_DUMP_MSG(a) (a == vapi_msg_id_hicn_api_face_stats_dump || \ + a == vapi_msg_id_hicn_api_routes_dump || \ + a == vapi_msg_id_hicn_api_faces_dump || \ + a == vapi_msg_id_sw_interface_dump) typedef struct __attribute__ ((__packed__)) { hc_msg_header_t hdr; @@ -161,7 +176,7 @@ typedef struct __attribute__((__packed__)) { * Control Data ******************************************************************************/ -hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size) { +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; @@ -173,7 +188,7 @@ hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size) { 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 = NULL; + data->complete_cb = complete_cb; return data; @@ -210,6 +225,9 @@ hc_sock_t *hc_sock_create_url(const char *url) { hc_sock_t *hc_sock_create(void) { hc_sock_t *s = malloc(sizeof(hc_sock_t)); + + if (!s) goto ERR_SOCK; + memset(s, 0, sizeof(hc_sock_t)); s->map = hc_sock_map_create(); @@ -222,6 +240,7 @@ hc_sock_t *hc_sock_create(void) { ERR_MAP: free(s); +ERR_SOCK: return NULL; } @@ -258,10 +277,12 @@ int hc_sock_get_fd(hc_sock_t *s) { return 1; } vapi_error_e vapi_cb(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e error, bool is_last, void *payload) { callback_ctx_t *ctx_call = (callback_ctx_t *)callback_ctx; hc_sock_t *s = ctx_call->s; + int ret = VAPI_OK; if ((s->woff != s->roff) && (s->woff % RECV_BUFLEN == 0)) { ERROR("[hc_sock_process] No more space on the buffer to store responces"); - return -1; + ret = VAPI_ENOMEM; + goto END; } if (is_last) { @@ -269,14 +290,17 @@ vapi_error_e vapi_cb(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e error, boo s->woff++; } - if(!payload) - return 0; + if(!payload) { + ret = VAPI_ENOMEM; + goto END; + } hc_sock_request_t *request = NULL; if (hc_sock_map_get(s->map, ctx_call->ctx_msg, &request) < 0) { ERROR("[hc_sock_process] Error searching for matching request"); - return -1; + ret = VAPI_ENOMEM; + goto END; } if (request->data->current == request->data->size) { @@ -284,20 +308,27 @@ vapi_error_e vapi_cb(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e error, boo request->data->size = 1; request->data->buffer = malloc(request->data->in_element_size * request->data->size); } else { - void *tmp = - malloc(request->data->in_element_size * request->data->size * 2); - memcpy(tmp, request->data->buffer, request->data->current * request->data->in_element_size); - free(request->data->buffer); - request->data->size *= 2; - request->data->buffer = tmp; + request->data->buffer = realloc(request->data->buffer, request->data->in_element_size * request->data->size * 2); + request->data->size *=2; } } + + if (!request->data->buffer) { + request->data->size = 0; + ret = VAPI_ENOMEM; + goto END; + } + memcpy(request->data->buffer + request->data->current * request->data->in_element_size, payload, request->data->in_element_size); request->data->current++; - return 0; +END: + if (is_last) + free(callback_ctx); + + return ret; } int hc_sock_connect(hc_sock_t *s) { @@ -349,7 +380,7 @@ int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) { vapi_store_request(s->g_vapi_ctx_instance, seq, false, (vapi_cb_t)callback, callback_ctx); } } - + if (rv != VAPI_OK) { if (VAPI_OK != vapi_producer_unlock (s->g_vapi_ctx_instance)) { abort (); /* this really shouldn't happen */ @@ -396,8 +427,11 @@ int hc_sock_process(hc_sock_t *s, hc_data_t **pdata) { return -1; } - err = request->parse((u8 *)request, NULL); + if(request->parse != NULL) + err = request->parse((u8 *)request, NULL); request->data->complete = 1; + if (!err && request->data->complete_cb != NULL) + err = request->data->complete_cb(request->data, s); s->roff++; if (pdata) *pdata = request->data; @@ -465,6 +499,7 @@ typedef struct { size_t size_in; size_t size_out; HC_PARSE parse; + data_callback_t complete_cb; } hc_command_params_t; int hc_execute_command(hc_sock_t *s, hc_msg_t *msg, size_t msg_len, @@ -476,7 +511,7 @@ int hc_execute_command(hc_sock_t *s, hc_msg_t *msg, size_t msg_len, switch (params->cmd) { case ACTION_CREATE: assert(params->size_in != 0); /* payload repeated */ - assert(params->size_out == 0); + //assert(params->size_out == 0); //Face will return the face id //assert(params->parse == NULL); break; case ACTION_DELETE: @@ -499,7 +534,7 @@ int hc_execute_command(hc_sock_t *s, hc_msg_t *msg, size_t msg_len, } /* XXX data will at least store the result (complete) */ - hc_data_t *data = hc_data_create(params->size_in, params->size_out); + hc_data_t *data = hc_data_create(params->size_in, params->size_out, params->complete_cb); if (!data) { ERROR("[hc_execute_command] Could not create data storage"); goto ERR_DATA; @@ -578,7 +613,6 @@ int hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) { } /* LISTENER GET */ - int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_listener_t **listener_found) { // NOT IMPLEMENTED @@ -597,10 +631,137 @@ int hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) { return -1; } +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; +} + +/* A listener in vpp is an interface with classify enabled */ +int listener_list_complete_cb(struct hc_data_s * data, void *ctx) { + // No need to write anything on the dst, no data expected + + hc_sock_t *s = (hc_sock_t *)ctx; + + int n_interfaces = data->current; + u32 *swifs = malloc(sizeof(u32) * n_interfaces); + int retval = VAPI_OK; + + if (!swifs) { + retval = VAPI_ENOMEM; + goto END; + } + + for (int i = 0; i < n_interfaces; i++) { + vapi_payload_sw_interface_details *reply = + (vapi_payload_sw_interface_details *)(data->buffer + i * data->in_element_size); + swifs[i] = reply->sw_if_index; + } + + vapi_payload_sw_interface_details * temp = (vapi_payload_sw_interface_details *)data->buffer; + data->buffer = malloc(sizeof(hc_listener_t)); + data->size = 1; + data->current = 0; + + if (!data->buffer) { + data->current = 0; + retval = VAPI_ENOMEM; + goto CLEAN; + } + + /* Query the forwarder for each interface */ + for(int i = 0; i < n_interfaces; i++) { + size_t index = data->current; + vapi_msg_ip_address_dump* msg = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); + msg->payload.sw_if_index = swifs[i]; + msg->payload.is_ipv6 = 0; + vapi_payload_sw_interface_details *reply = + &(temp[i]); + int retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info, data); + 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 = swifs[i]; + msg2->payload.is_ipv6 = 1; + retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, data); + for (size_t j = index; j < data->current; j++) { + memcpy(((hc_listener_t *)(data->buffer))[j].interface_name, reply->interface_name, INTERFACE_LEN); + } + + if (retval) goto CLEAN; + } + +CLEAN: + free(swifs); + free(temp); + +END: + data->size = data->current; + data->out_element_size = sizeof(hc_listener_t); + return retval; +} + /* LISTENER LIST */ int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; + hc_msg_s msg; + vapi_msg_sw_interface_dump *hicnp_msg; + hicnp_msg = vapi_alloc_sw_interface_dump(s->g_vapi_ctx_instance); + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_sw_interface_dump_hton; + + if (!(msg.callback_ctx)) return VAPI_ENOMEM; + + hicnp_msg->payload.sw_if_index = ~0; + hicnp_msg->payload.name_filter_valid = 0; + + //hicnp_msg->payload.type = 1; //0 v4, 1 v6 + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = LIST_LISTENERS, + .size_in = sizeof(vapi_msg_sw_interface_details), + .size_out = sizeof(hc_listener_t), + .parse = (HC_PARSE)NULL, + .complete_cb = listener_list_complete_cb, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, pdata, + false); } int hc_listener_list_async(hc_sock_t *s, hc_data_t **pdata) { @@ -634,9 +795,19 @@ GENERATE_FIND(listener) /* LISTENER SNPRINTF */ /* /!\ Please update constants in header file upon changes */ -int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; +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", listener->interface_name, local); } /*----------------------------------------------------------------------------* @@ -759,14 +930,20 @@ int parse_route_create(uint8_t *src, uint8_t *dst) { int _hc_route_create(hc_sock_t *s, hc_route_t *route, bool async) { if (!IS_VALID_FAMILY(route->family)) return -1; - hc_msg_s *msg = malloc(sizeof(hc_msg_s)); + hc_msg_s msg; + vapi_msg_hicn_api_route_nhops_add *hicnp_msg; hicnp_msg = vapi_alloc_hicn_api_route_nhops_add(s->g_vapi_ctx_instance); - msg->hicnp_msg = (hc_hicnp_t *)hicnp_msg; - msg->callback = &vapi_cb; - msg->callback_ctx = malloc(sizeof(callback_ctx_t)); - msg->callback_ctx->s = s; - msg->ntoh = (NTOH)&vapi_msg_hicn_api_route_nhops_add_hton; + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_route_nhops_add_hton; + + if (!(msg.callback_ctx)) return VAPI_ENOMEM; if (route->family == AF_INET) { memcpy(&hicnp_msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); @@ -789,7 +966,7 @@ int _hc_route_create(hc_sock_t *s, hc_route_t *route, bool async) { .parse = (HC_PARSE)parse_route_create, }; - return hc_execute_command(s, (hc_msg_t *)msg, sizeof(msg), ¶ms, NULL, + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, async); } @@ -818,14 +995,20 @@ int parse_route_delete(uint8_t *src, uint8_t *dst) { int _hc_route_delete(hc_sock_t *s, hc_route_t *route, bool async) { if (!IS_VALID_FAMILY(route->family)) return -1; - hc_msg_s *msg = malloc(sizeof(hc_msg_s)); + hc_msg_s msg; + vapi_msg_hicn_api_route_nhop_del *hicnp_msg; hicnp_msg = vapi_alloc_hicn_api_route_nhop_del(s->g_vapi_ctx_instance); - msg->hicnp_msg = (hc_hicnp_t *)hicnp_msg; - msg->callback = &vapi_cb; - msg->callback_ctx = malloc(sizeof(callback_ctx_t)); - msg->callback_ctx->s = s; - msg->ntoh = (NTOH)&vapi_msg_hicn_api_route_nhop_del_hton; + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_route_nhop_del_hton; + + if (!(msg.callback_ctx)) return VAPI_ENOMEM; memcpy(&hicnp_msg->payload.prefix.address.un.ip6[0], &route->remote_addr, 16); hicnp_msg->payload.prefix.address.af = @@ -842,7 +1025,7 @@ int _hc_route_delete(hc_sock_t *s, hc_route_t *route, bool async) { .parse = (HC_PARSE)parse_route_delete, }; - return hc_execute_command(s, (hc_msg_t *)msg, sizeof(msg), ¶ms, NULL, + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, async); } @@ -869,6 +1052,14 @@ int parse_route_list(uint8_t *src, uint8_t *dst) { } hc_route_t *output = malloc(sizeof(hc_route_t) * size); + int res = VAPI_OK; + + if (!output) { + size = 0; + res = VAPI_ENOMEM; + goto END; + } + int cur = 0; for (int j = 0; j < request->data->current; j++) { vapi_payload_hicn_api_routes_details *reply = @@ -891,22 +1082,29 @@ int parse_route_list(uint8_t *src, uint8_t *dst) { } } +END: free(request->data->buffer); request->data->buffer = (void *)output; request->data->size = size; request->data->out_element_size = sizeof(hc_route_t); - return 0; + return res; } int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) { - hc_msg_s *msg = malloc(sizeof(hc_msg_s)); + hc_msg_s msg; + vapi_msg_hicn_api_routes_dump *hicnp_msg; hicnp_msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance); - msg->hicnp_msg = (hc_hicnp_t *)hicnp_msg; - msg->callback = &vapi_cb; - msg->callback_ctx = malloc(sizeof(callback_ctx_t)); - msg->callback_ctx->s = s; - msg->ntoh = (NTOH)&vapi_msg_hicn_api_routes_dump_hton; + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_routes_dump_hton; + + if (!(msg.callback_ctx)) return VAPI_ENOMEM; hc_command_params_t params = { .cmd = ACTION_LIST, @@ -916,7 +1114,7 @@ int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) { .parse = (HC_PARSE)parse_route_list, }; - return hc_execute_command(s, (hc_msg_t *)msg, sizeof(msg), ¶ms, pdata, + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, pdata, async); } @@ -1003,24 +1201,275 @@ int hc_connection_to_local_listener(const hc_connection_t *connection, } /* FACE CREATE */ +int parse_face_create(uint8_t *src, uint8_t *dst) { + // No need to write anything on the dst, no data expected + + hc_sock_request_t *request = (hc_sock_request_t *)src; + vapi_payload_hicn_api_face_add_reply *reply = + (vapi_payload_hicn_api_face_add_reply *)request->data->buffer; -int hc_face_create(hc_sock_t *s, hc_face_t *face) { return 0; } + hc_face_t *output = malloc(sizeof(hc_face_t)); -int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found) { - return 0; + int retval = VAPI_OK; + int size = 1; + + if (!output) { + size = 0; + retval = VAPI_ENOMEM; + goto END; + } + + output->id = reply->faceid; + retval = reply->retval; + +END: + free(request->data->buffer); + request->data->buffer = (void *)output; + request->data->size = size; + request->data->out_element_size = sizeof(hc_face_t); + return retval; +} + +int hc_face_create(hc_sock_t *s, hc_face_t *face) { + hc_msg_s msg; + + vapi_msg_hicn_api_face_add *hicnp_msg; + hicnp_msg = vapi_alloc_hicn_api_face_add(s->g_vapi_ctx_instance); + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_face_add_hton; + + if (!msg.callback_ctx) return VAPI_ENOMEM; + + switch(face->face.type) { + case FACE_TYPE_HICN: + { + u8 check = ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)) == ip46_address_is_ip4((ip46_address_t *)&(face->face.remote_addr)); + if (!check) + return -1; + + hicnp_msg->payload.type = IP_FACE; + if (ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr))) + { + memcpy(hicnp_msg->payload.face.ip.local_addr.un.ip4, face->face.local_addr.v4.as_u8, 4); + memcpy(hicnp_msg->payload.face.ip.remote_addr.un.ip4, face->face.remote_addr.v4.as_u8, 4); + hicnp_msg->payload.face.ip.local_addr.af = ADDRESS_IP4; + hicnp_msg->payload.face.ip.remote_addr.af = ADDRESS_IP4; + } + else + { + memcpy(hicnp_msg->payload.face.ip.local_addr.un.ip6, face->face.local_addr.v6.as_u8, 16); + memcpy(hicnp_msg->payload.face.ip.remote_addr.un.ip6, face->face.remote_addr.v6.as_u8, 16); + hicnp_msg->payload.face.ip.local_addr.af = ADDRESS_IP6; + hicnp_msg->payload.face.ip.remote_addr.af = ADDRESS_IP6; + } + hicnp_msg->payload.face.ip.swif = face->face.netdevice.index; + memcpy(hicnp_msg->payload.face.ip.if_name, face->face.netdevice.name, IFNAMSIZ); + break; + } + case FACE_TYPE_UDP: + { + u8 check = ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)) == ip46_address_is_ip4((ip46_address_t *)&(face->face.remote_addr)); + if (!check) + return -1; + + hicnp_msg->payload.type = UDP_FACE; + if (ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr))) + { + memcpy(hicnp_msg->payload.face.udp.local_addr.un.ip4, face->face.local_addr.v4.as_u8, 4); + memcpy(hicnp_msg->payload.face.udp.remote_addr.un.ip4, face->face.remote_addr.v4.as_u8, 4); + hicnp_msg->payload.face.udp.local_addr.af = ADDRESS_IP4; + hicnp_msg->payload.face.udp.remote_addr.af = ADDRESS_IP4; + } + else + { + memcpy(hicnp_msg->payload.face.udp.local_addr.un.ip6, face->face.local_addr.v6.as_u8, 16); + memcpy(hicnp_msg->payload.face.udp.remote_addr.un.ip6, face->face.remote_addr.v6.as_u8, 16); + hicnp_msg->payload.face.udp.local_addr.af = ADDRESS_IP6; + hicnp_msg->payload.face.udp.remote_addr.af = ADDRESS_IP6; + } + hicnp_msg->payload.face.udp.lport = face->face.local_port; + hicnp_msg->payload.face.udp.rport = face->face.remote_port; + hicnp_msg->payload.face.udp.swif = face->face.netdevice.index; + memcpy(hicnp_msg->payload.face.udp.if_name, face->face.netdevice.name, IFNAMSIZ); + break; + } + default: + return -1; + } + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = ADD_CONNECTION, + .size_in = + sizeof(vapi_msg_hicn_api_face_add), + .size_out = sizeof(hc_face_t), + .parse = (HC_PARSE)parse_face_create, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, + false); } /* FACE DELETE */ +int parse_face_delete(uint8_t *src, uint8_t *dst) { + // No need to write anything on the dst, no data expected + + hc_sock_request_t *request = (hc_sock_request_t *)src; + vapi_payload_hicn_api_face_del_reply *reply = + (vapi_payload_hicn_api_face_del_reply *)request->data->buffer; + + int retval = reply->retval; + free(reply); + return retval; +} + +int hc_face_delete(hc_sock_t *s, hc_face_t *face) { + + hc_msg_s msg; + + vapi_msg_hicn_api_face_del *hicnp_msg; + hicnp_msg = vapi_alloc_hicn_api_face_del(s->g_vapi_ctx_instance); + + if (!hicnp_msg) return VAPI_ENOMEM; -int hc_face_delete(hc_sock_t *s, hc_face_t *face) { return 0; } + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_face_del_hton; + + if (!msg.callback_ctx) return VAPI_ENOMEM; + + hicnp_msg->payload.faceid = face->id; + + hc_command_params_t params = { + .cmd = ACTION_DELETE, + .cmd_id = REMOVE_ROUTE, + .size_in = + sizeof(vapi_msg_hicn_api_face_del), + .size_out = 0, + .parse = (HC_PARSE)parse_route_delete, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, + false); +} /* FACE LIST */ -int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { return 0; } +int parse_face_list(uint8_t *src, uint8_t *dst) { + // No need to write anything on the dst, no data expected + + hc_sock_request_t *request = (hc_sock_request_t *)src; + hc_face_t *output = malloc(sizeof(hc_face_t)*request->data->current); + + int retval = VAPI_OK; + int cur = 0; + + if (!output) { + retval = VAPI_ENOMEM; + request->data->current = 0; + goto END; + } + + for (int j = 0; j < request->data->current; j++) { + vapi_payload_hicn_api_faces_details *reply = + (vapi_payload_hicn_api_faces_details + *)(request->data->buffer + j * request->data->in_element_size); + retval = reply->retval; + switch(reply->type) + { + case IP_FACE: + { + if (reply->face.ip.local_addr.af == ADDRESS_IP4) + { + memcpy(output[j].face.local_addr.v4.as_u8, reply->face.ip.local_addr.un.ip4, IPV4_ADDR_LEN); + memcpy(output[j].face.remote_addr.v4.as_u8, reply->face.ip.remote_addr.un.ip4, IPV4_ADDR_LEN); + } + else + { + memcpy(output[j].face.local_addr.v6.as_u8, reply->face.ip.local_addr.un.ip6, IPV6_ADDR_LEN); + memcpy(output[j].face.remote_addr.v6.as_u8, reply->face.ip.remote_addr.un.ip6, IPV6_ADDR_LEN); + } + output[j].face.type = FACE_TYPE_HICN; + output[j].id = reply->faceid; + output[j].face.netdevice.index = reply->face.ip.swif; + memcpy(output[j].face.netdevice.name, reply->face.ip.if_name, IFNAMSIZ); + break; + } + case UDP_FACE: + { + if (reply->face.ip.local_addr.af == ADDRESS_IP4) + { + memcpy(output[j].face.local_addr.v4.as_u8, reply->face.udp.local_addr.un.ip4, IPV4_ADDR_LEN); + memcpy(output[j].face.remote_addr.v4.as_u8, reply->face.udp.remote_addr.un.ip4, IPV4_ADDR_LEN); + } + else + { + memcpy(output[j].face.local_addr.v6.as_u8, reply->face.udp.local_addr.un.ip6, IPV6_ADDR_LEN); + memcpy(output[j].face.remote_addr.v6.as_u8, reply->face.udp.remote_addr.un.ip6, IPV6_ADDR_LEN); + } + output[j].face.local_port = reply->face.udp.lport; + output[j].face.remote_port = reply->face.udp.rport; + output[j].face.type = FACE_TYPE_UDP; + output[j].id = reply->faceid; + output[j].face.netdevice.index = reply->face.udp.swif; + memcpy(output[j].face.netdevice.name, reply->face.udp.if_name, IFNAMSIZ); + break; + } + default: + retval = -1; + } + if (!retval) + cur++; + } + +END: + free(request->data->buffer); + request->data->buffer = (void *)output; + request->data->size = request->data->current; + request->data->out_element_size = sizeof(hc_face_t); + return retval; +} + +int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { + hc_msg_s msg; + + vapi_msg_hicn_api_faces_dump *hicnp_msg; + hicnp_msg = vapi_alloc_hicn_api_faces_dump(s->g_vapi_ctx_instance); + + if (!hicnp_msg) return VAPI_ENOMEM; + + msg.hicnp_msg = (hc_hicnp_t *)hicnp_msg; + msg.callback = &vapi_cb; + msg.callback_ctx = malloc(sizeof(callback_ctx_t)); + msg.callback_ctx->s = s; + msg.ntoh = (NTOH)&vapi_msg_hicn_api_faces_dump_hton; + + if (!msg.callback_ctx) return VAPI_ENOMEM; + + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = LIST_CONNECTIONS, + .size_in = sizeof(vapi_msg_hicn_api_faces_details), + .size_out = sizeof(hc_face_t), + .parse = (HC_PARSE)parse_face_list, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, (hc_data_t**)pdata, + false); + } int hc_connection_parse_to_face(void *in, hc_face_t *face) { return 0; } -int hc_face_list_async(hc_sock_t *s) //, hc_data_t ** pdata) +int hc_face_list_async(hc_sock_t *s) { return 0; } diff --git a/ctrl/libhicnctrl/src/util/hash.h b/ctrl/libhicnctrl/src/util/hash.h index 0bc48896b..7c7bb1e3a 100644 --- a/ctrl/libhicnctrl/src/util/hash.h +++ b/ctrl/libhicnctrl/src/util/hash.h @@ -240,7 +240,8 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) /* Helpers */ #define HASH_INITVAL 1 -#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL) +//#define hash(buf, len) (hash_t)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 */ -- cgit 1.2.3-korg