net/iface: Coalesce all RS timers through one
This reduces the size of struct net_if_ipv6 by 24 bytes by moving the k_delayed_work attribute into net_if core code. Then each net_if_ipv6 can be added to the timer handler via a slist. This does not make much gain if the system has only 1 network interface It starts to be interesting if it has 2+ network interfaces then. Fixes #8728 Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
09e7262be8
commit
b5bcd25398
3 changed files with 91 additions and 29 deletions
|
@ -220,9 +220,6 @@ struct net_if_ipv6 {
|
|||
/** Prefixes */
|
||||
struct net_if_ipv6_prefix prefix[NET_IF_MAX_IPV6_PREFIX];
|
||||
|
||||
/** Router solicitation timer */
|
||||
struct k_delayed_work rs_timer;
|
||||
|
||||
/** Default reachable time (RFC 4861, page 52) */
|
||||
u32_t base_reachable_time;
|
||||
|
||||
|
@ -231,12 +228,19 @@ struct net_if_ipv6 {
|
|||
|
||||
/** Retransmit timer (RFC 4861, page 52) */
|
||||
u32_t retrans_timer;
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
/** Router solicitation timer node */
|
||||
sys_snode_t rs_node;
|
||||
|
||||
/** IPv6 hop limit */
|
||||
u8_t hop_limit;
|
||||
/* RS start time */
|
||||
u32_t rs_start;
|
||||
|
||||
/** RS count */
|
||||
u8_t rs_count;
|
||||
#endif
|
||||
|
||||
/** IPv6 hop limit */
|
||||
u8_t hop_limit;
|
||||
};
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
|
@ -659,6 +663,21 @@ static inline void net_if_start_dad(struct net_if *iface)
|
|||
*/
|
||||
void net_if_start_rs(struct net_if *iface);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop neighbor discovery.
|
||||
*
|
||||
* @param iface Pointer to a network interface structure
|
||||
*/
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
void net_if_stop_rs(struct net_if *iface);
|
||||
#else
|
||||
static inline void net_if_stop_rs(struct net_if *iface)
|
||||
{
|
||||
ARG_UNUSED(iface);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6_ND */
|
||||
|
||||
/**
|
||||
* @brief Set a network interface's link address
|
||||
*
|
||||
|
|
|
@ -2429,7 +2429,7 @@ static enum net_verdict handle_ra_input(struct net_pkt *pkt,
|
|||
}
|
||||
|
||||
/* Cancel the RS timer on iface */
|
||||
k_delayed_work_cancel(&net_pkt_iface(pkt)->config.ip.ipv6->rs_timer);
|
||||
net_if_stop_rs(net_pkt_iface(pkt));
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
|
|
|
@ -65,6 +65,11 @@ static struct k_delayed_work dad_timer;
|
|||
static sys_slist_t active_dad_timers;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
static struct k_delayed_work rs_timer;
|
||||
static sys_slist_t active_rs_timers;
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
struct net_if_ipv6 ipv6;
|
||||
struct net_if *iface;
|
||||
|
@ -742,30 +747,49 @@ static inline void net_if_ipv6_start_dad(struct net_if *iface,
|
|||
|
||||
static void rs_timeout(struct k_work *work)
|
||||
{
|
||||
/* Did not receive RA yet. */
|
||||
struct net_if_ipv6 *ipv6 = CONTAINER_OF(work,
|
||||
struct net_if_ipv6,
|
||||
rs_timer);
|
||||
u32_t current_time = k_uptime_get_32();
|
||||
struct net_if_ipv6 *ipv6, *next;
|
||||
|
||||
ARG_UNUSED(work);
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_rs_timers,
|
||||
ipv6, next, rs_node) {
|
||||
struct net_if *iface;
|
||||
|
||||
if ((s32_t)(ipv6->rs_start + RS_TIMEOUT - current_time) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Removing the ipv6 from active_rs_timers list */
|
||||
sys_slist_remove(&active_rs_timers, NULL, &ipv6->rs_node);
|
||||
|
||||
/* Did not receive RA yet. */
|
||||
ipv6->rs_count++;
|
||||
|
||||
for (iface = __net_if_start; iface != __net_if_end; iface++) {
|
||||
if (iface->config.ip.ipv6 == ipv6) {
|
||||
goto found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("Interface IPv6 config %p not found", ipv6);
|
||||
return;
|
||||
|
||||
found:
|
||||
NET_DBG("RS no respond iface %p count %d", iface,
|
||||
ipv6->rs_count);
|
||||
|
||||
if (iface != __net_if_end) {
|
||||
NET_DBG("RS no respond iface %p count %d",
|
||||
iface, ipv6->rs_count);
|
||||
if (ipv6->rs_count < RS_COUNT) {
|
||||
net_if_start_rs(iface);
|
||||
}
|
||||
} else {
|
||||
NET_DBG("Interface IPv6 config %p not found", ipv6);
|
||||
}
|
||||
|
||||
ipv6 = NULL;
|
||||
}
|
||||
|
||||
if (ipv6) {
|
||||
k_delayed_work_submit(&rs_timer,
|
||||
ipv6->rs_start +
|
||||
RS_TIMEOUT - current_time);
|
||||
}
|
||||
}
|
||||
|
||||
void net_if_start_rs(struct net_if *iface)
|
||||
|
@ -779,17 +803,37 @@ void net_if_start_rs(struct net_if *iface)
|
|||
NET_DBG("Starting ND/RS for iface %p", iface);
|
||||
|
||||
if (!net_ipv6_start_rs(iface)) {
|
||||
k_delayed_work_submit(&ipv6->rs_timer, RS_TIMEOUT);
|
||||
ipv6->rs_start = k_uptime_get_32();
|
||||
sys_slist_append(&active_rs_timers, &ipv6->rs_node);
|
||||
|
||||
if (!k_delayed_work_remaining_get(&rs_timer)) {
|
||||
k_delayed_work_submit(&rs_timer, RS_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iface_ipv6_nd_init(struct net_if_ipv6 *ipv6)
|
||||
void net_if_stop_rs(struct net_if *iface)
|
||||
{
|
||||
k_delayed_work_init(&ipv6->rs_timer, rs_timeout);
|
||||
struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
|
||||
|
||||
if (!ipv6) {
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("Stopping ND/RS for iface %p", iface);
|
||||
|
||||
sys_slist_find_and_remove(&active_rs_timers, &ipv6->rs_node);
|
||||
}
|
||||
|
||||
static inline void iface_ipv6_nd_init(void)
|
||||
{
|
||||
k_delayed_work_init(&rs_timer, rs_timeout);
|
||||
sys_slist_init(&active_rs_timers);
|
||||
}
|
||||
|
||||
#else
|
||||
#define net_if_start_rs(...)
|
||||
#define net_if_stop_rs(...)
|
||||
#define iface_ipv6_nd_init(...)
|
||||
#endif /* CONFIG_NET_IPV6_ND */
|
||||
|
||||
|
@ -2207,6 +2251,7 @@ static void iface_ipv6_init(int if_count)
|
|||
int i;
|
||||
|
||||
iface_ipv6_dad_init();
|
||||
iface_ipv6_nd_init();
|
||||
|
||||
k_delayed_work_init(&address_lifetime_timer, address_lifetime_timeout);
|
||||
k_delayed_work_init(&prefix_lifetime_timer, prefix_lifetime_timeout);
|
||||
|
@ -2224,8 +2269,6 @@ static void iface_ipv6_init(int if_count)
|
|||
ipv6_addresses[i].ipv6.base_reachable_time = REACHABLE_TIME;
|
||||
|
||||
net_if_ipv6_set_reachable_time(&ipv6_addresses[i].ipv6);
|
||||
|
||||
iface_ipv6_nd_init(&ipv6_addresses[i].ipv6);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue