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 */
+/** @} */