Skip to content

Commit

Permalink
net: conn_mgr: Add IPv4 and IPv6 tracking
Browse files Browse the repository at this point in the history
conn_mgr now fires:

- NET_EVENT_CONN_IPV4_CONNECTED
- NET_EVENT_CONN_IPV4_DISCONNECTED
- NET_EVENT_CONN_IPV6_CONNECTED
- NET_EVENT_CONN_IPV6_DISCONNECTED

These events track whether there are any ready ifaces offering
specifically IPv4 or specifically IPv6 connectivity.

Signed-off-by: Georges Oates_Larsen <[email protected]>
  • Loading branch information
glarsennordic committed May 22, 2024
1 parent d10a993 commit 480c217
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
11 changes: 11 additions & 0 deletions doc/connectivity/networking/conn_mgr/main.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ Afterwards, ifaces can become ready or unready without firing additional events,

When there are no longer any ready ifaces left, the :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management <net_mgmt_interface>` event is triggered, and IP connectivity is said to be unready.

.. note::

Connection Manager also fires the following more specific ``CONNECTED`` / ``DISCONNECTED`` events:

- :c:macro:`NET_EVENT_CONN_IPV4_CONNECTED`
- :c:macro:`NET_EVENT_CONN_IPV4_DISCONNECTED`
- :c:macro:`NET_EVENT_CONN_IPV6_CONNECTED`
- :c:macro:`NET_EVENT_CONN_IPV6_DISCONNECTED`

These are similar to :c:macro:`NET_EVENT_L4_CONNECTED` and :c:macro:`NET_EVENT_L4_DISCONNECTED`, but specifically track whether IPv4- and IPv6-capable ifaces are ready.

.. _conn_mgr_monitoring_usage:

Usage
Expand Down
29 changes: 29 additions & 0 deletions include/zephyr/net/conn_mgr_connectivity.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@ extern "C" {
#define _NET_MGMT_CONN_BASE (_NET_MGMT_CONN_LAYER | _NET_MGMT_CONN_CODE | \
NET_MGMT_EVENT_BIT)
#define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE)
#define _NET_MGMT_CONN_EVENT (_NET_MGMT_CONN_BASE)

/** @endcond */

enum net_event_conn_cmd {
NET_EVENT_CONN_CMD_IF_TIMEOUT = 1,
NET_EVENT_CONN_CMD_IF_FATAL_ERROR,
NET_EVENT_CONN_CMD_IPV4_CONNECTED,
NET_EVENT_CONN_CMD_IPV4_DISCONNECTED,
NET_EVENT_CONN_CMD_IPV6_CONNECTED,
NET_EVENT_CONN_CMD_IPV6_DISCONNECTED,
};

/**
Expand All @@ -60,6 +65,30 @@ enum net_event_conn_cmd {
#define NET_EVENT_CONN_IF_FATAL_ERROR \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IF_FATAL_ERROR)

/**
* @brief net_mgmt event raised when IPv4 connectivity becomes available
*/
#define NET_EVENT_CONN_IPV4_CONNECTED \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IPV4_CONNECTED)

/**
* @brief net_mgmt event raised when IPv4 connectivity becomes lost
*/
#define NET_EVENT_CONN_IPV4_DISCONNECTED \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IPV4_DISCONNECTED)

/**
* @brief net_mgmt event raised when IPv6 connectivity becomes available
*/
#define NET_EVENT_CONN_IPV6_CONNECTED \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IPV6_CONNECTED)

/**
* @brief net_mgmt event raised when IPv6 connectivity becomes available
*/
#define NET_EVENT_CONN_IPV6_DISCONNECTED \
(_NET_MGMT_CONN_IF_EVENT | NET_EVENT_CONN_CMD_IPV6_DISCONNECTED)


/**
* @brief Per-iface connectivity flags
Expand Down
40 changes: 38 additions & 2 deletions subsys/net/conn_mgr/conn_mgr_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ static struct k_thread conn_mgr_mon_thread;
*/
uint16_t iface_states[CONN_MGR_IFACE_MAX];

/* Tracks the most recent total quantity of L4-ready ifaces */
/* Tracks the most recent total quantity of L4-ready ifaces (any, IPv4, IPv6) */
static uint16_t last_ready_count;
static uint16_t last_ready_count_v4;
static uint16_t last_ready_count_v6;

/* Tracks the last ifaces to change state in each respective direction */
static struct net_if *last_iface_down;
Expand Down Expand Up @@ -92,6 +94,8 @@ static void conn_mgr_mon_handle_update(void)
{
int idx;
int ready_count;
int ready_count_v4;
int ready_count_v6;
bool is_ip_ready;
bool is_ipv6_ready;
bool is_ipv4_ready;
Expand All @@ -103,6 +107,9 @@ static void conn_mgr_mon_handle_update(void)
k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER);

ready_count = 0;
ready_count_v4 = 0;
ready_count_v6 = 0;

for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
if (iface_states[idx] == 0) {
/* This interface is not used */
Expand All @@ -128,7 +135,12 @@ static void conn_mgr_mon_handle_update(void)
if (is_l4_ready) {
ready_count += 1;
}

if (is_l4_ready && is_ipv6_ready) {
ready_count_v6 += 1;
}
if (is_l4_ready && is_ipv4_ready) {
ready_count_v4 += 1;
}
}

/* If the total number of ready ifaces changed, possibly send an event */
Expand All @@ -142,7 +154,31 @@ static void conn_mgr_mon_handle_update(void)
}
}

/* Same, but specifically for IPv4 */
if (ready_count_v4 != last_ready_count_v4) {
if (ready_count_v4 == 0) {
/* We just lost IPv4 connectivity */
net_mgmt_event_notify(NET_EVENT_CONN_IPV4_DISCONNECTED, NULL);
} else if (last_ready_count_v4 == 0) {
/* We just gained IPv4 connectivity */
net_mgmt_event_notify(NET_EVENT_CONN_IPV4_CONNECTED, NULL);
}
}

/* Same, but specifically for IPv6 */
if (ready_count_v6 != last_ready_count_v6) {
if (ready_count_v6 == 0) {
/* We just lost IPv4 connectivity */
net_mgmt_event_notify(NET_EVENT_CONN_IPV6_DISCONNECTED, NULL);
} else if (last_ready_count_v6 == 0) {
/* We just gained IPv4 connectivity */
net_mgmt_event_notify(NET_EVENT_CONN_IPV6_CONNECTED, NULL);
}
}

last_ready_count = ready_count;
last_ready_count_v4 = ready_count_v4;
last_ready_count_v6 = ready_count_v6;

k_mutex_unlock(&conn_mgr_mon_lock);
}
Expand Down

0 comments on commit 480c217

Please sign in to comment.