From 2f2a009e7a38da4fbdd66ea1a1d9b2f26cf3897c Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 21 Jan 2021 17:31:15 +0100 Subject: [PATCH] congure: initial import of a congestion control framework --- sys/Kconfig | 1 + sys/Makefile.dep | 4 + sys/congure/Kconfig | 22 ++++ sys/congure/Makefile | 1 + sys/include/congure.h | 224 +++++++++++++++++++++++++++++++++++ sys/include/congure/config.h | 32 +++++ 6 files changed, 284 insertions(+) create mode 100644 sys/congure/Kconfig create mode 100644 sys/congure/Makefile create mode 100644 sys/include/congure.h create mode 100644 sys/include/congure/config.h diff --git a/sys/Kconfig b/sys/Kconfig index e1b64ba492..02a636d7c1 100644 --- a/sys/Kconfig +++ b/sys/Kconfig @@ -18,6 +18,7 @@ rsource "cb_mux/Kconfig" rsource "checksum/Kconfig" rsource "color/Kconfig" rsource "crypto/Kconfig" +rsource "congure/Kconfig" rsource "div/Kconfig" rsource "embunit/Kconfig" rsource "entropy_source/Kconfig" diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 1af2827552..54c243b363 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -21,6 +21,10 @@ ifneq (,$(filter arduino_pwm,$(FEATURES_USED))) FEATURES_REQUIRED += periph_pwm endif +ifneq (,$(filter congure_%,$(USEMODULE))) + USEMODULE += congure +endif + ifneq (,$(filter eepreg,$(USEMODULE))) FEATURES_REQUIRED += periph_eeprom endif diff --git a/sys/congure/Kconfig b/sys/congure/Kconfig new file mode 100644 index 0000000000..a4c788b615 --- /dev/null +++ b/sys/congure/Kconfig @@ -0,0 +1,22 @@ +# 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. + +if !TEST_KCONFIG +menu "CongURE congestion control abstraction" + depends on USEMODULE_CONGURE + +endmenu # CongURE congestion control abstraction +endif # !TEST_KCONFIG + +if TEST_KCONFIG +menuconfig MODULE_CONGURE + bool "CongURE congestion control abstraction" + depends on TEST_KCONFIG + +if MODULE_CONGURE + +endif # MODULE_CONGURE +endif # TEST_KCONFIG diff --git a/sys/congure/Makefile b/sys/congure/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/congure/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/include/congure.h b/sys/include/congure.h new file mode 100644 index 0000000000..9031b54b05 --- /dev/null +++ b/sys/include/congure.h @@ -0,0 +1,224 @@ +/* + * 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 may 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 may 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 */ +/** @} */ diff --git a/sys/include/congure/config.h b/sys/include/congure/config.h new file mode 100644 index 0000000000..d9b3e080ec --- /dev/null +++ b/sys/include/congure/config.h @@ -0,0 +1,32 @@ +/* + * 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_config CongURE compile time configuration + * @ingroup sys_congure + * @ingroup config + * @brief Configuration for congestion control using @ref sys_congure + * @{ + * + * @file + * + * @author Martine S. Lenders + */ +#ifndef CONGURE_CONFIG_H +#define CONGURE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CONGURE_CONFIG_H */ +/** @} */