net: conn_mgr: Ignore ifaces and L2s
Adds a flag to allow ifaces and L2s to be ignored. This is so that applictions have better control over what ifaces they want connectivity management for. Enabling the flag forces conn_mgr to consider the iface unready. Also increase NET_CONNECTION_MANAGER_PRIORITY default value from 0 to 1 so that applications can register SYS_INIT callbacks that fire just before conn_mgr initializes. This allows ignored ifaces to be configured before conn_mgr starts, if needed. Signed-off-by: Georges Oates_Larsen <georges.larsen@nordicsemi.no>
This commit is contained in:
parent
6cda221c53
commit
b6897c211a
@ -13,11 +13,75 @@ extern "C" {
|
||||
|
||||
#if defined(CONFIG_NET_CONNECTION_MANAGER)
|
||||
|
||||
struct net_if;
|
||||
struct net_l2;
|
||||
|
||||
/**
|
||||
* @brief Resend either NET_L4_CONNECTED or NET_L4_DISCONNECTED depending on whether connectivity
|
||||
* is currently available.
|
||||
*/
|
||||
void conn_mgr_resend_status(void);
|
||||
|
||||
/**
|
||||
* @brief Mark an iface to be ignored by conn_mgr.
|
||||
*
|
||||
* Ignoring an iface forces conn_mgr to consider it unready/disconnected.
|
||||
*
|
||||
* This means that events related to the iface connecting/disconnecting will not be fired,
|
||||
* and if the iface was connected before being ignored, events will be fired as though it
|
||||
* disconnected at that moment.
|
||||
*
|
||||
* @param iface - iface to be ignored.
|
||||
*/
|
||||
void conn_mgr_ignore_iface(struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Watch (stop ignoring) an iface.
|
||||
*
|
||||
* conn_mgr will no longer be forced to consider the iface unreadly/disconnected.
|
||||
*
|
||||
* Events related to the iface connecting/disconnecting will no longer be blocked,
|
||||
* and if the iface was connected before being watched, events will be fired as though
|
||||
* it connected in that moment.
|
||||
*
|
||||
* @param iface - iface to no longer ignore.
|
||||
*/
|
||||
void conn_mgr_watch_iface(struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Check whether the provided iface is currently ignored.
|
||||
*
|
||||
* @param iface - The iface to check.
|
||||
* @retval true if the iface is being ignored by conn_mgr.
|
||||
* @retval false if the iface is being watched by conn_mgr.
|
||||
*/
|
||||
bool conn_mgr_is_iface_ignored(struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Mark an L2 to be ignored by conn_mgr.
|
||||
*
|
||||
* This is a wrapper for conn_mgr_ignore_iface that ignores all ifaces that use the L2.
|
||||
*
|
||||
* @param l2 - L2 to be ignored.
|
||||
*/
|
||||
void conn_mgr_ignore_l2(const struct net_l2 *l2);
|
||||
|
||||
/**
|
||||
* @brief Watch (stop ignoring) an L2.
|
||||
*
|
||||
* This is a wrapper for conn_mgr_watch_iface that watches all ifaces that use the L2.
|
||||
*
|
||||
* @param l2 - L2 to watch.
|
||||
*/
|
||||
void conn_mgr_watch_l2(const struct net_l2 *l2);
|
||||
|
||||
#else
|
||||
|
||||
#define conn_mgr_resend_status(...)
|
||||
#define conn_mgr_ignore_iface(...)
|
||||
#define conn_mgr_watch_iface(...)
|
||||
#define conn_mgr_ignore_l2(...)
|
||||
#define conn_mgr_watch_l2(...)
|
||||
|
||||
#endif /* CONFIG_NET_CONNECTION_MANAGER */
|
||||
|
||||
|
||||
@ -31,7 +31,8 @@ config NET_CONNECTION_MANAGER_STACK_SIZE
|
||||
|
||||
config NET_CONNECTION_MANAGER_PRIORITY
|
||||
int "Thread starting priority"
|
||||
default 0
|
||||
default 1
|
||||
range 1 99
|
||||
help
|
||||
This sets the starting priority of the connection manager thread.
|
||||
|
||||
|
||||
@ -73,6 +73,17 @@ static struct net_if *conn_mgr_get_if_by_index(int index)
|
||||
return net_if_get_by_index(index + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the index in iface_states for the state corresponding to a provided iface.
|
||||
*
|
||||
* @param iface - iface to find the index of.
|
||||
* @return int - The index found.
|
||||
*/
|
||||
static int conn_mgr_get_index_for_if(struct net_if *iface)
|
||||
{
|
||||
return net_if_get_by_iface(iface) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies listeners of the current readiness state of the iface at the given index
|
||||
*
|
||||
@ -118,11 +129,11 @@ static void conn_mgr_act_on_changes(void)
|
||||
bool is_l4_ready;
|
||||
bool is_oper_up;
|
||||
bool was_l4_ready;
|
||||
bool is_ignored;
|
||||
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
|
||||
|
||||
if (iface_states[idx] == 0) {
|
||||
/* This interface is not used */
|
||||
continue;
|
||||
@ -140,7 +151,8 @@ static void conn_mgr_act_on_changes(void)
|
||||
is_ip_ready = conn_mgr_is_if_ipv6_ready(idx) || conn_mgr_is_if_ipv4_ready(idx);
|
||||
is_oper_up = iface_states[idx] & CONN_MGR_IF_UP;
|
||||
was_l4_ready = iface_states[idx] & CONN_MGR_IF_READY;
|
||||
is_l4_ready = is_oper_up && is_ip_ready;
|
||||
is_ignored = iface_states[idx] & CONN_MGR_IF_IGNORED;
|
||||
is_l4_ready = is_oper_up && is_ip_ready && !is_ignored;
|
||||
|
||||
/* Respond to changes to iface readiness */
|
||||
if (was_l4_ready != is_l4_ready) {
|
||||
@ -167,7 +179,7 @@ static void conn_mgr_initial_state(struct net_if *iface)
|
||||
|
||||
if (net_if_is_up(iface)) {
|
||||
NET_DBG("Iface %p UP", iface);
|
||||
iface_states[idx] = CONN_MGR_IF_UP;
|
||||
iface_states[idx] |= CONN_MGR_IF_UP;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_NATIVE_IPV6)) {
|
||||
@ -240,6 +252,99 @@ void conn_mgr_resend_status(void)
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
}
|
||||
|
||||
void conn_mgr_ignore_iface(struct net_if *iface)
|
||||
{
|
||||
int idx = conn_mgr_get_index_for_if(iface);
|
||||
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
if (!(iface_states[idx] & CONN_MGR_IF_IGNORED)) {
|
||||
/* Set ignored flag and mark state as changed */
|
||||
iface_states[idx] |= CONN_MGR_IF_IGNORED;
|
||||
iface_states[idx] |= CONN_MGR_IF_CHANGED;
|
||||
k_sem_give(&conn_mgr_event_signal);
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
}
|
||||
|
||||
void conn_mgr_watch_iface(struct net_if *iface)
|
||||
{
|
||||
int idx = conn_mgr_get_index_for_if(iface);
|
||||
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
if (iface_states[idx] & CONN_MGR_IF_IGNORED) {
|
||||
/* Clear ignored flag and mark state as changed */
|
||||
iface_states[idx] &= ~CONN_MGR_IF_IGNORED;
|
||||
iface_states[idx] |= CONN_MGR_IF_CHANGED;
|
||||
k_sem_give(&conn_mgr_event_signal);
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
}
|
||||
|
||||
bool conn_mgr_is_iface_ignored(struct net_if *iface)
|
||||
{
|
||||
int idx = conn_mgr_get_index_for_if(iface);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
ret = iface_states[idx] & CONN_MGR_IF_IGNORED;
|
||||
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a provided iface uses the provided L2.
|
||||
*
|
||||
* @param iface - iface to check.
|
||||
* @param l2 - L2 to check. NULL will match offloaded ifaces.
|
||||
* @retval true if the iface uses the provided L2.
|
||||
* @retval false otherwise.
|
||||
*/
|
||||
static bool iface_uses_l2(struct net_if *iface, const struct net_l2 *l2)
|
||||
{
|
||||
return (!l2 && net_if_offload(iface)) ||
|
||||
(net_if_l2(iface) == l2);
|
||||
}
|
||||
|
||||
void conn_mgr_ignore_l2(const struct net_l2 *l2)
|
||||
{
|
||||
/* conn_mgr_ignore_iface already locks the mutex, but we lock it here too
|
||||
* so that all matching ifaces are updated simultaneously.
|
||||
*/
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
STRUCT_SECTION_FOREACH(net_if, iface) {
|
||||
if (iface_uses_l2(iface, l2)) {
|
||||
conn_mgr_ignore_iface(iface);
|
||||
}
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
}
|
||||
|
||||
void conn_mgr_watch_l2(const struct net_l2 *l2)
|
||||
{
|
||||
/* conn_mgr_watch_iface already locks the mutex, but we lock it here too
|
||||
* so that all matching ifaces are updated simultaneously.
|
||||
*/
|
||||
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
|
||||
|
||||
STRUCT_SECTION_FOREACH(net_if, iface) {
|
||||
if (iface_uses_l2(iface, l2)) {
|
||||
conn_mgr_watch_iface(iface);
|
||||
}
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_mgr_lock);
|
||||
}
|
||||
|
||||
static int conn_mgr_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -24,7 +24,10 @@
|
||||
#define CONN_MGR_IF_IPV6_DAD_OK BIT(2)
|
||||
#define CONN_MGR_IF_IPV4_SET BIT(3)
|
||||
|
||||
/* Internal state flags */
|
||||
/* Configuration flags */
|
||||
#define CONN_MGR_IF_IGNORED BIT(7)
|
||||
|
||||
/* Internal state flags*/
|
||||
#define CONN_MGR_IF_READY BIT(14)
|
||||
|
||||
/* Event flags */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user