diff --git a/README.md b/README.md index 9909bfd..604400a 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ ## Performance +- **Test Overview** + One large packet with 100 Million bytes of data + - **Hardware & Conditions** Tested on a MacBook Air M3 (my daily driver machine, running multiple background applications) @@ -54,22 +57,25 @@ Real Wi-Fi interface: en0 - **Throughput** - 9.4 MB/s + 20.9 MB/s - **Memory Usage** - Peak memory footprint: 14 million bytes + **Peak memory footprint: 203 million bytes** + - 100M bytes are used for buffers on receiver and sender + - 3M bytes are used on internal data + - **CPU Usage** - Average utilization: ~7.7% + Average utilization: ~9% - **Detailed Timing (from /usr/bin/time -l)** - - Real (wall-clock) time: 5.32 seconds - - User CPU time: 0.24 seconds - - System CPU time: 0.17 seconds - - Total CPU time: 0.41 seconds + - Real (wall-clock) time: 4.78 seconds + - User CPU time: 0.07 seconds + - System CPU time: 0.31 seconds + - Total CPU time: 0.38 seconds - **CPU Cycles** - 1 005 063 001 cycles + 1 513 423 854 cycles ## Installation Follow these steps to install SwiftNet: diff --git a/src/execute_packet_callback.c b/src/execute_packet_callback.c index b9f5041..e5086e1 100644 --- a/src/execute_packet_callback.c +++ b/src/execute_packet_callback.c @@ -59,52 +59,51 @@ void execute_packet_callback( pthread_mutex_t* const execute_callback_mtx, pthread_cond_t* const execute_callback_cond ) { - while (1) { - if (atomic_load_explicit(closing, memory_order_acquire) == true) { - break; - } +check_packet: + if (unlikely(atomic_load_explicit(closing, memory_order_acquire) == true)) { + return; + } - pthread_mutex_lock(execute_callback_mtx); + pthread_mutex_lock(execute_callback_mtx); - const struct PacketCallbackQueueNode* const node = wait_for_next_packet_callback(queue); - if(node == NULL) { - pthread_cond_wait(execute_callback_cond, execute_callback_mtx); + const struct PacketCallbackQueueNode* const node = wait_for_next_packet_callback(queue); + if(node == NULL) { + pthread_cond_wait(execute_callback_cond, execute_callback_mtx); - pthread_mutex_unlock(execute_callback_mtx); + pthread_mutex_unlock(execute_callback_mtx); - continue; - } + goto check_packet; + } - pthread_mutex_unlock(execute_callback_mtx); + pthread_mutex_unlock(execute_callback_mtx); - atomic_thread_fence(memory_order_acquire); + if(node->packet_data == NULL) { + allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); + goto check_packet; + } - if(node->packet_data == NULL) { - allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); - continue; - } + if(node->pending_message != NULL) { + remove_pending_message_from_hashmap(pending_messages, node->pending_message); + } - if(node->pending_message != NULL) { - remove_pending_message_from_hashmap(pending_messages, node->pending_message); + void (*const packet_handler_loaded)(void* const, void* const) = atomic_load(packet_handler); + if (unlikely(packet_handler_loaded == NULL)) { + if (connection_type == CONNECTION_TYPE_CLIENT) { + swiftnet_client_destroy_packet_data(node->packet_data, connection); + } else { + swiftnet_client_destroy_packet_data(node->packet_data, connection); } - void (*const packet_handler_loaded)(void* const, void* const) = atomic_load(packet_handler); - if (unlikely(packet_handler_loaded == NULL)) { - if (connection_type == CONNECTION_TYPE_CLIENT) { - swiftnet_client_destroy_packet_data(node->packet_data, connection); - } else { - swiftnet_client_destroy_packet_data(node->packet_data, connection); - } + allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); - allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); + goto check_packet; + } - continue; - } + (*packet_handler_loaded)(node->packet_data, atomic_load_explicit(user_data, memory_order_acquire)); - (*packet_handler_loaded)(node->packet_data, atomic_load_explicit(user_data, memory_order_acquire)); + allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); - allocator_free(&packet_callback_queue_node_memory_allocator, (void*)node); - } + goto check_packet; } void* execute_packet_callback_client(void* const void_client) { diff --git a/src/handle_packets.c b/src/handle_packets.c index db0373a..c9f5870 100644 --- a/src/handle_packets.c +++ b/src/handle_packets.c @@ -66,8 +66,8 @@ static inline void swiftnet_handle_packets( const struct pcap_pkthdr* hdr, const uint8_t* packet, pthread_mutex_t* const process_packets_mtx, - pthread_cond_t* const process_packets_cond - + pthread_cond_t* const process_packets_cond, + _Atomic bool *const processing_packets ) { uint8_t* const packet_buffer = allocator_allocate(&packet_buffer_memory_allocator); if (unlikely(packet_buffer == NULL)) { @@ -100,15 +100,15 @@ static inline void swiftnet_handle_packets( struct PacketQueueNode* const node = construct_node(len, packet_buffer, sender_address); - atomic_thread_fence(memory_order_release); - - pthread_mutex_lock(process_packets_mtx); - insert_queue_node(node, packet_queue, connection_type); - pthread_cond_signal(process_packets_cond); + if (atomic_load_explicit(processing_packets, memory_order_acquire) != true) { + pthread_mutex_lock(process_packets_mtx); - pthread_mutex_unlock(process_packets_mtx); + pthread_cond_signal(process_packets_cond); + + pthread_mutex_unlock(process_packets_mtx); + } } static void handle_client_init(struct SwiftNetClientConnection* user, const struct pcap_pkthdr* hdr, const uint8_t* buffer) { @@ -177,7 +177,7 @@ static inline void handle_correct_receiver(const enum ConnectionType connection_ if (client_connection->initialized == false) { handle_client_init(client_connection, hdr, packet); } 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, client_connection->addr_type, hdr, packet, &client_connection->process_packets_mtx, &client_connection->process_packets_cond); + 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, client_connection->addr_type, hdr, packet, &client_connection->process_packets_mtx, &client_connection->process_packets_cond, &client_connection->processing_packets); } } else { LOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); @@ -189,7 +189,7 @@ static inline void handle_correct_receiver(const enum ConnectionType connection_ return; } - swiftnet_handle_packets(server->server_port, &server->process_packets_thread, server, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->closing, server->loopback, server->addr_type, hdr, packet, &server->process_packets_mtx, &server->process_packets_cond); + swiftnet_handle_packets(server->server_port, &server->process_packets_thread, server, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->closing, server->loopback, server->addr_type, hdr, packet, &server->process_packets_mtx, &server->process_packets_cond, &server->processing_packets); } } diff --git a/src/initialize_client_connection.c b/src/initialize_client_connection.c index ddf4749..382a6a7 100644 --- a/src/initialize_client_connection.c +++ b/src/initialize_client_connection.c @@ -56,7 +56,7 @@ void* request_server_information(void* const request_server_information_args_voi } #endif - swiftnet_pcap_send(request_server_information_args->pcap, request_server_information_args->data, request_server_information_args->size); + SWIFTNET_PCAP_SEND_SAFE(request_server_information_args->pcap, request_server_information_args->data, request_server_information_args->size); usleep(250000); } @@ -98,6 +98,7 @@ static inline struct SwiftNetClientConnection* const construct_client_connection UNLOCK_ATOMIC_DATA_TYPE(&new_connection->packet_queue.locked); 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->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); diff --git a/src/initialize_server.c b/src/initialize_server.c index 874fa60..f5c585d 100644 --- a/src/initialize_server.c +++ b/src/initialize_server.c @@ -39,6 +39,7 @@ static inline struct SwiftNetServer* const construct_server(const bool loopback, UNLOCK_ATOMIC_DATA_TYPE(&new_server->packet_queue.locked); 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->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); diff --git a/src/internal/datatype_allocator.c b/src/internal/datatype_allocator.c index c7f95dc..3ca6727 100644 --- a/src/internal/datatype_allocator.c +++ b/src/internal/datatype_allocator.c @@ -62,8 +62,6 @@ static inline void set_memory_status(struct SwiftNetMemoryAllocator* const memor return; } } - - printf("doesnt fall\n"); } static inline bool is_already_free(struct SwiftNetMemoryAllocator* const memory_allocator, void* const memory_location) { @@ -129,7 +127,7 @@ struct SwiftNetMemoryAllocatorStack* const find_free_pointer_stack(struct SwiftN if((bitmap | invalid_bitmap) == UINT64_MAX) { return NULL; } else { - first_free = __builtin_ctz(~(bitmap | invalid_bitmap)); + first_free = __builtin_ctzll(~(bitmap | invalid_bitmap)); } if (first_free >= stacks_allocated) { diff --git a/src/internal/internal.h b/src/internal/internal.h index 0d70745..32af631 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,11 @@ #define DISABLE_INTERNAL_CHECK #endif +#define SWIFTNET_PCAP_SEND_SAFE(pcap, buffer, len) \ + while(swiftnet_pcap_send(pcap, buffer, len) == -2) { \ + usleep(2000); \ + } \ + enum RequestLostPacketsReturnType { REQUEST_LOST_PACKETS_RETURN_UPDATED_BIT_ARRAY = 0x00, REQUEST_LOST_PACKETS_RETURN_COMPLETED_PACKET = 0x01 @@ -82,8 +88,8 @@ enum RequestLostPacketsReturnType { // Simple crc16 call with proper memory order #define HANDLE_CHECKSUM(buffer, size, prepend_size) \ - uint16_t checksum = htons(crc16(buffer, size)); \ - memcpy(buffer + prepend_size + offsetof(struct ip, ip_sum), &checksum, sizeof(checksum)); + const uint32_t checksum = crc32(buffer, size); \ + memcpy(buffer + prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), &checksum, sizeof(checksum)); // Number used in ip.proto #define PROT_NUMBER 253 @@ -99,50 +105,22 @@ enum RequestLostPacketsReturnType { #define MIN(one, two) (one > two ? two : one) -static const uint16_t crc16_table[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 -}; - -static inline uint16_t crc16(const uint8_t *data, size_t length) { - uint16_t crc = 0xFFFF; +static inline uint32_t crc32(uint8_t* data, uint32_t length) { + uint32_t crc = 0xFFFFFFFF; - for (size_t i = 0; i < length; i++) { - uint8_t byte = data[i]; - crc = (crc >> 8) ^ crc16_table[(crc ^ byte) & 0xFF]; + while (length >= 8) { + crc = __crc32d(crc, *(const uint64_t*)data); + data += 8; + length -= 8; + } + + while (length > 0) { + crc = __crc32b(crc, *data); + data++; + length--; } - return crc ^ 0xFFFF; + return ~crc; } enum StackCreatingState { @@ -325,7 +303,8 @@ static inline struct SwiftNetPacketInfo construct_packet_info(const uint32_t pac .chunk_amount = chunk_amount, .chunk_index = chunk_index, .maximum_transmission_unit = maximum_transmission_unit, - .port_info = port_info + .port_info = port_info, + .checksum = 0x00 }; } @@ -339,7 +318,7 @@ static struct ip construct_ip_header(struct in_addr destination_addr, const uint .ip_id = htons(packet_id), // Packet id .ip_off = htons(0), // Not used .ip_ttl = 64,// Time to live - .ip_sum = htons(0), // Checksum + .ip_sum = htons(0), // not used!! .ip_src = private_ip_address, // Source ip .ip_dst = destination_addr // Destination ip }; diff --git a/src/internal/pcap_open.c b/src/internal/pcap_open.c index 60a7f4c..bde41e3 100644 --- a/src/internal/pcap_open.c +++ b/src/internal/pcap_open.c @@ -1,4 +1,5 @@ #include "internal.h" +#include pcap_t* swiftnet_pcap_open(const char* interface) { char errbuf[PCAP_ERRBUF_SIZE]; diff --git a/src/internal/pcap_send.c b/src/internal/pcap_send.c index a1ecc6f..4525fa3 100644 --- a/src/internal/pcap_send.c +++ b/src/internal/pcap_send.c @@ -1,7 +1,15 @@ #include "internal.h" +#include +#include int swiftnet_pcap_send(pcap_t *pcap, const u_char *data, int len) { - if (pcap_inject(pcap, data, len) == -1) { + int ret = pcap_inject(pcap, data, len); + + if (ret == -1) { + if (errno == ENOBUFS) { + return -2; + } + PRINT_ERROR("inject error: %s", pcap_geterr(pcap)); return -1; } diff --git a/src/memory_cleanup_background_service.c b/src/memory_cleanup_background_service.c index e2180bf..4d73509 100644 --- a/src/memory_cleanup_background_service.c +++ b/src/memory_cleanup_background_service.c @@ -59,13 +59,15 @@ void* memory_cleanup_background_service() { gettimeofday(&end, NULL); - uint32_t diff_us = (uint32_t)((end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec)); + int64_t elapsed_us = (int64_t)(end.tv_sec - start.tv_sec) * 1000000LL + (end.tv_usec - start.tv_usec); - if (diff_us > PACKET_HISTORY_STORE_TIME * 1000000) { - continue; - } + if (elapsed_us < 0) elapsed_us = 0; + + uint64_t target_us = (uint64_t)PACKET_HISTORY_STORE_TIME * 1000000ULL; - usleep((PACKET_HISTORY_STORE_TIME * 1000000) - diff_us); + if ((uint64_t)elapsed_us < target_us) { + usleep(target_us - (uint64_t)elapsed_us); + } } return NULL; diff --git a/src/process_packets.c b/src/process_packets.c index cae7b17..314b3df 100644 --- a/src/process_packets.c +++ b/src/process_packets.c @@ -1,5 +1,6 @@ #include "internal/internal.h" #include "swift_net.h" +#include <_time.h> #include #include #include @@ -10,7 +11,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -40,23 +43,23 @@ static inline const uint32_t return_lost_chunk_indexes(const uint8_t* const chun for(uint8_t bit = 0; bit < 8; bit++) { if(offset * 4 + 4 > buffer_size) { - return buffer_size; + return offset; } - if((chunks_received[byte] & (1 << bit)) == 0x00) { + if((chunks_received[byte] & (1u << bit)) == 0x00) { buffer[offset] = byte * 8 + bit; offset++; } } } else { - const uint8_t bits_to_check = chunk_amount - byte * 8; + const uint32_t bits_to_check = chunk_amount - byte * 8; - for(uint8_t bit = 0; bit < bits_to_check; bit++) { + for(uint32_t bit = 0; bit < bits_to_check; bit++) { if(offset * 4 + 4 > buffer_size) { - return buffer_size; + return offset; } - if((chunks_received[byte] & (1 << bit)) == 0x00) { + if((chunks_received[byte] & (1u << bit)) == 0x00) { buffer[offset] = byte * 8 + bit; offset++; } @@ -192,8 +195,6 @@ static inline void pass_callback_execution(void* const packet_data, struct Packe node->pending_message = pending_message; node->packet_id = packet_id; - atomic_thread_fence(memory_order_release); - pthread_mutex_lock(execute_callback_mtx); insert_callback_queue_node(node, queue); @@ -228,6 +229,9 @@ static inline struct SwiftNetPendingMessage* const create_new_pending_message(st new_pending_message->packet_data_start = allocated_memory; new_pending_message->chunks_received_number = 0x00; + new_pending_message->last_index_checked = 0; + new_pending_message->sending_lost_packets = false; + new_pending_message->last_chunks_received_number = 0; new_pending_message->chunks_received_length = chunks_received_byte_size; new_pending_message->chunks_received = calloc(chunks_received_byte_size, 1); @@ -260,6 +264,33 @@ static inline struct SwiftNetPacketSending* const get_packet_sending(struct Swif return result; } +static inline void signal_delay_change(const enum PacketDelayUpdateStatus status, const struct ip* const ip_header, const uint16_t source_port, const uint16_t destination_port, const uint16_t addr_type, const uint8_t prepend_size, pcap_t* const pcap, const struct ether_header* const eth_hdr) { + const struct ip send_server_info_ip_header = construct_ip_header(ip_header->ip_src, PACKET_HEADER_SIZE, ip_header->ip_id); + + const struct SwiftNetPacketInfo packet_info_new = construct_packet_info( + sizeof(enum PacketDelayUpdateStatus), + PACKET_DELAY_UPDATE, + 1, + 0, + (struct SwiftNetPortInfo){ + .source_port = source_port, + .destination_port = destination_port + } + ); + + const struct SwiftNetServerInformation server_info = { + .maximum_transmission_unit = maximum_transmission_unit + }; + + HANDLE_PACKET_CONSTRUCTION(&send_server_info_ip_header, &packet_info_new, addr_type, ð_hdr, prepend_size + PACKET_HEADER_SIZE + sizeof(server_info), buffer) + + memcpy(buffer + prepend_size + PACKET_HEADER_SIZE, &server_info, sizeof(server_info)); + + HANDLE_CHECKSUM(buffer, sizeof(buffer), prepend_size) + + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer, sizeof(buffer)); +} + struct PacketQueueNode* const wait_for_next_packet(struct PacketQueue* const packet_queue) { LOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); @@ -286,8 +317,8 @@ struct PacketQueueNode* const wait_for_next_packet(struct PacketQueue* const pac return node_to_process; } -static inline bool packet_corrupted(const uint16_t checksum, const uint32_t chunk_size, const uint8_t* const buffer) { - return crc16(buffer, chunk_size) != checksum; +static inline bool packet_corrupted(const uint32_t checksum, const uint32_t chunk_size, uint8_t* const buffer) { + return crc32(buffer, chunk_size) != checksum; } static inline void swiftnet_process_packets( @@ -312,27 +343,45 @@ static inline void swiftnet_process_packets( 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 + pthread_cond_t* const execute_callback_cond, + _Atomic bool *const processing_packets ) { + uint8_t idle_stage = 0; // 0-3 + while(1) { if (atomic_load(closing) == true) { break; } - pthread_mutex_lock(process_packets_mtx); - struct PacketQueueNode* const node = wait_for_next_packet(packet_queue); if(node == NULL) { - pthread_cond_wait(process_packets_cond, process_packets_mtx); + switch (idle_stage) { + case 0: usleep(1000); break; + case 1: usleep(2000); break; + case 2: usleep(5000); break; + case 3: { + atomic_store_explicit(processing_packets, false, memory_order_release); + + pthread_mutex_lock(process_packets_mtx); + + pthread_cond_wait(process_packets_cond, process_packets_mtx); - pthread_mutex_unlock(process_packets_mtx); + pthread_mutex_unlock(process_packets_mtx); + + atomic_store_explicit(processing_packets, true, memory_order_release); + + idle_stage = 0; + + continue; + } + } + + idle_stage++; continue; } - pthread_mutex_unlock(process_packets_mtx); - - atomic_thread_fence(memory_order_acquire); + idle_stage = 0; uint8_t* const packet_buffer = node->data; if(packet_buffer == NULL) { @@ -354,9 +403,9 @@ static inline void swiftnet_process_packets( goto next_packet; } - const uint16_t checksum_received = ip_header.ip_sum; + const uint32_t checksum_received = packet_info.checksum; - memset(packet_buffer + prepend_size + offsetof(struct ip, ip_sum), 0x00, SIZEOF_FIELD(struct ip, ip_sum)); + memset(packet_buffer + prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, checksum), 0x00, SIZEOF_FIELD(struct SwiftNetPacketInfo, checksum)); memcpy(packet_buffer + prepend_size + offsetof(struct ip, ip_len), (void*)&node->data_read, SIZEOF_FIELD(struct ip, ip_len)); @@ -364,7 +413,7 @@ static inline void swiftnet_process_packets( if(ip_header.ip_sum != 0 && packet_corrupted(checksum_received, node->data_read, packet_buffer) == true) { #ifdef SWIFT_NET_DEBUG 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), packet_info.port_info.source_port, ip_header.ip_id, checksum_received, crc16(packet_buffer, node->data_read)); + 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), packet_info.port_info.source_port, ip_header.ip_id, checksum_received, crc32(packet_buffer, node->data_read)); } #endif @@ -376,7 +425,7 @@ static inline void swiftnet_process_packets( #ifdef SWIFT_NET_DEBUG 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), packet_info.port_info.source_port, ip_header.ip_id, packet_info.packet_type, packet_info.packet_length, packet_info.chunk_index, connection_type, checksum_received, crc16(node->data, node->data_read)); + 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), packet_info.port_info.source_port, ip_header.ip_id, packet_info.packet_type, packet_info.packet_length, packet_info.chunk_index, connection_type, checksum_received, crc32(node->data, node->data_read)); } #endif @@ -406,7 +455,7 @@ static inline void swiftnet_process_packets( HANDLE_CHECKSUM(buffer, sizeof(buffer), prepend_size) - swiftnet_pcap_send(pcap, buffer, sizeof(buffer)); + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer, sizeof(buffer)); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -437,7 +486,7 @@ static inline void swiftnet_process_packets( HANDLE_CHECKSUM(buffer, sizeof(buffer), prepend_size) - swiftnet_pcap_send(pcap, buffer, sizeof(buffer)); + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer, sizeof(buffer)); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -449,6 +498,8 @@ static inline void swiftnet_process_packets( goto next_packet; } + pending_message->sending_lost_packets = true; + struct ip send_lost_packets_ip_header = construct_ip_header(ip_header.ip_src, 0, ip_header.ip_id); struct SwiftNetPacketInfo packet_info_new = construct_packet_info( @@ -462,20 +513,23 @@ static inline void swiftnet_process_packets( } ); - const uint16_t header_size = sizeof(struct ip) + sizeof(struct SwiftNetPacketInfo) + prepend_size; + const uint16_t header_size = PACKET_HEADER_SIZE + prepend_size; HANDLE_PACKET_CONSTRUCTION(&send_lost_packets_ip_header, &packet_info_new, addr_type, ð_hdr, mtu + prepend_size, buffer) const uint32_t lost_chunk_indexes = return_lost_chunk_indexes(pending_message->chunks_received, pending_message->packet_info.chunk_amount, mtu - PACKET_HEADER_SIZE, (uint32_t*)(buffer + header_size)); - const uint32_t packet_length = sizeof(struct ip) + sizeof(struct SwiftNetPacketInfo) + (lost_chunk_indexes * sizeof(uint32_t)); + const uint32_t lost_indexes_size = lost_chunk_indexes * sizeof(uint32_t); + const uint32_t packet_length = PACKET_HEADER_SIZE + (lost_chunk_indexes * sizeof(uint32_t)); + const uint16_t packet_length_net_order = htons((uint16_t)packet_length); memcpy(buffer + prepend_size + offsetof(struct ip, ip_len), &packet_length_net_order, SIZEOF_FIELD(struct ip, ip_len)); + memcpy(buffer + prepend_size + sizeof(struct ip) + offsetof(struct SwiftNetPacketInfo, packet_length), &lost_indexes_size, sizeof(lost_indexes_size)); HANDLE_CHECKSUM(buffer, packet_length + prepend_size, prepend_size); - swiftnet_pcap_send(pcap, buffer, packet_length + prepend_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer, packet_length + prepend_size); allocator_free(&packet_buffer_memory_allocator, packet_buffer); @@ -527,6 +581,26 @@ static inline void swiftnet_process_packets( goto next_packet; } + case PACKET_DELAY_UPDATE: + { + const enum PacketDelayUpdateStatus* const status = (enum PacketDelayUpdateStatus*)packet_data; + + struct SwiftNetPacketSending* const target_packet_sending = get_packet_sending(packets_sending, ip_header.ip_id); + + uint32_t current_delay = atomic_load_explicit(&target_packet_sending->current_send_delay, memory_order_acquire); + + if (*status == INCREASE_DELAY) { + current_delay = (current_delay / 6) * 7; + } else { + current_delay = (current_delay / 6) * 5; + } + + atomic_store_explicit(&target_packet_sending->current_send_delay, current_delay, memory_order_release); + + allocator_free(&packet_buffer_memory_allocator, packet_buffer); + + goto next_packet; + } default: break; } @@ -709,14 +783,27 @@ static inline void swiftnet_process_packets( goto next_packet; } else { + const uint32_t new_packets = packet_info.chunk_index - pending_message->last_index_checked; + const uint32_t new_packets_validated = pending_message->chunks_received_number - pending_message->last_chunks_received_number; + + if (new_packets > 50) { + float ratio = (float)new_packets_validated / (float)new_packets; + if (ratio > 0.95) { + signal_delay_change(LOWER_DELAY, &ip_header, source_port, packet_info.port_info.source_port, addr_type, prepend_size, pcap, ð_hdr); + } else { + signal_delay_change(INCREASE_DELAY, &ip_header, source_port, packet_info.port_info.source_port, addr_type, prepend_size, pcap, ð_hdr); + } + + pending_message->last_chunks_received_number = pending_message->chunks_received_number; + pending_message->last_index_checked = packet_info.chunk_index; + } + memcpy(pending_message->packet_data_start + (chunk_data_size * packet_info.chunk_index), packet_data, bytes_to_write); chunk_received(pending_message->chunks_received, packet_info.chunk_index); pending_message->chunks_received_number++; - atomic_thread_fence(memory_order_release); - allocator_free(&packet_buffer_memory_allocator, packet_buffer); goto next_packet; @@ -735,7 +822,7 @@ static inline void swiftnet_process_packets( void* swiftnet_server_process_packets(void* const void_server) { struct SwiftNetServer* const server = (struct SwiftNetServer*)void_server; - swiftnet_process_packets((void*)&server->packet_handler, server->pcap, server->eth_header, server->server_port, server->loopback, server->addr_type, &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->prepend_size, &server->process_packets_mtx, &server->process_packets_cond, &server->execute_callback_mtx, &server->execute_callback_cond); + swiftnet_process_packets((void*)&server->packet_handler, server->pcap, server->eth_header, server->server_port, server->loopback, server->addr_type, &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->prepend_size, &server->process_packets_mtx, &server->process_packets_cond, &server->execute_callback_mtx, &server->execute_callback_cond, &server->processing_packets); return NULL; } @@ -743,7 +830,7 @@ void* swiftnet_server_process_packets(void* const void_server) { void* swiftnet_client_process_packets(void* const void_client) { struct SwiftNetClientConnection* const client = (struct SwiftNetClientConnection*)void_client; - swiftnet_process_packets((void*)&client->packet_handler, client->pcap, client->eth_header, client->port_info.source_port, client->loopback, client->addr_type, &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->prepend_size, &client->process_packets_mtx, &client->process_packets_cond, &client->execute_callback_mtx, &client->execute_callback_cond); + swiftnet_process_packets((void*)&client->packet_handler, client->pcap, client->eth_header, client->port_info.source_port, client->loopback, client->addr_type, &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->prepend_size, &client->process_packets_mtx, &client->process_packets_cond, &client->execute_callback_mtx, &client->execute_callback_cond, &client->processing_packets); return NULL; } diff --git a/src/send_packet.c b/src/send_packet.c index 7c90b35..48b6edd 100644 --- a/src/send_packet.c +++ b/src/send_packet.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -19,10 +20,10 @@ static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(const uint8_t* const raw_data, const uint32_t data_size, const struct sockaddr* const destination, pcap_t* const pcap, struct SwiftNetPacketSending* const packet_sending) { while(1) { if(check_debug_flag(SWIFTNET_DEBUG_LOST_PACKETS)) { - send_debug_message("Requested list of lost packets: {\"packet_id\": %d}\n", packet_sending->packet_id); + send_debug_message("Requested list of lost packets: {\"packet_id\": %d}\n", htons(packet_sending->packet_id)); } - swiftnet_pcap_send(pcap, raw_data, data_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, raw_data, data_size); for(uint8_t times_checked = 0; times_checked < 0xFF; times_checked++) { const enum PacketSendingUpdated status = atomic_load_explicit(&packet_sending->updated, memory_order_acquire); @@ -137,6 +138,7 @@ static inline void handle_lost_packets( for(uint32_t i = 0; i < packet_sending->lost_chunks_size; i++) { const uint32_t lost_chunk_index = packet_sending->lost_chunks[i]; + const uint32_t current_offset = lost_chunk_index * (mtu - PACKET_HEADER_SIZE); uint8_t* const current_buffer_header_ptr = packet->packet_data_start + current_offset - prepend_size - PACKET_HEADER_SIZE; @@ -151,8 +153,7 @@ static inline void handle_lost_packets( memcpy(current_buffer_header_ptr + sizeof(struct ip) + prepend_size + offsetof(struct SwiftNetPacketInfo, chunk_index), &lost_chunk_index, SIZEOF_FIELD(struct SwiftNetPacketInfo, chunk_index)); - const uint16_t null_sum = htons(0); - memcpy(current_buffer_header_ptr + prepend_size + offsetof(struct ip, ip_sum), &null_sum, SIZEOF_FIELD(struct ip, ip_sum)); + 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) { const uint32_t bytes_to_complete = packet_length - current_offset; @@ -162,11 +163,11 @@ static inline void handle_lost_packets( HANDLE_CHECKSUM(current_buffer_header_ptr, prepend_size + PACKET_HEADER_SIZE + bytes_to_complete, prepend_size) - swiftnet_pcap_send(pcap, current_buffer_header_ptr, bytes_to_complete + PACKET_HEADER_SIZE + prepend_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, current_buffer_header_ptr, bytes_to_complete + PACKET_HEADER_SIZE + prepend_size); } else { HANDLE_CHECKSUM(current_buffer_header_ptr, mtu + prepend_size, prepend_size) - swiftnet_pcap_send(pcap, current_buffer_header_ptr, mtu + prepend_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, current_buffer_header_ptr, mtu + prepend_size); } memcpy(current_buffer_header_ptr, temp_data_buffer, prepend_size + PACKET_HEADER_SIZE); @@ -247,7 +248,10 @@ inline void swiftnet_send_packet( port_info ); - const struct ip ip_header = construct_ip_header(*target_addr, mtu, packet_id); + struct ip ip_header = construct_ip_header(*target_addr, mtu, packet_id); + + const uint16_t net_order_len = htons(mtu + prepend_size); + ip_header.ip_len = net_order_len; struct SwiftNetPacketSending* const new_packet_sending = allocator_allocate(packets_sending_memory_allocator); if(unlikely(new_packet_sending == NULL)) { @@ -265,6 +269,8 @@ inline void swiftnet_send_packet( new_packet_sending->lost_chunks = NULL; new_packet_sending->lost_chunks_size = 0; new_packet_sending->packet_id = packet_id; + + atomic_store_explicit(&new_packet_sending->current_send_delay, 50, memory_order_release); atomic_store_explicit(&new_packet_sending->updated, NO_UPDATE, memory_order_release); hashmap_insert(key_data_mem, sizeof(uint16_t), new_packet_sending, packets_sending); @@ -299,17 +305,16 @@ inline void swiftnet_send_packet( uint8_t* const buffer_header_location = packet->packet_data_start + current_offset - prepend_size - PACKET_HEADER_SIZE; // Copy data into temp storage - memcpy(temp_data_buffer, buffer_header_location, prepend_size); + memcpy(temp_data_buffer, buffer_header_location, prepend_size + PACKET_HEADER_SIZE); memcpy(buffer_header_location, prepend_buffer, prepend_size + PACKET_HEADER_SIZE); memcpy(buffer_header_location + sizeof(struct ip) + prepend_size + offsetof(struct SwiftNetPacketInfo, chunk_index), &i, SIZEOF_FIELD(struct SwiftNetPacketInfo, chunk_index)); - const uint16_t null_sum = htons(0); - memcpy(buffer_header_location + prepend_size + offsetof(struct ip, ip_sum), &null_sum, SIZEOF_FIELD(struct ip, ip_sum)); + memset(buffer_header_location + sizeof(struct ip) + prepend_size + offsetof(struct SwiftNetPacketInfo, checksum), 0x00, SIZEOF_FIELD(struct SwiftNetPacketInfo, checksum)); if(current_offset + (mtu - PACKET_HEADER_SIZE) >= packet_info.packet_length) { - const uint16_t bytes_to_send = (uint16_t)packet_length - current_offset + PACKET_HEADER_SIZE + prepend_size; + const uint16_t bytes_to_send = (uint16_t)(packet_length - current_offset + PACKET_HEADER_SIZE + prepend_size); // Last chunk const uint16_t bytes_to_send_net_order = htons(bytes_to_send - prepend_size); @@ -318,7 +323,7 @@ inline void swiftnet_send_packet( HANDLE_CHECKSUM(buffer_header_location, bytes_to_send, prepend_size); - swiftnet_pcap_send(pcap, buffer_header_location, bytes_to_send); + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer_header_location, bytes_to_send); memcpy(buffer_header_location, temp_data_buffer, prepend_size + PACKET_HEADER_SIZE); @@ -335,9 +340,11 @@ inline void swiftnet_send_packet( HANDLE_CHECKSUM(buffer_header_location, bytes_to_send, prepend_size) - swiftnet_pcap_send(pcap, buffer_header_location, bytes_to_send); + SWIFTNET_PCAP_SEND_SAFE(pcap, buffer_header_location, bytes_to_send); memcpy(buffer_header_location, temp_data_buffer, prepend_size + PACKET_HEADER_SIZE); + + usleep(atomic_load_explicit(&new_packet_sending->current_send_delay, memory_order_acquire)); } } } else { @@ -367,7 +374,7 @@ inline void swiftnet_send_packet( HANDLE_CHECKSUM(packet->packet_buffer_start + sizeof(struct ether_header) - sizeof(family), final_packet_size, prepend_size) - swiftnet_pcap_send(pcap, packet->packet_buffer_start + sizeof(struct ether_header) - sizeof(family), final_packet_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, packet->packet_buffer_start + sizeof(struct ether_header) - sizeof(family), final_packet_size); } else if(addr_type == DLT_EN10MB) { memcpy(packet->packet_buffer_start, ð_hdr, sizeof(eth_hdr)); memcpy(packet->packet_buffer_start + sizeof(eth_hdr), &ip_header, sizeof(ip_header)); @@ -377,7 +384,7 @@ inline void swiftnet_send_packet( HANDLE_CHECKSUM(packet->packet_buffer_start, final_packet_size, prepend_size) - swiftnet_pcap_send(pcap, packet->packet_buffer_start, final_packet_size); + SWIFTNET_PCAP_SEND_SAFE(pcap, packet->packet_buffer_start, final_packet_size); } } } diff --git a/src/swift_net.h b/src/swift_net.h index f8237ff..c4c1cdb 100644 --- a/src/swift_net.h +++ b/src/swift_net.h @@ -29,6 +29,8 @@ extern "C" { #define SWIFT_NET_DEBUG #endif +#define SWIFT_NET_ALIGNED(bytes) __attribute__((aligned(bytes))) + // Multiplication of memory pre allocated. // More memory = better performance #define SWIFT_NET_MEMORY_USAGE 5 @@ -39,12 +41,18 @@ enum PacketType { SEND_LOST_PACKETS_REQUEST = 0x03, SEND_LOST_PACKETS_RESPONSE = 0x04, SUCCESSFULLY_RECEIVED_PACKET = 0x05, + PACKET_DELAY_UPDATE = 0x06, #ifdef SWIFT_NET_REQUESTS - REQUEST = 0x06, - RESPONSE = 0x07, + REQUEST = 0x07, + RESPONSE = 0x08, #endif }; +enum PacketDelayUpdateStatus { + LOWER_DELAY, + INCREASE_DELAY +}; + #define PACKET_INFO_ID_NONE 0xFFFF #define unlikely(x) __builtin_expect((x), 0x00) @@ -64,20 +72,20 @@ typedef uint8_t SwiftNetDebugFlags; struct SwiftNetDebugger { int flags; -}; +} SWIFT_NET_ALIGNED(8); #endif struct SwiftNetPortInfo { uint16_t destination_port; uint16_t source_port; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetClientAddrData { uint32_t maximum_transmission_unit; struct in_addr sender_address; uint16_t port; uint8_t mac_address[6]; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetPacketClientMetadata { uint32_t data_length; @@ -86,26 +94,30 @@ struct SwiftNetPacketClientMetadata { #ifdef SWIFT_NET_REQUESTS bool expecting_response; #endif -}; +} SWIFT_NET_ALIGNED(4); 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; uint8_t packet_type; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetPendingMessage { + struct SwiftNetPacketInfo packet_info; uint8_t* chunks_received; uint8_t* packet_data_start; - struct SwiftNetPacketInfo packet_info; uint32_t chunks_received_length; uint32_t chunks_received_number; + uint32_t last_index_checked; + uint32_t last_chunks_received_number; uint16_t source_port; uint16_t packet_id; -}; + bool sending_lost_packets; +} SWIFT_NET_ALIGNED(8); struct SwiftNetPacketServerMetadata { struct SwiftNetClientAddrData sender; @@ -115,11 +127,11 @@ struct SwiftNetPacketServerMetadata { #ifdef SWIFT_NET_REQUESTS bool expecting_response; #endif -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetServerInformation { uint32_t maximum_transmission_unit; -}; +} SWIFT_NET_ALIGNED(4); enum PacketSendingUpdated { NO_UPDATE, @@ -130,82 +142,85 @@ enum PacketSendingUpdated { struct SwiftNetPacketSending { uint32_t* lost_chunks; _Atomic enum PacketSendingUpdated updated; + _Atomic uint32_t current_send_delay; uint32_t lost_chunks_size; uint16_t packet_id; _Atomic bool locked; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetPacketCompleted { uint16_t packet_id; bool marked_cleanup; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetPacketBuffer { 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 -}; +} SWIFT_NET_ALIGNED(8); struct PacketQueueNode { struct PacketQueueNode* next; uint8_t* data; uint32_t data_read; struct in_addr sender_address; -}; +} SWIFT_NET_ALIGNED(8); struct PacketQueue { struct PacketQueueNode* first_node; struct PacketQueueNode* last_node; _Atomic bool locked; -}; +} SWIFT_NET_ALIGNED(8); struct PacketCallbackQueueNode { struct SwiftNetPendingMessage* pending_message; struct PacketCallbackQueueNode* next; void* packet_data; uint16_t packet_id; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetServerPacketData { struct SwiftNetPendingMessage* internal_pending_message; // Do not use!! uint8_t* data; uint8_t* current_pointer; struct SwiftNetPacketServerMetadata metadata; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetClientPacketData { struct SwiftNetPendingMessage* internal_pending_message; // Do not use!! uint8_t* data; uint8_t* current_pointer; struct SwiftNetPacketClientMetadata metadata; -}; +} SWIFT_NET_ALIGNED(8); struct PacketCallbackQueue { struct PacketCallbackQueueNode* first_node; struct PacketCallbackQueueNode* last_node; _Atomic bool locked; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetSentSuccessfullyCompletedPacketSignal { uint16_t packet_id; bool confirmed; -}; +} SWIFT_NET_ALIGNED(4); struct SwiftNetMemoryAllocatorStack { void* pointers; void* data; - uint16_t index; + #ifdef SWIFT_NET_INTERNAL_TESTING + uint8_t* ptr_status; + #endif _Atomic uint32_t size; + uint16_t index; #ifdef SWIFT_NET_INTERNAL_TESTING _Atomic bool accessing_ptr_status; - uint8_t* ptr_status; #endif -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetChunkStorageManager { _Atomic(void*) first_item; _Atomic(void*) last_item; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetMemoryAllocator { _Atomic uint64_t occupied; @@ -214,88 +229,89 @@ struct SwiftNetMemoryAllocator { uint32_t item_size; uint32_t chunk_item_amount; _Atomic uint8_t creating_stack; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetVector { void** data; uint32_t size; uint32_t capacity; _Atomic bool locked; -}; +} SWIFT_NET_ALIGNED(8); struct SwiftNetHashMapItem { - uint32_t key_original_data_size; struct SwiftNetHashMapItem* next; // Contains next element with same key. void* key_original_data; // Dynamically allocated original key data void* value; // Data stored in item -}; + uint32_t key_original_data_size; +} SWIFT_NET_ALIGNED(8); // Custom implementation of a hashmap struct SwiftNetHashMap { - _Atomic bool atomic_lock; - uint32_t capacity; - uint32_t size; struct SwiftNetHashMapItem* items; struct SwiftNetMemoryAllocator* key_memory_allocator; uint32_t* item_occupation; // Bitset tracking which indexes of items array are occupied for looping through items without many cycles. -}; + uint32_t capacity; + uint32_t size; + _Atomic bool atomic_lock; +} SWIFT_NET_ALIGNED(8); // Connection data struct SwiftNetClientConnection { - pcap_t* pcap; - _Atomic(void (*)(struct SwiftNetClientPacketData* const, void* const user)) packet_handler; - _Atomic(void*) packet_handler_user_arg; struct SwiftNetHashMap packets_completed; - struct SwiftNetMemoryAllocator packets_completed_memory_allocator; - struct PacketQueue packet_queue; - pthread_mutex_t process_packets_mtx; - pthread_cond_t process_packets_cond; - pthread_t process_packets_thread; struct SwiftNetHashMap pending_messages; - struct SwiftNetMemoryAllocator pending_messages_memory_allocator; struct SwiftNetHashMap packets_sending; + struct SwiftNetMemoryAllocator packets_completed_memory_allocator; + struct SwiftNetMemoryAllocator pending_messages_memory_allocator; struct SwiftNetMemoryAllocator packets_sending_memory_allocator; + struct PacketQueue packet_queue; struct PacketCallbackQueue packet_callback_queue; + pcap_t* pcap; + _Atomic(void (*)(struct SwiftNetClientPacketData* const, void* const user)) packet_handler; + _Atomic(void*) packet_handler_user_arg; + pthread_mutex_t process_packets_mtx; pthread_mutex_t execute_callback_mtx; + pthread_cond_t process_packets_cond; pthread_cond_t execute_callback_cond; + pthread_t process_packets_thread; pthread_t execute_callback_thread; struct SwiftNetPortInfo port_info; - uint16_t addr_type; - struct in_addr server_addr; struct ether_header eth_header; uint32_t maximum_transmission_unit; + struct in_addr server_addr; + uint16_t addr_type; uint8_t prepend_size; bool loopback; + _Atomic bool processing_packets; _Atomic bool closing; _Atomic bool initialized; }; struct SwiftNetServer { - pcap_t* pcap; - _Atomic(void (*)(struct SwiftNetServerPacketData* const, void* const user)) packet_handler; - _Atomic(void*) packet_handler_user_arg; - uint8_t* current_read_pointer; - struct PacketQueue packet_queue; - pthread_mutex_t process_packets_mtx; - pthread_cond_t process_packets_cond; - pthread_t process_packets_thread; + struct SwiftNetHashMap packets_completed; struct SwiftNetHashMap pending_messages; - struct SwiftNetMemoryAllocator pending_messages_memory_allocator; struct SwiftNetHashMap packets_sending; - struct SwiftNetMemoryAllocator packets_sending_memory_allocator; - struct SwiftNetHashMap packets_completed; struct SwiftNetMemoryAllocator packets_completed_memory_allocator; + struct SwiftNetMemoryAllocator pending_messages_memory_allocator; + struct SwiftNetMemoryAllocator packets_sending_memory_allocator; + struct PacketQueue packet_queue; struct PacketCallbackQueue packet_callback_queue; + pcap_t* pcap; + _Atomic(void (*)(struct SwiftNetServerPacketData* const, void* const user)) packet_handler; + _Atomic(void*) packet_handler_user_arg; + pthread_mutex_t process_packets_mtx; pthread_mutex_t execute_callback_mtx; + pthread_cond_t process_packets_cond; pthread_cond_t execute_callback_cond; + pthread_t process_packets_thread; pthread_t execute_callback_thread; struct ether_header eth_header; uint16_t server_port; uint16_t addr_type; uint8_t prepend_size; bool loopback; + _Atomic bool processing_packets; _Atomic bool closing; -}; +} SWIFT_NET_ALIGNED(8); // Set a custom message (packet) handler for the server. extern void swiftnet_server_set_message_handler( diff --git a/tests/performance_tests/build/CMakeLists.txt b/tests/performance_tests/build/CMakeLists.txt index 6c3e203..3357d82 100644 --- a/tests/performance_tests/build/CMakeLists.txt +++ b/tests/performance_tests/build/CMakeLists.txt @@ -21,7 +21,7 @@ endif() link_directories(${CMAKE_SOURCE_DIR}/../../../build/output) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g") file(GLOB SRC_FILES "${CMAKE_SOURCE_DIR}/../src/*.c") diff --git a/tests/performance_tests/build/build_tests.sh b/tests/performance_tests/build/build_tests.sh index d7954ca..43d73ca 100755 --- a/tests/performance_tests/build/build_tests.sh +++ b/tests/performance_tests/build/build_tests.sh @@ -1,2 +1,8 @@ -cmake . -DCMAKE_BUILD_TYPE=Release -DSANITIZER=none -B . +rm -f CMakeCache.txt +rm -rf CMakeFiles +rm -rf cmake +rm -f Makefile +rm -f cmake_install.cmake + +cmake . -DCMAKE_BUILD_TYPE=Debug -DSANITIZER=none -B . make -B -j8 diff --git a/tests/performance_tests/src/main.c b/tests/performance_tests/src/main.c index e051729..38e85c3 100644 --- a/tests/performance_tests/src/main.c +++ b/tests/performance_tests/src/main.c @@ -8,11 +8,14 @@ #include "../../shared.h" -#define PACKET_SIZE 1000000 // 1 MILLION BYTES -#define PACKETS_TO_SEND 50 // HOW MANY PACKETS TO SEND +//#define PACKET_SIZE 1000000 // 1 MILLION BYTES +//#define PACKETS_TO_SEND 50 // HOW MANY PACKETS TO SEND + +#define PACKET_SIZE 100000000 // 100 MILLION BYTES +#define PACKETS_TO_SEND 1 // HOW MANY PACKETS TO SEND // ********************** // -// SEND 50 MILLION BYTES // +// SEND 100 MILLION BYTES // // ********************** // char private_ip_address_testing[INET_ADDRSTRLEN]; @@ -52,12 +55,7 @@ void send_large_packets(const bool loopback) { struct SwiftNetPacketBuffer buffer = swiftnet_create_packet_buffer(PACKET_SIZE); - uint8_t* const random_data = malloc(PACKET_SIZE); - for (uint32_t i = 0; i < PACKET_SIZE; i++) { - random_data[i] = rand(); - } - - swiftnet_append_to_buffer(random_data, PACKET_SIZE, &buffer); + buffer.packet_append_pointer += PACKET_SIZE; clock_gettime(CLOCK_MONOTONIC, &start);; @@ -86,8 +84,6 @@ void send_large_packets(const bool loopback) { int main() { swiftnet_initialize(); - //swiftnet_add_debug_flags(SWIFTNET_DEBUG_FLAGS(SWIFTNET_DEBUG_PACKETS_SENDING | SWIFTNET_DEBUG_PACKETS_RECEIVING | SWIFTNET_DEBUG_INITIALIZATION | SWIFTNET_DEBUG_LOST_PACKETS)); - send_large_packets(false); swiftnet_cleanup();