From 7d3b07fdfb842d6c1e84d084b0e3f13bf6006d5f Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Mon, 15 Apr 2019 14:52:00 +0530 Subject: [PATCH] igmp/mld6: Add on-demand timers config IGMP and MLD6 timers activated only when joining groups or receiving QUERY packets. This reduces the power consumption in applications that do not use IGMP and MLD6. Signed-off-by: Sachin Parekh Co-Authored-By: Axel Lin (espressif/esp-lwip@b1eec77b) Ref IDF-4837 --- .github/workflows/ci-linux.yml | 2 +- .gitlab-ci.yml | 2 +- src/core/ipv4/igmp.c | 39 ++++++++++++++++++++++++++++++++++ src/core/ipv6/mld6.c | 38 +++++++++++++++++++++++++++++++++ src/core/timeouts.c | 4 ++-- src/include/lwip/opt.h | 2 +- test/unit/lwipopts.h | 10 ++++++--- 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index a170a76c..75a87c61 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -48,7 +48,7 @@ jobs: run: | cp ${CONTRIB}/examples/example_app/lwipcfg.h.example ${CONTRIB}/examples/example_app/lwipcfg.h cd ${CONTRIB}/ports/unix/example_app - export CFLAGS="-DESP_LWIP=LWIP_NETCONN_FULLDUPLEX" + export CFLAGS="-DESP_LWIP=LWIP_NETCONN_FULLDUPLEX -DESP_LWIP_IGMP_TIMERS_ONDEMAND=ESP_LWIP -DESP_LWIP_MLD6_TIMERS_ONDEMAND=ESP_LWIP" export LWIPDIR=../../../../src/ chmod +x iteropts.sh && ./iteropts.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3e71427c..c8cedf42 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -86,7 +86,7 @@ validate_opts: - *get_contrib - cp ${CONTRIB}/examples/example_app/lwipcfg.h.example ${CONTRIB}/examples/example_app/lwipcfg.h - cd ${CONTRIB}/ports/unix/example_app - - export CFLAGS="-DESP_LWIP=LWIP_NETCONN_FULLDUPLEX" + - export CFLAGS="-DESP_LWIP=LWIP_NETCONN_FULLDUPLEX -DESP_LWIP_IGMP_TIMERS_ONDEMAND=ESP_LWIP -DESP_LWIP_MLD6_TIMERS_ONDEMAND=ESP_LWIP -DESP_DNS=ESP_LWIP" - export LWIPDIR=../../../../src/ - chmod +x iteropts.sh && ./iteropts.sh diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index b655aa3a..9d94decb 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -93,6 +93,7 @@ Steve Reynolds #include "lwip/netif.h" #include "lwip/stats.h" #include "lwip/prot/igmp.h" +#include "lwip/timeouts.h" #include @@ -107,6 +108,11 @@ static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type static ip4_addr_t allsystems; static ip4_addr_t allrouters; +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND +#include +static bool is_tmr_start = false; +#endif + /** * Initialize the IGMP module */ @@ -633,6 +639,17 @@ igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) } } +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND +/** + * Wrapper function with matching prototype which calls the actual callback + */ +static void igmp_timeout_cb(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + igmp_tmr(); +} +#endif /** * The igmp timer function (both for NO_SYS=1 and =0) * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). @@ -641,6 +658,9 @@ void igmp_tmr(void) { struct netif *netif; +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND + bool tmr_restart = false; +#endif NETIF_FOREACH(netif) { struct igmp_group *group = netif_igmp_data(netif); @@ -651,10 +671,23 @@ igmp_tmr(void) if (group->timer == 0) { igmp_timeout(netif, group); } +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND + else { + tmr_restart = true; + } +#endif } group = group->next; } } +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND + if (tmr_restart) { + sys_timeout(IGMP_TMR_INTERVAL, igmp_timeout_cb, NULL); + } else { + sys_untimeout(igmp_timeout_cb, NULL); + is_tmr_start = false; + } +#endif } /** @@ -701,6 +734,12 @@ igmp_start_timer(struct igmp_group *group, u8_t max_time) if (group->timer == 0) { group->timer = 1; } +#if ESP_LWIP_IGMP_TIMERS_ONDEMAND + if (!is_tmr_start) { + sys_timeout(IGMP_TMR_INTERVAL, igmp_timeout_cb, NULL); + is_tmr_start = true; + } +#endif } /** diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c index 087af74a..f690c3ed 100644 --- a/src/core/ipv6/mld6.c +++ b/src/core/ipv6/mld6.c @@ -66,6 +66,7 @@ #include "lwip/netif.h" #include "lwip/memp.h" #include "lwip/stats.h" +#include "lwip/timeouts.h" #include @@ -86,6 +87,10 @@ static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND +#include +static bool is_tmr_start = false; +#endif /** * Stop MLD processing on interface @@ -488,6 +493,17 @@ mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) return ERR_VAL; } +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND +/** + * Wrapper function with matching prototype which calls the actual callback + */ +static void mld6_timeout_cb(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + mld6_tmr(); +} +#endif /** * Periodic timer for mld processing. Must be called every @@ -499,6 +515,9 @@ void mld6_tmr(void) { struct netif *netif; +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND + bool tmr_restart = false; +#endif NETIF_FOREACH(netif) { struct mld_group *group = netif_mld6_data(netif); @@ -514,10 +533,23 @@ mld6_tmr(void) group->group_state = MLD6_GROUP_IDLE_MEMBER; } } +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND + else { + tmr_restart = true; + } +#endif } group = group->next; } } +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND + if (tmr_restart) { + sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); + } else { + sys_untimeout(mld6_timeout_cb, NULL); + is_tmr_start = false; + } +#endif } /** @@ -550,6 +582,12 @@ mld6_delayed_report(struct mld_group *group, u16_t maxresp_in) ((group->timer == 0) || (maxresp < group->timer)))) { group->timer = maxresp; group->group_state = MLD6_GROUP_DELAYING_MEMBER; +#if ESP_LWIP_MLD6_TIMERS_ONDEMAND + if (!is_tmr_start) { + sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); + is_tmr_start = true; + } +#endif } } diff --git a/src/core/timeouts.c b/src/core/timeouts.c index f37acfec..34aad13a 100644 --- a/src/core/timeouts.c +++ b/src/core/timeouts.c @@ -94,7 +94,7 @@ const struct lwip_cyclic_timer lwip_cyclic_timers[] = { #if LWIP_AUTOIP {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, #endif /* LWIP_AUTOIP */ -#if LWIP_IGMP +#if LWIP_IGMP && !ESP_LWIP_IGMP_TIMERS_ONDEMAND {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, #endif /* LWIP_IGMP */ #endif /* LWIP_IPV4 */ @@ -106,7 +106,7 @@ const struct lwip_cyclic_timer lwip_cyclic_timers[] = { #if LWIP_IPV6_REASS {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)}, #endif /* LWIP_IPV6_REASS */ -#if LWIP_IPV6_MLD +#if LWIP_IPV6_MLD && !ESP_LWIP_MLD6_TIMERS_ONDEMAND {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)}, #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_DHCP6 diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 87e22973..2e6f5e7f 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -505,7 +505,7 @@ * The number of sys timeouts used by the core stack (not apps) * The default number of timeouts is calculated here for all enabled modules. */ -#define LWIP_NUM_SYS_TIMEOUT_INTERNAL (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD))) +#define LWIP_NUM_SYS_TIMEOUT_INTERNAL (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + (ESP_LWIP_IGMP_TIMERS_ONDEMAND ? 0 : LWIP_IGMP) + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + (ESP_LWIP_MLD6_TIMERS_ONDEMAND ? 0 : LWIP_IPV6_MLD)))) /** * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. diff --git a/test/unit/lwipopts.h b/test/unit/lwipopts.h index 36adf955..05b320c9 100644 --- a/test/unit/lwipopts.h +++ b/test/unit/lwipopts.h @@ -151,10 +151,14 @@ u32_t esp_random(void); #define UDP_DEBUG LWIP_DBG_ON #define TCP_DEBUG LWIP_DBG_ON #endif /* ESP_TEST_DEBUG */ +#define ESP_LWIP_IGMP_TIMERS_ONDEMAND 1 +#define ESP_LWIP_MLD6_TIMERS_ONDEMAND 1 + #else -#define ESP_LWIP 0 -#define ESP_DHCP 0 -#define ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER 1 +#define ESP_LWIP 0 +#define ESP_LWIP_IGMP_TIMERS_ONDEMAND 0 +#define ESP_LWIP_MLD6_TIMERS_ONDEMAND 0 + #endif /* ESP_LWIP */ #endif /* LWIP_HDR_LWIPOPTS_H */