/* * Copyright (C) 2021 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @defgroup sys_congure CongURE - A Congestion control framework * @ingroup sys * @brief Congestion control utilizing re-usable * elements * @{ * * @file * * @author Martine S. Lenders */ #ifndef CONGURE_H #define CONGURE_H #include #include "clist.h" #include "ztimer.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Maximum value the window size can take */ #define CONGURE_WND_SIZE_MAX (UINT16_MAX) /** * @brief Define type for window size to allow for possible window size * scaling */ typedef uint16_t congure_wnd_size_t; /** * @brief Forward-declariton for the driver struct */ typedef struct congure_snd_driver congure_snd_driver_t; /** * @brief Base state object for CongURE implementations */ typedef struct { /** * @brief Driver for the state object. See @ref congure_snd_driver_t. */ const congure_snd_driver_t *driver; /** * @brief Context for callbacks specific to the congestion control * * E.g. A TCP PCB. */ void *ctx; congure_wnd_size_t cwnd; /**< Congestion window size */ } congure_snd_t; /** * @brief Object to represent a collection of sent messages. */ typedef struct { clist_node_t super; /**< see @ref clist_node_t */ /** * @brief timestamp in milliseconds of when the message was sent. */ ztimer_now_t send_time; congure_wnd_size_t size; /**< size in initiator-defined units */ /** * @brief number of times the message has already been resent. * * This does not include the first send. */ uint8_t resends; } congure_snd_msg_t; /** * @brief Object to represent an ACK to a message */ typedef struct { /** * @brief Timestamp in milliseconds of when the ACK was received. */ ztimer_now_t recv_time; uint32_t id; /**< ID of the message the ACK is for */ /** * @brief size of the ACK in initiator-defined units */ congure_wnd_size_t size; /** * @brief the peer-reported window size in caller defined units. Leave * 0 if not supplied by the protocol. */ congure_wnd_size_t wnd; /** * @brief true, if ACK only contains an ACK, false if not * * This e.g. can be used to tell the congestion control mechanism that the * SYN or FIN tag are cleared in the ACK with TCP. */ uint16_t clean; /** * @brief the peer-reported time in milliseconds the ACK was delayed * since message reception. Leave 0 if not supplied by the * protocol. */ uint16_t delay; } congure_snd_ack_t; /** * @brief Driver for CongURE objects. */ struct congure_snd_driver { /** * @brief Initializes a CongURE object. * * @param[in,out] c The CongURE object to initialize. * @param[in] ctx Context for callbacks specific to the * congestion control (such as a TCP PCB). * May be NULL. */ void (*init)(congure_snd_t *c, void *ctx); /** * @brief Get current interval between messages for pacing. * * @param[in] c The CongURE state object. * @param[in] msg_size The size of the next message to send in * caller-defined unit. * * @return The current interval between sent messages in microseconds * when pacing supported by congestion control implementation. * @return -1, if pacing is not supported by the congestion control * implementation. */ int32_t (*inter_msg_interval)(congure_snd_t *c, unsigned msg_size); /** * @brief Report that a message was sent. * * @param[in] c The CongURE state object. * @param[in] msg_size Size of the message in caller-defined unit. */ void (*report_msg_sent)(congure_snd_t *c, unsigned msg_size); /** * @brief Report message as discarded. * * Discarded messages are not further taken into account for congestion * control. * * @param[in] c The CongURE state object. * @param[in] msg_size Size of the discarded message in caller-defined * unit. */ void (*report_msg_discarded)(congure_snd_t *c, unsigned msg_size); /** * @brief Report that the ACKs for a collection of messages timed out. * * @note As many congestion control algorithms do not distinguish loss * and ACK timeout, this method and * congure_snd_t::report_msgs_lost need to have the same * signature so the same function can be used here * * @param[in] c The CongURE state object. * @param[in] msgs A collection of messages for which the ACK * timed out. The list must not be changed by the * method. */ void (*report_msgs_timeout)(congure_snd_t *c, congure_snd_msg_t *msgs); /** * @brief Report that a collection of messages that is known to be lost. * * One indicator for a lost message may e.g. be the reception of an ACK of a * later sent packet, but not a ACK timeout (see * congure_snd_driver_t::report_msgs_timeout() for that). * * @note As many congestion control algorithms do not distinguish loss * and ACK timeout, this method and * congure_snd_t::report_msgs_timeout need to have the same * signature so the same function can be used here * * @param[in] c The CongURE state object. * @param[in] msgs A collection of messages that are known to * be lost. The list must not be be changed by the * method. */ void (*report_msgs_lost)(congure_snd_t *c, congure_snd_msg_t *msgs); /** * @brief Report that the ACK for a message was received. * * @param[in] c The CongURE state object. * @param[in] msg The ACK'd message. * @param[in] ack The received ACK. */ void (*report_msg_acked)(congure_snd_t *c, congure_snd_msg_t *msg, congure_snd_ack_t *ack); /** * @brief Report that "congestion encountered" CE signals were received * for a message by means of explicit congestion notification * (ECN). * * @param[in] c The CongURE state object. * @param[in] time Timestamp in milliseconds of the message the CE * event occurred for was sent. */ void (*report_ecn_ce)(congure_snd_t *c, ztimer_now_t time); }; #ifdef __cplusplus } #endif #endif /* CONGURE_H */ /** @} */