diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f4987f..cbbee5a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,6 +18,11 @@ jobs: os: ubuntu-24.04-arm - name: macos-arm64 os: macos-latest + - name: windows-arm64 + os: windows-11-arm + - name: windows-x86 + os: windows-latest + name: ${{ matrix.name }} runs-on: ${{ matrix.os }} @@ -26,11 +31,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: show_arch - run: | - uname -m - cc -dumpmachine - - name: install_dependencies_linux if: runner.os == 'Linux' run: | @@ -41,16 +41,101 @@ jobs: if: runner.os == 'macOS' run: brew install cmake + - name: install_dependencies_windows + if: runner.os == 'Windows' + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + + if("${{ runner.arch }}" -eq "ARM64") { + $LlvmUrl = "https://github.com/mstorsjo/llvm-mingw/releases/download/20261020/llvm-mingw-20261020-ucrt-aarch64.zip" + } else { + $LlvmUrl = "https://github.com/mstorsjo/llvm-mingw/releases/download/20261020/llvm-mingw-20261020-ucrt-x86_64.zip" + } + + choco install cmake make -y --no-progress + + if ($LASTEXITCODE -ne 0) { + throw "Chocolatey installation failed: $LASTEXITCODE" + } + + $sdk = "$env:RUNNER_TEMP\npcap-sdk.zip" + $dest = "$env:RUNNER_TEMP\npcap-sdk" + + Invoke-WebRequest ` + -Uri "https://npcap.com/dist/npcap-sdk-1.17.zip" ` + -OutFile $sdk + + Expand-Archive -Path $sdk -DestinationPath $dest -Force + + $header = Get-ChildItem $dest -Filter pcap.h -Recurse | Select-Object -First 1 + + if (!$header) { + throw "Npcap SDK headers not found" + } + + $sdkRoot = $header.Directory.Parent.FullName + + if (!(Test-Path "$sdkRoot\Lib\ARM64\wpcap.lib")) { + throw "ARM64 wpcap.lib missing" + } + if (!(Test-Path "$sdkRoot\Lib\ARM64\Packet.lib")) { + throw "ARM64 Packet.lib missing" + } + + if (!(Test-Path "$sdkRoot\Lib\x64\wpcap.lib")) { + throw "ARM64 wpcap.lib missing" + } + if (!(Test-Path "$sdkRoot\Lib\x64\Packet.lib")) { + throw "ARM64 Packet.lib missing" + } + + "NPCAP_SDK=$sdkRoot" >> $env:GITHUB_ENV + + $llvmDownloadLoc = "$env:RUNNER_TEMP\llvm-mingw.zip" + $llvmDest = "$env:RUNNER_TEMP\llvm-mingw" + + Invoke-WebRequest ` + -Uri $LlvmUrl ` + -OutFile $llvmDownloadLoc + + Expand-Archive -Path $llvmDownloadLoc -DestinationPath $llvmDest -Force + + $clang = Get-ChildItem $llvmDest -Filter clang.exe -Recurse | + Select-Object -First 1 + + if (!$clang) { + throw "LLVM clang.exe not found" + } + + $llvmBin = $clang.Directory.FullName + + "$llvmBin" >> $env:GITHUB_PATH + + & "$llvmBin\clang.exe" --version + + if ($LASTEXITCODE -ne 0) { + throw "LLVM installation verification failed" + } + - name: build_integration_tests_pcap + if: runner.os == 'Linux' || runner.os == 'macOS' run: | ./build_pcap_tests.sh working-directory: tests/integration_tests/build - name: run_integration_tests_pcap + if: runner.os == 'Linux' || runner.os == 'macOS' run: | sudo ./run_tests working-directory: tests/integration_tests/output + - name: build_integration_tests_pcap_win + if: runner.os == 'Windows' + run: | + ./build_pcap_tests.bat + working-directory: tests/integration_tests/build + - name: enable_hugepages if: runner.os == 'Linux' run: sudo sysctl -w vm.nr_hugepages=128 diff --git a/.gitignore b/.gitignore index f8451ef..3d42f9f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,10 @@ Makefile *.cache !/build/profile_template.cmake !/build/profiles/* +.vscode +**/*.dll +**/*.a **/*.trace **/diff.git diff --git a/README.md b/README.md index f2ae480..82c9e5f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,9 @@ ## Supported Platforms - **Apple Silicon (macOS arm64)** -- **Linux arm64** (Release build works, but testing is disabled due to TSAN issues) +- **Windows 11 (aarch64)** +- **Windows 11 (x86-64)** +- **Linux aarch64** (Release build works, but testing is disabled due to TSAN issues) - **Linux x86-64** ## Features @@ -81,23 +83,62 @@ vcpkg install morcules-swiftnet ``` ## From Source -1. Clone the repository to your local machine: + +## Windows + +1. Install NPcap (only supported backend on windows right now) +2. Install NPcap SDK +3. Put the NPcap SDK location into ENV variable "NPCAP_SDK" +4. Clone the repository to your local machine: +```bash +git clone https://github.com/SwiftNetProject/SwiftNet +``` +5. Navigate to the build directory inside the SwiftNet directory: +```bash +cd SwiftNet/build +``` +6. Copy profile: +```bash +cp profiles/x_profile.cmake profile.cmake +``` +7. Compile: +Run it with admin privileges +```bash +sudo ./build.bat +``` +8. To use SwiftNet in your project: +- Include `swift_net.h` in your main source file (e.g., `main.c`). +- Link against the static library `libswiftnet.a` using your compiler. + +## Linux/MacOS + +1. Install a backend (either libpcap-dev or libdpdk-dev (Only use DPDK with enough experience and in production) +macOS +```bash +brew install libpcap-dev | brew install libdpdk-dev +``` +linux +```bash +apt install libpcap-dev | apt install libdpdk-dev +``` + +2. Clone the repository to your local machine: ```bash -git clone https://github.com/morcules/SwiftNet +git clone https://github.com/SwiftNetProject/SwiftNet ``` -2. Navigate to the build directory inside the SwiftNet directory: +3. Navigate to the build directory inside the SwiftNet directory: ```bash cd SwiftNet/build ``` -3. Copy profile: +4. Copy profile: ```bash cp profiles/x_profile.cmake profile.cmake ``` -3. Compile: +5. Compile: ```bash ./build.sh ``` -4. To use SwiftNet in your project: +6. To use SwiftNet in your project: - Include `swift_net.h` in your main source file (e.g., `main.c`). - Link against the static library `libswiftnet.a` using your compiler. diff --git a/build/build.bat b/build/build.bat new file mode 100644 index 0000000..409512d --- /dev/null +++ b/build/build.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +cmake -S ..\src -B . -G "MinGW Makefiles" ^ + -DCMAKE_C_COMPILER=clang ^ + -DCMAKE_CXX_COMPILER=clang++ ^ + -DCMAKE_VERBOSE_MAKEFILE=OFF ^ + -DCMAKE_MAKE_PROGRAM=make + +if errorlevel 1 exit /b %errorlevel% + +cmake --build . --parallel 4 --clean-first + +if errorlevel 1 exit /b %errorlevel% + +endlocal diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01691a0..d28d251 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,10 +65,21 @@ elseif(BACKEND STREQUAL "dpdk") endif() -if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - add_compile_options(-march=armv8-a) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|i.86") - add_compile_options(-march=x86-64 -msse3 -mssse3) +execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE TARGET_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +message(STATUS "Compiler target: ${TARGET_TRIPLE}") + +if(TARGET_TRIPLE MATCHES "^(aarch64|arm64)") + add_compile_options(-march=armv8-a) + set(SN_ARCH aarch64) +elseif(TARGET_TRIPLE MATCHES "^(x86_64|amd64|i[3-6]86)") + add_compile_options(-march=x86-64 -msse3 -mssse3) + set(SN_ARCH x86) endif() add_library(swiftnet STATIC ${SOURCE_FILES}) @@ -147,10 +158,74 @@ if(BACKEND STREQUAL "pcap") message(WARNING "libpcap not found!!!") endif() else() - target_link_options(swiftnet PRIVATE -lpcap) - target_link_options(swiftnet_shared PRIVATE -lpcap) + if(WIN32) + find_path(NPCAP_INCLUDE_DIR + NAMES pcap.h + PATH_SUFFIXES Include include + PATHS + "C:/Npcap" + "$ENV{NPCAP_SDK}" + ) + + if(SN_ARCH MATCHES aarch64) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + elseif(SN_ARCH MATCHES x86) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + endif() + + if(NOT NPCAP_INCLUDE_DIR OR + NOT NPCAP_WPCAP_LIBRARY OR + NOT NPCAP_PACKET_LIBRARY) + message(FATAL_ERROR "Npcap SDK not found") + endif() + + target_include_directories(swiftnet PRIVATE + "${NPCAP_INCLUDE_DIR}" + ) + + target_link_libraries(swiftnet PRIVATE + "${NPCAP_WPCAP_LIBRARY}" + "${NPCAP_PACKET_LIBRARY}" + ) + + target_include_directories(swiftnet_shared PRIVATE + "${NPCAP_INCLUDE_DIR}" + ) + + target_link_libraries(swiftnet_shared PRIVATE + "${NPCAP_WPCAP_LIBRARY}" + "${NPCAP_PACKET_LIBRARY}" + ) + else() + target_link_options(swiftnet PRIVATE -lpcap) + target_link_options(swiftnet_shared PRIVATE -lpcap) - message("using linking option: -lpcap") + message("using linking option: -lpcap") + endif() endif() elseif(BACKEND STREQUAL "dpdk") find_package(PkgConfig REQUIRED) @@ -172,6 +247,20 @@ elseif(BACKEND STREQUAL "dpdk") message(STATUS "DPDK backend selected") endif() +if(WIN32) + target_link_libraries(swiftnet PRIVATE + ws2_32 + iphlpapi + pthread + ) + + target_link_libraries(swiftnet_shared PRIVATE + ws2_32 + iphlpapi + pthread + ) +endif() + set_target_properties(swiftnet PROPERTIES OUTPUT_NAME "swiftnet" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output" diff --git a/src/cleanup_connection.c b/src/cleanup_connection.c index 915ee89..2ab27df 100644 --- a/src/cleanup_connection.c +++ b/src/cleanup_connection.c @@ -3,8 +3,6 @@ #include "internal/networking.h" #include #include -#include -#include #include #include diff --git a/src/cleanup_swiftnet.c b/src/cleanup_swiftnet.c index 4bc8752..d62c91d 100644 --- a/src/cleanup_swiftnet.c +++ b/src/cleanup_swiftnet.c @@ -83,5 +83,9 @@ void swiftnet_cleanup(void) { #ifdef SWIFT_NET_INTERNAL_TESTING printf("Bytes leaked: %d\nItems leaked: %d\n", bytes_leaked, items_leaked); #endif + + #ifdef _WIN32 + WSACleanup(); + #endif } diff --git a/src/handle_packets.c b/src/handle_packets.c index c44c7ea..3c09a02 100644 --- a/src/handle_packets.c +++ b/src/handle_packets.c @@ -1,16 +1,17 @@ #include "internal/networking.h" #include "swift_net.h" -#include #include #include #include #include #include -#include -#include #include "internal/internal.h" #include +#if defined (__APPLE__) || defined(__linux__) +#include +#endif + static inline void insert_queue_node( struct SwiftNetPacketQueueNode* const new_node, struct SwiftNetPacketQueue* const packet_queue @@ -60,7 +61,7 @@ static inline struct SwiftNetPacketQueueNode* construct_node(const uint32_t data static inline bool valid_chunk_metadata(const struct SwiftNetNetworkData* restrict const network_data, const struct ReceiverPacketData* const restrict packet_data) { struct SwiftNetChunkMetadata* restrict chunk_metadata; - chunk_metadata = (struct SwiftNetChunkMetadata*)(packet_data->data + GET_PREPEND_SIZE(network_data) + sizeof(struct ip)); + chunk_metadata = (struct SwiftNetChunkMetadata*)(packet_data->data + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp)); if(chunk_metadata->packet_type <= PACKET_TYPE_END) return true; @@ -68,11 +69,11 @@ static inline bool valid_chunk_metadata(const struct SwiftNetNetworkData* restri } static inline bool valid_ip_header(const struct SwiftNetNetworkData* restrict const network_data, const struct ReceiverPacketData* const restrict packet_data) { - struct ip* restrict ip_header; + struct SwiftNetIp* restrict ip_header; bool valid_const_fields; - ip_header = (struct ip*)(packet_data->data + GET_PREPEND_SIZE(network_data)); + ip_header = (struct SwiftNetIp*)(packet_data->data + GET_PREPEND_SIZE(network_data)); valid_const_fields = ( ip_header->ip_hl == 5 && @@ -127,8 +128,8 @@ static inline void swiftnet_handle_packets( sender_address = 0; 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; + if (ntohs(((struct SwiftNetEtherHeader *)packet_buffer)->ether_type) == ETH_TYPE_IP) { + sender_address = ((struct SwiftNetIp *)(packet_buffer + sizeof(struct SwiftNetEtherHeader)))->ip_src.s_addr; } else { allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -195,7 +196,7 @@ static void handle_client_init(struct SwiftNetClientConnection* const client_con } if (addr_type != 0) { - memcpy(client_connection->eth_header.ether_dhost, ((struct ether_header*)buffer)->ether_shost, sizeof(client_connection->eth_header.ether_dhost)); + memcpy(client_connection->eth_header.ether_dhost, ((struct SwiftNetEtherHeader*)buffer)->ether_shost, sizeof(client_connection->eth_header.ether_dhost)); } @@ -205,7 +206,7 @@ static void handle_client_init(struct SwiftNetClientConnection* const client_con if(chunk_metadata->port_info.destination_port != client_connection->port_info.source_port || chunk_metadata->port_info.source_port != client_connection->port_info.destination_port) { #ifndef SWIFT_NET_DISABLE_DEBUGGING if (check_debug_flag(SWIFTNET_DEBUG_INITIALIZATION)) { - send_debug_message("Port info does not match: {\"destination_port\": %d, \"source_port\": %d, \"source_ip_address\": \"%s\"}\n", chunk_metadata->port_info.destination_port, chunk_metadata->port_info.source_port, inet_ntoa(((struct ip*)(buffer + prepend_size))->ip_src)); + send_debug_message("Port info does not match: {\"destination_port\": %d, \"source_port\": %d, \"source_ip_address\": \"%s\"}\n", chunk_metadata->port_info.destination_port, chunk_metadata->port_info.source_port, inet_ntoa(((struct SwiftNetIp*)(buffer + prepend_size))->ip_src)); } #endif @@ -264,6 +265,8 @@ static inline uint8_t handle_correct_receiver(const enum ConnectionType connecti LOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); + printf("dest port: %d\n", port_info->destination_port); + server = hashmap_get(&port_info->destination_port, sizeof(uint16_t), &listener->servers); UNLOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); @@ -285,7 +288,7 @@ static void pcap_packet_handle(uint8_t* const user, const struct pcap_pkthdr* re listener = (struct Listener*)user; - port_info = (struct SwiftNetPortInfo*)(packet + PACKET_PREPEND_SIZE(listener->addr_type) + sizeof(struct ip) + offsetof(struct SwiftNetChunkMetadata, port_info)); + port_info = (struct SwiftNetPortInfo*)(packet + PACKET_PREPEND_SIZE(listener->addr_type) + sizeof(struct SwiftNetIp) + offsetof(struct SwiftNetChunkMetadata, port_info)); struct ReceiverPacketData packet_data = (struct ReceiverPacketData){.data = packet, .data_len = hdr->caplen}; @@ -293,7 +296,7 @@ static void pcap_packet_handle(uint8_t* const user, const struct pcap_pkthdr* re } #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 SwiftNetChunkMetadata, port_info)); + struct SwiftNetPortInfo* restrict const port_info = (struct SwiftNetPortInfo*)(packet + PACKET_PREPEND_SIZE(listener->addr_type) + sizeof(struct SwiftNetIp) + offsetof(struct SwiftNetChunkMetadata, 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); diff --git a/src/initialize_client_connection.c b/src/initialize_client_connection.c index d3d848a..6360584 100644 --- a/src/initialize_client_connection.c +++ b/src/initialize_client_connection.c @@ -2,24 +2,22 @@ #include #include #include -#include #include #include #include #include -#include #include -#include -#include -#include #include "internal/internal.h" #include "swift_net.h" #include #include #include -#include #include "internal/networking.h" +#if defined(__APPLE__) || defined(__linux__) +#include +#endif + struct RequestServerInformationArgs { uint32_t size; struct in_addr server_addr; @@ -74,7 +72,7 @@ void* request_server_information(void* restrict const request_server_information return NULL; } -static inline struct SwiftNetClientConnection* construct_client_connection(const bool loopback, const uint16_t destination_port, const in_addr_t server_address) { +static inline struct SwiftNetClientConnection* construct_client_connection(const bool loopback, const uint16_t destination_port, const SwiftNetAddrIpv4 server_address) { struct SwiftNetClientConnection* new_connection; new_connection = allocator_allocate(&client_connection_memory_allocator); @@ -122,26 +120,25 @@ static inline void remove_con_from_listener(struct SwiftNetClientConnection* con } struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_address, const uint16_t port, const uint32_t timeout_ms) { - struct in_addr addr; + SwiftNetAddrIpv4 addr; uint32_t ip; bool loopback; struct SwiftNetClientConnection* new_connection; struct SwiftNetChunkMetadata request_server_information_chunk_metadata; struct SwiftNetPacketMetadata request_server_information_packet_metadata; - struct ip request_server_info_ip_header; + struct SwiftNetIp request_server_info_ip_header; pthread_t send_request_thread; struct RequestServerInformationArgs thread_args; struct Listener* listener; struct SwiftNetNetworkData network_data; + addr_ipv4_from_string(ip_address, &addr); - inet_aton(ip_address, &addr); - - ip = ntohl(addr.s_addr); + ip = ntohl(addr); loopback = (ip >> 24) == 127; - new_connection = construct_client_connection(loopback, port, addr.s_addr); + new_connection = construct_client_connection(loopback, port, addr); listener = check_existing_listener(new_connection, CONNECTION_TYPE_CLIENT, loopback); @@ -169,7 +166,7 @@ struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_add .network_data = &network_data, .data = request_server_info_buffer, .size = (uint32_t)sizeof(request_server_info_buffer), - .server_addr = addr, + .server_addr = {addr}, .timeout_ms = timeout_ms, .connection = new_connection #ifdef SWIFT_NET_BACKEND_DPDK diff --git a/src/initialize_server.c b/src/initialize_server.c index d6c3008..265fbd0 100644 --- a/src/initialize_server.c +++ b/src/initialize_server.c @@ -1,13 +1,8 @@ #include #include -#include #include #include #include -#include -#include -#include -#include #include #include #include "internal/internal.h" diff --git a/src/initialize_swiftnet.c b/src/initialize_swiftnet.c index b190428..8052cab 100644 --- a/src/initialize_swiftnet.c +++ b/src/initialize_swiftnet.c @@ -1,14 +1,17 @@ -#include #include #include #include -#include -#include -#include #include "swift_net.h" #include "internal/internal.h" #include +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#elif defined(_WIN32) + WSADATA wsaData; +#endif + #ifndef SWIFT_NET_DISABLE_DEBUGGING struct SwiftNetDebugger debugger = {.flags = 0}; #endif @@ -23,7 +26,7 @@ uint32_t semaphore_counter = 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)]; +char default_network_interface[MAX_INTERFACE_LEN]; struct SwiftNetMemoryAllocator packet_queue_node_memory_allocator; struct SwiftNetMemoryAllocator packet_callback_queue_node_memory_allocator; @@ -60,7 +63,7 @@ static inline void initialize_allocators(void) { packet_callback_queue_node_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketCallbackQueueNode), 40 * SWIFT_NET_MEMORY_USAGE); server_packet_data_memory_allocator = allocator_create(sizeof(struct SwiftNetServerPacketData), 40 * SWIFT_NET_MEMORY_USAGE); client_packet_data_memory_allocator = allocator_create(sizeof(struct SwiftNetClientPacketData), 40 * SWIFT_NET_MEMORY_USAGE); - packet_buffer_memory_allocator = allocator_create(maximum_transmission_unit + sizeof(struct ether_header), 40 * SWIFT_NET_MEMORY_USAGE); + packet_buffer_memory_allocator = allocator_create(maximum_transmission_unit + sizeof(struct SwiftNetEtherHeader), 40 * SWIFT_NET_MEMORY_USAGE); server_memory_allocator = allocator_create(sizeof(struct SwiftNetServer), 10); client_connection_memory_allocator = allocator_create(sizeof(struct SwiftNetClientConnection), 10); listener_memory_allocator = allocator_create(sizeof(struct Listener), 40 * SWIFT_NET_MEMORY_USAGE); @@ -123,6 +126,13 @@ void swiftnet_initialize(void) { if (rte_eal_init(argc, argv) < 0) rte_exit(EXIT_FAILURE, "EAL init failed\n"); #endif + #ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + PRINT_ERROR("WSAStartup failed\n"); + exit(EXIT_FAILURE); + } + #endif + int temp_socket; struct sockaddr_in remote = {0}; struct sockaddr private_sockaddr; @@ -170,7 +180,11 @@ void swiftnet_initialize(void) { exit(EXIT_FAILURE); } + #if defined(_WIN32) + maximum_transmission_unit = get_mtu(default_network_interface + 12, temp_socket); + #elif defined(__APPLE__) || defined(__linux__) maximum_transmission_unit = get_mtu(default_network_interface, temp_socket); + #endif if(unlikely(maximum_transmission_unit == 0)) { PRINT_ERROR("Failed to get the maximum transmission unit"); close(temp_socket); diff --git a/src/internal/get_default_interface_and_mac.c b/src/internal/get_default_interface_and_mac.c index c3512c7..b21b95a 100644 --- a/src/internal/get_default_interface_and_mac.c +++ b/src/internal/get_default_interface_and_mac.c @@ -1,22 +1,26 @@ #include "internal.h" -#include -#include #include -#include +#include #include -#include -#include -#include -#include #ifdef __linux__ #include #include + +#include #elif defined(__APPLE__) #include + +#include +#elif defined(_WIN32) +#include +#include +#include +#include #endif +#if defined(__linux__) || defined(__APPLE__) int get_default_interface_and_mac(char* restrict interface_name, const uint32_t interface_name_length, uint8_t* restrict mac_out, const int sockfd) { struct sockaddr_in local_addr; socklen_t addr_len; @@ -126,4 +130,110 @@ int get_default_interface_and_mac(char* restrict interface_name, const uint32_t return 0; } +#elif defined(_WIN32) +int get_default_interface_and_mac( + char* restrict interface_name, + const uint32_t interface_name_length, + uint8_t* restrict mac_out, + const int sockfd +) { + struct sockaddr_in local_addr; + uint32_t addr_len; + uint32_t buffer_size; + uint64_t result; + IP_ADAPTER_ADDRESSES* adapters; + IP_ADAPTER_ADDRESSES* adapter; + IP_ADAPTER_ADDRESSES* match; + + addr_len = sizeof(local_addr); + + if (getsockname((SOCKET)sockfd, (struct sockaddr*)&local_addr, (int*)&addr_len) == SOCKET_ERROR) { + PRINT_ERROR("getsockname failed: %d", WSAGetLastError()); + return -1; + } + + buffer_size = 15000; + adapters = NULL; + + for (;;) { + adapters = malloc(buffer_size); + + if (!adapters) { + return -1; + } + + result = GetAdaptersAddresses( + AF_INET, + GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER, + NULL, + adapters, + (unsigned long*)&buffer_size + ); + + if (result != ERROR_BUFFER_OVERFLOW) { + break; + } + + free(adapters); + adapters = NULL; + } + + if (result != NO_ERROR) { + PRINT_ERROR("GetAdaptersAddresses failed: %lu", (unsigned long)result); + free(adapters); + return -1; + } + + match = NULL; + + for (adapter = adapters; adapter != NULL; adapter = adapter->Next) { + IP_ADAPTER_UNICAST_ADDRESS* unicast; + + + for (unicast = adapter->FirstUnicastAddress; unicast != NULL; unicast = unicast->Next) { + + struct sockaddr_in* sin; + + if (unicast->Address.lpSockaddr == NULL || + unicast->Address.lpSockaddr->sa_family != AF_INET) { + continue; + } + + sin = (struct sockaddr_in*)unicast->Address.lpSockaddr; + + if (sin->sin_addr.s_addr == local_addr.sin_addr.s_addr) { + match = adapter; + break; + } + } + + if (match != NULL) { + break; + } + } + + if (match == NULL) { + PRINT_ERROR("No matching interface found for socket IPv4 address"); + free(adapters); + return -1; + } + + snprintf(interface_name, interface_name_length, "\\Device\\NPF_%s", match->AdapterName); + + if (match->PhysicalAddressLength != 6) { + PRINT_ERROR("Invalid mac adress size"); + free(adapters); + return -1; + } + + memcpy(mac_out, match->PhysicalAddress, 6); + + printf("Found interface: %s\n", interface_name); + + free(adapters); + return 0; +} +#endif diff --git a/src/internal/get_mtu.c b/src/internal/get_mtu.c index 0d5728b..ae803f1 100644 --- a/src/internal/get_mtu.c +++ b/src/internal/get_mtu.c @@ -1,21 +1,21 @@ #include "internal.h" -#include "stdlib.h" -#include "stdio.h" #include -#include #include -#include -#include #include -#include + +// TODO: Windows equivalent +#if defined(__APPLE__) || defined(__linux__) +#include "stdio.h" +#include +#include #include -uint16_t get_mtu(const char* restrict const interface, const int sockfd) { +uint16_t get_mtu(const char* restrict const net_interface, const int sockfd) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, interface, IFNAMSIZ - 1); + strncpy(ifr.ifr_name, net_interface, MAX_INTERFACE_LEN - 1); if(ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) { PRINT_ERROR("ioctl failed"); @@ -24,4 +24,60 @@ uint16_t get_mtu(const char* restrict const interface, const int sockfd) { return (uint16_t)ifr.ifr_mtu; } +#elif defined(_WIN32) +#include +#include + +uint16_t get_mtu(const char* restrict const net_interface, const int sockfd) { + uint32_t buffer_size; + uint64_t result; + IP_ADAPTER_ADDRESSES* adapters; + IP_ADAPTER_ADDRESSES* adapter; + uint16_t mtu; + + buffer_size = 15000; + adapters = NULL; + + for (;;) { + adapters = malloc(buffer_size); + + if (unlikely(adapters == NULL)) { + exit(EXIT_FAILURE); + } + + result = GetAdaptersAddresses( + AF_UNSPEC, + GAA_FLAG_INCLUDE_ALL_INTERFACES, + NULL, + adapters, + (unsigned long*)&buffer_size + ); + + if (result != ERROR_BUFFER_OVERFLOW) { + break; + } + + free(adapters); + adapters = NULL; + } + + if (result != NO_ERROR) { + PRINT_ERROR("GetAdaptersAddresses failed: %llu", result); + free(adapters); + exit(EXIT_FAILURE); + } + + for (adapter = adapters; adapter != NULL; adapter = adapter->Next) { + if (strcmp(adapter->AdapterName, net_interface) == 0) { + mtu = (uint16_t)adapter->Mtu; + free(adapters); + return mtu; + } + } + + PRINT_ERROR("Interface not found: %s\n", net_interface); + free(adapters); + exit(EXIT_FAILURE); +} +#endif diff --git a/src/internal/internal.h b/src/internal/internal.h index eefc060..7373d20 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -1,17 +1,22 @@ #pragma once -#include #include -#include -#include #include -#include -#include #include #include -#include #include "../swift_net.h" +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#include +#include +#include +#include +#elif defined(_WIN32) +#include +#endif + #ifdef SWIFT_NET_BACKEND_PCAP #include #endif @@ -29,7 +34,13 @@ #define ASAN_POISON(addr, size) ((void)(addr), (void)(size)) #endif +#if defined (_WIN32) +#define MAX_INTERFACE_LEN 128 +#elif defined(__APPLE__) || defined(__linux__) +#define MAX_INTERFACE_LEN 16 +#endif #define IS_NET_MESSAGE(packet_type) (packet_type >= REQUEST_INFORMATION) +#define ETH_TYPE_IP UINT16_C(0x0800) #ifdef __APPLE__ #include @@ -71,6 +82,9 @@ extern uint32_t lcores_used[]; #elif defined(__APPLE__) #define CLIENT_LOOPBACK_INTERFACE_NAME "lo0\0" #define SERVER_LOOPBACK_INTERFACE_NAME "lo0\0" +#elif defined(_WIN32) +#define CLIENT_LOOPBACK_INTERFACE_NAME "\\Device\\NPF_Loopback\0" +#define SERVER_LOOPBACK_INTERFACE_NAME "\\Device\\NPF_Loopback\0" #endif #elif defined(SWIFT_NET_BACKEND_DPDK) #define CLIENT_LOOPBACK_INTERFACE_NAME "net_ring0\0" @@ -81,9 +95,9 @@ extern uint32_t lcores_used[]; (connection_type == CONNECTION_TYPE_CLIENT ? (loopback ? CLIENT_LOOPBACK_INTERFACE_NAME : default_network_interface) : (loopback ? SERVER_LOOPBACK_INTERFACE_NAME : default_network_interface)) #define IP_HEADER_LOCATION(buffer, network_data) (buffer + GET_PREPEND_SIZE(network_data)) -#define CHUNK_METADATA_LOCATION(buffer, network_data) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip)) -#define PACKET_METADATA_LOCATION(buffer, network_data) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip) + sizeof(struct SwiftNetChunkMetadata)) -#define DATA_LOCATION(buffer, network_data, packet_metadata_present) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip) + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata_present ? sizeof(struct SwiftNetPacketMetadata) : 0)) +#define CHUNK_METADATA_LOCATION(buffer, network_data) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp)) +#define PACKET_METADATA_LOCATION(buffer, network_data) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp) + sizeof(struct SwiftNetChunkMetadata)) +#define DATA_LOCATION(buffer, network_data, packet_metadata_present) (buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp) + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata_present ? sizeof(struct SwiftNetPacketMetadata) : 0)) #ifdef SWIFT_NET_INTERNAL_TESTING #define ENABLE_INTERNAL_CHECK , 0 @@ -147,13 +161,13 @@ struct ReceiverPacketData { // 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) +#define PACKET_PREPEND_SIZE(addr_type) sizeof(struct SwiftNetEtherHeader) #elif defined(SWIFT_NET_BACKEND_PCAP) -#define PACKET_PREPEND_SIZE(addr_type) ((addr_type == DLT_NULL) ? (uint8_t)sizeof(uint32_t) : addr_type == DLT_EN10MB ? (uint8_t)sizeof(struct ether_header) : (uint8_t)0) +#define PACKET_PREPEND_SIZE(addr_type) ((addr_type == DLT_NULL) ? (uint8_t)sizeof(uint32_t) : addr_type == DLT_EN10MB ? (uint8_t)sizeof(struct SwiftNetEtherHeader) : (uint8_t)0) #endif -#define PACKET_HEADER_SIZE (sizeof(struct ip) + sizeof(struct SwiftNetChunkMetadata)) +#define PACKET_HEADER_SIZE (sizeof(struct SwiftNetIp) + sizeof(struct SwiftNetChunkMetadata)) -#define DEFAULT_MAC_ADDRESS_STRUCT (struct ether_header){.ether_dhost = {0xff,0xff,0xff,0xff,0xff,0xff}, .ether_type = htons(0x0800)} +#define DEFAULT_MAC_ADDRESS_STRUCT (struct SwiftNetEtherHeader){.ether_dhost = {0xff,0xff,0xff,0xff,0xff,0xff}, .ether_type = htons(0x0800)} // Number used in ip.proto #define PROT_NUMBER 253 @@ -231,7 +245,7 @@ CRC_TARGET MAYBE_UNUSED static uint32_t crc32(const uint8_t* const data, const u return ~crc; } -static uint16_t ip_checksum(const uint8_t* header) { +MAYBE_UNUSED static uint16_t ip_checksum(const uint8_t* header) { uint32_t sum = 0; for(uint16_t i = 0; i < 20; i+=2) { @@ -244,6 +258,14 @@ static uint16_t ip_checksum(const uint8_t* header) { return (uint16_t)~sum; } +MAYBE_UNUSED static inline ALWAYS_INLINE void addr_ipv4_from_string(const char* const restrict address, SwiftNetAddrIpv4* restrict const target) { + #if defined(_WIN32) + InetPtonA(AF_INET, address, target); + #elif defined(__APPLE__) || defined(__linux__) + inet_aton(address, (struct in_addr*)target); + #endif +} + enum StackCreatingState { STACK_CREATING_LOCKED = 0, STACK_CREATING_UNLOCKED = 1 @@ -277,7 +299,7 @@ struct Listener { #endif struct SwiftNetHashMap servers; struct SwiftNetHashMap client_connections; - char interface_name[IFNAMSIZ]; + char interface_name[MAX_INTERFACE_LEN]; uint16_t addr_type; bool loopback; }; @@ -305,7 +327,7 @@ extern _Atomic bool swiftnet_closing; 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 uint16_t get_mtu(const char* restrict const interface, const int sockfd); +extern uint16_t get_mtu(const char* restrict const net_interface, const int sockfd); extern void* swiftnet_server_process_packets(void* const void_server); extern void* swiftnet_client_process_packets(void* const void_client); @@ -315,7 +337,7 @@ extern void* execute_packet_callback_server(void* const void_server); extern struct in_addr private_ip_address; extern uint8_t mac_address[6]; -extern char default_network_interface[SIZEOF_FIELD(struct ifreq, ifr_name)]; +extern char default_network_interface[MAX_INTERFACE_LEN]; extern void* check_existing_listener(void* const connection, const enum ConnectionType connection_type, const bool loopback); @@ -421,7 +443,7 @@ extern void swiftnet_send_packet( const uint32_t packet_length, const struct in_addr* const target_addr, struct SwiftNetHashMap* const packets_sending, - const struct ether_header eth_hdr, + const struct SwiftNetEtherHeader eth_hdr, const struct SwiftNetNetworkData network_data #ifndef SWIFT_NET_DISABLE_REQUESTS , struct RequestSent* const request_sent @@ -447,11 +469,11 @@ static inline ALWAYS_INLINE struct SwiftNetPacketMetadata construct_packet_metad }; } -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; +static inline ALWAYS_INLINE struct SwiftNetIp construct_ip_header(const struct in_addr destination_addr, const uint16_t packet_size, const uint16_t packet_id) { + struct SwiftNetIp ip_header; - ip_header = (struct ip){ + ip_header = (struct SwiftNetIp){ .ip_hl = 5, .ip_v = 4, .ip_tos = 0, diff --git a/src/internal/networking.h b/src/internal/networking.h index 72a53f7..7386442 100644 --- a/src/internal/networking.h +++ b/src/internal/networking.h @@ -16,9 +16,9 @@ #define HANDLE_CHECKSUM(buffer, size, network_data, packet_metadata) \ { \ const uint16_t ip_sum = htons(ip_checksum(buffer + GET_PREPEND_SIZE(network_data))); \ - const uint32_t checksum = crc32(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip), size + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata ? sizeof(struct SwiftNetPacketMetadata) : 0)); \ - memcpy(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip) + offsetof(struct SwiftNetChunkMetadata, checksum), &checksum, sizeof(checksum)); \ - memcpy(buffer + GET_PREPEND_SIZE(network_data) + offsetof(struct ip, ip_sum), &ip_sum, SIZEOF_FIELD(struct ip, ip_sum)); \ + const uint32_t checksum = crc32(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp), size + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata ? sizeof(struct SwiftNetPacketMetadata) : 0)); \ + memcpy(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp) + offsetof(struct SwiftNetChunkMetadata, checksum), &checksum, sizeof(checksum)); \ + memcpy(buffer + GET_PREPEND_SIZE(network_data) + offsetof(struct SwiftNetIp, ip_sum), &ip_sum, SIZEOF_FIELD(struct SwiftNetIp, ip_sum)); \ } #define GET_ADDR_TYPE(network_data) (network_data)->addr_type @@ -41,12 +41,12 @@ #define FREE_PACKET_CONSTRUCTION(buffer_name, network_data) - extern void swiftnet_pcap_open(const char* const restrict interface, struct SwiftNetNetworkData* const network_data); + extern void swiftnet_pcap_open(const char* const restrict net_interface, struct SwiftNetNetworkData* const network_data); 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) { + inline static struct SwiftNetNetworkData swiftnet_initialize_networking(const char* const restrict net_interface) { struct SwiftNetNetworkData network_data; - swiftnet_pcap_open(interface, &network_data); + swiftnet_pcap_open(net_interface, &network_data); if (unlikely(network_data.pcap == NULL)) { PRINT_ERROR("Failed to open pcap"); @@ -94,9 +94,9 @@ #define HANDLE_CHECKSUM(buffer, size, network_data, packet_metadata) \ { \ const uint16_t ip_sum = htons(ip_checksum(buffer + GET_PREPEND_SIZE(network_data))); \ - const uint32_t checksum = crc32(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip), size + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata ? sizeof(struct SwiftNetPacketMetadata) : 0)); \ - memcpy(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct ip) + offsetof(struct SwiftNetChunkMetadata, checksum), &checksum, sizeof(checksum)); \ - memcpy(buffer + GET_PREPEND_SIZE(network_data) + offsetof(struct ip, ip_sum), &ip_sum, SIZEOF_FIELD(struct ip, ip_sum)); \ + const uint32_t checksum = crc32(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp), size + sizeof(struct SwiftNetChunkMetadata) + (packet_metadata ? sizeof(struct SwiftNetPacketMetadata) : 0)); \ + memcpy(buffer + GET_PREPEND_SIZE(network_data) + sizeof(struct SwiftNetIp) + offsetof(struct SwiftNetChunkMetadata, checksum), &checksum, sizeof(checksum)); \ + memcpy(buffer + GET_PREPEND_SIZE(network_data) + offsetof(struct SwiftNetIp, ip_sum), &ip_sum, SIZEOF_FIELD(struct ip, ip_sum)); \ } #define GET_ADDR_TYPE(network_data) (network_data)->addr_type diff --git a/src/internal/pcap/pcap_buffer.c b/src/internal/pcap/pcap_buffer.c index cb59a66..50bce7f 100644 --- a/src/internal/pcap/pcap_buffer.c +++ b/src/internal/pcap/pcap_buffer.c @@ -1,12 +1,10 @@ #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) + sizeof(struct SwiftNetPacketMetadata)); - uint8_t* restrict const data_pointer = mem + PACKET_HEADER_SIZE + sizeof(struct ether_header) + sizeof(struct SwiftNetPacketMetadata); + uint8_t* restrict const mem = malloc(buffer_size + PACKET_HEADER_SIZE + sizeof(struct SwiftNetEtherHeader) + sizeof(struct SwiftNetPacketMetadata)); + uint8_t* restrict const data_pointer = mem + PACKET_HEADER_SIZE + sizeof(struct SwiftNetEtherHeader) + sizeof(struct SwiftNetPacketMetadata); return (struct SwiftNetPacketBuffer){ .packet_buffer_start = mem, @@ -30,7 +28,7 @@ static inline void resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNe 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) + sizeof(struct SwiftNetPacketMetadata); + new_buffer_size += PACKET_HEADER_SIZE + sizeof(struct SwiftNetEtherHeader) + sizeof(struct SwiftNetPacketMetadata); new_ptr = realloc(packet_buffer->packet_buffer_start, new_buffer_size); if (unlikely(new_ptr == NULL)) { @@ -38,7 +36,7 @@ static inline void resize_packet_buffer(uint32_t new_buffer_size, struct SwiftNe exit(EXIT_FAILURE); } - data_start = new_ptr + PACKET_HEADER_SIZE + sizeof(struct ether_header); + data_start = new_ptr + PACKET_HEADER_SIZE + sizeof(struct SwiftNetEtherHeader); *packet_buffer = (struct SwiftNetPacketBuffer){ .packet_buffer_start = new_ptr, diff --git a/src/internal/pcap/pcap_open.c b/src/internal/pcap/pcap_open.c index 56737bc..36dc8d1 100644 --- a/src/internal/pcap/pcap_open.c +++ b/src/internal/pcap/pcap_open.c @@ -1,17 +1,16 @@ #include "../internal.h" #include -void swiftnet_pcap_open(const char* const restrict interface, struct SwiftNetNetworkData* const network_data) { +void swiftnet_pcap_open(const char* const restrict net_interface, struct SwiftNetNetworkData* const network_data) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* p; char filter_exp[] = "ip proto 253"; bpf_u_int32 net; - net = 0; p = pcap_open_live( - interface, + net_interface, 65535, 1, 25, diff --git a/src/process_packets.c b/src/process_packets.c index 1c9dd21..26e411f 100644 --- a/src/process_packets.c +++ b/src/process_packets.c @@ -1,25 +1,19 @@ #include "internal/internal.h" #include "internal/networking.h" #include "swift_net.h" -#include -#include -#include #include #include #include #include #include #include -#include #include -#include #include #include #include -#include MAYBE_UNUSED static inline bool is_private_ip(const struct in_addr ip) { - in_addr_t addr = htonl(ip.s_addr); + SwiftNetAddrIpv4 addr = htonl(ip.s_addr); return ((addr >> 24) & 0xFF) == 127; } @@ -291,8 +285,8 @@ static inline struct SwiftNetPacketSending* get_packet_sending(struct SwiftNetHa } #ifndef DISABLE_DYNAMIC_RATE_LIMITING -static inline void signal_delay_change(const enum SwiftNetPacketDelayUpdateStatus 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; +static inline void signal_delay_change(const enum SwiftNetPacketDelayUpdateStatus status, const struct SwiftNetIp* restrict const ip_header, const uint16_t source_port, const uint16_t destination_port, const struct SwiftNetEtherHeader* const eth_hdr, const struct SwiftNetNetworkData* const net_data) { + struct SwiftNetIp send_server_info_ip_header; struct SwiftNetChunkMetadata chunk_metadata_new; struct SwiftNetPacketMetadata packet_metadata_new; @@ -356,7 +350,7 @@ static inline bool packet_corrupted(const uint32_t checksum, const uint32_t chun } static inline void swiftnet_process_packets( - const struct ether_header eth_hdr, + const struct SwiftNetEtherHeader eth_hdr, const uint16_t source_port, const struct SwiftNetNetworkData network_data, struct SwiftNetHashMap* const packets_sending, @@ -377,7 +371,7 @@ static inline void swiftnet_process_packets( struct SwiftNetPacketQueueNode* node; uint8_t* packet_buffer; uint8_t* packet_data; - struct ip ip_header; + struct SwiftNetIp ip_header; struct SwiftNetChunkMetadata chunk_metadata; struct SwiftNetPacketMetadata packet_metadata; uint32_t checksum_received; @@ -526,10 +520,10 @@ static inline void swiftnet_process_packets( memset(CHUNK_METADATA_LOCATION(packet_buffer, &network_data) + offsetof(struct SwiftNetChunkMetadata, checksum), 0x00, SIZEOF_FIELD(struct SwiftNetChunkMetadata, checksum)); - memcpy(IP_HEADER_LOCATION(packet_buffer, &network_data) + offsetof(struct ip, ip_len), (void*)&node->data_read, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(IP_HEADER_LOCATION(packet_buffer, &network_data) + offsetof(struct SwiftNetIp, ip_len), (void*)&node->data_read, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); - if(node->data_read > sizeof(struct ip) + prepend_size && memcmp(&ip_header.ip_src, &ip_header.ip_dst, sizeof(struct in_addr)) != 0) { - if(packet_corrupted(checksum_received, node->data_read - sizeof(struct ip) - prepend_size, packet_buffer + prepend_size + sizeof(struct ip)) == true) { + if(node->data_read > sizeof(struct SwiftNetIp) + prepend_size && memcmp(&ip_header.ip_src, &ip_header.ip_dst, sizeof(struct in_addr)) != 0) { + if(packet_corrupted(checksum_received, node->data_read - sizeof(struct SwiftNetIp) - prepend_size, packet_buffer + prepend_size + sizeof(struct SwiftNetIp)) == true) { #ifndef SWIFT_NET_DISABLE_DEBUGGING if (check_debug_flag(SWIFTNET_DEBUG_PACKETS_RECEIVING)) { send_debug_message("Received corrupted packet: {\"source_ip_address\": \"%s\", \"source_port\": %d, \"packet_id\": %d, \"received_checsum\": %d, \"real_checksum\": %d}\n", inet_ntoa(ip_header.ip_src), chunk_metadata.port_info.source_port, ip_header.ip_id, checksum_received, crc32(packet_buffer, node->data_read)); @@ -544,7 +538,7 @@ static inline void swiftnet_process_packets( #ifndef SWIFT_NET_DISABLE_DEBUGGING if (check_debug_flag(SWIFTNET_DEBUG_PACKETS_RECEIVING)) { - send_debug_message("Received packet: {\"source_ip_address\": \"%s\", \"source_port\": %d, \"packet_id\": %d, \"packet_type\": %d, \"packet_length\": %d, \"chunk_index\": %d, \"connection_type\": %d, \"checksum_received\": %d, \"real_checksum\": %d}\n", inet_ntoa(ip_header.ip_src), chunk_metadata.port_info.source_port, ip_header.ip_id, chunk_metadata.packet_type, packet_metadata.packet_length, chunk_metadata.chunk_index, connection_type, checksum_received, crc32(packet_buffer + prepend_size + sizeof(struct ip), node->data_read - sizeof(struct ip) - prepend_size)); + send_debug_message("Received packet: {\"source_ip_address\": \"%s\", \"source_port\": %d, \"packet_id\": %d, \"packet_type\": %d, \"packet_length\": %d, \"chunk_index\": %d, \"connection_type\": %d, \"checksum_received\": %d, \"real_checksum\": %d}\n", inet_ntoa(ip_header.ip_src), chunk_metadata.port_info.source_port, ip_header.ip_id, chunk_metadata.packet_type, packet_metadata.packet_length, chunk_metadata.chunk_index, connection_type, checksum_received, crc32(packet_buffer + prepend_size + sizeof(struct SwiftNetIp), node->data_read - sizeof(struct SwiftNetIp) - prepend_size)); } #endif @@ -553,7 +547,7 @@ static inline void swiftnet_process_packets( switch(chunk_metadata.packet_type) { case REQUEST_INFORMATION: { - struct ip send_server_info_ip_header; + struct SwiftNetIp send_server_info_ip_header; struct SwiftNetChunkMetadata chunk_metadata_new; @@ -586,10 +580,10 @@ static inline void swiftnet_process_packets( { uint16_t case_mtu; bool packet_already_completed; - struct ip send_packet_ip_header; + struct SwiftNetIp send_packet_ip_header; struct SwiftNetChunkMetadata send_chunk_metadata; struct SwiftNetPacketMetadata send_packet_metadata; - struct ip send_lost_packets_ip_header; + struct SwiftNetIp send_lost_packets_ip_header; MAYBE_UNUSED uint16_t header_size; uint32_t lost_chunk_indexes; uint32_t lost_indexes_size; @@ -660,7 +654,7 @@ static inline void swiftnet_process_packets( packet_length = PACKET_HEADER_SIZE + sizeof(struct SwiftNetPacketMetadata) + data_len; packet_length_net_order = htons((uint16_t)packet_length); - memcpy(IP_HEADER_LOCATION(buffer, &network_data) + offsetof(struct ip, ip_len), &packet_length_net_order, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(IP_HEADER_LOCATION(buffer, &network_data) + offsetof(struct SwiftNetIp, ip_len), &packet_length_net_order, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); ((struct SwiftNetPacketMetadata*)(PACKET_METADATA_LOCATION(buffer, &network_data)))->packet_length = sizeof(uint32_t); @@ -684,7 +678,7 @@ static inline void swiftnet_process_packets( packet_length_net_order = htons((uint16_t)packet_length); - memcpy(IP_HEADER_LOCATION(buffer, &network_data) + offsetof(struct ip, ip_len), &packet_length_net_order, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(IP_HEADER_LOCATION(buffer, &network_data) + offsetof(struct SwiftNetIp, ip_len), &packet_length_net_order, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); ((struct SwiftNetPacketMetadata*)(PACKET_METADATA_LOCATION(buffer, &network_data)))->packet_length = lost_indexes_size; diff --git a/src/send_packet.c b/src/send_packet.c index f63e24d..968d1ec 100644 --- a/src/send_packet.c +++ b/src/send_packet.c @@ -1,22 +1,21 @@ #include "internal/networking.h" #include "swift_net.h" -#include #include #include #include -#include #include #include #include -#include #include -#include -#include #include -#include -#include #include "internal/internal.h" -#include + +#if defined(__APPLE__) || defined(__linux__) +#include +#include +#include +#include +#endif PCAP_ONLY static inline ALWAYS_INLINE void prepare_packet_for_send(uint8_t* const dest_hdr_location, uint8_t* const temp_data_buffer, uint8_t* const prepend_buffer, const uint32_t data_exchange_size, const struct SwiftNetNetworkData* const network_data, const uint32_t chunk_index) { if(temp_data_buffer != NULL) memcpy(temp_data_buffer, dest_hdr_location, data_exchange_size); @@ -87,7 +86,7 @@ static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(co static inline ALWAYS_INLINE void handle_lost_packets( struct SwiftNetPacketSending* const packet_sending, const struct SwiftNetPacketBuffer* restrict const packet, - const struct ether_header eth_hdr, + const struct SwiftNetEtherHeader eth_hdr, const struct in_addr* restrict const destination_address, const uint16_t source_port, const uint16_t destination_port, @@ -103,7 +102,7 @@ static inline ALWAYS_INLINE void handle_lost_packets( uint8_t prepend_size = GET_PREPEND_SIZE(network_data); uint32_t chunk_amount; struct SwiftNetPortInfo port_info; - struct ip request_lost_packets_ip_header; + struct SwiftNetIp request_lost_packets_ip_header; struct SwiftNetChunkMetadata request_chunk_metadata; struct SwiftNetPacketMetadata request_packet_metadata; enum RequestLostPacketsReturnType request_lost_packets_bitarray_response; @@ -111,7 +110,7 @@ static inline ALWAYS_INLINE void handle_lost_packets( 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 SwiftNetIp resend_chunk_ip_header; PCAP_ONLY struct SwiftNetChunkMetadata resend_chunk_metadata; PCAP_ONLY uint8_t temp_data_buffer[prepend_size + PACKET_HEADER_SIZE + sizeof(struct SwiftNetPacketMetadata)]; @@ -219,13 +218,13 @@ static inline ALWAYS_INLINE void handle_lost_packets( 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)); + memcpy(current_buffer_header_ptr + offsetof(struct SwiftNetIp, ip_len), &new_ip_len, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); HANDLE_CHECKSUM(current_buffer_header_ptr, bytes_to_complete, network_data, false); SWIFTNET_SEND_PACKET(network_data, current_buffer_header_ptr, bytes_to_complete, false); - memcpy(current_buffer_header_ptr + offsetof(struct ip, ip_len), &mtu, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(current_buffer_header_ptr + offsetof(struct SwiftNetIp, ip_len), &mtu, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); } else { bool send_packet_metadata; @@ -269,7 +268,7 @@ static inline ALWAYS_INLINE void handle_lost_packets( current_buf->pkt_len = bytes_to_complete; new_ip_len = htons(bytes_to_complete); - memcpy(IP_HEADER_LOCATION(buf_data, network_data) + offsetof(struct ip, ip_len), &new_ip_len, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(IP_HEADER_LOCATION(buf_data, network_data) + offsetof(struct SwiftNetIp, ip_len), &new_ip_len, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); HANDLE_CHECKSUM(buf_data, data_complete_size, network_data, false); @@ -306,7 +305,7 @@ void swiftnet_send_packet( const uint32_t packet_length, const struct in_addr* const target_addr, struct SwiftNetHashMap* const packets_sending, - const struct ether_header eth_hdr, + const struct SwiftNetEtherHeader eth_hdr, const struct SwiftNetNetworkData network_data #ifndef SWIFT_NET_DISABLE_REQUESTS , struct RequestSent* const request_sent @@ -368,7 +367,7 @@ void swiftnet_send_packet( if(chunk_amount > 1) { struct SwiftNetChunkMetadata chunk_metadata; struct SwiftNetPacketMetadata packet_metadata; - struct ip ip_header; + struct SwiftNetIp ip_header; uint16_t net_order_len; struct SwiftNetPacketSending* new_packet_sending; struct PacketSendingKey* key_data_mem; @@ -469,7 +468,7 @@ void swiftnet_send_packet( bytes_to_send_net_order = htons(bytes_to_send - prepend_size); - memcpy(IP_HEADER_LOCATION(buffer_header_location, &network_data) + offsetof(struct ip, ip_len), &bytes_to_send_net_order, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(IP_HEADER_LOCATION(buffer_header_location, &network_data) + offsetof(struct SwiftNetIp, ip_len), &bytes_to_send_net_order, SIZEOF_FIELD(struct SwiftNetIp, ip_len)); HANDLE_CHECKSUM(buffer_header_location, packet_length - current_offset, &network_data, false); @@ -540,7 +539,7 @@ void swiftnet_send_packet( old_len = current_buffer->data_len; - memcpy(IP_HEADER_LOCATION(buf_addr, &network_data) + offsetof(struct ip, ip_len), &bytes_to_send_net_order, sizeof(bytes_to_send_net_order)); + memcpy(IP_HEADER_LOCATION(buf_addr, &network_data) + offsetof(struct SwiftNetIp, 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; @@ -576,7 +575,7 @@ void swiftnet_send_packet( uint16_t final_packet_size; struct SwiftNetChunkMetadata chunk_metadata; struct SwiftNetPacketMetadata packet_metadata; - struct ip ip_header; + struct SwiftNetIp ip_header; DPDK_ONLY uint8_t* buf_ptr; DPDK_ONLY struct rte_mbuf* restrict buffer; @@ -649,7 +648,7 @@ void swiftnet_client_send_packet(struct SwiftNetClientConnection* const client, 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; + struct SwiftNetEtherHeader eth_hdr; port_info = (struct SwiftNetPortInfo){ .destination_port = target.port, diff --git a/src/swift_net.h b/src/swift_net.h index 03e8203..6f20392 100644 --- a/src/swift_net.h +++ b/src/swift_net.h @@ -1,14 +1,19 @@ #pragma once #include +#include +#include +#include + +#if defined(__linux__) || defined(__APPLE__) #include #include #include #include -#include -#include #include -#include +#elif defined(_WIN32) +#include +#endif #ifdef SWIFT_NET_BACKEND_PCAP #include @@ -33,6 +38,30 @@ extern "C" { #define SWIFT_NET_MEMORY_USAGE 5 #endif +typedef uint32_t SwiftNetAddrIpv4; + +struct SwiftNetEtherHeader { + uint8_t ether_dhost[6]; + uint8_t ether_shost[6]; + uint16_t ether_type; +} SWIFT_NET_PACKED; + +struct SwiftNetIp { +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t ip_hl:4, ip_v:4; +#elif BYTE_ORDER == BIG_ENDIAN + uint8_t ip_v:4, ip_hl:4; +#endif + uint8_t ip_tos; + uint16_t ip_len; + uint16_t ip_id; + uint16_t ip_off; + uint8_t ip_ttl; + uint8_t ip_p; + uint16_t ip_sum; + struct in_addr ip_src, ip_dst; +} SWIFT_NET_PACKED; + struct SwiftNetNetworkData { #ifdef SWIFT_NET_BACKEND_DPDK struct rte_mempool* mem_pool; @@ -314,7 +343,7 @@ struct SwiftNetClientConnection { pthread_t process_packets_thread; pthread_t execute_callback_thread; struct SwiftNetPortInfo port_info; - struct ether_header eth_header; + struct SwiftNetEtherHeader eth_header; uint16_t maximum_transmission_unit; struct in_addr server_addr; bool loopback; @@ -339,7 +368,7 @@ struct SwiftNetServer { pthread_cond_t execute_callback_cond; pthread_t process_packets_thread; pthread_t execute_callback_thread; - struct ether_header eth_header; + struct SwiftNetEtherHeader eth_header; uint16_t server_port; bool loopback; _Atomic bool processing_packets; diff --git a/tests/integration_tests/build/CMakeLists.txt b/tests/integration_tests/build/CMakeLists.txt index a2ee050..86769d2 100644 --- a/tests/integration_tests/build/CMakeLists.txt +++ b/tests/integration_tests/build/CMakeLists.txt @@ -25,35 +25,119 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0") file(GLOB SRC_FILES "${CMAKE_SOURCE_DIR}/../src/*.c") +execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE TARGET_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +message(STATUS "Compiler target: ${TARGET_TRIPLE}") + +if(TARGET_TRIPLE MATCHES "^(aarch64|arm64)") + add_compile_options(-march=armv8-a) + set(SN_ARCH aarch64) +elseif(TARGET_TRIPLE MATCHES "^(x86_64|amd64|i[3-6]86)") + add_compile_options(-march=x86-64 -msse3 -mssse3) + set(SN_ARCH x86) +endif() + add_executable(run_tests ${SRC_FILES}) if(BACKEND STREQUAL "pcap") -add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + + if(WIN32) + find_path(NPCAP_INCLUDE_DIR + NAMES pcap.h + PATH_SUFFIXES Include include + PATHS + "C:/Npcap" + "$ENV{NPCAP_SDK}" + ) + + if(SN_ARCH MATCHES aarch64) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + elseif(SN_ARCH MATCHES x86) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + endif() -target_link_libraries(run_tests PRIVATE -lpcap) -target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + if(NOT NPCAP_INCLUDE_DIR OR + NOT NPCAP_WPCAP_LIBRARY OR + NOT NPCAP_PACKET_LIBRARY) + message(FATAL_ERROR "Npcap SDK not found") + endif() + + target_include_directories(run_tests PRIVATE + "${NPCAP_INCLUDE_DIR}" + ) + + target_link_libraries(run_tests PRIVATE + "${NPCAP_WPCAP_LIBRARY}" + "${NPCAP_PACKET_LIBRARY}" + ) + + target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + else() + target_link_libraries(run_tests PRIVATE -lpcap) + + target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + endif() elseif(BACKEND STREQUAL "dpdk") -add_compile_definitions(SWIFT_NET_BACKEND_DPDK) + add_compile_definitions(SWIFT_NET_BACKEND_DPDK) -add_library(swiftnet STATIC IMPORTED) + add_library(swiftnet STATIC IMPORTED) -set_target_properties(swiftnet PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a" -) + 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(swiftnet INTERFACE + rte_eal + rte_ethdev + rte_mbuf + rte_mempool + rte_ring + rte_net + ) + + target_link_libraries(run_tests PRIVATE swiftnet) +endif() -target_link_libraries(run_tests PRIVATE swiftnet) +if(WIN32) + target_link_libraries(run_tests PRIVATE + ws2_32 + iphlpapi + pthread + ) endif() + target_link_options(run_tests PRIVATE -g -O0) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/tests/integration_tests/build/build_pcap_tests.bat b/tests/integration_tests/build/build_pcap_tests.bat new file mode 100644 index 0000000..873015c --- /dev/null +++ b/tests/integration_tests/build/build_pcap_tests.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +del -f CMakeCache.txt +rmdir /s /q CMakeFiles +rmdir /s /q cmake +del -f Makefile +del -f cmake_install.cmake + +cd ..\..\..\build +copy profiles\pcap_profile.cmake .\profile.cmake +call .\build.bat +cd ..\tests\integration_tests\build + +cmake . -G "MinGW Makefiles" -DCMAKE_C_COMPILER=clang -DCMAKE_MAKE_PROGRAM=make -DBACKEND=pcap -DCMAKE_BUILD_TYPE=Debug -DSANITIZER=none -B . +make -B -j8 \ No newline at end of file diff --git a/tests/integration_tests/src/making_request.c b/tests/integration_tests/src/making_request.c index b56bb6e..2d478de 100644 --- a/tests/integration_tests/src/making_request.c +++ b/tests/integration_tests/src/making_request.c @@ -147,7 +147,7 @@ static void on_server_packet(struct SwiftNetServerPacketData* packet, void* cons 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", + PRINT_ERROR("Server received invalid data size: %d | %zu", packet->metadata.data_length, sizeof(g_make_request_code) ); @@ -284,7 +284,7 @@ int test_making_request(const union Args* args_ptr) { 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) { + if (args.receiver == CONNECTION_TYPE_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); diff --git a/tests/integration_tests/src/run_tests.c b/tests/integration_tests/src/run_tests.c index 3917b82..c1b086b 100644 --- a/tests/integration_tests/src/run_tests.c +++ b/tests/integration_tests/src/run_tests.c @@ -7,15 +7,22 @@ #include #include #include +#include "../../shared.h" + +char private_ip_address_testing[MAX_INTERFACE_LEN]; + +#if defined(__APPLE__) || defined(__linux__) #include #include #include #include -#include "../../shared.h" - -char private_ip_address_testing[INET_ADDRSTRLEN]; +#elif defined(_WIN32) +#endif int main(void) { + swiftnet_initialize(); + swiftnet_add_debug_flags(SWIFTNET_DEBUG_FLAGS(SWIFTNET_DEBUG_PACKETS_SENDING | SWIFTNET_DEBUG_PACKETS_RECEIVING | SWIFTNET_DEBUG_INITIALIZATION | SWIFTNET_DEBUG_LOST_PACKETS)); + get_private_ip_from_socket(); struct Test tests[] = { @@ -55,7 +62,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Server, + .receiver = CONNECTION_TYPE_SERVER, .request_data_len = 100, .response_data_len = 100 }}, @@ -66,7 +73,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Client, + .receiver = CONNECTION_TYPE_CLIENT, .request_data_len = 100, .response_data_len = 100 }}, @@ -77,7 +84,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Client, + .receiver = CONNECTION_TYPE_CLIENT, .request_data_len = 10000, .response_data_len = 100 }}, @@ -88,7 +95,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Server, + .receiver = CONNECTION_TYPE_SERVER, .request_data_len = 10000, .response_data_len = 100 }}, @@ -99,7 +106,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Client, + .receiver = CONNECTION_TYPE_CLIENT, .request_data_len = 100, .response_data_len = 10000 }}, @@ -110,7 +117,7 @@ int main(void) { .args = {.test_making_request_args = { .ip_address = "127.0.0.1", .loopback = true, - .receiver = Server, + .receiver = CONNECTION_TYPE_SERVER, .request_data_len = 100, .response_data_len = 10000 }}, @@ -118,10 +125,6 @@ int main(void) { }, }; - 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]; @@ -141,7 +144,7 @@ int main(void) { // Test default network interface only on macos, because it works without any setup - #ifdef __APPLE__ + #if defined(__APPLE__) || defined(_WIN32) for (uint16_t i = 0; i < sizeof(tests) / sizeof(struct Test); i++) { struct Test* current_test = &tests[i]; if (current_test->function == test_making_request) { diff --git a/tests/integration_tests/src/sending_packet.c b/tests/integration_tests/src/sending_packet.c index 0d89937..beb2c5a 100644 --- a/tests/integration_tests/src/sending_packet.c +++ b/tests/integration_tests/src/sending_packet.c @@ -3,6 +3,7 @@ #include #include "../../../src/swift_net.h" #include +#include #include #include #include "run_tests.h" @@ -144,6 +145,7 @@ int test_sending_packet(const union Args* args_ptr) { return -1; } + printf("Creating client on ip: %s\n", args.ip_address); swiftnet_server_set_message_handler(server, on_server_packet, NULL); struct SwiftNetClientConnection* const client_conn = swiftnet_create_client(args.ip_address, 8080, 10000); diff --git a/tests/performance_tests/build/CMakeLists.txt b/tests/performance_tests/build/CMakeLists.txt index f2934ce..2d21c66 100644 --- a/tests/performance_tests/build/CMakeLists.txt +++ b/tests/performance_tests/build/CMakeLists.txt @@ -25,35 +25,119 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") file(GLOB SRC_FILES "${CMAKE_SOURCE_DIR}/../src/*.c") +execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE TARGET_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +message(STATUS "Compiler target: ${TARGET_TRIPLE}") + +if(TARGET_TRIPLE MATCHES "^(aarch64|arm64)") + add_compile_options(-march=armv8-a) + set(SN_ARCH aarch64) +elseif(TARGET_TRIPLE MATCHES "^(x86_64|amd64|i[3-6]86)") + add_compile_options(-march=x86-64 -msse3 -mssse3) + set(SN_ARCH x86) +endif() + add_executable(run_tests ${SRC_FILES}) if(BACKEND STREQUAL "pcap") -add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + add_compile_definitions(SWIFT_NET_BACKEND_PCAP) + + if(WIN32) + find_path(NPCAP_INCLUDE_DIR + NAMES pcap.h + PATH_SUFFIXES Include include + PATHS + "C:/Npcap" + "$ENV{NPCAP_SDK}" + ) + + if(SN_ARCH MATCHES aarch64) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/ARM64" + "$ENV{NPCAP_SDK}/Lib/ARM64" + ) + elseif(SN_ARCH MATCHES x86) + find_library(NPCAP_WPCAP_LIBRARY + NAMES wpcap + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + + find_library(NPCAP_PACKET_LIBRARY + NAMES Packet + PATHS + "C:/Npcap/Lib/x64" + "$ENV{NPCAP_SDK}/Lib/x64" + ) + endif() -target_link_libraries(run_tests PRIVATE -lpcap) -target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + if(NOT NPCAP_INCLUDE_DIR OR + NOT NPCAP_WPCAP_LIBRARY OR + NOT NPCAP_PACKET_LIBRARY) + message(FATAL_ERROR "Npcap SDK not found") + endif() + + target_include_directories(run_tests PRIVATE + "${NPCAP_INCLUDE_DIR}" + ) + + target_link_libraries(run_tests PRIVATE + "${NPCAP_WPCAP_LIBRARY}" + "${NPCAP_PACKET_LIBRARY}" + ) + + target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + else() + target_link_libraries(run_tests PRIVATE -lpcap) + + target_link_libraries(run_tests PRIVATE ${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a) + endif() elseif(BACKEND STREQUAL "dpdk") -add_compile_definitions(SWIFT_NET_BACKEND_DPDK) + add_compile_definitions(SWIFT_NET_BACKEND_DPDK) -add_library(swiftnet STATIC IMPORTED) + add_library(swiftnet STATIC IMPORTED) -set_target_properties(swiftnet PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../../../build/output/libswiftnet.a" -) + 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(swiftnet INTERFACE + rte_eal + rte_ethdev + rte_mbuf + rte_mempool + rte_ring + rte_net + ) + + target_link_libraries(run_tests PRIVATE swiftnet) +endif() -target_link_libraries(run_tests PRIVATE swiftnet) +if(WIN32) + target_link_libraries(run_tests PRIVATE + ws2_32 + iphlpapi + pthread + ) endif() + target_link_options(run_tests PRIVATE -O3) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/tests/performance_tests/build/build_pcap_tests.bat b/tests/performance_tests/build/build_pcap_tests.bat new file mode 100644 index 0000000..0c71afe --- /dev/null +++ b/tests/performance_tests/build/build_pcap_tests.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +del -f CMakeCache.txt +rmdir /s /q CMakeFiles +rmdir /s /q cmake +del -f Makefile +del -f cmake_install.cmake + +cd ..\..\..\build +copy profiles\pcap_peft_profile.cmake .\profile.cmake +call .\build.bat +cd ..\tests\performance_tests\build + +cmake . -G "MinGW Makefiles" -DCMAKE_C_COMPILER=clang -DCMAKE_MAKE_PROGRAM=make -DBACKEND=pcap -DCMAKE_BUILD_TYPE=Release -DSANITIZER=none -B . +make -B -j8 \ No newline at end of file diff --git a/tests/shared.h b/tests/shared.h index c24ee1e..b92ef9f 100644 --- a/tests/shared.h +++ b/tests/shared.h @@ -3,31 +3,42 @@ #include #include #include -#include -#include -#include -#include #include #ifdef __linux__ #include #include + +#define MAX_INTERFACE_LEN 16 #elif defined(__APPLE__) #include + +#define MAX_INTERFACE_LEN 16 +#elif defined(_WIN32) +#include +#include + +#define MAX_INTERFACE_LEN 128 #endif +enum ConnectionType { + CONNECTION_TYPE_SERVER, + CONNECTION_TYPE_CLIENT +}; + #define PRINT_ERROR(error, ...) \ - printf("\033[31m" error "\033[0m\n", ##__VA_ARGS__) + printf("\033[31m" error "\033[0m\n", ##__VA_ARGS__); #define PRINT_SUCCESS(error, ...) \ printf("\033[32m" error "\033[0m\n", ##__VA_ARGS__); -enum ConnectionType { - Server, - Client -}; +extern char private_ip_address_testing[MAX_INTERFACE_LEN]; -extern char private_ip_address_testing[INET_ADDRSTRLEN]; +#if defined(__APPLE__) || defined(__linux__) +#include +#include +#include +#include static inline int get_private_ip_from_socket(void) { const int temp_socket = socket(AF_INET, SOCK_DGRAM, 0); @@ -64,3 +75,58 @@ static inline int get_private_ip_from_socket(void) { return 0; } +#elif defined(_WIN32) +static inline int get_private_ip_from_socket(void) { + const SOCKET temp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (temp_socket == INVALID_SOCKET) { + PRINT_ERROR("Failed to create temp socket"); + exit(EXIT_FAILURE); + } + + struct sockaddr_in remote = {0}; + remote.sin_family = AF_INET; + remote.sin_port = htons(53); + + if (inet_pton(AF_INET, "8.8.8.8", &remote.sin_addr) != 1) { + PRINT_ERROR("Failed to parse remote IP"); + closesocket(temp_socket); + exit(EXIT_FAILURE); + } + + if (connect(temp_socket, (struct sockaddr *)&remote, sizeof(remote)) == SOCKET_ERROR) { + PRINT_ERROR("Failed to connect temp socket"); + closesocket(temp_socket); + exit(EXIT_FAILURE); + } + + struct sockaddr_in private_sockaddr = {0}; + int private_sockaddr_len = sizeof(private_sockaddr); + + if (getsockname( + temp_socket, + (struct sockaddr *)&private_sockaddr, + &private_sockaddr_len + ) == SOCKET_ERROR) { + PRINT_ERROR("Failed to get private IP address"); + closesocket(temp_socket); + exit(EXIT_FAILURE); + } + + if (!inet_ntop( + AF_INET, + &private_sockaddr.sin_addr, + private_ip_address_testing, + sizeof(private_ip_address_testing) + )) { + PRINT_ERROR("Failed to convert private IP address"); + closesocket(temp_socket); + exit(EXIT_FAILURE); + } + + printf("Private IP: %s\n", private_ip_address_testing); + + closesocket(temp_socket); + return 0; +} +#endif