/* SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "heap.h" #include #include #include #include // // A two-path UDP tunnel implementation. // // The tunnel uses two physical paths to transmit packets to the same destination. // // Sent packets are assigned a sequence number and transmitted through one of the // two paths according to a weighted round-robin scheduler. // // On the receiving end, packets are buffered in a reorder buffer and a best effort is made // to deliver packets in order. // #define MPU_MTU (1500U - 20 - 8) //!< Maximum payload size for traditional IP/UDP headers typedef struct { int sockfd; float weight; } mpu_path_t; //!< Physical path for packet transmission typedef struct { uint64_t seq_num; } mpu_hdr_t; //!< Tunnel packet header typedef struct { uint64_t timestamp; // in milliseconds uint16_t packet_len; union { uint8_t buf[MPU_MTU]; mpu_hdr_t hdr; } packet; } mpu_slot_t; //!< Packet slot for reorder buffer typedef struct { mpu_path_t paths[2]; // Weighted round-robin scheduler state float credits[2]; uint64_t send_seq_num; // Reorder buffer uint64_t recv_seq_num; int reorder_window; // in milliseconds heap_t reorder_heap; } mpu_ctx_t; /// Initialize MPU context with two physical paths /// Returns 0 on success, -1 on failure (errno is set). int mpu_init(mpu_ctx_t* ctx, int sock0, float weight0, int sock1, float weight1, int reorder_window, // in milliseconds size_t reorder_slots); /// Send a packet through the tunnel. Packet must not exceed MPU_MTU - sizeof(mpu_hdr_t). /// Returns 0 on success, -1 on failure (errno is set). int mpu_send(mpu_ctx_t* ctx, const uint8_t* data, size_t len); /// Receive a packet from the tunnel, blocking until one is available. /// Returns the length of the received data, or -1 on failure (errno is set). ssize_t mpu_recv(mpu_ctx_t* ctx, uint8_t* data, size_t len);