diff --git a/.github/workflows/run_all_tests.yml b/.github/workflows/run_all_tests.yml index 5c38915..8c0d1e5 100644 --- a/.github/workflows/run_all_tests.yml +++ b/.github/workflows/run_all_tests.yml @@ -22,14 +22,14 @@ jobs: - uses: actions/checkout@v4 - name: build run: | - cp profile_template.cmake profile.cmake + cp profiles/pcap_profile.cmake profile.cmake ./build.sh working-directory: build - name: build_integration_tests run: | ./build_tests.sh - working-directory: tests/integration_tests/build + working-directory: tests/integration_tests_pcap/build - name: run_integration_tests run: | sudo ./run_tests - working-directory: tests/integration_tests/output + working-directory: tests/integration_tests_pcap/output diff --git a/.gitignore b/.gitignore index 2f88ba2..b8f59a0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ Makefile *.cmake *.cache !/build/profile_template.cmake +!/build/profiles/* !/build/cmake diff --git a/build/build.sh b/build/build.sh index 8f4fef5..2a90c1f 100755 --- a/build/build.sh +++ b/build/build.sh @@ -4,5 +4,11 @@ rm -rf cmake rm -f Makefile rm -f cmake_install.cmake -cmake ../src -B . +cmake ../src \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_FLAGS="-Wall -Wextra -Wpedantic -Werror -Wconversion -Wsign-conversion -Wshadow -Wdouble-promotion -Wformat=2 -Wnull-dereference -Wimplicit-fallthrough -Wunreachable-code -Wstrict-prototypes" \ + -DCMAKE_VERBOSE_MAKEFILE=ON \ + -B . + make -B -j8 diff --git a/build/build_for_asm_view.sh b/build/build_for_asm_view.sh index 8dbd569..4860acb 100755 --- a/build/build_for_asm_view.sh +++ b/build/build_for_asm_view.sh @@ -1,3 +1,6 @@ #!/bin/bash -cmake --build . --config RelWithDebInfo --target swiftnet_debug -j 1 + +cmake -DCMAKE_C_COMPILER=clang . +cmake --build . --config RelWithDebInfo --target swiftnet_debug + exit 0 diff --git a/build/build_instructions.md b/build/build_instructions.md index 12df4c0..c518aae 100644 --- a/build/build_instructions.md +++ b/build/build_instructions.md @@ -1,4 +1,4 @@ ## Create profile -- Copy the profile_template.cmake file and name it profile.cmake +- Copy a profile file inside profiles and name it profile.cmake - Configure the profile correctly - Run build.sh diff --git a/build/profiles/dpdk_profile.cmake b/build/profiles/dpdk_profile.cmake new file mode 100644 index 0000000..bc0fa16 --- /dev/null +++ b/build/profiles/dpdk_profile.cmake @@ -0,0 +1,11 @@ +set(CMAKE_BUILD_TYPE Debug) + +add_compile_definitions( + SWIFT_NET_MEMORY_USAGE=5 + DPDK_LCORES=1 +) + +set(SWIFT_NET_INTERNAL_TESTING ON) +set(SANITIZER "none") +set(BACKEND "dpdk") +set(DPDK_EXTRA_ARGS "--no-pci, --vdev=net_ring0") # Basic loopback setup diff --git a/build/profiles/pcap_profile.cmake b/build/profiles/pcap_profile.cmake new file mode 100644 index 0000000..f27b057 --- /dev/null +++ b/build/profiles/pcap_profile.cmake @@ -0,0 +1,9 @@ +set(CMAKE_BUILD_TYPE Debug) + +add_compile_definitions( + SWIFT_NET_MEMORY_USAGE=5 +) + +set(SWIFT_NET_INTERNAL_TESTING ON) +set(SANITIZER "none") +set(BACKEND "pcap") diff --git a/build/profile_template.cmake b/build/profiles/profile_template.cmake similarity index 62% rename from build/profile_template.cmake rename to build/profiles/profile_template.cmake index eb4513a..99ded49 100644 --- a/build/profile_template.cmake +++ b/build/profiles/profile_template.cmake @@ -3,8 +3,13 @@ set(CMAKE_BUILD_TYPE Debug) add_compile_definitions( # SWIFT_NET_DISABLE_REQUESTS # Compile source without request features (make_request, make_response) SWIFT_NET_MEMORY_USAGE=5 # Multiplier of memory preallocated + + # DPDK SPECIFIC SETTINGS + DPDK_LCORES=1,2 # List of cores to use for DPDK (every unique interface used requires one lcore) ) set(SWIFT_NET_INTERNAL_TESTING ON) # Only used when debugging the library itself set(SANITIZER "none") # (thread, address, undefined, none (no sanitizer)) -set(BACKEND "pcap") # (pcap, dpdk) +set(BACKEND "") # (pcap, dpdk) +# DPDK SPECIFIC SETTINGS +set(DPDK_EXTRA_ARGS "") # Extra DPDK args diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4865eb2..f586e12 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(swiftnet C CXX) include(GNUInstallDirs) include(../build/profile.cmake) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 23) set(SOURCE_FILES initialize_swiftnet.c @@ -16,7 +16,6 @@ set(SOURCE_FILES cleanup_connection.c process_packets.c execute_packet_callback.c - packet_buffer.c manipulate_debug_flags.c cleanup_swiftnet.c make_response.c @@ -50,13 +49,24 @@ if(BACKEND STREQUAL "pcap") add_compile_definitions(SWIFT_NET_BACKEND_PCAP) list(APPEND SOURCE_FILES + internal/pcap/pcap_buffer.c internal/pcap/pcap_send.c internal/pcap/pcap_open.c ) +elseif(BACKEND STREQUAL "dpdk") + add_compile_definitions(SWIFT_NET_BACKEND_DPDK) + + list(APPEND SOURCE_FILES + internal/dpdk/dpdk_buffer.c + internal/dpdk/dpdk_open.c + internal/dpdk/dpdk_send.c + ) endif() -add_compile_options(-march=native) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + add_compile_options(-march=armv8-a+crc) +endif() add_library(swiftnet STATIC ${SOURCE_FILES}) add_library(swiftnet_shared SHARED ${SOURCE_FILES}) @@ -78,7 +88,7 @@ else() target_compile_options(swiftnet PRIVATE -O3 - -march=native + -flto=auto -funroll-loops -fomit-frame-pointer @@ -96,7 +106,6 @@ else() target_compile_options(swiftnet_shared PRIVATE -O3 - -march=native -flto=auto -funroll-loops -fomit-frame-pointer @@ -141,6 +150,24 @@ if(BACKEND STREQUAL "pcap") message("using linking option: -lpcap") endif() +elseif(BACKEND STREQUAL "dpdk") + find_package(PkgConfig REQUIRED) + pkg_check_modules(DPDK REQUIRED libdpdk) + + string(REPLACE " " "" DPDK_EXTRA_ARGS_STRIPPED "${DPDK_EXTRA_ARGS}") + string(REPLACE "," ";" DPDK_EXTRA_ARGS_REPLACED "${DPDK_EXTRA_ARGS_STRIPPED}") + + list(JOIN DPDK_EXTRA_ARGS_REPLACED "\", \"" DPDK_EXTRA_ARGS_JOINED) + + set(DPDK_EXTRA_ARGS_PARSED "{\"${DPDK_EXTRA_ARGS_JOINED}\", NULL};") + + add_compile_definitions(DPDK_EXTRA_ARGS=${DPDK_EXTRA_ARGS_PARSED}) + + target_include_directories(swiftnet PUBLIC ${DPDK_INCLUDE_DIRS}) + target_include_directories(swiftnet_shared PUBLIC ${DPDK_INCLUDE_DIRS}) + target_link_libraries(swiftnet PUBLIC -static ${DPDK_LIBRARIES}) + target_link_libraries(swiftnet_shared PUBLIC ${DPDK_LIBRARIES}) + message(STATUS "DPDK backend selected") endif() set_target_properties(swiftnet PROPERTIES diff --git a/src/cleanup_connection.c b/src/cleanup_connection.c index a9676e0..00d1bb9 100644 --- a/src/cleanup_connection.c +++ b/src/cleanup_connection.c @@ -1,6 +1,6 @@ +#include "swift_net.h" #include "internal/internal.h" #include "internal/networking.h" -#include "swift_net.h" #include #include #include @@ -31,11 +31,12 @@ static inline void cleanup_connection_resources(const enum ConnectionType connec } } -static inline void remove_listener(const enum ConnectionType connection_type, const char* const restrict interface_name, void* const connection) { +static inline void remove_listener(const enum ConnectionType connection_type, char* const restrict interface_name, void* const connection) { uint32_t interface_len; struct Listener* listener; - interface_len = strlen(interface_name); + + interface_len = (uint32_t)strlen(interface_name); LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); @@ -60,11 +61,32 @@ static inline void remove_listener(const enum ConnectionType connection_type, co UNLOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); } + if(listener->servers.size + listener->client_connections.size == 0) { + hashmap_destroy(&listener->servers); + hashmap_destroy(&listener->client_connections); + + SWIFTNET_BREAK_RECEIVER_LOOP(&listener->network_data); + + #ifdef SWIFT_NET_BACKEND_PCAP + pthread_join(listener->listener_thread, NULL); + #elif defined(SWIFT_NET_BACKEND_DPDK) + rte_eal_wait_lcore(listener->lcore); + + lcores_used[listener->lcore_internal_index] = listener->lcore; + #endif + + SWIFTNET_CLOSE_CONNECTION(&listener->network_data); + + allocator_free(&listener_memory_allocator, listener); + + hashmap_remove(interface_name, interface_len, &listeners); + } + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); } -static inline const char* get_interface_name(const bool loopback) { - return loopback ? LOOPBACK_INTERFACE_NAME : default_network_interface; +static inline char* get_interface_name(const bool loopback, const enum ConnectionType con_type) { + return loopback ? con_type == CONNECTION_TYPE_CLIENT ? CLIENT_LOOPBACK_INTERFACE_NAME : SERVER_LOOPBACK_INTERFACE_NAME : default_network_interface; } static inline void close_threads(const enum ConnectionType connection_type, void* const connection) { @@ -114,33 +136,30 @@ static inline void close_threads(const enum ConnectionType connection_type, void } void swiftnet_client_cleanup(struct SwiftNetClientConnection* const client) { - const char* restrict interface_name; + char* restrict interface_name; cleanup_connection_resources(CONNECTION_TYPE_CLIENT, client); - interface_name = get_interface_name(client->loopback); + interface_name = get_interface_name(client->loopback, CONNECTION_TYPE_CLIENT); remove_listener(CONNECTION_TYPE_CLIENT, interface_name, client); close_threads(CONNECTION_TYPE_CLIENT, client); - SWIFTNET_CLOSE_CONNECTION(&client->network_data); - allocator_free(&client_connection_memory_allocator, client); } void swiftnet_server_cleanup(struct SwiftNetServer* const server) { - const char* restrict interface_name; + char* restrict interface_name; + cleanup_connection_resources(CONNECTION_TYPE_SERVER, server); - interface_name = get_interface_name(server->loopback); + interface_name = get_interface_name(server->loopback, CONNECTION_TYPE_SERVER); remove_listener(CONNECTION_TYPE_SERVER, interface_name, server); close_threads(CONNECTION_TYPE_SERVER, server); - SWIFTNET_CLOSE_CONNECTION(&server->network_data); - allocator_free(&server_memory_allocator, server); } diff --git a/src/cleanup_swiftnet.c b/src/cleanup_swiftnet.c index 5f4e223..c14363b 100644 --- a/src/cleanup_swiftnet.c +++ b/src/cleanup_swiftnet.c @@ -13,7 +13,7 @@ static inline void close_listeners() { SWIFTNET_BREAK_RECEIVER_LOOP(¤t_listener->network_data); - pthread_join(current_listener->listener_thread, NULL); + WAIT_LISTENER_THREAD(current_listener); SWIFTNET_CLOSE_CONNECTION(¤t_listener->network_data); @@ -58,5 +58,21 @@ void swiftnet_cleanup() { printf("Bytes leaked: %d\nItems leaked: %d\n", bytes_leaked, items_leaked); #endif + #ifdef SWIFT_NET_BACKEND_DPDK + uint16_t port_id; + uint16_t count; + + count = rte_eth_dev_count_avail(); + + for (port_id = 0; port_id < count; port_id++) { + if (!rte_eth_dev_is_valid_port(port_id)) + continue; + + rte_eth_dev_close(port_id); + } + + rte_eal_cleanup(); + #endif + close_background_service(); } diff --git a/src/execute_packet_callback.c b/src/execute_packet_callback.c index dc3f853..c1b856f 100644 --- a/src/execute_packet_callback.c +++ b/src/execute_packet_callback.c @@ -7,7 +7,7 @@ #include #include -static struct PacketCallbackQueueNode *const wait_for_next_packet_callback(struct PacketCallbackQueue* const packet_queue) { +static struct PacketCallbackQueueNode* wait_for_next_packet_callback(struct PacketCallbackQueue* const packet_queue) { struct PacketCallbackQueueNode* restrict node_to_process; @@ -51,18 +51,22 @@ void execute_packet_callback( struct PacketCallbackQueue* const queue, void (*const _Atomic * const packet_handler)(void *const, void *const), const enum ConnectionType connection_type, - struct SwiftNetMemoryAllocator* const pending_message_memory_allocator, const _Atomic bool * const closing, void * const connection, struct SwiftNetHashMap* const pending_messages, _Atomic(void *) * const user_data, pthread_mutex_t* const execute_callback_mtx, - pthread_cond_t* const execute_callback_cond + pthread_cond_t* const execute_callback_cond, + _Atomic bool* const executing_packets ) { void (*packet_handler_loaded)(void *const, void *const); struct PacketCallbackQueueNode* restrict current_node; + uint8_t idle_stage; + + + idle_stage = 0; goto check_packet; @@ -72,18 +76,35 @@ void execute_packet_callback( return; } - pthread_mutex_lock(execute_callback_mtx); - current_node = wait_for_next_packet_callback(queue); if (current_node == NULL) { - pthread_cond_wait(execute_callback_cond, execute_callback_mtx); + switch (idle_stage) { + case 64: usleep(1000); break; + case 128: usleep(2000); break; + case 194: usleep(5000); break; + case 255: { + atomic_store_explicit(executing_packets, false, memory_order_release); + + pthread_mutex_lock(execute_callback_mtx); + + pthread_cond_wait(execute_callback_cond, execute_callback_mtx); + + pthread_mutex_unlock(execute_callback_mtx); + + atomic_store_explicit(executing_packets, true, memory_order_release); + + idle_stage = 0; + + goto check_packet; + } + } - pthread_mutex_unlock(execute_callback_mtx); + idle_stage++; goto check_packet; } - pthread_mutex_unlock(execute_callback_mtx); + idle_stage = 0; packet_handler_loaded = atomic_load_explicit(packet_handler, memory_order_acquire); @@ -127,12 +148,12 @@ void* execute_packet_callback_client(void* const void_client) { &client->packet_callback_queue, (void *)&client->packet_handler, CONNECTION_TYPE_CLIENT, - &client->pending_messages_memory_allocator, &client->closing, void_client, &client->pending_messages, &client->packet_handler_user_arg, &client->execute_callback_mtx, - &client->execute_callback_cond + &client->execute_callback_cond, + &client->executing_packets ); return NULL; @@ -145,12 +166,12 @@ void* execute_packet_callback_server(void* const void_server) { &server->packet_callback_queue, (void *)&server->packet_handler, CONNECTION_TYPE_SERVER, - &server->pending_messages_memory_allocator, &server->closing, void_server, &server->pending_messages, &server->packet_handler_user_arg, &server->execute_callback_mtx, - &server->execute_callback_cond + &server->execute_callback_cond, + &server->executing_packets ); return NULL; diff --git a/src/generic_functions.c b/src/generic_functions.c index f039196..74746d0 100644 --- a/src/generic_functions.c +++ b/src/generic_functions.c @@ -6,30 +6,8 @@ #include #include -// These functions append data to a packet buffer and advance the current pointer by the data size. -static inline void validate_append_to_packet_args(const void* restrict const data, const uint32_t data_size) { - if(unlikely(data == NULL || data_size == 0)) { - PRINT_ERROR("Error: Invalid arguments given"); - exit(EXIT_FAILURE); - } -} - -static inline void append_data(uint8_t* restrict * restrict const append_pointer, const void* restrict const data, const uint32_t data_size) { - memcpy(*append_pointer, data, data_size); - - (*append_pointer) += data_size; -} - -void swiftnet_append_to_buffer(const void* restrict const data, const uint32_t data_size, struct SwiftNetPacketBuffer* restrict const buffer) { - #ifdef SWIFT_NET_ERROR - validate_append_to_packet_args(data, data_size); - #endif - - append_data(&buffer->packet_append_pointer, data, data_size); -} - // Set the handler for incoming packets/messages on the server or client -static inline void swiftnet_validate_new_handler(const void* const new_handler) { +static inline void swiftnet_validate_new_handler(void(*new_handler)(void)) { #ifdef SWIFT_NET_ERROR if(unlikely(new_handler == NULL)) { PRINT_ERROR("Error: Invalid arguments given"); @@ -38,15 +16,15 @@ static inline void swiftnet_validate_new_handler(const void* const new_handler) #endif } -void swiftnet_client_set_message_handler(struct SwiftNetClientConnection* const client, void (* const new_handler)(struct SwiftNetClientPacketData* const, void* const), void* const user_arg) { - swiftnet_validate_new_handler(new_handler); +void swiftnet_client_set_message_handler(struct SwiftNetClientConnection* const client, void (*new_handler)(struct SwiftNetClientPacketData* const, void* const), void* const user_arg) { + swiftnet_validate_new_handler((void(*)(void))new_handler); atomic_store_explicit(&client->packet_handler, new_handler, memory_order_release); atomic_store_explicit(&client->packet_handler_user_arg, user_arg, memory_order_release); } void swiftnet_server_set_message_handler(struct SwiftNetServer* const server, void (* const new_handler)(struct SwiftNetServerPacketData* const, void* const), void* const user_arg) { - swiftnet_validate_new_handler(new_handler); + swiftnet_validate_new_handler((void(*)(void))new_handler); atomic_store_explicit(&server->packet_handler, new_handler, memory_order_release); atomic_store_explicit(&server->packet_handler_user_arg, user_arg, memory_order_release); @@ -54,7 +32,7 @@ void swiftnet_server_set_message_handler(struct SwiftNetServer* const server, vo // Read packet data into buffers void* swiftnet_client_read_packet(struct SwiftNetClientPacketData* restrict const packet_data, const uint32_t data_size) { - const uint32_t data_already_read = (packet_data->current_pointer - packet_data->data) + data_size; + const uint32_t data_already_read = (uint32_t)(packet_data->current_pointer - packet_data->data) + data_size; if (data_already_read > packet_data->metadata.data_length) { PRINT_ERROR("Error: Tried to read more data than there actually is"); return NULL; @@ -68,7 +46,7 @@ void* swiftnet_client_read_packet(struct SwiftNetClientPacketData* restrict cons } void* swiftnet_server_read_packet(struct SwiftNetServerPacketData* restrict const packet_data, const uint32_t data_size) { - const uint32_t data_already_read = (packet_data->current_pointer - packet_data->data) + data_size; + const uint32_t data_already_read = (uint32_t)(packet_data->current_pointer - packet_data->data) + data_size; if (data_already_read > packet_data->metadata.data_length) { PRINT_ERROR("Error: Tried to read more data than there actually is"); return NULL; diff --git a/src/handle_packets.c b/src/handle_packets.c index 27202d8..8ca22e4 100644 --- a/src/handle_packets.c +++ b/src/handle_packets.c @@ -13,8 +13,7 @@ static inline void insert_queue_node( struct PacketQueueNode* restrict const new_node, - struct PacketQueue* const packet_queue, - const enum ConnectionType contype + struct PacketQueue* const packet_queue ) { if(unlikely(new_node == NULL)) { return; @@ -66,41 +65,31 @@ static inline struct PacketQueueNode* construct_node(const uint32_t data_read, v } static inline void swiftnet_handle_packets( - const uint16_t source_port, - pthread_t* const process_packets_thread, - void* const connection, - const enum ConnectionType connection_type, struct PacketQueue* const packet_queue, - const _Atomic bool* const closing, - const bool loopback, - const uint8_t* restrict const packet, pthread_mutex_t* const process_packets_mtx, pthread_cond_t* const process_packets_cond, _Atomic bool *const processing_packets, struct SwiftNetNetworkData network_data, - const uint32_t packet_len + struct ReceiverPacketData* restrict const packet_data ) { - uint8_t prepend_size; - uint8_t addr_type; + uint16_t addr_type; uint32_t sender_address; uint8_t* restrict packet_buffer; - prepend_size = GET_PREPEND_SIZE(&network_data); addr_type = GET_ADDR_TYPE(&network_data); + if (unlikely(packet_data->data_len == 0)) { + goto exit; + } + packet_buffer = allocator_allocate(&packet_buffer_memory_allocator); if (unlikely(packet_buffer == NULL)) { goto exit; } - memcpy(packet_buffer, packet, packet_len); - - if (unlikely(packet_len == 0)) { - allocator_free(&packet_buffer_memory_allocator, packet_buffer); - return; - } + memcpy(packet_buffer, packet_data->data, packet_data->data_len); goto get_sender_addr; @@ -108,7 +97,7 @@ static inline void swiftnet_handle_packets( get_sender_addr: sender_address = 0; - if (addr_type == DLT_EN10MB) { + if (addr_type != 0) { if (ntohs(((struct ether_header *)packet_buffer)->ether_type) == ETHERTYPE_IP) { sender_address = ((struct ip *)(packet_buffer + sizeof(struct ether_header)))->ip_src.s_addr; @@ -122,7 +111,7 @@ static inline void swiftnet_handle_packets( insert_node: - insert_queue_node(construct_node(packet_len, packet_buffer, sender_address), packet_queue, connection_type); + insert_queue_node(construct_node(packet_data->data_len, packet_buffer, sender_address), packet_queue); goto unlock_processing_thread; @@ -140,18 +129,27 @@ static inline void swiftnet_handle_packets( exit: + #ifdef SWIFT_NET_BACKEND_DPDK + rte_pktmbuf_free(packet_data->dpdk_buf); + #endif + return; } -static void handle_client_init(struct SwiftNetClientConnection* const client_connection, const uint8_t* restrict const buffer, const uint32_t bytes_received) { +static void handle_client_init(struct SwiftNetClientConnection* const client_connection, struct ReceiverPacketData* const restrict packet_data) { struct SwiftNetPacketInfo* restrict packet_info; struct SwiftNetServerInformation* restrict server_information; + uint8_t* buffer; + uint32_t bytes_received; + uint8_t prepend_size; - uint8_t addr_type; + uint16_t addr_type; prepend_size = GET_PREPEND_SIZE(&client_connection->network_data); addr_type = GET_ADDR_TYPE(&client_connection->network_data); + buffer = (uint8_t*)packet_data->data; + bytes_received = packet_data->data_len; goto check_closing; @@ -168,7 +166,7 @@ static void handle_client_init(struct SwiftNetClientConnection* const client_con if(bytes_received != PACKET_HEADER_SIZE + sizeof(struct SwiftNetServerInformation) + prepend_size) { #ifdef SWIFT_NET_DEBUG if (check_debug_flag(SWIFTNET_DEBUG_INITIALIZATION)) { - send_debug_message("Invalid packet received from server. Expected server information: {\"bytes_received\": %u, \"expected_bytes\": %u}\n", bytes_received, PACKET_HEADER_SIZE + sizeof(struct SwiftNetServerInformation)); + send_debug_message("Invalid packet received from server. Expected server information: {\"bytes_received\": %u, \"expected_bytes\": %lu}\n", bytes_received, PACKET_HEADER_SIZE + sizeof(struct SwiftNetServerInformation)); } #endif @@ -178,7 +176,7 @@ static void handle_client_init(struct SwiftNetClientConnection* const client_con goto handle_mac_address; handle_mac_address: - if (addr_type == DLT_EN10MB) { + if (addr_type != 0) { memcpy(client_connection->eth_header.ether_dhost, ((struct ether_header*)buffer)->ether_shost, sizeof(client_connection->eth_header.ether_dhost)); } @@ -222,10 +220,14 @@ static void handle_client_init(struct SwiftNetClientConnection* const client_con exit: + #ifdef SWIFT_NET_BACKEND_DPDK + rte_pktmbuf_free(packet_data->dpdk_buf); + #endif + return; } -static inline uint8_t handle_correct_receiver(const enum ConnectionType connection_type, struct Listener* const listener, const uint8_t* restrict const packet, const struct SwiftNetPortInfo* restrict const port_info, const uint32_t packet_len) { +static inline uint8_t handle_correct_receiver(const enum ConnectionType connection_type, struct Listener* const listener, const struct SwiftNetPortInfo* restrict const port_info, struct ReceiverPacketData* const restrict packet_data) { if (connection_type == CONNECTION_TYPE_CLIENT) { struct SwiftNetClientConnection* client_connection; @@ -239,9 +241,9 @@ static inline uint8_t handle_correct_receiver(const enum ConnectionType connecti } if (atomic_load_explicit(&client_connection->initialized, memory_order_acquire) == false) { - handle_client_init(client_connection, packet, packet_len); + handle_client_init(client_connection, packet_data); } else { - swiftnet_handle_packets(client_connection->port_info.source_port, &client_connection->process_packets_thread, client_connection, CONNECTION_TYPE_CLIENT, &client_connection->packet_queue, &client_connection->closing, client_connection->loopback, packet, &client_connection->process_packets_mtx, &client_connection->process_packets_cond, &client_connection->processing_packets, client_connection->network_data, packet_len); + swiftnet_handle_packets(&client_connection->packet_queue, &client_connection->process_packets_mtx, &client_connection->process_packets_cond, &client_connection->processing_packets, client_connection->network_data, packet_data); } return 1; @@ -258,25 +260,43 @@ static inline uint8_t handle_correct_receiver(const enum ConnectionType connecti return 0; } - swiftnet_handle_packets(server->server_port, &server->process_packets_thread, server, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->closing, server->loopback, packet, &server->process_packets_mtx, &server->process_packets_cond, &server->processing_packets, server->network_data, packet_len); + swiftnet_handle_packets(&server->packet_queue, &server->process_packets_mtx, &server->process_packets_cond, &server->processing_packets, server->network_data, packet_data); return 1; } } #ifdef SWIFT_NET_BACKEND_PCAP -static void pcap_packet_handle(uint8_t* const user, const struct pcap_pkthdr* restrict const hdr, const uint8_t* restrict const packet) { +static void pcap_packet_handle(uint8_t* const user, const struct pcap_pkthdr* restrict const hdr, const uint8_t* const packet) { struct Listener* const listener = (struct Listener*)user; struct SwiftNetPortInfo* restrict const port_info = (struct SwiftNetPortInfo*)(packet + PACKET_PREPEND_SIZE(listener->addr_type) + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, port_info)); + struct ReceiverPacketData packet_data = (struct ReceiverPacketData){.data = packet, .data_len = hdr->caplen}; - if(handle_correct_receiver(CONNECTION_TYPE_CLIENT, listener, packet, port_info, hdr->caplen) == 0) handle_correct_receiver(CONNECTION_TYPE_SERVER, listener, packet, port_info, hdr->caplen); + if(handle_correct_receiver(CONNECTION_TYPE_CLIENT, listener, port_info, &packet_data) == 0) handle_correct_receiver(CONNECTION_TYPE_SERVER, listener, port_info, &packet_data); +} +#elif defined(SWIFT_NET_BACKEND_DPDK) +static void dpdk_packet_handle(struct Listener* const listener, struct rte_mbuf* const restrict dpdk_buf, uint8_t* restrict const packet) { + struct SwiftNetPortInfo* restrict const port_info = (struct SwiftNetPortInfo*)(packet + PACKET_PREPEND_SIZE(listener->addr_type) + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, port_info)); + struct ReceiverPacketData packet_data = (struct ReceiverPacketData){.data = packet, .data_len = dpdk_buf->data_len, .dpdk_buf = dpdk_buf}; + + if(handle_correct_receiver(CONNECTION_TYPE_CLIENT, listener, port_info, &packet_data) == 0) handle_correct_receiver(CONNECTION_TYPE_SERVER, listener, port_info, &packet_data); } #endif -void* interface_start_listening(void* listener_void) { +#ifdef SWIFT_NET_BACKEND_PCAP +void* interface_start_listening_pcap(void* listener_void) { struct Listener* listener = listener_void; SWIFTNET_LOOP_PACKETS(&listener->network_data, listener); - + return NULL; } +#elif defined(SWIFT_NET_BACKEND_DPDK) +int interface_start_listening_dpdk(void* listener_void) { + struct Listener* listener = listener_void; + + SWIFTNET_LOOP_PACKETS(&listener->network_data, listener); + + return 0; +} +#endif diff --git a/src/initialize_client_connection.c b/src/initialize_client_connection.c index fe37009..14b96fb 100644 --- a/src/initialize_client_connection.c +++ b/src/initialize_client_connection.c @@ -27,6 +27,9 @@ struct RequestServerInformationArgs { uint32_t timeout_ms; void* restrict data; struct SwiftNetClientConnection* connection; + #ifdef SWIFT_NET_BACKEND_DPDK + struct rte_mbuf* data_internal_mem_buf; + #endif }; void* request_server_information(void* restrict const request_server_information_args_void) { @@ -38,7 +41,7 @@ void* request_server_information(void* restrict const request_server_information gettimeofday(&tv, NULL); - start = (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + start = (uint32_t)tv.tv_sec * 1000 + (uint32_t)tv.tv_usec / 1000; goto init_connection_request; @@ -60,7 +63,7 @@ void* request_server_information(void* restrict const request_server_information } #endif - SWIFTNET_SEND_PACKET(request_server_information_args->network_data, request_server_information_args->data, request_server_information_args->size); + SWIFTNET_SEND_INTERNAL_PACKET(request_server_information_args->network_data, request_server_information_args->data, request_server_information_args->size); usleep(250000); @@ -71,7 +74,7 @@ void* request_server_information(void* restrict const request_server_information return NULL; } -static inline struct SwiftNetClientConnection* const construct_client_connection(const bool loopback, const uint16_t destination_port, const in_addr_t server_address, struct SwiftNetNetworkData* const network_data) { +static inline struct SwiftNetClientConnection* construct_client_connection(const bool loopback, const uint16_t destination_port, const in_addr_t server_address) { struct SwiftNetClientConnection* const new_connection = allocator_allocate(&client_connection_memory_allocator); struct ether_header eth_header = { @@ -84,11 +87,10 @@ static inline struct SwiftNetClientConnection* const construct_client_connection *new_connection = (struct SwiftNetClientConnection){ .eth_header = eth_header, - .port_info = (struct SwiftNetPortInfo){.source_port = rand(), .destination_port = destination_port}, + .port_info = (struct SwiftNetPortInfo){.source_port = (uint16_t)rand(), .destination_port = destination_port}, .server_addr.s_addr = server_address, .packet_handler = NULL, .loopback = loopback, - .network_data = *network_data, .pending_messages_memory_allocator = allocator_create(sizeof(struct SwiftNetPendingMessage), 40 * SWIFT_NET_MEMORY_USAGE), .packets_sending_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketSending), 40 * SWIFT_NET_MEMORY_USAGE), .packets_completed_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketCompleted), 40 * SWIFT_NET_MEMORY_USAGE), @@ -105,6 +107,7 @@ static inline struct SwiftNetClientConnection* const construct_client_connection UNLOCK_ATOMIC_DATA_TYPE(&new_connection->packet_callback_queue.locked); atomic_store_explicit(&new_connection->processing_packets, true, memory_order_release); + atomic_store_explicit(&new_connection->executing_packets, true, memory_order_release); atomic_store_explicit(&new_connection->closing, false, memory_order_release); atomic_store_explicit(&new_connection->initialized, false, memory_order_release); atomic_store_explicit(&new_connection->packet_handler_user_arg, NULL, memory_order_release); @@ -133,7 +136,6 @@ struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_add struct RequestServerInformationArgs thread_args; struct Listener* listener; struct SwiftNetNetworkData net_data; - struct SwiftNetNetworkData null_net_data; goto init_connection; @@ -146,14 +148,13 @@ struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_add loopback = (ip >> 24) == 127; - net_data = swiftnet_initialize_networking(loopback ? LOOPBACK_INTERFACE_NAME : default_network_interface); + new_connection = construct_client_connection(loopback, port, addr.s_addr); - memset(&null_net_data, 0, sizeof(null_net_data)); - if (unlikely(memcmp(&null_net_data, &net_data, sizeof(net_data))) == 0) { - return NULL; - } + listener = check_existing_listener(loopback ? CLIENT_LOOPBACK_INTERFACE_NAME : default_network_interface, new_connection, CONNECTION_TYPE_CLIENT, loopback); + + net_data = listener->network_data; - new_connection = construct_client_connection(loopback, port, addr.s_addr, &net_data); + new_connection->network_data = net_data; goto request_initialization; @@ -168,23 +169,24 @@ struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_add new_connection->port_info ); - request_server_info_ip_header = construct_ip_header(new_connection->server_addr, PACKET_HEADER_SIZE, rand()); - + request_server_info_ip_header = construct_ip_header(new_connection->server_addr, PACKET_HEADER_SIZE, (uint16_t)rand()); + HANDLE_PACKET_CONSTRUCTION(&request_server_info_ip_header, &request_server_information_packet_info, &net_data, &new_connection->eth_header, PACKET_HEADER_SIZE + GET_PREPEND_SIZE(&new_connection->network_data), request_server_info_buffer); - HANDLE_CHECKSUM(request_server_info_buffer, sizeof(request_server_info_buffer), &net_data); + HANDLE_CHECKSUM(request_server_info_buffer, (uint32_t)sizeof(request_server_info_buffer), &net_data); thread_args = (struct RequestServerInformationArgs){ .network_data = &net_data, .data = request_server_info_buffer, - .size = sizeof(request_server_info_buffer), + .size = (uint32_t)sizeof(request_server_info_buffer), .server_addr = addr, .timeout_ms = timeout_ms, .connection = new_connection + #ifdef SWIFT_NET_BACKEND_DPDK + , .data_internal_mem_buf = request_server_info_buffer_internal_mem_buf + #endif }; - listener = check_existing_listener(loopback ? LOOPBACK_INTERFACE_NAME : default_network_interface, new_connection, CONNECTION_TYPE_CLIENT, loopback); - pthread_create(&send_request_thread, NULL, request_server_information, (void*)&thread_args); pthread_join(send_request_thread, NULL); @@ -192,7 +194,7 @@ struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_add if (atomic_load_explicit(&new_connection->initialized, memory_order_acquire) == false) { atomic_store_explicit(&new_connection->closing, true, memory_order_release); - swiftnet_close_connection(&new_connection->network_data); + SWIFTNET_CLOSE_CONNECTION(&new_connection->network_data); allocator_free(&client_connection_memory_allocator, new_connection); diff --git a/src/initialize_server.c b/src/initialize_server.c index b76c214..70d258d 100644 --- a/src/initialize_server.c +++ b/src/initialize_server.c @@ -14,18 +14,9 @@ #include "internal/networking.h" #include "swift_net.h" -static inline struct SwiftNetServer* const construct_server(const bool loopback, const uint16_t server_port) { +static inline struct SwiftNetServer* construct_server(const bool loopback, const uint16_t server_port) { struct SwiftNetServer* restrict new_server; struct ether_header eth_header; - struct SwiftNetNetworkData null_net_data; - - - memset(&null_net_data, 0x00, sizeof(null_net_data)); - - struct SwiftNetNetworkData net_data = swiftnet_initialize_networking(loopback ? LOOPBACK_INTERFACE_NAME : default_network_interface); - if (unlikely(memcmp(&net_data, &null_net_data, sizeof(struct SwiftNetNetworkData)) == 0)) { - return NULL; - } new_server = allocator_allocate(&server_memory_allocator); eth_header = DEFAULT_MAC_ADDRESS_STRUCT; @@ -33,7 +24,6 @@ static inline struct SwiftNetServer* const construct_server(const bool loopback, memcpy(eth_header.ether_shost, mac_address, sizeof(eth_header.ether_shost)); *new_server = (struct SwiftNetServer){ - .network_data = net_data, .eth_header = eth_header, .server_port = server_port, .loopback = loopback, @@ -49,6 +39,7 @@ static inline struct SwiftNetServer* const construct_server(const bool loopback, UNLOCK_ATOMIC_DATA_TYPE(&new_server->packet_callback_queue.locked); atomic_store_explicit(&new_server->processing_packets, true, memory_order_release); + atomic_store_explicit(&new_server->executing_packets, true, memory_order_release); atomic_store_explicit(&new_server->packet_handler, NULL, memory_order_release); atomic_store_explicit(&new_server->packet_handler_user_arg, NULL, memory_order_release); atomic_store_explicit(&new_server->closing, false, memory_order_release); @@ -75,7 +66,9 @@ struct SwiftNetServer* swiftnet_create_server(const uint16_t port, const bool lo } // Create a new thread that will handle all packets received - check_existing_listener(loopback ? LOOPBACK_INTERFACE_NAME : default_network_interface, new_server, CONNECTION_TYPE_SERVER, loopback); + struct Listener* const new_listener = check_existing_listener(loopback ? SERVER_LOOPBACK_INTERFACE_NAME : default_network_interface, new_server, CONNECTION_TYPE_SERVER, loopback); + + new_server->network_data = new_listener->network_data; pthread_create(&new_server->process_packets_thread, NULL, swiftnet_server_process_packets, new_server); pthread_create(&new_server->execute_callback_thread, NULL, execute_packet_callback_server, new_server); diff --git a/src/initialize_swiftnet.c b/src/initialize_swiftnet.c index 345312e..28d5520 100644 --- a/src/initialize_swiftnet.c +++ b/src/initialize_swiftnet.c @@ -20,7 +20,7 @@ uint32_t semaphore_counter = 0x00; -uint32_t maximum_transmission_unit = 0x00; +uint16_t maximum_transmission_unit = 0x00; struct in_addr private_ip_address; uint8_t mac_address[6]; char default_network_interface[SIZEOF_FIELD(struct ifreq, ifr_name)]; @@ -66,7 +66,6 @@ static inline void initialize_allocators() { #ifdef SWIFT_NET_REQUESTS requests_sent_memory_allocator = allocator_create(sizeof(struct RequestSent), 40 * SWIFT_NET_MEMORY_USAGE); #endif - } static inline void initialize_vectors() { @@ -82,12 +81,43 @@ static inline void initialize_memory_cleanup_thread() { } void swiftnet_initialize() { + #ifdef SWIFT_NET_BACKEND_DPDK + char dpdk_args[1024]; + char* argv[32]; + char* current_dpdk_arg_ptr = dpdk_args; + #ifdef DPDK_EXTRA_ARGS + char* extra_args[] = DPDK_EXTRA_ARGS; + #endif + + static int argc = 0; + + argv[argc] = current_dpdk_arg_ptr; + current_dpdk_arg_ptr = current_dpdk_arg_ptr + snprintf(current_dpdk_arg_ptr, sizeof(dpdk_args), "%s", "-l") + 1; + argc++; + + argv[argc] = current_dpdk_arg_ptr; + current_dpdk_arg_ptr = current_dpdk_arg_ptr + snprintf(current_dpdk_arg_ptr, sizeof(dpdk_args), "%s", TOSTRING(DPDK_LCORES)) + 1; + argc++; + + for(uint32_t i = 0; i < (sizeof(extra_args) / sizeof(char*)) - 1; i++) { + argv[argc] = current_dpdk_arg_ptr; + current_dpdk_arg_ptr = current_dpdk_arg_ptr + snprintf(current_dpdk_arg_ptr, sizeof(dpdk_args), "%s", extra_args[i]) + 1; + argc++; + } + + for (int i = 0; i < argc; i++) { + printf("argv[%d] = '%s'\n", i, argv[i]); + } + + if (rte_eal_init(argc, argv) < 0) rte_exit(EXIT_FAILURE, "EAL init failed\n"); + #endif + int temp_socket; struct sockaddr_in remote = {0}; struct sockaddr private_sockaddr; socklen_t private_sockaddr_len = sizeof(private_sockaddr); - seed = rand(); + seed = (uint64_t)rand(); atomic_store_explicit(&swiftnet_closing, false, memory_order_release); diff --git a/src/internal/check_existing_listener.c b/src/internal/check_existing_listener.c index 91f468b..9b43cb0 100644 --- a/src/internal/check_existing_listener.c +++ b/src/internal/check_existing_listener.c @@ -3,6 +3,10 @@ #include #include #include + +#ifdef SWIFT_NET_BACKEND_DPDK +uint32_t lcores_used[] = {DPDK_LCORES}; +#endif void* check_existing_listener(const char* restrict const interface_name, void* const connection, const enum ConnectionType connection_type, const bool loopback) { uint32_t interface_len; @@ -14,7 +18,7 @@ void* check_existing_listener(const char* restrict const interface_name, void* c LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - interface_len = strlen(interface_name); + interface_len = (uint32_t)(strlen(interface_name)); existing_listener = hashmap_get(interface_name, interface_len, &listeners); @@ -70,6 +74,10 @@ void* check_existing_listener(const char* restrict const interface_name, void* c } listener_key = malloc(interface_len); + if(unlikely(listener_key == NULL)) { + PRINT_ERROR("Failed malloc"); + exit(EXIT_FAILURE); + } memcpy(listener_key, interface_name, interface_len); @@ -77,7 +85,26 @@ void* check_existing_listener(const char* restrict const interface_name, void* c UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - pthread_create(&new_listener->listener_thread, NULL, interface_start_listening, new_listener); + #ifdef SWIFT_NET_BACKEND_PCAP + pthread_create(&new_listener->listener_thread, NULL, interface_start_listening_pcap, new_listener); + #elif defined(SWIFT_NET_BACKEND_DPDK) + for(uint16_t i = 0; i < sizeof(lcores_used) / sizeof(lcores_used[0]); i++) { + uint32_t* current_lcore; + + current_lcore = &lcores_used[i]; + + if(((*current_lcore >> 31) & 1u) == 1u) continue; + + rte_eal_remote_launch(interface_start_listening_dpdk, new_listener, *current_lcore); + + new_listener->lcore = *current_lcore; + new_listener->lcore_internal_index = i; + + *current_lcore |= (1u << 31); + + break; + } + #endif return new_listener; } diff --git a/src/internal/datatype_allocator.c b/src/internal/datatype_allocator.c index 15b42cf..7008544 100644 --- a/src/internal/datatype_allocator.c +++ b/src/internal/datatype_allocator.c @@ -67,7 +67,7 @@ static inline void set_memory_status(struct SwiftNetMemoryAllocator* const memor && casted_memory_loc < casted_data + (memory_allocator->item_size * memory_allocator->chunk_item_amount) ) { - offset = casted_memory_loc - casted_data; + offset = (uint32_t)(casted_memory_loc - casted_data); index = offset / memory_allocator->item_size; byte = index / 8; @@ -115,7 +115,7 @@ static inline bool is_already_free(struct SwiftNetMemoryAllocator* const memory_ && casted_memory_loc < casted_data + (memory_allocator->item_size * memory_allocator->chunk_item_amount) ) { - offset = casted_memory_loc - casted_data; + offset = (uint32_t)(casted_memory_loc - casted_data); index = offset / memory_allocator->item_size; byte = index / 8; @@ -140,7 +140,7 @@ static inline bool is_already_free(struct SwiftNetMemoryAllocator* const memory_ #endif // Type is either 0/1 - 1 = allocation - 0 = freeing -struct SwiftNetMemoryAllocatorStack* const find_free_pointer_stack(struct SwiftNetMemoryAllocator* const allocator, const uint8_t type) { +struct SwiftNetMemoryAllocatorStack* find_free_pointer_stack(struct SwiftNetMemoryAllocator* const allocator, const uint8_t type) { uint16_t stacks_allocated; uint64_t bitmap; uint16_t first_free; @@ -164,7 +164,7 @@ struct SwiftNetMemoryAllocatorStack* const find_free_pointer_stack(struct SwiftN if((bitmap | invalid_bitmap) == UINT64_MAX) { return NULL; } else { - first_free = __builtin_ctzll(~(bitmap | invalid_bitmap)); + first_free = (uint16_t)__builtin_ctzll(~(bitmap | invalid_bitmap)); } if(first_free >= stacks_allocated) { @@ -185,7 +185,7 @@ struct SwiftNetMemoryAllocatorStack* const find_free_pointer_stack(struct SwiftN process_stack: stack_size = atomic_load_explicit(&stack->size, memory_order_acquire); - valid_size = type == 0 ? (stack_size < allocator->chunk_item_amount && stack_size >= 0) : (stack_size <= allocator->chunk_item_amount && stack_size > 0); + valid_size = type == 0 ? (stack_size < allocator->chunk_item_amount) : (stack_size <= allocator->chunk_item_amount && stack_size > 0); if(valid_size) { return stack; @@ -355,7 +355,10 @@ void* allocator_allocate(struct SwiftNetMemoryAllocator* const memory_allocator) void allocator_free(struct SwiftNetMemoryAllocator* const memory_allocator, void* const memory_location) { struct SwiftNetMemoryAllocatorStack* free_stack; uint32_t size; + #ifdef SWIFT_NET_INTERNAL_TESTING bool already_free; + #endif + #ifdef SWIFT_NET_INTERNAL_TESTING @@ -453,4 +456,4 @@ void allocator_destroy(struct SwiftNetMemoryAllocator* const memory_allocator free(current_stack); } -} \ No newline at end of file +} diff --git a/src/internal/datatype_hashmap.c b/src/internal/datatype_hashmap.c index db54969..0783cee 100644 --- a/src/internal/datatype_hashmap.c +++ b/src/internal/datatype_hashmap.c @@ -28,7 +28,7 @@ static inline uint64_t hash64(const uint8_t* const data, const uint32_t data_siz static inline uint32_t get_key(const void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* const hashmap) { // Mapping to max value of items allocated // Must rehash when scalling hashmap - return ((__uint128_t)hash64(key_data, data_size) * hashmap->capacity) >> 64; + return (uint32_t)(((__uint128_t)hash64(key_data, data_size) * hashmap->capacity) >> 64); } // Must rehash every key. Takes many cpu cycles. @@ -77,8 +77,8 @@ static inline void hashmap_resize(struct SwiftNetHashMap* const hashmap) { new_mem_hashmap_item = hashmap->items + new_key; - byte = new_key / 32; - bit = new_key % 32; + byte = (uint32_t)(new_key / 32); + bit = (uint8_t)(new_key % 32); *(hashmap->item_occupation + byte) |= 1 << bit; @@ -184,10 +184,10 @@ void hashmap_insert(void* const key_data, const uint32_t data_size, void* const hashmap->size++; - byte = key / 32; - bit = key % 32; + byte = (uint32_t)(key / 32); + bit = (uint8_t)(key % 32); - *(hashmap->item_occupation + byte) |= 0 << bit; + *(hashmap->item_occupation + byte) |= (uint32_t)(0 << bit); if(hashmap->size >= hashmap->capacity) { hashmap_resize(hashmap); @@ -217,10 +217,10 @@ void hashmap_remove(void* const key_data, const uint32_t data_size, struct Swift current_target_item = hashmap->items + key; if(current_target_item->next == NULL) { - byte = key / 32; - bit = key % 32; + byte = (uint32_t)(key / 32); + bit = (uint8_t)(key % 32); - *(hashmap->item_occupation + byte) &= ~(0 << bit); + *(hashmap->item_occupation + byte) &= (uint32_t)(~(0 << bit)); } goto find_item; @@ -302,4 +302,4 @@ void hashmap_destroy(struct SwiftNetHashMap* const hashmap) { } free(hashmap->items); -} \ No newline at end of file +} diff --git a/src/internal/datatype_vector.c b/src/internal/datatype_vector.c index e9d70a6..f4d7903 100644 --- a/src/internal/datatype_vector.c +++ b/src/internal/datatype_vector.c @@ -68,4 +68,5 @@ void* vector_get(struct SwiftNetVector* const vector, const uint32_t index) { data_ptr = ((void**)vector->data) + index; return *data_ptr; -} \ No newline at end of file +} + diff --git a/src/internal/dpdk/dpdk_buffer.c b/src/internal/dpdk/dpdk_buffer.c new file mode 100644 index 0000000..38a31ef --- /dev/null +++ b/src/internal/dpdk/dpdk_buffer.c @@ -0,0 +1,263 @@ +#include "../internal.h" +#include "../networking.h" +#include "../../swift_net.h" +#include +#include +#include +#include +#include +#include + +static inline ALWAYS_INLINE uint16_t mbuf_size_for_data(const uint16_t data_size, const uint8_t prepend_size) { + return data_size + PACKET_HEADER_SIZE + prepend_size; +} + +static inline ALWAYS_INLINE uint16_t mbuf_size_for_full_chunk(const uint8_t prepend_size) { + return maximum_transmission_unit + prepend_size; +} + +static inline struct SwiftNetPacketBuffer create_packet_buffer(const uint32_t buffer_size, const struct SwiftNetNetworkData* const network_data) { + uint32_t chunk_amount; + uint16_t remaining_data; + uint16_t data_len_per_packet; + struct rte_mbuf** buffers; + + data_len_per_packet = (uint16_t)(maximum_transmission_unit - PACKET_HEADER_SIZE); + + remaining_data = (uint16_t)(buffer_size % data_len_per_packet); + chunk_amount = buffer_size / data_len_per_packet; + + buffers = malloc(sizeof(void*) * (chunk_amount + 1)); + + if (chunk_amount > 0) { + rte_pktmbuf_alloc_bulk(network_data->mem_pool, buffers, chunk_amount); + + for(uint32_t i = 0; i < chunk_amount; i++) { + struct rte_mbuf* restrict current_buffer; + + + current_buffer = buffers[i]; + + rte_pktmbuf_append(current_buffer, mbuf_size_for_full_chunk(GET_PREPEND_SIZE(network_data))); + } + } + + buffers[chunk_amount] = rte_pktmbuf_alloc(network_data->mem_pool); + + rte_pktmbuf_append(buffers[chunk_amount], mbuf_size_for_data(remaining_data, GET_PREPEND_SIZE(network_data))); + + return (struct SwiftNetPacketBuffer){ + .buf_amount = chunk_amount + 1, + .dpdk_buffers = buffers, + .total_data_size = buffer_size, + .data_len_per_packet = data_len_per_packet, + .append_offset = 0 + }; +} + +struct SwiftNetPacketBuffer swiftnet_client_create_packet_buffer(const uint32_t buffer_size, const struct SwiftNetClientConnection* const client_connection) { + return create_packet_buffer(buffer_size, &client_connection->network_data); +} + +struct SwiftNetPacketBuffer swiftnet_server_create_packet_buffer(const uint32_t buffer_size, const struct SwiftNetServer* const server) { + return create_packet_buffer(buffer_size, &server->network_data); +} + +static inline void resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer, const struct SwiftNetNetworkData* const network_data) { + uint32_t data_size_change; + uint16_t data_len_per_packet; + uint8_t prepend_size; + struct rte_mbuf* restrict last_packet; + uint16_t last_packet_data_size; + + data_len_per_packet = packet_buffer->data_len_per_packet; + prepend_size = GET_PREPEND_SIZE(network_data); + + if (unlikely(new_buffer_size == packet_buffer->total_data_size)) { + return; + } + + last_packet = packet_buffer->dpdk_buffers[packet_buffer->buf_amount - 1]; + last_packet_data_size = last_packet->data_len - PACKET_HEADER_SIZE - prepend_size; + + if (new_buffer_size > packet_buffer->total_data_size) { + uint32_t chunk_amount; + uint16_t remainder; + uint32_t new_slots; + struct rte_mbuf** restrict new_buffers; + + data_size_change = new_buffer_size - packet_buffer->total_data_size; + + if (data_size_change + last_packet_data_size <= data_len_per_packet) { + rte_pktmbuf_append(last_packet, (uint16_t)data_size_change); + packet_buffer->total_data_size = new_buffer_size; + return; + } + + rte_pktmbuf_append(last_packet, data_len_per_packet - last_packet_data_size); + data_size_change -= data_len_per_packet - last_packet_data_size; + + chunk_amount = data_size_change / data_len_per_packet; + remainder = (uint16_t)(data_size_change % data_len_per_packet); + new_slots = chunk_amount + (remainder != 0 ? 1 : 0); + + new_buffers = realloc(packet_buffer->dpdk_buffers, sizeof(void*) * (packet_buffer->buf_amount + new_slots)); + if (unlikely(new_buffers == NULL)) { + PRINT_ERROR("Failed to realloc"); + exit(EXIT_FAILURE); + } + + packet_buffer->dpdk_buffers = new_buffers; + + if (chunk_amount > 0) { + rte_pktmbuf_alloc_bulk(network_data->mem_pool, packet_buffer->dpdk_buffers + packet_buffer->buf_amount, chunk_amount); + + for (uint32_t i = 0; i < chunk_amount; i++) { + rte_pktmbuf_append(packet_buffer->dpdk_buffers[packet_buffer->buf_amount + i], mbuf_size_for_full_chunk(prepend_size)); + } + + packet_buffer->buf_amount += chunk_amount; + } + + if (likely(remainder != 0)) { + struct rte_mbuf* restrict new_last_packet; + + new_last_packet = rte_pktmbuf_alloc(network_data->mem_pool); + packet_buffer->dpdk_buffers[packet_buffer->buf_amount] = new_last_packet; + rte_pktmbuf_append(new_last_packet, mbuf_size_for_data(remainder, prepend_size)); + packet_buffer->buf_amount++; + } + + packet_buffer->total_data_size = new_buffer_size; + + return; + } + + data_size_change = packet_buffer->total_data_size - new_buffer_size; + + if (data_size_change <= last_packet_data_size) { + uint16_t new_last_packet_data_size; + uint16_t new_size; + + new_last_packet_data_size = (uint16_t)(last_packet_data_size - data_size_change); + new_size = mbuf_size_for_data(new_last_packet_data_size, prepend_size); + + last_packet->data_len = new_size; + last_packet->pkt_len = new_size; + + packet_buffer->total_data_size = new_buffer_size; + + return; + } + + data_size_change -= last_packet_data_size; + rte_pktmbuf_free(last_packet); + packet_buffer->buf_amount--; + + while (data_size_change >= data_len_per_packet && packet_buffer->buf_amount > 1) { + rte_pktmbuf_free(packet_buffer->dpdk_buffers[packet_buffer->buf_amount - 1]); + packet_buffer->buf_amount--; + data_size_change -= data_len_per_packet; + } + + last_packet = packet_buffer->dpdk_buffers[packet_buffer->buf_amount - 1]; + last_packet_data_size = last_packet->data_len - PACKET_HEADER_SIZE - prepend_size; + + if (data_size_change >= last_packet_data_size) { + rte_pktmbuf_free(last_packet); + packet_buffer->buf_amount--; + + last_packet = rte_pktmbuf_alloc(network_data->mem_pool); + packet_buffer->dpdk_buffers[packet_buffer->buf_amount] = last_packet; + rte_pktmbuf_append(last_packet, mbuf_size_for_data(0, prepend_size)); + packet_buffer->buf_amount++; + } else { + uint16_t data_size = mbuf_size_for_data((uint16_t)(last_packet_data_size - data_size_change), prepend_size); + + last_packet->data_len = data_size; + last_packet->pkt_len = data_size; + } + + packet_buffer->dpdk_buffers = realloc(packet_buffer->dpdk_buffers, sizeof(void*) * packet_buffer->buf_amount); + packet_buffer->total_data_size = new_buffer_size; +} + +void swiftnet_client_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer, const struct SwiftNetClientConnection* const client_connection) { + resize_packet_buffer(new_buffer_size, packet_buffer, &client_connection->network_data); +} + +void swiftnet_server_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer, const struct SwiftNetServer* const server) { + resize_packet_buffer(new_buffer_size, packet_buffer, &server->network_data); +} + +static inline void write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, const void* restrict data, uint32_t data_size) { + uint32_t chunk_num_start; + uint32_t current_offset; + uint32_t bytes_remaining; + + chunk_num_start = byte_offset / packet_buffer->data_len_per_packet; + current_offset = byte_offset % packet_buffer->data_len_per_packet; + bytes_remaining = data_size; + + while (bytes_remaining > 0) { + struct rte_mbuf* restrict current_buf; + uint8_t* buf_addr; + uint32_t bytes_this_chunk; + uint32_t real_offset; + uint32_t reserved_header; + + current_buf = packet_buffer->dpdk_buffers[chunk_num_start]; + + reserved_header = maximum_transmission_unit - packet_buffer->data_len_per_packet + sizeof(struct ether_header); + real_offset = reserved_header + current_offset; + + bytes_this_chunk = MIN(packet_buffer->data_len_per_packet - current_offset, bytes_remaining); + + buf_addr = rte_pktmbuf_mtod(current_buf, uint8_t*); + + memcpy(buf_addr + real_offset, data, bytes_this_chunk); + + data = (uint8_t*)data + bytes_this_chunk; + bytes_remaining -= bytes_this_chunk; + current_offset = 0; + chunk_num_start++; + } +} + +void swiftnet_client_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, void* restrict const data, const uint32_t data_size, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + write_packet_buffer(byte_offset, packet_buffer, data, data_size); +} + +void swiftnet_server_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, void* restrict const data, const uint32_t data_size, MAYBE_UNUSED const struct SwiftNetServer* const server) { + write_packet_buffer(byte_offset, packet_buffer, data, data_size); +} + +static inline void validate_append_to_packet_args(const void* restrict const data, const uint32_t data_size) { + if(unlikely(data == NULL || data_size == 0)) { + PRINT_ERROR("Error: Invalid arguments given"); + exit(EXIT_FAILURE); + } +} + +void swiftnet_append_to_buffer(const void* restrict const data, const uint32_t data_size, struct SwiftNetPacketBuffer* restrict const buffer) { + #ifdef SWIFT_NET_ERROR + validate_append_to_packet_args(data, data_size); + #endif + + write_packet_buffer(buffer->append_offset, buffer, data, data_size); + + buffer->append_offset += data_size; +} + +static inline void destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet) { + rte_pktmbuf_free_bulk(packet->dpdk_buffers, packet->buf_amount); + free(packet->dpdk_buffers); +} + +void swiftnet_client_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + destroy_packet_buffer(packet); +} + +void swiftnet_server_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, MAYBE_UNUSED const struct SwiftNetServer* const server) { + destroy_packet_buffer(packet); +} diff --git a/src/internal/dpdk/dpdk_open.c b/src/internal/dpdk/dpdk_open.c new file mode 100644 index 0000000..83b89b6 --- /dev/null +++ b/src/internal/dpdk/dpdk_open.c @@ -0,0 +1,31 @@ +#include + +#include "../networking.h" + +void swiftnet_dpdk_open_port(const uint16_t port, struct SwiftNetNetworkData* const network_data) { + struct rte_eth_conf port_conf = {0}; + char name[32]; + + port_conf.rxmode.mtu = RTE_ETHER_MAX_LEN; + + snprintf(name, sizeof(name), "mbuf_pool_%u", port); + + network_data->mem_pool = rte_pktmbuf_pool_create(name, 1024, 512, 0,RTE_MBUF_DEFAULT_BUF_SIZE, (int)rte_socket_id()); + + if (unlikely(network_data->mem_pool == NULL)) + rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); + + if (unlikely(rte_eth_dev_configure(port, 1, 1, &port_conf) < 0)) + rte_exit(EXIT_FAILURE, "Cannot configure port\n"); + + if (unlikely(rte_eth_rx_queue_setup(port, 0, 128, rte_socket_id(), NULL, network_data->mem_pool) < 0)) + rte_exit(EXIT_FAILURE, "Cannot setup RX queue\n"); + + if (unlikely(rte_eth_tx_queue_setup(port, 0, 128, rte_socket_id(), NULL) < 0)) + rte_exit(EXIT_FAILURE, "Cannot setup TX queue\n"); + + if (unlikely(rte_eth_dev_start(port) < 0)) + rte_exit(EXIT_FAILURE, "Cannot start port\n"); + + rte_eth_promiscuous_enable(port); +} diff --git a/src/internal/dpdk/dpdk_send.c b/src/internal/dpdk/dpdk_send.c new file mode 100644 index 0000000..28aa8bd --- /dev/null +++ b/src/internal/dpdk/dpdk_send.c @@ -0,0 +1,12 @@ +#include "../internal.h" +#include + +int swiftnet_dpdk_send(const struct SwiftNetNetworkData* const network_data, struct rte_mbuf* buf) { + struct rte_mbuf* buf_clone = rte_pktmbuf_clone(buf, network_data->mem_pool); + + if(rte_eth_tx_burst(network_data->port, 0, &buf_clone, 1) != 1) { + rte_pktmbuf_free(buf_clone); + }; + + return 0; +} diff --git a/src/internal/get_default_interface_and_mac.c b/src/internal/get_default_interface_and_mac.c index 086fcbf..0ceda94 100644 --- a/src/internal/get_default_interface_and_mac.c +++ b/src/internal/get_default_interface_and_mac.c @@ -123,4 +123,5 @@ int get_default_interface_and_mac(char* restrict interface_name, const uint32_t } return 0; -} \ No newline at end of file +} + diff --git a/src/internal/get_mtu.c b/src/internal/get_mtu.c index 5198bba..a3d82a5 100644 --- a/src/internal/get_mtu.c +++ b/src/internal/get_mtu.c @@ -3,13 +3,14 @@ #include "stdio.h" #include #include +#include #include #include #include #include #include -const uint32_t get_mtu(const char* restrict const interface, const int sockfd) { +uint16_t get_mtu(const char* restrict const interface, const int sockfd) { struct ifreq ifr; @@ -21,5 +22,5 @@ const uint32_t get_mtu(const char* restrict const interface, const int sockfd) { exit(EXIT_FAILURE); } - return ifr.ifr_mtu; -} \ No newline at end of file + return (uint16_t)ifr.ifr_mtu; +} diff --git a/src/internal/internal.h b/src/internal/internal.h index 40df122..e21c20a 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -19,10 +19,36 @@ #include #endif +#define STRINGIFY(...) #__VA_ARGS__ +#define TOSTRING(...) STRINGIFY(__VA_ARGS__) + +#define ASSUME(cond) __builtin_assume(cond) +#define ALWAYS_INLINE __attribute__((always_inline)) +#define MAYBE_UNUSED [[maybe_unused]] + +#ifdef SWIFT_NET_BACKEND_PCAP + #define PCAP_ONLY + #define DPDK_ONLY MAYBE_UNUSED +#elif defined(SWIFT_NET_BACKEND_DPDK) + #define PCAP_ONLY MAYBE_UNUSED + #define DPDK_ONLY +#endif + +#ifdef SWIFT_NET_BACKEND_DPDK +extern uint32_t lcores_used[]; +#endif + +#ifdef SWIFT_NET_BACKEND_PCAP #ifdef __linux__ -#define LOOPBACK_INTERFACE_NAME "lo\0" +#define CLIENT_LOOPBACK_INTERFACE_NAME "lo\0" +#define SERVER_LOOPBACK_INTERFACE_NAME "lo\0" #elif defined(__APPLE__) -#define LOOPBACK_INTERFACE_NAME "lo0\0" +#define CLIENT_LOOPBACK_INTERFACE_NAME "lo0\0" +#define SERVER_LOOPBACK_INTERFACE_NAME "lo0\0" +#endif +#elif defined(SWIFT_NET_BACKEND_DPDK) +#define CLIENT_LOOPBACK_INTERFACE_NAME "net_ring0\0" +#define SERVER_LOOPBACK_INTERFACE_NAME "net_ring0\0" #endif #ifdef SWIFT_NET_INTERNAL_TESTING @@ -38,6 +64,12 @@ enum RequestLostPacketsReturnType { REQUEST_LOST_PACKETS_RETURN_COMPLETED_PACKET = 0x01 }; +struct ReceiverPacketData { + const uint8_t* const data; + DPDK_ONLY struct rte_mbuf* dpdk_buf; + uint32_t data_len; +}; + // in body use variables "hashmap_item" and "hashmap_data" // "hashmap_item" contains pointer to current struct SwiftNetHashMapItem // "hashmap_data" contains data stored inside struct SwiftNetHashMapItem @@ -49,7 +81,7 @@ enum RequestLostPacketsReturnType { } \ uint32_t inverted = ~(current_index); \ while(inverted != UINT32_MAX) { \ - uint32_t bit_index = __builtin_ctz(inverted); \ + uint32_t bit_index = (uint32_t)(__builtin_ctzl(inverted)); \ inverted |= 1 << bit_index; \ for(struct SwiftNetHashMapItem* hashmap_item = (hashmap)->items + ((i * 32) + bit_index); hashmap_item != NULL; hashmap_item = hashmap_item->next) { \ void* const hashmap_data = hashmap_item->value; \ @@ -71,7 +103,11 @@ enum RequestLostPacketsReturnType { // Size of memory allocated before ip header. // Memory should contain either an eth hdr or any specific data depending on addr type (loopback or real interface) +#ifdef SWIFT_NET_BACKEND_DPDK +#define PACKET_PREPEND_SIZE(addr_type) sizeof(struct ether_header) +#elif defined(SWIFT_NET_BACKEND_PCAP) #define PACKET_PREPEND_SIZE(addr_type) ((addr_type == DLT_NULL) ? sizeof(uint32_t) : addr_type == DLT_EN10MB ? sizeof(struct ether_header) : 0) +#endif #define PACKET_HEADER_SIZE (sizeof(struct ip) + sizeof(struct SwiftNetPacketInfo)) #define DEFAULT_MAC_ADDRESS_STRUCT (struct ether_header){.ether_dhost = {0xff,0xff,0xff,0xff,0xff,0xff}, .ether_type = htons(0x0800)} @@ -85,27 +121,32 @@ enum RequestLostPacketsReturnType { // How many seconds between each memory cleanup. #define PACKET_HISTORY_STORE_TIME 5 -#define PRINT_ERROR(fmt, ...) \ - do { fprintf(stderr, fmt " | function: %s | line: %d\n", ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0) +#define PRINT_ERROR(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, " | function: %s | line: %d\n", __func__, __LINE__); \ + } while (0) #define MIN(one, two) (one > two ? two : one) -static inline void* swiftnet_allocate_memory(const uint32_t size) { +/* +inline void* swiftnet_allocate_memory(const uint32_t size) { // Future return NULL; } -static inline void swiftnet_free_memory(const uint32_t size, const void* restrict const ptr) { +inline void swiftnet_free_memory(const uint32_t size, const void* restrict const ptr) { // Future return; } -static inline void swiftnet_reallocate_memory(const uint32_t new_size, const void* restrict const ptr) { +inline void swiftnet_reallocate_memory(const uint32_t new_size, const void* restrict const ptr) { // Future return; } +*/ -static inline uint32_t crc32(const uint8_t* const data, const uint32_t length) { +static inline ALWAYS_INLINE uint32_t crc32(const uint8_t* const data, const uint32_t length) { const uint8_t* ptr = data; uint32_t remaining = length; uint32_t crc = 0xFFFFFFFF; @@ -142,7 +183,12 @@ struct PacketCompletedKey { struct Listener { struct SwiftNetNetworkData network_data; + #ifdef SWIFT_NET_BACKEND_PCAP pthread_t listener_thread; + #elif defined(SWIFT_NET_BACKEND_DPDK) + uint32_t lcore; + uint16_t lcore_internal_index; + #endif struct SwiftNetHashMap servers; struct SwiftNetHashMap client_connections; char interface_name[IFNAMSIZ]; @@ -165,10 +211,10 @@ extern struct SwiftNetMemoryAllocator packet_completed_key_allocator; extern pthread_t memory_cleanup_thread; extern _Atomic bool swiftnet_closing; -extern void* memory_cleanup_background_service(); +extern void* memory_cleanup_background_service(void* user); extern int get_default_interface_and_mac(char* restrict interface_name, const uint32_t interface_name_length, uint8_t* restrict mac_out, const int sockfd); -extern const uint32_t get_mtu(const char* restrict const interface, const int sockfd); +extern uint16_t get_mtu(const char* restrict const interface, const int sockfd); extern void* swiftnet_server_process_packets(void* const void_server); extern void* swiftnet_client_process_packets(void* const void_client); @@ -190,31 +236,17 @@ extern uint32_t items_leaked; #ifdef SWIFT_NET_DEBUG extern struct SwiftNetDebugger debugger; -static inline bool check_debug_flag(const SwiftNetDebugFlags flag) { +static inline ALWAYS_INLINE bool check_debug_flag(const SwiftNetDebugFlags flag) { return (debugger.flags & flag) != 0; } -static inline void send_debug_message(const char* restrict const message, ...) { +MAYBE_UNUSED __attribute__((format(printf, 1, 2))) static inline ALWAYS_INLINE void send_debug_message(const char *restrict const message, ...) { va_list args; - char* prefix; - uint32_t prefix_length; - uint32_t message_length; - va_start(args, message); - prefix = "[DEBUG] "; - - prefix_length = strlen(prefix); - message_length = strlen(message); - - char full_message[prefix_length + message_length + 1]; - - memcpy(full_message, prefix, prefix_length); - memcpy(full_message + prefix_length, message, message_length); - full_message[prefix_length + message_length] = '\0'; - - vprintf(full_message, args); + printf("[DEBUG] "); + vprintf(message, args); va_end(args); } @@ -249,7 +281,8 @@ extern struct SwiftNetMemoryAllocator client_connection_memory_allocator; extern struct SwiftNetMemoryAllocator listener_memory_allocator; extern struct SwiftNetMemoryAllocator hashmap_item_memory_allocator; -extern void* interface_start_listening(void* const listener_void); +extern void* interface_start_listening_pcap(void* const listener_void); +extern int interface_start_listening_dpdk(void* const listener_void); extern void* vector_get(struct SwiftNetVector* const vector, const uint32_t index); extern void vector_remove(struct SwiftNetVector* const vector, const uint32_t index); @@ -278,8 +311,7 @@ extern struct SwiftNetHashMap requests_sent; #endif extern void swiftnet_send_packet( - const void* const connection, - const uint32_t target_maximum_transmission_unit, + const uint16_t target_maximum_transmission_unit, const struct SwiftNetPortInfo port_info, const struct SwiftNetPacketBuffer* const packet, const uint32_t packet_length, @@ -287,7 +319,6 @@ extern void swiftnet_send_packet( struct SwiftNetHashMap* const packets_sending, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, const struct ether_header eth_hdr, - const bool loopback, const struct SwiftNetNetworkData network_data #ifdef SWIFT_NET_REQUESTS , struct RequestSent* const request_sent @@ -296,31 +327,31 @@ extern void swiftnet_send_packet( #endif ); -static inline struct SwiftNetPacketInfo construct_packet_info(const uint32_t packet_length, const uint8_t packet_type, const uint32_t chunk_amount, const uint32_t chunk_index, const struct SwiftNetPortInfo port_info) { +static inline ALWAYS_INLINE struct SwiftNetPacketInfo construct_packet_info(const uint32_t packet_length, const uint8_t packet_type, const uint32_t chunk_amount, const uint32_t chunk_index, const struct SwiftNetPortInfo port_info) { return (struct SwiftNetPacketInfo){ .packet_length = packet_length, - .packet_type = packet_type, .chunk_amount = chunk_amount, .chunk_index = chunk_index, .maximum_transmission_unit = maximum_transmission_unit, + .checksum = 0x00, .port_info = port_info, - .checksum = 0x00 + .packet_type = packet_type }; } -static struct ip construct_ip_header(const struct in_addr destination_addr, const uint32_t packet_size, const uint16_t packet_id) { +static inline ALWAYS_INLINE struct ip construct_ip_header(const struct in_addr destination_addr, const uint16_t packet_size, const uint16_t packet_id) { struct ip ip_header; ip_header = (struct ip){ - .ip_v = 4, .ip_hl = 5, + .ip_v = 4, .ip_tos = 0, - .ip_p = PROT_NUMBER, .ip_len = htons(packet_size), .ip_id = htons(packet_id), .ip_off = htons(0), .ip_ttl = 64, + .ip_p = PROT_NUMBER, .ip_sum = htons(0), .ip_src = private_ip_address, .ip_dst = destination_addr diff --git a/src/internal/networking.h b/src/internal/networking.h index a8fde7f..54db59a 100644 --- a/src/internal/networking.h +++ b/src/internal/networking.h @@ -7,11 +7,17 @@ #ifdef SWIFT_NET_BACKEND_PCAP +#include #include + #define WAIT_LISTENER_THREAD(listener) \ + pthread_join((listener)->listener_thread, NULL); + // Simple crc16 call with proper memory order #define HANDLE_CHECKSUM(buffer, size, network_data) \ + { \ const uint32_t checksum = crc32(buffer, size); \ - memcpy(buffer + (network_data)->prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), &checksum, sizeof(checksum)); + memcpy(buffer + (network_data)->prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), &checksum, sizeof(checksum)); \ + } #define GET_ADDR_TYPE(network_data) (network_data)->addr_type #define GET_PREPEND_SIZE(network_data) (network_data)->prepend_size @@ -27,22 +33,25 @@ memcpy(buffer_name, eth_hdr, sizeof(*eth_hdr)); \ memcpy(buffer_name + sizeof(*eth_hdr), ip_header, sizeof(*ip_header)); \ memcpy(buffer_name + sizeof(*eth_hdr) + sizeof(*ip_header), packet_info, sizeof(*packet_info)); \ - } \ + } + #define FREE_PACKET_CONSTRUCTION(buffer_name, network_data) extern pcap_t* swiftnet_pcap_open(const char* const restrict interface); - extern int swiftnet_pcap_send(pcap_t *pcap, const uint8_t *data, int len); + extern int swiftnet_pcap_send(pcap_t *pcap, const uint8_t *data, const uint32_t len); inline static struct SwiftNetNetworkData swiftnet_initialize_networking(const char* const restrict interface) { pcap_t* pcap = swiftnet_pcap_open(interface); if (unlikely(pcap == NULL)) { + PRINT_ERROR("Failed to open pcap"); + struct SwiftNetNetworkData net_data_null; memset(&net_data_null, 0x00, sizeof(net_data_null)); return net_data_null; } - const uint8_t addr_type = pcap_datalink(pcap); + const uint8_t addr_type = (uint8_t)pcap_datalink(pcap); struct SwiftNetNetworkData network_data = { .pcap = pcap, @@ -53,15 +62,11 @@ return network_data; } - inline static void swiftnet_close_connection(struct SwiftNetNetworkData* restrict const network_data) { - pcap_close(network_data->pcap); - } - #define SWIFTNET_BREAK_RECEIVER_LOOP(network_data) \ pcap_breakloop((network_data)->pcap) #define SWIFTNET_LOOP_PACKETS(network_data, listener) \ - pcap_loop((network_data)->pcap, 0, pcap_packet_handle, (void*)listener) + pcap_loop((network_data)->pcap, 0, pcap_packet_handle, (void*)listener); #define SWIFTNET_CLOSE_CONNECTION(network_data) \ pcap_close((network_data)->pcap); @@ -70,6 +75,103 @@ while(swiftnet_pcap_send((network_data)->pcap, buffer, len) == -2) { \ usleep(2000); \ } -#elif SWIFTNET_PCAP_DPDK -// future backend functions + + #define SWIFTNET_SEND_INTERNAL_PACKET(network_data, buffer, len) \ + while(swiftnet_pcap_send((network_data)->pcap, buffer, len) == -2) { \ + usleep(2000); \ + } +#elif defined(SWIFT_NET_BACKEND_DPDK) + #include + #include + + #define WAIT_LISTENER_THREAD(listener) \ + rte_eal_wait_lcore((listener)->lcore); + + #define HANDLE_CHECKSUM(buffer, size, network_data) \ + { \ + const uint32_t checksum = crc32(buffer, size); \ + memcpy((uint8_t*)buffer + (network_data)->prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), &checksum, sizeof(checksum)); \ + } + + #define GET_ADDR_TYPE(network_data) (network_data)->addr_type + #define GET_PREPEND_SIZE(network_data) (network_data)->prepend_size + + #define HANDLE_PACKET_CONSTRUCTION(ip_header, packet_info, network_data, eth_hdr, buffer_size, buffer_name) \ + struct rte_mbuf* buffer_name##_internal_mem_buf = rte_pktmbuf_alloc((network_data)->mem_pool); \ + if(unlikely(buffer_name##_internal_mem_buf == NULL)) { \ + PRINT_ERROR("Failed to alloc pktmbuf"); \ + exit(EXIT_FAILURE); \ + } \ + uint8_t* restrict const buffer_name = (uint8_t*)rte_pktmbuf_append(buffer_name##_internal_mem_buf, buffer_size); \ + ASSUME(buffer_name != NULL); \ + buffer_name##_internal_mem_buf->data_len = buffer_size; \ + buffer_name##_internal_mem_buf->pkt_len = buffer_size; \ + if((network_data)->addr_type == 0) { \ + memcpy(buffer_name, ip_header, sizeof(*ip_header)); \ + memcpy(buffer_name + sizeof(*ip_header), packet_info, sizeof(*packet_info)); \ + } else { \ + memcpy(buffer_name, eth_hdr, sizeof(*eth_hdr)); \ + memcpy(buffer_name + sizeof(*eth_hdr), ip_header, sizeof(*ip_header)); \ + memcpy(buffer_name + sizeof(*eth_hdr) + sizeof(*ip_header), packet_info, sizeof(*packet_info)); \ + } + + #define SWIFTNET_LOOP_PACKETS(network_data, listener) \ + while(atomic_load_explicit(&(network_data)->closing, memory_order_acquire) == false) { \ + struct rte_mbuf* buffers[DPDK_BURST_SIZE]; \ + uint16_t nb_rx = rte_eth_rx_burst((network_data)->port, 0, buffers, DPDK_BURST_SIZE); \ + if (likely(nb_rx > 0)) { \ + for (uint16_t i = 0; i < nb_rx; i++) { \ + struct rte_mbuf* buffer = buffers[i]; \ + uint8_t* const raw_data_ptr = rte_pktmbuf_mtod(buffer, uint8_t*); \ + dpdk_packet_handle(listener, buffer, raw_data_ptr); \ + } \ + } else { \ + rte_pause(); \ + } \ + } + + #define FREE_PACKET_CONSTRUCTION(buffer_name, network_data) \ + rte_pktmbuf_free(buffer_name##_internal_mem_buf); + + #define SWIFTNET_BREAK_RECEIVER_LOOP(network_data) \ + atomic_store_explicit(&(network_data)->closing, true, memory_order_release); + + extern void swiftnet_dpdk_open_port(const uint16_t port, struct SwiftNetNetworkData* restrict const); + extern int swiftnet_dpdk_send(const struct SwiftNetNetworkData* const network_data, struct rte_mbuf* buf); + + inline static struct SwiftNetNetworkData swiftnet_initialize_networking(const char* const restrict interface) { + struct SwiftNetNetworkData network_data; + uint16_t interface_port; + int ret; + + ret = rte_eth_dev_get_port_by_name(interface, &interface_port); + + if(ret < 0) { + PRINT_ERROR("Failed to get dpdk port id on interface: %s err = %d", interface, ret); + exit(EXIT_FAILURE); + } + + network_data = (struct SwiftNetNetworkData) { + .port = interface_port, + .addr_type = 1, + .prepend_size = sizeof(struct ether_header) + }; + + swiftnet_dpdk_open_port(interface_port, &network_data); + + atomic_store_explicit(&network_data.closing, false, memory_order_release); + + return network_data; + } + + + #define SWIFTNET_CLOSE_CONNECTION(network_data) \ + rte_eth_dev_stop((network_data)->port); \ + rte_mempool_free((network_data)->mem_pool); + + #define SWIFTNET_SEND_INTERNAL_PACKET(network_data, buffer, len) \ + swiftnet_dpdk_send((network_data), buffer##_internal_mem_buf); + + #define SWIFTNET_SEND_PACKET(network_data, buffer) \ + swiftnet_dpdk_send((network_data), buffer); #endif diff --git a/src/internal/pcap/pcap_buffer.c b/src/internal/pcap/pcap_buffer.c new file mode 100644 index 0000000..51eb25b --- /dev/null +++ b/src/internal/pcap/pcap_buffer.c @@ -0,0 +1,102 @@ +#include "../internal.h" +#include "../../swift_net.h" +#include +#include +#include + +static inline struct SwiftNetPacketBuffer create_packet_buffer(const uint32_t buffer_size) { + uint8_t* restrict const mem = malloc(buffer_size + PACKET_HEADER_SIZE + sizeof(struct ether_header)); + uint8_t* restrict const data_pointer = mem + PACKET_HEADER_SIZE + sizeof(struct ether_header); + + return (struct SwiftNetPacketBuffer){ + .packet_buffer_start = mem, + .packet_data_start = data_pointer, + .packet_append_pointer = data_pointer + }; +} + +struct SwiftNetPacketBuffer swiftnet_client_create_packet_buffer(const uint32_t buffer_size, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + return create_packet_buffer(buffer_size); +} + +struct SwiftNetPacketBuffer swiftnet_server_create_packet_buffer(const uint32_t buffer_size, MAYBE_UNUSED const struct SwiftNetServer* const server) { + return create_packet_buffer(buffer_size); +} + +static inline void resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer) { + uint8_t* new_ptr; + uint8_t* data_start; + + const uint32_t current_offset = (uint32_t)(packet_buffer->packet_append_pointer - packet_buffer->packet_data_start); + + + new_buffer_size += PACKET_HEADER_SIZE + sizeof(struct ether_header); + + new_ptr = realloc(packet_buffer->packet_buffer_start, new_buffer_size); + if (unlikely(new_ptr == NULL)) { + PRINT_ERROR("Failed to realloc"); + exit(EXIT_FAILURE); + } + + data_start = new_ptr + PACKET_HEADER_SIZE + sizeof(struct ether_header); + + *packet_buffer = (struct SwiftNetPacketBuffer){ + .packet_buffer_start = new_ptr, + .packet_data_start = data_start, + .packet_append_pointer = data_start + current_offset + }; +} + +void swiftnet_client_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + resize_packet_buffer(new_buffer_size, packet_buffer); +} + +void swiftnet_server_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer, MAYBE_UNUSED const struct SwiftNetServer* const server) { + resize_packet_buffer(new_buffer_size, packet_buffer); +} + +static inline void write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, const void* restrict const data, const uint32_t data_size) { + memcpy(packet_buffer->packet_data_start + byte_offset, data, data_size); +} + +void swiftnet_client_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, void* restrict const data, const uint32_t data_size, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + write_packet_buffer(byte_offset, packet_buffer, data, data_size); +} + +void swiftnet_server_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, void* restrict const data, const uint32_t data_size, MAYBE_UNUSED const struct SwiftNetServer* const server) { + write_packet_buffer(byte_offset, packet_buffer, data, data_size); +} + +// These functions append data to a packet buffer and advance the current pointer by the data size. +static inline void validate_append_to_packet_args(const void* restrict const data, const uint32_t data_size) { + if(unlikely(data == NULL || data_size == 0)) { + PRINT_ERROR("Error: Invalid arguments given"); + exit(EXIT_FAILURE); + } +} + +static inline void append_data(uint8_t* restrict * restrict const append_pointer, const void* restrict const data, const uint32_t data_size) { + memcpy(*append_pointer, data, data_size); + + (*append_pointer) += data_size; +} + +void swiftnet_append_to_buffer(const void* restrict const data, const uint32_t data_size, struct SwiftNetPacketBuffer* restrict const buffer) { + #ifdef SWIFT_NET_ERROR + validate_append_to_packet_args(data, data_size); + #endif + + append_data(&buffer->packet_append_pointer, data, data_size); +} + +static inline void destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet) { + free(packet->packet_buffer_start); +} + +void swiftnet_client_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, MAYBE_UNUSED const struct SwiftNetClientConnection* const client_connection) { + destroy_packet_buffer(packet); +} + +void swiftnet_server_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, MAYBE_UNUSED const struct SwiftNetServer* const server) { + destroy_packet_buffer(packet); +} diff --git a/src/internal/pcap/pcap_open.c b/src/internal/pcap/pcap_open.c index 65aff3d..946f5f3 100644 --- a/src/internal/pcap/pcap_open.c +++ b/src/internal/pcap/pcap_open.c @@ -14,7 +14,7 @@ pcap_t* swiftnet_pcap_open(const char* const restrict interface) { p = pcap_open_live( interface, 65535, - 0, + 1, 25, errbuf ); @@ -33,5 +33,6 @@ pcap_t* swiftnet_pcap_open(const char* const restrict interface) { PRINT_ERROR("Unable to set filter: %s", pcap_geterr(p)); } + return p; } diff --git a/src/internal/pcap/pcap_send.c b/src/internal/pcap/pcap_send.c index 680d609..66b0518 100644 --- a/src/internal/pcap/pcap_send.c +++ b/src/internal/pcap/pcap_send.c @@ -2,11 +2,11 @@ #include #include -int swiftnet_pcap_send(pcap_t* const pcap, const uint8_t* restrict const data, const int len) { +int swiftnet_pcap_send(pcap_t* const pcap, const uint8_t* restrict const data, const uint32_t len) { int ret; - ret = pcap_inject(pcap, data, len); + ret = pcap_inject(pcap, data, (size_t)len); if(ret == -1) { if(errno == ENOBUFS) { diff --git a/src/make_request.c b/src/make_request.c index c6766dd..a06f03b 100644 --- a/src/make_request.c +++ b/src/make_request.c @@ -18,7 +18,7 @@ static inline void delete_request_sent(struct RequestSent* restrict const reques allocator_free(&requests_sent_memory_allocator, request_sent); } -static inline struct RequestSent* const construct_request_sent(const struct in_addr address) { +static inline struct RequestSent* construct_request_sent(const struct in_addr address) { struct RequestSent* const request_sent = allocator_allocate(&requests_sent_memory_allocator); *request_sent = (struct RequestSent){.address = address, .packet_data = NULL}; @@ -35,20 +35,24 @@ struct SwiftNetClientPacketData* swiftnet_client_make_request(struct SwiftNetCli request_sent = construct_request_sent(client->server_addr); - packet_length = packet->packet_append_pointer - packet->packet_data_start; + #ifdef SWIFT_NET_BACKEND_DPDK + packet_length = packet->total_data_size; + #else + packet_length = (uint32_t)(packet->packet_append_pointer - packet->packet_data_start); + #endif - swiftnet_send_packet(client, client->maximum_transmission_unit, client->port_info, packet, packet_length, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->loopback, client->network_data, request_sent, false, 0); + swiftnet_send_packet(client->maximum_transmission_unit, client->port_info, packet, packet_length, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->network_data, request_sent, false, 0); gettimeofday(&tv, NULL); - start = (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + start = (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); goto check_response; check_response: gettimeofday(&tv, NULL); - end = (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + end = (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); if (start + timeout_ms < end) { delete_request_sent(request_sent); @@ -79,21 +83,25 @@ struct SwiftNetServerPacketData* swiftnet_server_make_request(struct SwiftNetSer request_sent = construct_request_sent(addr_data.sender_address); - packet_length = packet->packet_append_pointer - packet->packet_data_start; + #ifdef SWIFT_NET_BACKEND_DPDK + packet_length = packet->total_data_size; + #else + packet_length = (uint32_t)(packet->packet_append_pointer - packet->packet_data_start); + #endif port_info = (struct SwiftNetPortInfo){.destination_port = addr_data.port, .source_port = server->server_port}; - swiftnet_send_packet(server, addr_data.maximum_transmission_unit, port_info, packet, packet_length, &addr_data.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, server->eth_header, server->loopback, server->network_data, request_sent, false, 0); + swiftnet_send_packet(addr_data.maximum_transmission_unit, port_info, packet, packet_length, &addr_data.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, server->eth_header, server->network_data, request_sent, false, 0); gettimeofday(&tv, NULL); - start = (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + start = (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); goto check_response; check_response: gettimeofday(&tv, NULL); - end = (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; + end = (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); if (start + timeout_ms < end) { delete_request_sent(request_sent); diff --git a/src/make_response.c b/src/make_response.c index 6334e3d..990be5d 100644 --- a/src/make_response.c +++ b/src/make_response.c @@ -4,16 +4,24 @@ #ifdef SWIFT_NET_REQUESTS void swiftnet_client_make_response(struct SwiftNetClientConnection* const client, struct SwiftNetClientPacketData* const packet_data, struct SwiftNetPacketBuffer* restrict const buffer) { - const uint32_t packet_length = buffer->packet_append_pointer - buffer->packet_data_start; + #ifdef SWIFT_NET_BACKEND_DPDK + const uint32_t packet_length = buffer->total_data_size; + #else + const uint32_t packet_length = (uint32_t)(buffer->packet_append_pointer - buffer->packet_data_start); + #endif - swiftnet_send_packet(client, client->maximum_transmission_unit, client->port_info, buffer, packet_length, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->loopback, client->network_data, NULL, true, packet_data->metadata.packet_id); + swiftnet_send_packet(client->maximum_transmission_unit, client->port_info, buffer, packet_length, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->network_data, NULL, true, packet_data->metadata.packet_id); } void swiftnet_server_make_response(struct SwiftNetServer* const server, struct SwiftNetServerPacketData* const packet_data, struct SwiftNetPacketBuffer* restrict const buffer) { - const uint32_t packet_length = buffer->packet_append_pointer - buffer->packet_data_start; + #ifdef SWIFT_NET_BACKEND_DPDK + const uint32_t packet_length = buffer->total_data_size; + #else + const uint32_t packet_length = (uint32_t)(buffer->packet_append_pointer - buffer->packet_data_start); + #endif const struct SwiftNetPortInfo port_info = {.source_port = server->server_port, .destination_port = packet_data->metadata.port_info.source_port}; - swiftnet_send_packet(server, packet_data->metadata.sender.maximum_transmission_unit, port_info, buffer, packet_length, &packet_data->metadata.sender.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, server->eth_header, server->loopback, server->network_data, NULL, true, packet_data->metadata.packet_id); + swiftnet_send_packet(packet_data->metadata.sender.maximum_transmission_unit, port_info, buffer, packet_length, &packet_data->metadata.sender.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, server->eth_header, server->network_data, NULL, true, packet_data->metadata.packet_id); } #endif diff --git a/src/memory_cleanup_background_service.c b/src/memory_cleanup_background_service.c index ca4a2e2..b86bd0f 100644 --- a/src/memory_cleanup_background_service.c +++ b/src/memory_cleanup_background_service.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static inline void cleanup_packets_completed(struct SwiftNetHashMap* const packets_completed, struct SwiftNetMemoryAllocator* const packets_completed_allocator) { @@ -42,10 +43,12 @@ static inline void handle_listener(struct Listener* const current_listener) { UNLOCK_ATOMIC_DATA_TYPE(&client_connections->atomic_lock); } -void* memory_cleanup_background_service() { +void* memory_cleanup_background_service(MAYBE_UNUSED void* user) { struct timeval start, end; - int64_t elapsed_us; - uint64_t target_us = (uint64_t)PACKET_HISTORY_STORE_TIME * 1000000ULL; + suseconds_t elapsed_us; + suseconds_t target_us = (suseconds_t)(PACKET_HISTORY_STORE_TIME * 1000000ULL); + + goto start_loop; start_loop: @@ -63,12 +66,10 @@ void* memory_cleanup_background_service() { gettimeofday(&end, NULL); - elapsed_us = (int64_t)(end.tv_sec - start.tv_sec) * 1000000LL + (end.tv_usec - start.tv_usec); - - if (elapsed_us < 0) elapsed_us = 0; + elapsed_us = (suseconds_t)((end.tv_sec - start.tv_sec) * 1000000LL) + (end.tv_usec - start.tv_usec); - if ((uint64_t)elapsed_us < target_us) { - usleep(target_us - (uint64_t)elapsed_us); + if (elapsed_us < target_us) { + usleep((useconds_t)(target_us - elapsed_us)); } goto start_loop; diff --git a/src/packet_buffer.c b/src/packet_buffer.c deleted file mode 100644 index 7984e1e..0000000 --- a/src/packet_buffer.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "internal/internal.h" -#include "swift_net.h" -#include -#include -#include - -static inline struct SwiftNetPacketBuffer create_packet_buffer(const uint32_t buffer_size) { - uint8_t* restrict const mem = malloc(buffer_size + PACKET_HEADER_SIZE + sizeof(struct ether_header)); - uint8_t* restrict const data_pointer = mem + PACKET_HEADER_SIZE + sizeof(struct ether_header); - - return (struct SwiftNetPacketBuffer){ - .packet_buffer_start = mem, - .packet_data_start = data_pointer, - .packet_append_pointer = data_pointer - }; -} - -struct SwiftNetPacketBuffer swiftnet_create_packet_buffer(const uint32_t buffer_size) { - return create_packet_buffer(buffer_size); -} - -void swiftnet_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const packet_buffer) { - void* new_ptr; - void* data_start; - - const uint32_t current_offset = packet_buffer->packet_append_pointer - packet_buffer->packet_data_start; - - - new_buffer_size += PACKET_HEADER_SIZE + sizeof(struct ether_header); - - new_ptr = realloc(packet_buffer->packet_buffer_start, new_buffer_size); - if (unlikely(new_ptr == NULL)) { - PRINT_ERROR("Failed to realloc"); - exit(EXIT_FAILURE); - } - - data_start = new_ptr + PACKET_HEADER_SIZE + sizeof(struct ether_header); - - *packet_buffer = (struct SwiftNetPacketBuffer){ - .packet_buffer_start = new_ptr, - .packet_data_start = data_start, - .packet_append_pointer = data_start + current_offset - }; -} - -void swiftnet_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const packet_buffer, void* restrict const data, const uint32_t data_size) { - memcpy(packet_buffer->packet_data_start + byte_offset, data, data_size); -} - -void swiftnet_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet) { - free(packet->packet_buffer_start); -} diff --git a/src/process_packets.c b/src/process_packets.c index 0b91029..8510fa7 100644 --- a/src/process_packets.c +++ b/src/process_packets.c @@ -20,12 +20,8 @@ static inline bool is_private_ip(const struct in_addr ip) { in_addr_t addr = htonl(ip.s_addr); - uint8_t octet1 = (addr >> 24) & 0xFF; - uint8_t octet2 = (addr >> 16) & 0xFF; - uint8_t octet3 = (addr >> 8) & 0xFF; - uint8_t octet4 = addr & 0xFF; - return !(octet1 == 192 && octet2 == 168) == false && (octet1 == 127 && octet2 == 0 && octet3 == 0); + return ((addr >> 24) & 0xFF) == 127; } // Returns an array of 4 byte uint32_t, that contain indexes of lost chunks @@ -112,7 +108,7 @@ static inline bool check_packet_already_completed(const uint16_t packet_id, cons return item != NULL; } -static inline struct SwiftNetPendingMessage* get_pending_message(struct SwiftNetHashMap* const pending_messages, const enum ConnectionType connection_type, const uint16_t packet_id, const uint16_t source_port) { +static inline struct SwiftNetPendingMessage* get_pending_message(struct SwiftNetHashMap* const pending_messages, const uint16_t packet_id, const uint16_t source_port) { struct PendingMessagesKey key; struct SwiftNetPendingMessage* pending_message; @@ -152,7 +148,7 @@ static inline void insert_callback_queue_node(struct PacketCallbackQueueNode* re #ifdef SWIFT_NET_REQUESTS -static inline void handle_request_response(uint16_t packet_id, const struct SwiftNetPendingMessage* restrict const pending_message, void* restrict const packet_data, struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_message_memory_allocator, const enum ConnectionType connection_type, const bool loopback, const uint16_t source_port) { +static inline void handle_request_response(uint16_t packet_id, const struct SwiftNetPendingMessage* restrict const pending_message, void* restrict const packet_data, struct SwiftNetHashMap* const pending_messages, const uint16_t source_port) { struct RequestSent* request_sent; LOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); @@ -187,20 +183,22 @@ static inline void handle_request_response(uint16_t packet_id, const struct Swif #endif -static inline void pass_callback_execution(void* const packet_data, struct PacketCallbackQueue* const queue, struct SwiftNetPendingMessage* restrict const pending_message, const uint16_t packet_id, pthread_mutex_t* const execute_callback_mtx, pthread_cond_t* const execute_callback_cond) { +static inline void pass_callback_execution(void* const packet_data, struct PacketCallbackQueue* const queue, struct SwiftNetPendingMessage* restrict const pending_message, const uint16_t packet_id, pthread_mutex_t* const execute_callback_mtx, pthread_cond_t* const execute_callback_cond, _Atomic bool* const executing_packets) { struct PacketCallbackQueueNode* node; node = allocator_allocate(&packet_callback_queue_node_memory_allocator); *node = (struct PacketCallbackQueueNode){.packet_data = packet_data, .next = NULL, .pending_message = pending_message, .packet_id = packet_id}; - pthread_mutex_lock(execute_callback_mtx); - insert_callback_queue_node(node, queue); - pthread_cond_signal(execute_callback_cond); + if (atomic_load_explicit(executing_packets, memory_order_acquire) != true) { + pthread_mutex_lock(execute_callback_mtx); + + pthread_cond_signal(execute_callback_cond); - pthread_mutex_unlock(execute_callback_mtx); + pthread_mutex_unlock(execute_callback_mtx); + } } static inline bool chunk_already_received(const uint8_t* restrict const chunks_received, const uint32_t index) { @@ -217,7 +215,7 @@ static inline void chunk_received(uint8_t* restrict const chunks_received, const chunks_received[byte] |= (uint8_t)(1U << bit); } -static inline struct SwiftNetPendingMessage* create_new_pending_message(struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, const struct SwiftNetPacketInfo* restrict const packet_info, const enum ConnectionType connection_type, const uint16_t packet_id, const uint16_t source_port) { +static inline struct SwiftNetPendingMessage* create_new_pending_message(struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, const struct SwiftNetPacketInfo* restrict const packet_info, const uint16_t packet_id, const uint16_t source_port) { struct SwiftNetPendingMessage* new_pending_message; uint8_t* allocated_memory; struct PendingMessagesKey* key; @@ -274,13 +272,12 @@ static inline struct SwiftNetPacketSending* get_packet_sending(struct SwiftNetHa static inline void signal_delay_change(const enum PacketDelayUpdateStatus status, const struct ip* restrict const ip_header, const uint16_t source_port, const uint16_t destination_port, const struct ether_header* const eth_hdr, const struct SwiftNetNetworkData* const net_data) { struct ip send_server_info_ip_header; struct SwiftNetPacketInfo packet_info_new; - struct SwiftNetServerInformation server_info; uint16_t prepend_size; prepend_size = GET_PREPEND_SIZE(net_data); - send_server_info_ip_header = construct_ip_header(ip_header->ip_src, PACKET_HEADER_SIZE, ip_header->ip_id); + send_server_info_ip_header = construct_ip_header(ip_header->ip_src, PACKET_HEADER_SIZE + sizeof(status), ip_header->ip_id); packet_info_new = construct_packet_info( sizeof(enum PacketDelayUpdateStatus), @@ -293,18 +290,13 @@ static inline void signal_delay_change(const enum PacketDelayUpdateStatus status } ); - server_info = (struct SwiftNetServerInformation){ - .maximum_transmission_unit = maximum_transmission_unit - }; - - - HANDLE_PACKET_CONSTRUCTION(&send_server_info_ip_header, &packet_info_new, net_data, eth_hdr, prepend_size + PACKET_HEADER_SIZE + sizeof(server_info), buffer); + HANDLE_PACKET_CONSTRUCTION(&send_server_info_ip_header, &packet_info_new, net_data, eth_hdr, prepend_size + PACKET_HEADER_SIZE + sizeof(status), buffer); - memcpy(buffer + prepend_size + PACKET_HEADER_SIZE, &server_info, sizeof(server_info)); + memcpy(buffer + prepend_size + PACKET_HEADER_SIZE, &status, sizeof(status)); - HANDLE_CHECKSUM(buffer, sizeof(buffer), net_data); + HANDLE_CHECKSUM(buffer, (uint32_t)sizeof(buffer), net_data); - SWIFTNET_SEND_PACKET(net_data, buffer, sizeof(buffer)); + SWIFTNET_SEND_INTERNAL_PACKET(net_data, buffer, (uint32_t)sizeof(buffer)); } struct PacketQueueNode* wait_for_next_packet(struct PacketQueue* const packet_queue) { @@ -341,13 +333,10 @@ static inline bool packet_corrupted(const uint32_t checksum, const uint32_t chun } static inline void swiftnet_process_packets( - void* _Atomic * const packet_handler, const struct ether_header eth_hdr, const uint16_t source_port, - const bool loopback, const struct SwiftNetNetworkData network_data, struct SwiftNetHashMap* const packets_sending, - struct SwiftNetMemoryAllocator* const packets_sending_messages_memory_allocator, struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, struct SwiftNetHashMap* const packets_completed_history, @@ -355,13 +344,13 @@ static inline void swiftnet_process_packets( const enum ConnectionType connection_type, struct PacketQueue* const packet_queue, struct PacketCallbackQueue* const packet_callback_queue, - void* const connection, _Atomic bool* const closing, pthread_mutex_t* const process_packets_mtx, pthread_cond_t* const process_packets_cond, pthread_mutex_t* const execute_callback_mtx, pthread_cond_t* const execute_callback_cond, - _Atomic bool* const processing_packets + _Atomic bool* const processing_packets, + _Atomic bool* const executing_packets ) { uint8_t idle_stage; struct PacketQueueNode* node; @@ -371,7 +360,7 @@ static inline void swiftnet_process_packets( struct SwiftNetPacketInfo packet_info; uint32_t checksum_received; struct SwiftNetClientAddrData sender; - uint32_t mtu; + uint16_t mtu; uint32_t chunk_data_size; struct SwiftNetPendingMessage* pending_message; uint16_t prepend_size; @@ -391,10 +380,10 @@ static inline void swiftnet_process_packets( node = wait_for_next_packet(packet_queue); if(node == NULL) { switch (idle_stage) { - case 0: usleep(1000); break; - case 1: usleep(2000); break; - case 2: usleep(5000); break; - case 3: { + case 64: usleep(1000); break; + case 128: usleep(2000); break; + case 194: usleep(5000); break; + case 255: { atomic_store_explicit(processing_packets, false, memory_order_release); pthread_mutex_lock(process_packets_mtx); @@ -470,7 +459,7 @@ static inline void swiftnet_process_packets( struct SwiftNetServerInformation server_info; - send_server_info_ip_header = construct_ip_header(ip_header.ip_src, PACKET_HEADER_SIZE, rand()); + send_server_info_ip_header = construct_ip_header(ip_header.ip_src, PACKET_HEADER_SIZE, (uint16_t)rand()); packet_info_new = construct_packet_info( sizeof(struct SwiftNetServerInformation), @@ -491,9 +480,9 @@ static inline void swiftnet_process_packets( memcpy(buffer + prepend_size + PACKET_HEADER_SIZE, &server_info, sizeof(server_info)); - HANDLE_CHECKSUM(buffer, sizeof(buffer), &network_data); + HANDLE_CHECKSUM(buffer, (uint32_t)sizeof(buffer), &network_data); - SWIFTNET_SEND_PACKET(&network_data, buffer, sizeof(buffer)); + SWIFTNET_SEND_INTERNAL_PACKET(&network_data, buffer, (uint32_t)sizeof(buffer)); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -501,7 +490,7 @@ static inline void swiftnet_process_packets( } case SEND_LOST_PACKETS_REQUEST: { - uint32_t case_mtu; + uint16_t case_mtu; struct SwiftNetPendingMessage* case_pending_message; bool packet_already_completed; struct ip send_packet_ip_header; @@ -517,7 +506,7 @@ static inline void swiftnet_process_packets( case_mtu = MIN(packet_info.maximum_transmission_unit, maximum_transmission_unit); - case_pending_message = get_pending_message(pending_messages, connection_type, ip_header.ip_id, packet_info.port_info.source_port); + case_pending_message = get_pending_message(pending_messages, ip_header.ip_id, packet_info.port_info.source_port); if(case_pending_message == NULL) { packet_already_completed = check_packet_already_completed(ip_header.ip_id, packet_info.port_info.source_port, packets_completed_history); if(likely(packet_already_completed == true)) { @@ -536,9 +525,9 @@ static inline void swiftnet_process_packets( HANDLE_PACKET_CONSTRUCTION(&send_packet_ip_header, &send_packet_info, &network_data, ð_hdr, prepend_size + PACKET_HEADER_SIZE, buffer); - HANDLE_CHECKSUM(buffer, sizeof(buffer), &network_data); + HANDLE_CHECKSUM(buffer, (uint32_t)sizeof(buffer), &network_data); - SWIFTNET_SEND_PACKET(&network_data, buffer, sizeof(buffer)); + SWIFTNET_SEND_INTERNAL_PACKET(&network_data, buffer, (uint32_t)sizeof(buffer)); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -581,7 +570,7 @@ static inline void swiftnet_process_packets( HANDLE_CHECKSUM(buffer, packet_length + prepend_size, &network_data); - SWIFTNET_SEND_PACKET(&network_data, buffer, packet_length + prepend_size); + SWIFTNET_SEND_INTERNAL_PACKET(&network_data, buffer, packet_length + prepend_size); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -590,7 +579,6 @@ static inline void swiftnet_process_packets( case SEND_LOST_PACKETS_RESPONSE: { struct SwiftNetPacketSending* target_packet_sending; - uint32_t packets_lost; target_packet_sending = get_packet_sending(packets_sending, ip_header.ip_id); @@ -605,10 +593,12 @@ static inline void swiftnet_process_packets( if(target_packet_sending->lost_chunks == NULL) { target_packet_sending->lost_chunks = malloc(maximum_transmission_unit - PACKET_HEADER_SIZE); + if(unlikely(target_packet_sending->lost_chunks == NULL)) { + PRINT_ERROR("Malloc failed"); + exit(EXIT_FAILURE); + } } - packets_lost = (packet_info.packet_length) / sizeof(uint32_t); - memcpy((void*)target_packet_sending->lost_chunks, packet_data, packet_info.packet_length); target_packet_sending->lost_chunks_size = packet_info.packet_length / 4; @@ -679,21 +669,21 @@ static inline void swiftnet_process_packets( .port = packet_info.port_info.source_port, }; - if (addr_type == DLT_EN10MB) { + if (addr_type != 0) { memcpy(&sender.mac_address, eth_hdr.ether_shost, sizeof(sender.mac_address)); } mtu = MIN(packet_info.maximum_transmission_unit, maximum_transmission_unit); chunk_data_size = mtu - PACKET_HEADER_SIZE; - pending_message = get_pending_message(pending_messages, connection_type, ip_header.ip_id, packet_info.port_info.source_port); + pending_message = get_pending_message(pending_messages, ip_header.ip_id, packet_info.port_info.source_port); if(pending_message == NULL) { if(packet_info.packet_length > chunk_data_size) { struct SwiftNetPendingMessage* new_pending_message; - new_pending_message = create_new_pending_message(pending_messages, pending_messages_memory_allocator, &packet_info, connection_type, ip_header.ip_id, packet_info.port_info.source_port); + new_pending_message = create_new_pending_message(pending_messages, pending_messages_memory_allocator, &packet_info, ip_header.ip_id, packet_info.port_info.source_port); new_pending_message->chunks_received_number = 1; @@ -727,12 +717,12 @@ static inline void swiftnet_process_packets( #ifdef SWIFT_NET_REQUESTS if (packet_info.packet_type == RESPONSE) { - handle_request_response(ip_header.ip_id, NULL, new_packet_data, pending_messages, pending_messages_memory_allocator, connection_type, loopback, packet_info.port_info.source_port); + handle_request_response(ip_header.ip_id, NULL, new_packet_data, pending_messages, packet_info.port_info.source_port); } else { - pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); } #else - pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); #endif } else { struct SwiftNetClientPacketData* new_packet_data; @@ -753,12 +743,12 @@ static inline void swiftnet_process_packets( #ifdef SWIFT_NET_REQUESTS if (packet_info.packet_type == RESPONSE) { - handle_request_response(ip_header.ip_id, NULL, new_packet_data, pending_messages, pending_messages_memory_allocator, connection_type, loopback, packet_info.port_info.source_port); + handle_request_response(ip_header.ip_id, NULL, new_packet_data, pending_messages, packet_info.port_info.source_port); } else { - pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); } #else - pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(new_packet_data, packet_callback_queue, NULL, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); #endif } @@ -775,7 +765,7 @@ static inline void swiftnet_process_packets( bytes_to_write = (packet_info.chunk_index + 1) >= packet_info.chunk_amount ? packet_info.packet_length % chunk_data_size : chunk_data_size; - if (GET_ADDR_TYPE(&network_data) == DLT_EN10MB) { + if (GET_ADDR_TYPE(&network_data) != 0) { memcpy(&sender.mac_address, eth_hdr.ether_shost, sizeof(sender.mac_address)); } @@ -831,12 +821,12 @@ static inline void swiftnet_process_packets( #ifdef SWIFT_NET_REQUESTS if (packet_info.packet_type == RESPONSE) { - handle_request_response(ip_header.ip_id, pending_message, server_packet_data, pending_messages, pending_messages_memory_allocator, connection_type, loopback, packet_info.port_info.source_port); + handle_request_response(ip_header.ip_id, pending_message, server_packet_data, pending_messages, packet_info.port_info.source_port); } else { - pass_callback_execution(server_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(server_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); } #else - pass_callback_execution(server_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(server_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); #endif } else { uint8_t* ptr; @@ -860,12 +850,12 @@ static inline void swiftnet_process_packets( #ifdef SWIFT_NET_REQUESTS if (packet_info.packet_type == RESPONSE) { - handle_request_response(ip_header.ip_id, pending_message, client_packet_data, pending_messages, pending_messages_memory_allocator, connection_type, loopback, packet_info.port_info.source_port); + handle_request_response(ip_header.ip_id, pending_message, client_packet_data, pending_messages, packet_info.port_info.source_port); } else { - pass_callback_execution(client_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(client_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); } #else - pass_callback_execution(client_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond); + pass_callback_execution(client_packet_data, packet_callback_queue, pending_message, ip_header.ip_id, execute_callback_mtx, execute_callback_cond, executing_packets); #endif } @@ -884,7 +874,7 @@ static inline void swiftnet_process_packets( if (pending_message->sending_lost_packets == false) { if (new_packets > 50) { ratio = (float)new_packets_validated / (float)new_packets; - if (ratio > 0.95) { + if (ratio > 0.95f) { signal_delay_change(LOWER_DELAY, &ip_header, source_port, packet_info.port_info.source_port, ð_hdr, &network_data); } else { signal_delay_change(INCREASE_DELAY, &ip_header, source_port, packet_info.port_info.source_port, ð_hdr, &network_data); @@ -907,9 +897,10 @@ static inline void swiftnet_process_packets( } } - goto next_packet; - next_packet: + #ifdef SWIFT_NET_BACKEND_DPDK + #endif + allocator_free(&packet_queue_node_memory_allocator, (void*)node); goto process_packet; @@ -923,7 +914,7 @@ void* swiftnet_server_process_packets(void* const void_server) { server = void_server; - swiftnet_process_packets((void*)&server->packet_handler, server->eth_header, server->server_port, server->loopback, server->network_data, &server->packets_sending, &server->packets_sending_memory_allocator, &server->pending_messages, &server->pending_messages_memory_allocator, &server->packets_completed, &server->packets_completed_memory_allocator, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->packet_callback_queue, server, &server->closing, &server->process_packets_mtx, &server->process_packets_cond, &server->execute_callback_mtx, &server->execute_callback_cond, &server->processing_packets); + swiftnet_process_packets(server->eth_header, server->server_port, server->network_data, &server->packets_sending, &server->pending_messages, &server->pending_messages_memory_allocator, &server->packets_completed, &server->packets_completed_memory_allocator, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->packet_callback_queue, &server->closing, &server->process_packets_mtx, &server->process_packets_cond, &server->execute_callback_mtx, &server->execute_callback_cond, &server->processing_packets, &server->executing_packets); return NULL; } @@ -934,7 +925,7 @@ void* swiftnet_client_process_packets(void* const void_client) { client = (struct SwiftNetClientConnection*)void_client; - swiftnet_process_packets((void*)&client->packet_handler, client->eth_header, client->port_info.source_port, client->loopback, client->network_data, &client->packets_sending, &client->packets_sending_memory_allocator, &client->pending_messages, &client->pending_messages_memory_allocator, &client->packets_completed, &client->packets_completed_memory_allocator, CONNECTION_TYPE_CLIENT, &client->packet_queue, &client->packet_callback_queue, client, &client->closing, &client->process_packets_mtx, &client->process_packets_cond, &client->execute_callback_mtx, &client->execute_callback_cond, &client->processing_packets); + swiftnet_process_packets(client->eth_header, client->port_info.source_port, client->network_data, &client->packets_sending, &client->pending_messages, &client->pending_messages_memory_allocator, &client->packets_completed, &client->packets_completed_memory_allocator, CONNECTION_TYPE_CLIENT, &client->packet_queue, &client->packet_callback_queue, &client->closing, &client->process_packets_mtx, &client->process_packets_cond, &client->execute_callback_mtx, &client->execute_callback_cond, &client->processing_packets, &client->executing_packets); return NULL; } diff --git a/src/send_packet.c b/src/send_packet.c index 509dcec..77fd55b 100644 --- a/src/send_packet.c +++ b/src/send_packet.c @@ -18,7 +18,14 @@ #include "internal/internal.h" #include -static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(const uint8_t* restrict const raw_data, const uint32_t data_size, const struct SwiftNetNetworkData* restrict const network_data, struct SwiftNetPacketSending* const packet_sending) { +static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(const struct SwiftNetNetworkData* restrict const network_data, struct SwiftNetPacketSending* const packet_sending +#ifdef SWIFT_NET_BACKEND_DPDK + , struct rte_mbuf* restrict const raw_data_internal_mem_buf +#elif defined(SWIFT_NET_BACKEND_PCAP) + , const uint8_t* restrict const raw_data + , const uint32_t data_size +#endif + ) { uint8_t times_checked; enum PacketSendingUpdated status; @@ -30,7 +37,7 @@ static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(co send_debug_message("Requested list of lost packets: {\"packet_id\": %d}\n", htons(packet_sending->packet_id)); } - SWIFTNET_SEND_PACKET(network_data, raw_data, data_size); + SWIFTNET_SEND_INTERNAL_PACKET(network_data, raw_data, data_size); for(times_checked = 0; times_checked < 0xFF; times_checked++) { status = atomic_load_explicit(&packet_sending->updated, memory_order_acquire); @@ -53,9 +60,8 @@ static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(co goto request_lost_packets; } -static inline void handle_lost_packets( +static inline ALWAYS_INLINE void handle_lost_packets( struct SwiftNetPacketSending* const packet_sending, - const uint32_t mtu, const struct SwiftNetPacketBuffer* restrict const packet, const struct ether_header eth_hdr, const struct in_addr* restrict const destination_address, @@ -63,24 +69,27 @@ static inline void handle_lost_packets( const uint16_t destination_port, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, struct SwiftNetHashMap* const packets_sending, - const bool loopback, - const struct SwiftNetNetworkData* restrict const network_data + const struct SwiftNetNetworkData* restrict const network_data, + const uint32_t packet_length, + PCAP_ONLY const uint16_t mtu, + PCAP_ONLY uint32_t chunk_amount #ifdef SWIFT_NET_REQUESTS - , const bool response - , const uint8_t packet_type + , PCAP_ONLY const uint8_t packet_type #endif ) { uint8_t prepend_size = GET_PREPEND_SIZE(network_data); struct SwiftNetPortInfo port_info; struct ip request_lost_packets_ip_header; struct SwiftNetPacketInfo request_lost_packets_bit_array; - uint32_t packet_length; - uint32_t chunk_amount; - struct SwiftNetPacketInfo resend_chunk_packet_info; - struct ip resend_chunk_ip_header; - uint8_t temp_data_buffer[prepend_size + PACKET_HEADER_SIZE]; enum RequestLostPacketsReturnType request_lost_packets_bitarray_response; + DPDK_ONLY struct rte_mbuf* restrict current_buf; + DPDK_ONLY uint8_t* buf_data; + + PCAP_ONLY struct ip resend_chunk_ip_header; + PCAP_ONLY struct SwiftNetPacketInfo resend_chunk_packet_info; + PCAP_ONLY uint8_t temp_data_buffer[prepend_size + PACKET_HEADER_SIZE]; + port_info = (struct SwiftNetPortInfo){ .source_port = source_port, @@ -99,11 +108,9 @@ static inline void handle_lost_packets( HANDLE_PACKET_CONSTRUCTION(&request_lost_packets_ip_header, &request_lost_packets_bit_array, network_data, ð_hdr, PACKET_HEADER_SIZE + prepend_size, request_lost_packets_buffer); - HANDLE_CHECKSUM(request_lost_packets_buffer, sizeof(request_lost_packets_buffer), network_data); + HANDLE_CHECKSUM(request_lost_packets_buffer, (uint32_t)sizeof(request_lost_packets_buffer), network_data); - packet_length = packet->packet_append_pointer - packet->packet_data_start; - chunk_amount = (packet_length + (mtu - PACKET_HEADER_SIZE) - 1) / (mtu - PACKET_HEADER_SIZE); - + #ifdef SWIFT_NET_BACKEND_PCAP resend_chunk_packet_info = construct_packet_info( packet_length, #ifdef SWIFT_NET_REQUESTS @@ -119,15 +126,25 @@ static inline void handle_lost_packets( resend_chunk_ip_header = construct_ip_header(*destination_address, mtu, packet_sending->packet_id); HANDLE_PACKET_CONSTRUCTION(&resend_chunk_ip_header, &resend_chunk_packet_info, network_data, ð_hdr, prepend_size + PACKET_HEADER_SIZE, prepend_buffer); + #elif defined(SWIFT_NET_BACKEND_PCAP) + #endif while(1) { uint32_t i; uint32_t lost_chunk_index; uint32_t current_offset; - uint8_t* restrict current_buffer_header_ptr; + PCAP_ONLY uint8_t* restrict current_buffer_header_ptr; - request_lost_packets_bitarray_response = request_lost_packets_bitarray(request_lost_packets_buffer, PACKET_HEADER_SIZE + prepend_size, network_data, packet_sending); + + request_lost_packets_bitarray_response = request_lost_packets_bitarray(network_data, packet_sending + #ifdef SWIFT_NET_BACKEND_DPDK + , request_lost_packets_buffer_internal_mem_buf + #elif defined(SWIFT_NET_BACKEND_PCAP) + , request_lost_packets_buffer + , PACKET_HEADER_SIZE + prepend_size + #endif + ); LOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); @@ -146,6 +163,7 @@ static inline void handle_lost_packets( return; } + #ifdef SWIFT_NET_BACKEND_PCAP for(i = 0; i < packet_sending->lost_chunks_size; i++) { lost_chunk_index = packet_sending->lost_chunks[i]; @@ -166,18 +184,18 @@ static inline void handle_lost_packets( memset(current_buffer_header_ptr + prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), 0x00, SIZEOF_FIELD(struct SwiftNetPacketInfo, checksum)); if(current_offset + mtu - PACKET_HEADER_SIZE >= packet_length) { - uint32_t bytes_to_complete; + uint16_t bytes_to_complete; uint16_t new_ip_len; - bytes_to_complete = packet_length - current_offset; + bytes_to_complete = (uint16_t)(packet_length - current_offset); new_ip_len = htons(bytes_to_complete + PACKET_HEADER_SIZE); memcpy(current_buffer_header_ptr + offsetof(struct ip, ip_len), &new_ip_len, SIZEOF_FIELD(struct ip, ip_len)); HANDLE_CHECKSUM(current_buffer_header_ptr, prepend_size + PACKET_HEADER_SIZE + bytes_to_complete, network_data); - SWIFTNET_SEND_PACKET(network_data, current_buffer_header_ptr, bytes_to_complete + PACKET_HEADER_SIZE + prepend_size); + SWIFTNET_SEND_PACKET(network_data, current_buffer_header_ptr, (uint32_t)(bytes_to_complete + PACKET_HEADER_SIZE + prepend_size)); } else { HANDLE_CHECKSUM(current_buffer_header_ptr, mtu + prepend_size, network_data); @@ -186,14 +204,57 @@ static inline void handle_lost_packets( memcpy(current_buffer_header_ptr, temp_data_buffer, prepend_size + PACKET_HEADER_SIZE); } + #elif defined(SWIFT_NET_BACKEND_DPDK) + for(i = 0; i < packet_sending->lost_chunks_size; i++) { + lost_chunk_index = packet_sending->lost_chunks[i]; + + current_buf = packet->dpdk_buffers[i]; + buf_data = current_buf->buf_addr; + + current_offset = lost_chunk_index * (packet->data_len_per_packet); + + if (check_debug_flag(SWIFTNET_DEBUG_LOST_PACKETS) == true) { + send_debug_message("Packet lost: {\"packet_id\": %d, \"chunk index\": %d}\n", packet_sending->packet_id, lost_chunk_index); + } + + memset(buf_data + sizeof(struct ether_header) + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), 0x00, SIZEOF_FIELD(struct SwiftNetPacketInfo, checksum)); + + if((current_offset + packet->data_len_per_packet) < packet->data_len_per_packet && current_offset + current_buf->data_len != packet_length) { + uint16_t bytes_to_complete; + uint16_t new_ip_len; + uint16_t old_len; + + + bytes_to_complete = (uint16_t)(packet_length - current_offset + PACKET_HEADER_SIZE + sizeof(struct ether_header)); + + old_len = current_buf->data_len; + + current_buf->data_len = bytes_to_complete; + current_buf->pkt_len = bytes_to_complete; + + new_ip_len = htons(bytes_to_complete); + memcpy(buf_data + sizeof(struct ether_header) + offsetof(struct ip, ip_len), &new_ip_len, SIZEOF_FIELD(struct ip, ip_len)); + + HANDLE_CHECKSUM(buf_data, bytes_to_complete, network_data); + + SWIFTNET_SEND_PACKET(network_data, current_buf); + + current_buf->data_len = old_len; + current_buf->pkt_len = old_len; + } else { + HANDLE_CHECKSUM(buf_data, current_buf->data_len, network_data); + + SWIFTNET_SEND_PACKET(network_data, current_buf); + } + } + #endif UNLOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); } } -inline void swiftnet_send_packet( - const void* const connection, - const uint32_t target_maximum_transmission_unit, +void swiftnet_send_packet( + const uint16_t target_maximum_transmission_unit, const struct SwiftNetPortInfo port_info, const struct SwiftNetPacketBuffer* const packet, const uint32_t packet_length, @@ -201,7 +262,6 @@ inline void swiftnet_send_packet( struct SwiftNetHashMap* const packets_sending, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, const struct ether_header eth_hdr, - const bool loopback, const struct SwiftNetNetworkData network_data #ifdef SWIFT_NET_REQUESTS , struct RequestSent* const request_sent @@ -209,7 +269,7 @@ inline void swiftnet_send_packet( , const uint16_t request_packet_id #endif ) { - uint32_t mtu; + uint16_t mtu; uint32_t chunk_amount; uint16_t packet_id; #ifdef SWIFT_NET_REQUESTS @@ -229,7 +289,7 @@ inline void swiftnet_send_packet( if (response == true) { packet_id = request_packet_id; } else { - packet_id = rand(); + packet_id = (uint16_t)rand(); } if (request_sent != NULL) { @@ -265,13 +325,15 @@ inline void swiftnet_send_packet( uint16_t net_order_len; struct SwiftNetPacketSending* new_packet_sending; uint16_t* key_data_mem; - uint8_t temp_data_buffer[prepend_size + PACKET_HEADER_SIZE]; - uint32_t i; uint32_t current_offset; - uint8_t* buffer_header_location; uint16_t bytes_to_send; uint16_t bytes_to_send_net_order; + PCAP_ONLY uint8_t* buffer_header_location; + PCAP_ONLY uint8_t temp_data_buffer[prepend_size + PACKET_HEADER_SIZE]; + + DPDK_ONLY struct rte_mbuf* restrict current_buffer; + packet_info = construct_packet_info( packet_length, @@ -314,10 +376,12 @@ inline void swiftnet_send_packet( hashmap_insert(key_data_mem, sizeof(uint16_t), new_packet_sending, packets_sending); UNLOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); + + #ifdef SWIFT_NET_BACKEND_PCAP HANDLE_PACKET_CONSTRUCTION(&ip_header, &packet_info, &network_data, ð_hdr, prepend_size + PACKET_HEADER_SIZE, prepend_buffer); - for(i = 0; ; i++) { + for(uint32_t i = 0; ; i++) { current_offset = i * (mtu - PACKET_HEADER_SIZE); #ifdef SWIFT_NET_DEBUG @@ -349,9 +413,8 @@ inline void swiftnet_send_packet( memcpy(buffer_header_location, temp_data_buffer, prepend_size + PACKET_HEADER_SIZE); - handle_lost_packets(new_packet_sending, mtu, packet, eth_hdr, target_addr, port_info.source_port, port_info.destination_port, packets_sending_memory_allocator, packets_sending, loopback, &network_data + handle_lost_packets(new_packet_sending, packet, eth_hdr, target_addr, port_info.source_port, port_info.destination_port, packets_sending_memory_allocator, packets_sending, &network_data, packet_length, mtu, chunk_amount #ifdef SWIFT_NET_REQUESTS - , response , packet_type #endif ); @@ -369,13 +432,77 @@ inline void swiftnet_send_packet( usleep(atomic_load_explicit(&new_packet_sending->current_send_delay, memory_order_acquire)); } } + #elif defined(SWIFT_NET_BACKEND_DPDK) + for (uint32_t i = 0; i < packet->buf_amount; i++) { + uint8_t* buf_addr; + + current_offset = i * packet->data_len_per_packet; + + #ifdef SWIFT_NET_DEBUG + if (check_debug_flag(SWIFTNET_DEBUG_PACKETS_SENDING)) { + send_debug_message("Sent chunk: {\"chunk_index\": %d}\n", i); + } + #endif + + current_buffer = packet->dpdk_buffers[i]; + buf_addr = rte_pktmbuf_mtod(current_buffer, uint8_t*); + + packet_info.chunk_index = i; + packet_info.checksum = 0; + + memcpy(buf_addr, ð_hdr, sizeof(eth_hdr)); + memcpy(buf_addr + sizeof(eth_hdr), &ip_header, sizeof(ip_header)); + memcpy(buf_addr + sizeof(eth_hdr) + sizeof(struct ip), &packet_info, sizeof(packet_info)); + + if (current_offset + packet->data_len_per_packet > packet_length) { + uint16_t old_len; + + bytes_to_send = (uint16_t)(packet_length - current_offset + PACKET_HEADER_SIZE); + + bytes_to_send_net_order = htons(bytes_to_send); + + old_len = current_buffer->data_len; + + memcpy((uint8_t*)current_buffer->buf_addr + sizeof(eth_hdr) + offsetof(struct ip, ip_len), &bytes_to_send_net_order, sizeof(bytes_to_send_net_order)); + + current_buffer->data_len = bytes_to_send + prepend_size; + current_buffer->pkt_len = bytes_to_send + prepend_size; + + HANDLE_CHECKSUM(buf_addr, current_buffer->data_len, &network_data); + + SWIFTNET_SEND_PACKET(&network_data, current_buffer); + + current_buffer->data_len = old_len; + current_buffer->pkt_len = old_len; + + handle_lost_packets(new_packet_sending, packet, eth_hdr, target_addr, port_info.source_port, port_info.destination_port, packets_sending_memory_allocator, packets_sending, &network_data, packet_length, mtu, chunk_amount + #ifdef SWIFT_NET_REQUESTS + , packet_type + #endif + ); + + + break; + } + + HANDLE_CHECKSUM(buf_addr, current_buffer->data_len, &network_data); + + SWIFTNET_SEND_PACKET(&network_data, current_buffer); + + usleep(atomic_load_explicit(&new_packet_sending->current_send_delay, memory_order_acquire)); + } + #endif } else { - uint32_t final_packet_size; + uint16_t final_packet_size; struct SwiftNetPacketInfo packet_info; struct ip ip_header; + #ifdef SWIFT_NET_BACKEND_DPDK + uint8_t* buf_ptr; + struct rte_mbuf* restrict buffer; + #endif - final_packet_size = prepend_size + PACKET_HEADER_SIZE + packet_length; + final_packet_size = (uint16_t)(prepend_size + PACKET_HEADER_SIZE + packet_length); packet_info = construct_packet_info( packet_length, @@ -391,6 +518,7 @@ inline void swiftnet_send_packet( ip_header = construct_ip_header(*target_addr, final_packet_size - prepend_size, packet_id); + #ifdef SWIFT_NET_BACKEND_PCAP if(GET_ADDR_TYPE(&network_data) == DLT_NULL) { uint32_t family = PF_INET; @@ -414,30 +542,47 @@ inline void swiftnet_send_packet( SWIFTNET_SEND_PACKET(&network_data, packet->packet_buffer_start, final_packet_size); } - } -} + #elif defined(SWIFT_NET_BACKEND_DPDK) + buffer = packet->dpdk_buffers[0]; + buf_ptr = rte_pktmbuf_mtod(buffer, uint8_t*); + + memcpy(buf_ptr, ð_hdr, sizeof(eth_hdr)); + memcpy(buf_ptr + sizeof(eth_hdr), &ip_header, sizeof(ip_header)); + memcpy(buf_ptr + sizeof(eth_hdr) + sizeof(ip_header), &packet_info, sizeof(packet_info)); + + HANDLE_CHECKSUM(buf_ptr, final_packet_size, &network_data); -void swiftnet_client_send_packet(struct SwiftNetClientConnection* const client, struct SwiftNetPacketBuffer* restrict const packet) { - uint32_t packet_length; + if(final_packet_size != buffer->data_len) { + uint16_t old_len; + old_len = buffer->data_len; - packet_length = packet->packet_append_pointer - packet->packet_data_start; + buffer->pkt_len = final_packet_size; + buffer->data_len = final_packet_size; - swiftnet_send_packet(client, client->maximum_transmission_unit, client->port_info, packet, packet_length, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->loopback, client->network_data + SWIFTNET_SEND_PACKET(&network_data, buffer); + + buffer->pkt_len = old_len; + buffer->data_len = old_len; + } else { + SWIFTNET_SEND_PACKET(&network_data, buffer); + } + #endif + } +} + +void swiftnet_client_send_packet(struct SwiftNetClientConnection* const client, struct SwiftNetPacketBuffer* restrict const packet, const uint32_t bytes_to_send) { + swiftnet_send_packet(client->maximum_transmission_unit, client->port_info, packet, bytes_to_send, &client->server_addr, &client->packets_sending, &client->packets_sending_memory_allocator, client->eth_header, client->network_data #ifdef SWIFT_NET_REQUESTS , NULL, false, 0 #endif ); } -void swiftnet_server_send_packet(struct SwiftNetServer* const server, struct SwiftNetPacketBuffer* restrict const packet, const struct SwiftNetClientAddrData target) { - uint32_t packet_length; +void swiftnet_server_send_packet(struct SwiftNetServer* const server, struct SwiftNetPacketBuffer* restrict const packet, const struct SwiftNetClientAddrData target, const uint32_t bytes_to_send) { struct SwiftNetPortInfo port_info; struct ether_header eth_hdr; - - packet_length = packet->packet_append_pointer - packet->packet_data_start; - port_info = (struct SwiftNetPortInfo){ .destination_port = target.port, .source_port = server->server_port @@ -446,7 +591,7 @@ void swiftnet_server_send_packet(struct SwiftNetServer* const server, struct Swi memcpy(ð_hdr, &server->eth_header, sizeof(eth_hdr)); memcpy(ð_hdr.ether_dhost, &target.mac_address, sizeof(eth_hdr.ether_dhost)); - swiftnet_send_packet(server, target.maximum_transmission_unit, port_info, packet, packet_length, &target.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, eth_hdr, server->loopback, server->network_data + swiftnet_send_packet(target.maximum_transmission_unit, port_info, packet, bytes_to_send, &target.sender_address, &server->packets_sending, &server->packets_sending_memory_allocator, eth_hdr, server->network_data #ifdef SWIFT_NET_REQUESTS , NULL, false, 0 #endif diff --git a/src/swift_net.h b/src/swift_net.h index 4ef3a68..f105ed8 100644 --- a/src/swift_net.h +++ b/src/swift_net.h @@ -15,6 +15,9 @@ #endif #ifdef SWIFT_NET_BACKEND_DPDK +#include + +#define DPDK_BURST_SIZE 32 #endif #ifdef __cplusplus @@ -42,6 +45,13 @@ extern "C" { #define SWIFT_NET_MEMORY_USAGE 5 struct SwiftNetNetworkData { + #ifdef SWIFT_NET_BACKEND_DPDK + struct rte_mempool* mem_pool; + uint16_t port; + uint16_t addr_type; + uint8_t prepend_size; + _Atomic bool closing; + #endif #ifdef SWIFT_NET_BACKEND_PCAP pcap_t* pcap; uint16_t addr_type; @@ -69,10 +79,12 @@ enum PacketDelayUpdateStatus { #define PACKET_INFO_ID_NONE 0xFFFF +#ifndef likely #define unlikely(x) __builtin_expect((x), 0x00) #define likely(x) __builtin_expect((x), 0x01) +#endif -extern uint32_t maximum_transmission_unit; +extern uint16_t maximum_transmission_unit; #ifdef SWIFT_NET_DEBUG #define SWIFTNET_DEBUG_FLAGS(num) ((SwiftNetDebugFlags)(num)) @@ -95,7 +107,7 @@ struct SwiftNetPortInfo { } SWIFT_NET_ALIGNED(4); struct SwiftNetClientAddrData { - uint32_t maximum_transmission_unit; + uint16_t maximum_transmission_unit; struct in_addr sender_address; uint16_t port; uint8_t mac_address[6]; @@ -114,9 +126,9 @@ struct SwiftNetPacketInfo { uint32_t packet_length; uint32_t chunk_amount; uint32_t chunk_index; - uint32_t maximum_transmission_unit; uint32_t checksum; struct SwiftNetPortInfo port_info; + uint16_t maximum_transmission_unit; uint8_t packet_type; } SWIFT_NET_ALIGNED(4); @@ -144,7 +156,7 @@ struct SwiftNetPacketServerMetadata { } SWIFT_NET_ALIGNED(4); struct SwiftNetServerInformation { - uint32_t maximum_transmission_unit; + uint16_t maximum_transmission_unit; } SWIFT_NET_ALIGNED(4); enum PacketSendingUpdated { @@ -168,9 +180,17 @@ struct SwiftNetPacketCompleted { } SWIFT_NET_ALIGNED(4); struct SwiftNetPacketBuffer { + #ifdef SWIFT_NET_BACKEND_DPDK + struct rte_mbuf** dpdk_buffers; + uint32_t total_data_size; // Only counting data stored not eth, ip headers or packet info + uint32_t buf_amount; + uint16_t data_len_per_packet; + uint32_t append_offset; + #elif defined(SWIFT_NET_BACKEND_PCAP) uint8_t* packet_buffer_start; // Start of the allocated buffer uint8_t* packet_data_start; // Start of the stored data uint8_t* packet_append_pointer; // Current position to append new data + #endif } SWIFT_NET_ALIGNED(8); struct PacketQueueNode { @@ -290,10 +310,11 @@ struct SwiftNetClientConnection { pthread_t execute_callback_thread; struct SwiftNetPortInfo port_info; struct ether_header eth_header; - uint32_t maximum_transmission_unit; + uint16_t maximum_transmission_unit; struct in_addr server_addr; bool loopback; _Atomic bool processing_packets; + _Atomic bool executing_packets; _Atomic bool closing; _Atomic bool initialized; }; @@ -320,6 +341,7 @@ struct SwiftNetServer { uint16_t server_port; bool loopback; _Atomic bool processing_packets; + _Atomic bool executing_packets; _Atomic bool closing; } SWIFT_NET_ALIGNED(8); @@ -355,28 +377,42 @@ extern void swiftnet_initialize(); // Send a packet from the client to its connected server. extern void swiftnet_client_send_packet( struct SwiftNetClientConnection* const client, - struct SwiftNetPacketBuffer* restrict const packet + struct SwiftNetPacketBuffer* restrict const packet, + const uint32_t bytes_to_send ); // Send a packet from the server to a specified client. extern void swiftnet_server_send_packet( struct SwiftNetServer* const server, struct SwiftNetPacketBuffer* restrict const packet, - const struct SwiftNetClientAddrData target + const struct SwiftNetClientAddrData target, + const uint32_t bytes_to_send ); -// Create a packet buffer. -extern struct SwiftNetPacketBuffer swiftnet_create_packet_buffer(const uint32_t buffer_size); +// Create a packet buffer (client). +extern struct SwiftNetPacketBuffer swiftnet_client_create_packet_buffer(const uint32_t buffer_size, const struct SwiftNetClientConnection* const client_connection); + +// Create a packet buffer (server). +extern struct SwiftNetPacketBuffer swiftnet_server_create_packet_buffer(const uint32_t buffer_size, const struct SwiftNetServer* const server); + +// Resizes packet buffer (client). +extern void swiftnet_client_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const, const struct SwiftNetClientConnection* const client_connection); + +// Resizes packet buffer (server). +extern void swiftnet_server_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const, const struct SwiftNetServer* const server); + +// Writes to packet buffer at specific offset (client). +extern void swiftnet_client_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const, void* restrict const data, const uint32_t data_size, const struct SwiftNetClientConnection* const client_connection); -// Resizes packet buffer. -extern void swiftnet_resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNetPacketBuffer* restrict const); +// Writes to packet buffer at specific offset (server). +extern void swiftnet_server_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const, void* restrict const data, const uint32_t data_size, const struct SwiftNetServer* const server); -// Writes to packet buffer at specific offset -extern void swiftnet_write_packet_buffer(const uint32_t byte_offset, struct SwiftNetPacketBuffer* restrict const, void* restrict const data, const uint32_t data_size); +// Destroy a packet buffer (client). +extern void swiftnet_client_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, const struct SwiftNetClientConnection* const client_connection); -// Destroy a packet buffer and free resources. -extern void swiftnet_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet); +// Destroy a packet buffer (server). +extern void swiftnet_server_destroy_packet_buffer(const struct SwiftNetPacketBuffer* restrict const packet, const struct SwiftNetServer* const server); // Create and initialize a server. extern struct SwiftNetServer* swiftnet_create_server(const uint16_t port, const bool loopback); diff --git a/tests/integration_tests/.clangd b/tests/integration_tests_dpdk/.clangd similarity index 100% rename from tests/integration_tests/.clangd rename to tests/integration_tests_dpdk/.clangd diff --git a/tests/integration_tests_dpdk/build/CMakeLists.txt b/tests/integration_tests_dpdk/build/CMakeLists.txt new file mode 100644 index 0000000..58a855e --- /dev/null +++ b/tests/integration_tests_dpdk/build/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.15) +project(SwiftNetTests C) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../output) + +add_compile_definitions(SWIFT_NET_BACKEND_DPDK) + +if(SANITIZER STREQUAL "address") + message(STATUS "Using AddressSanitizer") + add_compile_options(-fsanitize=address -fno-omit-frame-pointer) + add_link_options(-fsanitize=address) +elseif(SANITIZER STREQUAL "thread") + message(STATUS "Using ThreadSanitizer") + add_compile_options(-fsanitize=thread -fno-omit-frame-pointer) + add_link_options(-fsanitize=thread) +elseif(SANITIZER STREQUAL "undefined") + message(STATUS "Using UndefinedBehaviorSanitizer") + add_compile_options(-fsanitize=undefined -fno-omit-frame-pointer) + add_link_options(-fsanitize=undefined) +else() + message(STATUS "No sanitizer enabled") +endif() + +link_directories(${CMAKE_SOURCE_DIR}/../../../build/output) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0") + +file(GLOB SRC_FILES "${CMAKE_SOURCE_DIR}/../src/*.c") + +add_executable(run_tests ${SRC_FILES}) + +add_library(swiftnet STATIC IMPORTED) + +set_target_properties(swiftnet PROPERTIES + IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a" +) + +target_link_libraries(swiftnet INTERFACE + rte_eal + rte_ethdev + rte_mbuf + rte_mempool + rte_ring + rte_net +) + +target_link_libraries(run_tests PRIVATE swiftnet) +target_link_options(run_tests PRIVATE -g -O0) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/tests/integration_tests_dpdk/build/build_tests.sh b/tests/integration_tests_dpdk/build/build_tests.sh new file mode 100755 index 0000000..85753c7 --- /dev/null +++ b/tests/integration_tests_dpdk/build/build_tests.sh @@ -0,0 +1,8 @@ +rm -f CMakeCache.txt +rm -rf CMakeFiles +rm -rf cmake +rm -f Makefile +rm -f cmake_install.cmake + +cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug -DSANITIZER=none -B . +make -B -j8 diff --git a/tests/integration_tests/src/making_request.c b/tests/integration_tests_dpdk/src/making_request.c similarity index 92% rename from tests/integration_tests/src/making_request.c rename to tests/integration_tests_dpdk/src/making_request.c index 7ea8152..04def0d 100644 --- a/tests/integration_tests/src/making_request.c +++ b/tests/integration_tests_dpdk/src/making_request.c @@ -1,3 +1,4 @@ +#include "run_tests.h" #include #include #include @@ -5,7 +6,6 @@ #include #include #include -#include "run_tests.h" static _Atomic (struct SwiftNetClientConnection*) g_client_conn = NULL; static _Atomic (struct SwiftNetServer*) g_server = NULL; @@ -86,13 +86,13 @@ static void on_client_packet(struct SwiftNetClientPacketData* packet, void* cons const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); - struct SwiftNetPacketBuffer send_buffer = swiftnet_create_packet_buffer(response_data_len); + struct SwiftNetPacketBuffer send_buffer = swiftnet_client_create_packet_buffer(response_data_len, client_conn); swiftnet_append_to_buffer(response_data, response_data_len, &send_buffer); swiftnet_client_make_response(atomic_load_explicit(&g_client_conn, memory_order_acquire), packet, &send_buffer); - swiftnet_destroy_packet_buffer(&send_buffer); + swiftnet_client_destroy_packet_buffer(&send_buffer, client_conn); swiftnet_client_destroy_packet_data(packet, client_conn); atomic_store_explicit(&g_sent_response, true, memory_order_release); @@ -133,13 +133,13 @@ static void on_server_packet(struct SwiftNetServerPacketData* packet, void* cons const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); - struct SwiftNetPacketBuffer send_buffer = swiftnet_create_packet_buffer(response_data_len); + struct SwiftNetPacketBuffer send_buffer = swiftnet_server_create_packet_buffer(response_data_len, server); swiftnet_append_to_buffer(response_data, response_data_len, &send_buffer); swiftnet_server_make_response(atomic_load_explicit(&g_server, memory_order_acquire), packet, &send_buffer); - swiftnet_destroy_packet_buffer(&send_buffer); + swiftnet_server_destroy_packet_buffer(&send_buffer, server); swiftnet_server_destroy_packet_data(packet, server); atomic_store_explicit(&g_sent_response, true, memory_order_release); @@ -174,13 +174,13 @@ static void on_server_packet(struct SwiftNetServerPacketData* packet, void* cons const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); - struct SwiftNetPacketBuffer buffer = swiftnet_create_packet_buffer(request_data_len); + struct SwiftNetPacketBuffer buffer = swiftnet_server_create_packet_buffer(request_data_len, server); swiftnet_append_to_buffer(request_data, request_data_len, &buffer); struct SwiftNetServerPacketData* response = swiftnet_server_make_request(atomic_load_explicit(&g_server, memory_order_acquire), &buffer, packet->metadata.sender, 1000); - swiftnet_destroy_packet_buffer(&buffer); + swiftnet_server_destroy_packet_buffer(&buffer, server); if (response == NULL) { int result = atomic_load_explicit(&g_test_result, memory_order_acquire); @@ -275,13 +275,13 @@ int test_making_request(const union Args* args_ptr) { atomic_store_explicit(&g_response_data_len, args.response_data_len, memory_order_release); if (args.receiver == Server) { - struct SwiftNetPacketBuffer buffer = swiftnet_create_packet_buffer(args.request_data_len); + struct SwiftNetPacketBuffer buffer = swiftnet_client_create_packet_buffer(args.request_data_len, client_conn); swiftnet_append_to_buffer(req_data, args.request_data_len, &buffer); struct SwiftNetClientPacketData* const response = swiftnet_client_make_request(client_conn, &buffer, 1000); - swiftnet_destroy_packet_buffer(&buffer); + swiftnet_client_destroy_packet_buffer(&buffer, client_conn); if (response == NULL) { int result = atomic_load_explicit(&g_test_result, memory_order_acquire); @@ -330,13 +330,13 @@ int test_making_request(const union Args* args_ptr) { return 0; } else { - struct SwiftNetPacketBuffer buffer = swiftnet_create_packet_buffer(sizeof(g_make_request_code)); + struct SwiftNetPacketBuffer buffer = swiftnet_client_create_packet_buffer(sizeof(g_make_request_code), client_conn); swiftnet_append_to_buffer(&g_make_request_code, sizeof(g_make_request_code), &buffer); - swiftnet_client_send_packet(client_conn, &buffer); + swiftnet_client_send_packet(client_conn, &buffer, sizeof(g_make_request_code)); - swiftnet_destroy_packet_buffer(&buffer); + swiftnet_client_destroy_packet_buffer(&buffer, client_conn); for ( ;; ) { int result = atomic_load_explicit(&g_test_result, memory_order_acquire); diff --git a/tests/integration_tests_dpdk/src/run_tests.c b/tests/integration_tests_dpdk/src/run_tests.c new file mode 100644 index 0000000..7aaca26 --- /dev/null +++ b/tests/integration_tests_dpdk/src/run_tests.c @@ -0,0 +1,145 @@ +#include "run_tests.h" +#include "../../../src/swift_net.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../shared.h" + +char private_ip_address_testing[INET_ADDRSTRLEN]; + +int main() { + get_private_ip_from_socket(); + + const struct Test tests[] = { + // Loopback tests + { + .function = test_sending_packet, + .args = {.test_sending_packet_args = { + .client_data_len = 50, + .server_data_len = 50, + .ip_address = "127.0.0.1", + .loopback = true + }}, + .test_name = "Test sending small packets" + }, + { + .function = test_sending_packet, + .args = {.test_sending_packet_args = { + .client_data_len = 0, + .server_data_len = 10000, + .ip_address = "127.0.0.1", + .loopback = true + }}, + .test_name = "Test client sending large packet" + }, + { + .function = test_sending_packet, + .args = {.test_sending_packet_args = { + .client_data_len = 10000, + .server_data_len = 10, + .ip_address = "127.0.0.1", + .loopback = true + }}, + .test_name = "Test server sending large packet" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Server, + .request_data_len = 100, + .response_data_len = 100 + }}, + .test_name = "Test client making small request" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Client, + .request_data_len = 100, + .response_data_len = 100 + }}, + .test_name = "Test server making small request" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Client, + .request_data_len = 10000, + .response_data_len = 100 + }}, + .test_name = "Test server making large request" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Server, + .request_data_len = 10000, + .response_data_len = 100 + }}, + .test_name = "Test client making large request" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Client, + .request_data_len = 100, + .response_data_len = 10000 + }}, + .test_name = "Test client making large response" + }, + { + .function = test_making_request, + .args = {.test_making_request_args = { + .ip_address = "127.0.0.1", + .loopback = true, + .receiver = Server, + .request_data_len = 100, + .response_data_len = 10000 + }}, + .test_name = "Test server making large response" + }, + }; + + swiftnet_initialize(); + + swiftnet_add_debug_flags(SWIFTNET_DEBUG_FLAGS(SWIFTNET_DEBUG_PACKETS_SENDING | SWIFTNET_DEBUG_PACKETS_RECEIVING | SWIFTNET_DEBUG_INITIALIZATION | SWIFTNET_DEBUG_LOST_PACKETS)); + + for (uint16_t i = 0; i < sizeof(tests) / sizeof(struct Test); i++) { + const struct Test* current_test = &tests[i]; + + int result = current_test->function(¤t_test->args); + if (result != 0) { + PRINT_ERROR("Failed test: %s", current_test->test_name); + + swiftnet_cleanup(); + + return -1; + } + + PRINT_SUCCESS("Successfully completed test: %s", current_test->test_name); + + continue; + } + + swiftnet_cleanup(); + + return 0; +} diff --git a/tests/integration_tests/src/run_tests.h b/tests/integration_tests_dpdk/src/run_tests.h similarity index 100% rename from tests/integration_tests/src/run_tests.h rename to tests/integration_tests_dpdk/src/run_tests.h diff --git a/tests/integration_tests_dpdk/src/sending_packet.c b/tests/integration_tests_dpdk/src/sending_packet.c new file mode 100644 index 0000000..0340ca9 --- /dev/null +++ b/tests/integration_tests_dpdk/src/sending_packet.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include "../../../src/swift_net.h" +#include +#include +#include +#include "run_tests.h" + +static _Atomic (struct SwiftNetClientConnection*) g_client_conn = NULL; +static _Atomic (struct SwiftNetServer*) g_server = NULL; + +static _Atomic bool g_client_send_done = false; +static _Atomic bool g_server_send_done = false; +static _Atomic int g_test_result = INT_MAX; + +static _Atomic (uint8_t*) g_client_data = NULL; +static _Atomic (uint8_t*) g_server_data = NULL; + +static _Atomic uint32_t g_client_data_len = 0; +static _Atomic uint32_t g_server_data_len = 0; + +static void reset_test_state() { + swiftnet_server_cleanup(atomic_load_explicit(&g_server, memory_order_acquire)); + swiftnet_client_cleanup(atomic_load_explicit(&g_client_conn, memory_order_acquire)); + + uint8_t* client_data = atomic_load_explicit(&g_client_data, memory_order_acquire); + uint8_t* server_data = atomic_load_explicit(&g_server_data, memory_order_acquire); + + if (client_data) free(client_data); + if (server_data) free(server_data); + + atomic_store_explicit(&g_client_send_done, false, memory_order_release); + atomic_store_explicit(&g_server_send_done, false, memory_order_release); + + atomic_store_explicit(&g_client_data, NULL, memory_order_release); + atomic_store_explicit(&g_server_data, NULL, memory_order_release); + + atomic_store_explicit(&g_client_data_len, 0, memory_order_release); + atomic_store_explicit(&g_server_data_len, 0, memory_order_release); + + atomic_store_explicit(&g_client_conn, NULL, memory_order_release); + atomic_store_explicit(&g_server, NULL, memory_order_release); + + atomic_store_explicit(&g_test_result, INT_MAX, memory_order_release); +} + +static void on_client_packet(struct SwiftNetClientPacketData* packet, void* const user) { + struct SwiftNetClientConnection* const client_conn = atomic_load_explicit(&g_client_conn, memory_order_acquire); + + while (!atomic_load_explicit(&g_client_send_done, memory_order_acquire)) usleep(1000); + + if (packet->metadata.data_length != atomic_load_explicit(&g_client_data_len, memory_order_acquire)) { + PRINT_ERROR("Client received invalid data size: %d | %d", + packet->metadata.data_length, + atomic_load_explicit(&g_client_data_len, memory_order_acquire) + ); + + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + const uint8_t* data = atomic_load_explicit(&g_client_data, memory_order_acquire); + + for (uint32_t i = 0; i < packet->metadata.data_length; i++) { + uint8_t received_byte = *(uint8_t*)swiftnet_client_read_packet(packet, 1); + if (data[i] != received_byte) { + PRINT_ERROR("Client received invalid data"); + + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + } + + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_test_result, 0, memory_order_release); +} + +static void on_server_packet(struct SwiftNetServerPacketData* packet, void* const user) { + struct SwiftNetServer* const server = atomic_load_explicit(&g_server, memory_order_acquire); + + while (!atomic_load_explicit(&g_server_send_done, memory_order_acquire)) usleep(1000); + + if (packet->metadata.data_length != atomic_load_explicit(&g_server_data_len, memory_order_acquire)) { + PRINT_ERROR("Server received invalid data size: %d | %d", + packet->metadata.data_length, + atomic_load_explicit(&g_server_data_len, memory_order_acquire) + ); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + const uint8_t* data = atomic_load_explicit(&g_server_data, memory_order_acquire); + + for (uint32_t i = 0; i < packet->metadata.data_length; i++) { + uint8_t byte_received = *(uint8_t*)swiftnet_server_read_packet(packet, 1); + if (data[i] != byte_received) { + PRINT_ERROR("Server received invalid data"); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + } + + if (atomic_load_explicit(&g_client_data_len, memory_order_acquire) != 0) { + uint32_t size = atomic_load_explicit(&g_client_data_len, memory_order_acquire); + uint8_t* send_data = atomic_load_explicit(&g_client_data, memory_order_acquire); + + struct SwiftNetPacketBuffer buf = swiftnet_server_create_packet_buffer(size, server); + swiftnet_append_to_buffer(send_data, size, &buf); + swiftnet_server_send_packet(atomic_load_explicit(&g_server, memory_order_acquire), &buf, packet->metadata.sender, size); + swiftnet_server_destroy_packet_buffer(&buf, server); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_client_send_done, true, memory_order_release); + } else { + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, 0, memory_order_release); + } +} + +int test_sending_packet(const union Args* args_ptr) { + const struct TestSendingPacketArgs args = args_ptr->test_sending_packet_args; + + struct SwiftNetServer* const server = swiftnet_create_server(8080, args.loopback); + if (server == NULL) { + PRINT_ERROR("Failed to create server"); + return -1; + } + + swiftnet_server_set_message_handler(server, on_server_packet, NULL); + + struct SwiftNetClientConnection* const client_conn = swiftnet_create_client(args.ip_address, 8080, 10000); + if (client_conn == NULL) { + PRINT_ERROR("Failed to create client connection"); + return -1; + } + + swiftnet_client_set_message_handler(client_conn, on_client_packet, NULL); + + atomic_store_explicit(&g_client_conn, client_conn, memory_order_release); + atomic_store_explicit(&g_server, server, memory_order_release); + + g_client_data_len = args.client_data_len; + g_server_data_len = args.server_data_len; + + uint8_t* c_data = malloc(args.client_data_len); + if (!c_data) { + PRINT_ERROR("Failed to allocate memory"); + return -1; + } + + for (uint32_t i = 0; i < args.client_data_len; i++) c_data[i] = rand(); + + atomic_store_explicit(&g_client_data, c_data, memory_order_release); + + if (args.server_data_len != 0) { + uint8_t* s_data = malloc(args.server_data_len); + if (!s_data) { + PRINT_ERROR("Failed to allocate memory"); + return -1; + } + + for (uint32_t i = 0; i < args.server_data_len; i++) s_data[i] = rand(); + + atomic_store_explicit(&g_server_data, s_data, memory_order_release); + } + + struct SwiftNetPacketBuffer buf = swiftnet_client_create_packet_buffer(args.server_data_len, client_conn); + swiftnet_append_to_buffer(atomic_load_explicit(&g_server_data, memory_order_acquire), args.server_data_len, &buf); + swiftnet_client_send_packet(client_conn, &buf, args.server_data_len); + swiftnet_client_destroy_packet_buffer(&buf, client_conn); + + atomic_store_explicit(&g_server_send_done, true, memory_order_release); + + for ( ;; ) { + int result = atomic_load_explicit(&g_test_result, memory_order_acquire); + if (result == INT_MAX) { + usleep(1000); + continue; + } + reset_test_state(); + return result; + } +} diff --git a/tests/integration_tests_pcap/.clangd b/tests/integration_tests_pcap/.clangd new file mode 100644 index 0000000..869e3c0 --- /dev/null +++ b/tests/integration_tests_pcap/.clangd @@ -0,0 +1,4 @@ +CompileFlags: + Add: + - "-L../build" + - "-lswift_net" diff --git a/tests/integration_tests/build/CMakeLists.txt b/tests/integration_tests_pcap/build/CMakeLists.txt similarity index 92% rename from tests/integration_tests/build/CMakeLists.txt rename to tests/integration_tests_pcap/build/CMakeLists.txt index d7937ad..6a30609 100644 --- a/tests/integration_tests/build/CMakeLists.txt +++ b/tests/integration_tests_pcap/build/CMakeLists.txt @@ -3,6 +3,8 @@ project(SwiftNetTests C) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../output) +add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + if(SANITIZER STREQUAL "address") message(STATUS "Using AddressSanitizer") add_compile_options(-fsanitize=address -fno-omit-frame-pointer) @@ -27,7 +29,7 @@ file(GLOB SRC_FILES "${CMAKE_SOURCE_DIR}/../src/*.c") add_executable(run_tests ${SRC_FILES}) -target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a -lpcap ) +target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a -lpcap) target_link_options(run_tests PRIVATE -g -O0) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/tests/integration_tests/build/build_tests.sh b/tests/integration_tests_pcap/build/build_tests.sh similarity index 100% rename from tests/integration_tests/build/build_tests.sh rename to tests/integration_tests_pcap/build/build_tests.sh diff --git a/tests/integration_tests_pcap/src/making_request.c b/tests/integration_tests_pcap/src/making_request.c new file mode 100644 index 0000000..04def0d --- /dev/null +++ b/tests/integration_tests_pcap/src/making_request.c @@ -0,0 +1,357 @@ +#include "run_tests.h" +#include +#include +#include +#include "../../../src/swift_net.h" +#include +#include +#include + +static _Atomic (struct SwiftNetClientConnection*) g_client_conn = NULL; +static _Atomic (struct SwiftNetServer*) g_server = NULL; + +static _Atomic int g_test_result = INT_MAX; + +static _Atomic (uint8_t*) g_request_data = NULL; +static _Atomic (uint8_t*) g_response_data = NULL; + +static _Atomic bool g_sent_response = false; + +static _Atomic uint32_t g_request_data_len = 0; +static _Atomic uint32_t g_response_data_len = 0; + +const uint8_t g_make_request_code = 0xFF; + +static void wait_until_response_sent() { + while (atomic_load_explicit(&g_sent_response, memory_order_acquire) == false) { + usleep(1000); + } +} + +static void reset_test_state() { + swiftnet_server_cleanup(atomic_load_explicit(&g_server, memory_order_acquire)); + swiftnet_client_cleanup(atomic_load_explicit(&g_client_conn, memory_order_acquire)); + + uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); + uint8_t* request_data = atomic_load_explicit(&g_request_data, memory_order_acquire); + + if (response_data) free(response_data); + if (request_data) free(request_data); + + atomic_store_explicit(&g_response_data, NULL, memory_order_release); + atomic_store_explicit(&g_request_data, NULL, memory_order_release); + + atomic_store_explicit(&g_response_data_len, 0, memory_order_release); + atomic_store_explicit(&g_request_data_len, 0, memory_order_release); + + atomic_store_explicit(&g_client_conn, NULL, memory_order_release); + atomic_store_explicit(&g_server, NULL, memory_order_release); + + atomic_store_explicit(&g_sent_response, false, memory_order_release); + + atomic_store_explicit(&g_test_result, INT_MAX, memory_order_release); +} + +static void on_client_packet(struct SwiftNetClientPacketData* packet, void* const user) { + struct SwiftNetClientConnection* const client_conn = atomic_load_explicit(&g_client_conn, memory_order_acquire); + + if (packet->metadata.data_length != atomic_load_explicit(&g_request_data_len, memory_order_acquire)) { + PRINT_ERROR("Server received invalid data size: %d | %d", + packet->metadata.data_length, + atomic_load_explicit(&g_request_data_len, memory_order_acquire) + ); + + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + const uint8_t* data = atomic_load_explicit(&g_request_data, memory_order_acquire); + + for (uint32_t i = 0; i < packet->metadata.data_length; i++) { + uint8_t byte_received = *(uint8_t*)swiftnet_client_read_packet(packet, 1); + if (data[i] != byte_received) { + PRINT_ERROR("Client received invalid data"); + + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + } + + const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); + uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); + + struct SwiftNetPacketBuffer send_buffer = swiftnet_client_create_packet_buffer(response_data_len, client_conn); + + swiftnet_append_to_buffer(response_data, response_data_len, &send_buffer); + + swiftnet_client_make_response(atomic_load_explicit(&g_client_conn, memory_order_acquire), packet, &send_buffer); + + swiftnet_client_destroy_packet_buffer(&send_buffer, client_conn); + swiftnet_client_destroy_packet_data(packet, client_conn); + + atomic_store_explicit(&g_sent_response, true, memory_order_release); +} + +static void on_server_packet(struct SwiftNetServerPacketData* packet, void* const user) { + struct SwiftNetServer* const server = atomic_load_explicit(&g_server, memory_order_acquire); + + if (packet->metadata.expecting_response) { + if (packet->metadata.data_length != atomic_load_explicit(&g_request_data_len, memory_order_acquire)) { + PRINT_ERROR("Server received invalid data size: %d | %d", + packet->metadata.data_length, + atomic_load_explicit(&g_request_data_len, memory_order_acquire) + ); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + const uint8_t* data = atomic_load_explicit(&g_request_data, memory_order_acquire); + + for (uint32_t i = 0; i < packet->metadata.data_length; i++) { + uint8_t byte_received = *(uint8_t*)swiftnet_server_read_packet(packet, 1); + if (data[i] != byte_received) { + PRINT_ERROR("Server received invalid data"); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + } + + const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); + uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); + + struct SwiftNetPacketBuffer send_buffer = swiftnet_server_create_packet_buffer(response_data_len, server); + + swiftnet_append_to_buffer(response_data, response_data_len, &send_buffer); + + swiftnet_server_make_response(atomic_load_explicit(&g_server, memory_order_acquire), packet, &send_buffer); + + swiftnet_server_destroy_packet_buffer(&send_buffer, server); + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_sent_response, true, memory_order_release); + } else { + if (packet->metadata.data_length != sizeof(g_make_request_code)) { + PRINT_ERROR("Server received invalid data size: %d | %lu", + packet->metadata.data_length, + sizeof(g_make_request_code) + ); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + uint8_t byte_received = *(uint8_t*)swiftnet_server_read_packet(packet, 1); + + if (byte_received != g_make_request_code) { + PRINT_ERROR("Server received invalid data"); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + const uint32_t request_data_len = atomic_load_explicit(&g_request_data_len, memory_order_acquire); + uint8_t* request_data = atomic_load_explicit(&g_request_data, memory_order_acquire); + const uint32_t response_data_len = atomic_load_explicit(&g_response_data_len, memory_order_acquire); + uint8_t* response_data = atomic_load_explicit(&g_response_data, memory_order_acquire); + + struct SwiftNetPacketBuffer buffer = swiftnet_server_create_packet_buffer(request_data_len, server); + + swiftnet_append_to_buffer(request_data, request_data_len, &buffer); + + struct SwiftNetServerPacketData* response = swiftnet_server_make_request(atomic_load_explicit(&g_server, memory_order_acquire), &buffer, packet->metadata.sender, 1000); + + swiftnet_server_destroy_packet_buffer(&buffer, server); + + if (response == NULL) { + int result = atomic_load_explicit(&g_test_result, memory_order_acquire); + if (result == INT_MAX) { + swiftnet_server_destroy_packet_data(packet, server); + + return; + } + + PRINT_ERROR("Did not receive response from server"); + + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + if (response->metadata.data_length != response_data_len) { + PRINT_ERROR("Server received invalid data size: %d | %d", + response->metadata.data_length, + response_data_len + ); + + swiftnet_server_destroy_packet_data(response, server); + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + + for (uint32_t i = 0; i < response->metadata.data_length; i++) { + uint8_t received_byte = *(uint8_t*)swiftnet_server_read_packet(response, 1); + if (response_data[i] != received_byte) { + PRINT_ERROR("Client received invalid data"); + + swiftnet_server_destroy_packet_data(response, server); + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, -1, memory_order_release); + + return; + } + } + + swiftnet_server_destroy_packet_data(response, server); + swiftnet_server_destroy_packet_data(packet, server); + + atomic_store_explicit(&g_test_result, 0, memory_order_release); + } +} + +int test_making_request(const union Args* args_ptr) { + const struct TestMakingRequestArgs args = args_ptr->test_making_request_args; + + struct SwiftNetServer* const server = swiftnet_create_server(8080, args.loopback); + if (server == NULL) { + PRINT_ERROR("Failed to create server"); + return -1; + } + + swiftnet_server_set_message_handler(server, on_server_packet, NULL); + + struct SwiftNetClientConnection* const client_conn = swiftnet_create_client(args.ip_address, 8080, 1000); + if (client_conn == NULL) { + PRINT_ERROR("Failed to create client connection"); + return -1; + } + + swiftnet_client_set_message_handler(client_conn, on_client_packet, NULL); + + atomic_store_explicit(&g_client_conn, client_conn, memory_order_release); + atomic_store_explicit(&g_server, server, memory_order_release); + + uint8_t* req_data = malloc(args.request_data_len); + if (!req_data) { + PRINT_ERROR("Failed to allocate memory"); + return -1; + } + + uint8_t* res_data = malloc(args.response_data_len); + if (!res_data) { + PRINT_ERROR("Failed to allocate memory"); + return -1; + } + + atomic_store_explicit(&g_request_data, req_data, memory_order_release); + atomic_store_explicit(&g_response_data, res_data, memory_order_release); + + atomic_store_explicit(&g_request_data_len, args.request_data_len, memory_order_release); + atomic_store_explicit(&g_response_data_len, args.response_data_len, memory_order_release); + + if (args.receiver == Server) { + struct SwiftNetPacketBuffer buffer = swiftnet_client_create_packet_buffer(args.request_data_len, client_conn); + + swiftnet_append_to_buffer(req_data, args.request_data_len, &buffer); + + struct SwiftNetClientPacketData* const response = swiftnet_client_make_request(client_conn, &buffer, 1000); + + swiftnet_client_destroy_packet_buffer(&buffer, client_conn); + + if (response == NULL) { + int result = atomic_load_explicit(&g_test_result, memory_order_acquire); + if (result != INT_MAX) { + return result; + } + + PRINT_ERROR("Did not receive response from server"); + + reset_test_state(); + + return -1; + } + + if (response->metadata.data_length != args.response_data_len) { + PRINT_ERROR("Client received invalid data size: %d | %d", + response->metadata.data_length, + args.response_data_len + ); + + swiftnet_client_destroy_packet_data(response, client_conn); + + reset_test_state(); + + return -1; + } + + for (uint32_t i = 0; i < response->metadata.data_length; i++) { + uint8_t received_byte = *(uint8_t*)swiftnet_client_read_packet(response, 1); + if (res_data[i] != received_byte) { + PRINT_ERROR("Client received invalid data"); + + swiftnet_client_destroy_packet_data(response, client_conn); + + reset_test_state(); + + return -1; + } + } + + swiftnet_client_destroy_packet_data(response, client_conn); + + wait_until_response_sent(); + + reset_test_state(); + + return 0; + } else { + struct SwiftNetPacketBuffer buffer = swiftnet_client_create_packet_buffer(sizeof(g_make_request_code), client_conn); + + swiftnet_append_to_buffer(&g_make_request_code, sizeof(g_make_request_code), &buffer); + + swiftnet_client_send_packet(client_conn, &buffer, sizeof(g_make_request_code)); + + swiftnet_client_destroy_packet_buffer(&buffer, client_conn); + + for ( ;; ) { + int result = atomic_load_explicit(&g_test_result, memory_order_acquire); + if (result == INT_MAX) { + usleep(1000); + continue; + } + + if (result == 0) { + wait_until_response_sent(); + } + + reset_test_state(); + + return result; + } + } +} diff --git a/tests/integration_tests/src/run_tests.c b/tests/integration_tests_pcap/src/run_tests.c similarity index 100% rename from tests/integration_tests/src/run_tests.c rename to tests/integration_tests_pcap/src/run_tests.c diff --git a/tests/integration_tests_pcap/src/run_tests.h b/tests/integration_tests_pcap/src/run_tests.h new file mode 100644 index 0000000..1698d8f --- /dev/null +++ b/tests/integration_tests_pcap/src/run_tests.h @@ -0,0 +1,37 @@ +#pragma once + +#define SWIFT_NET_BACKEND_PCAP + +#include +#include +#include +#include "../../shared.h" + +struct TestSendingPacketArgs { + const char* ip_address; + const bool loopback; + const uint32_t client_data_len; + const uint32_t server_data_len; +}; + +struct TestMakingRequestArgs { + const char* ip_address; + const bool loopback; + const enum ConnectionType receiver; + const uint32_t request_data_len; + const uint32_t response_data_len; +}; + +union Args { + struct TestSendingPacketArgs test_sending_packet_args; + struct TestMakingRequestArgs test_making_request_args; +}; + +struct Test { + int (*function)(const union Args*); + const union Args args; + const char* test_name; +}; + +extern int test_sending_packet(const union Args* args_ptr); +extern int test_making_request(const union Args* args_ptr); diff --git a/tests/integration_tests/src/sending_packet.c b/tests/integration_tests_pcap/src/sending_packet.c similarity index 93% rename from tests/integration_tests/src/sending_packet.c rename to tests/integration_tests_pcap/src/sending_packet.c index d922961..31491e9 100644 --- a/tests/integration_tests/src/sending_packet.c +++ b/tests/integration_tests_pcap/src/sending_packet.c @@ -120,10 +120,10 @@ static void on_server_packet(struct SwiftNetServerPacketData* packet, void* cons uint32_t size = atomic_load_explicit(&g_client_data_len, memory_order_acquire); uint8_t* send_data = atomic_load_explicit(&g_client_data, memory_order_acquire); - struct SwiftNetPacketBuffer buf = swiftnet_create_packet_buffer(size); + struct SwiftNetPacketBuffer buf = swiftnet_server_create_packet_buffer(size, server); swiftnet_append_to_buffer(send_data, size, &buf); - swiftnet_server_send_packet(atomic_load_explicit(&g_server, memory_order_acquire), &buf, packet->metadata.sender); - swiftnet_destroy_packet_buffer(&buf); + swiftnet_server_send_packet(atomic_load_explicit(&g_server, memory_order_acquire), &buf, packet->metadata.sender, size); + swiftnet_server_destroy_packet_buffer(&buf, server); swiftnet_server_destroy_packet_data(packet, server); @@ -182,10 +182,10 @@ int test_sending_packet(const union Args* args_ptr) { atomic_store_explicit(&g_server_data, s_data, memory_order_release); } - struct SwiftNetPacketBuffer buf = swiftnet_create_packet_buffer(args.server_data_len); + struct SwiftNetPacketBuffer buf = swiftnet_client_create_packet_buffer(args.server_data_len, client_conn); swiftnet_append_to_buffer(atomic_load_explicit(&g_server_data, memory_order_acquire), args.server_data_len, &buf); - swiftnet_client_send_packet(client_conn, &buf); - swiftnet_destroy_packet_buffer(&buf); + swiftnet_client_send_packet(client_conn, &buf, args.server_data_len); + swiftnet_client_destroy_packet_buffer(&buf, client_conn); atomic_store_explicit(&g_server_send_done, true, memory_order_release); diff --git a/tests/performance_tests/build/CMakeLists.txt b/tests/performance_tests/build/CMakeLists.txt index 3357d82..808240a 100644 --- a/tests/performance_tests/build/CMakeLists.txt +++ b/tests/performance_tests/build/CMakeLists.txt @@ -3,6 +3,8 @@ project(SwiftNetPerformanceTests C) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../output) +add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + if(SANITIZER STREQUAL "address") message(STATUS "Using AddressSanitizer") add_compile_options(-fsanitize=address -fno-omit-frame-pointer) diff --git a/tests/performance_tests/src/main.c b/tests/performance_tests/src/main.c index 38e85c3..fe7f77c 100644 --- a/tests/performance_tests/src/main.c +++ b/tests/performance_tests/src/main.c @@ -1,3 +1,4 @@ +#define SWIFT_NET_BACKEND_PCAP #include #include #include @@ -7,7 +8,6 @@ #include "../../../src/swift_net.h" #include "../../shared.h" - //#define PACKET_SIZE 1000000 // 1 MILLION BYTES //#define PACKETS_TO_SEND 50 // HOW MANY PACKETS TO SEND @@ -53,21 +53,21 @@ void send_large_packets(const bool loopback) { exit(EXIT_FAILURE); } - struct SwiftNetPacketBuffer buffer = swiftnet_create_packet_buffer(PACKET_SIZE); + struct SwiftNetPacketBuffer buffer = swiftnet_client_create_packet_buffer(PACKET_SIZE, client); buffer.packet_append_pointer += PACKET_SIZE; clock_gettime(CLOCK_MONOTONIC, &start);; for (uint32_t i = 0; i < PACKETS_TO_SEND; i++) { - swiftnet_client_send_packet(client, &buffer); + swiftnet_client_send_packet(client, &buffer, PACKET_SIZE); } while (atomic_load_explicit(&finished, memory_order_acquire) == false) { continue; } - swiftnet_destroy_packet_buffer(&buffer); + swiftnet_client_destroy_packet_buffer(&buffer, client); clock_gettime(CLOCK_MONOTONIC, &end);; @@ -82,9 +82,9 @@ void send_large_packets(const bool loopback) { } int main() { - swiftnet_initialize(); + swiftnet_initialize(NULL, 0); - send_large_packets(false); + send_large_packets(true); swiftnet_cleanup();