Skip to content

Commit

Permalink
ESP32: Handle RIO with lifetime over LWIP_UINT32_MAX/(4 * 1000) (#25074)
Browse files Browse the repository at this point in the history
* ESP32: Handle RIO with lifetime over LWIP_UINT32_MAX/(4 * 1000)

* ESP32: Remove the rio_header struct and use route_option struct defined in LwIP

---------

Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Aug 8, 2023
1 parent 125bf01 commit 1043211
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 32 deletions.
4 changes: 2 additions & 2 deletions examples/lighting-app/esp32/main/DeviceCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ void AppDeviceCallbacks::OnColorControlAttributeChangeCallback(EndpointId endpoi
if (attributeId == CurrentHue::Id)
{
hue = *value;
CurrentSaturation::Get(&saturation);
CurrentSaturation::Get(endpointId, &saturation);
}
else
{
saturation = *value;
CurrentHue::Get(&hue);
CurrentHue::Get(endpointId, &hue);
}
AppLED.SetColor(hue, saturation);

Expand Down
36 changes: 12 additions & 24 deletions src/platform/ESP32/route_hook/ESP32RouteHook.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,7 @@ typedef struct esp_route_hook_t
struct esp_route_hook_t * next;
} esp_route_hook_t;

PACK_STRUCT_BEGIN
struct rio_header_t
{
PACK_STRUCT_FLD_8(u8_t type);
PACK_STRUCT_FLD_8(u8_t length);
PACK_STRUCT_FLD_8(u8_t prefix_length);
PACK_STRUCT_FLD_8(u8_t preference);
PACK_STRUCT_FIELD(u32_t route_lifetime);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

typedef struct rio_header_t rio_header_t;
typedef struct route_option route_option_t;

static esp_route_hook_t * s_hooks;

Expand Down Expand Up @@ -75,21 +64,20 @@ static void ra_recv_handler(struct netif * netif, const uint8_t * icmp_payload,
uint8_t opt_type = icmp_payload[0];
uint8_t opt_len = icmp_payload[1] << 3;

if (opt_type == ND6_OPTION_TYPE_ROUTE_INFO && opt_len >= sizeof(rio_header_t) && !is_self_address(netif, src_addr) &&
payload_len >= opt_len)
if (opt_type == ND6_OPTION_TYPE_ROUTE_INFO && opt_len >= sizeof(route_option_t) - sizeof(ip6_addr_p_t) &&
!is_self_address(netif, src_addr) && payload_len >= opt_len)
{
rio_header_t rio_header;
memcpy(&rio_header, icmp_payload, sizeof(rio_header));
route_option_t route_option;
memcpy(&route_option, icmp_payload, sizeof(route_option));

// skip if prefix is longer than IPv6 address.
if (rio_header.prefix_length > 128)
if (route_option.prefix_length > 128)
{
break;
}
uint8_t prefix_len_bytes = (rio_header.prefix_length + 7) / 8;
int8_t preference = -2 * ((rio_header.preference >> 4) & 1) + (((rio_header.preference) >> 3) & 1);
const uint8_t * rio_data = &icmp_payload[sizeof(rio_header_t)];
uint8_t rio_data_len = opt_len - sizeof(rio_header_t);
uint8_t prefix_len_bytes = (route_option.prefix_length + 7) / 8;
int8_t preference = -2 * ((route_option.preference >> 4) & 1) + (((route_option.preference) >> 3) & 1);
uint8_t rio_data_len = opt_len - sizeof(route_option) + sizeof(ip6_addr_p_t);

ESP_LOGI(TAG, "Received RIO");
if (rio_data_len >= prefix_len_bytes)
Expand All @@ -98,13 +86,13 @@ static void ra_recv_handler(struct netif * netif, const uint8_t * icmp_payload,
esp_route_entry_t route;

memset(&prefix, 0, sizeof(prefix));
memcpy(&prefix.addr, rio_data, prefix_len_bytes);
memcpy(&prefix.addr, route_option.prefix.addr, prefix_len_bytes);
route.netif = netif;
route.gateway = *src_addr;
route.prefix_length = rio_header.prefix_length;
route.prefix_length = route_option.prefix_length;
route.prefix = prefix;
route.preference = preference;
route.lifetime_seconds = lwip_ntohl(rio_header.route_lifetime);
route.lifetime_seconds = lwip_ntohl(route_option.route_lifetime);
ESP_LOGI(TAG, "prefix %s lifetime %" PRIu32, ip6addr_ntoa(&prefix), route.lifetime_seconds);
if (esp_route_table_add_route_entry(&route) == NULL)
{
Expand Down
23 changes: 17 additions & 6 deletions src/platform/ESP32/route_hook/ESP32RouteTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "lwip/netif.h"
#include "lwip/timeouts.h"

#define MAX_RIO_TIMEOUT UINT32_MAX / (1000 * 4) // lwIP defined reasonable timeout value
#define LWIP_MAX_TIMEOUT_SECONDS LWIP_UINT32_MAX / (1000 * 4) // lwIP defined reasonable timeout value

static esp_route_entry_t * s_route_entries = NULL;

Expand Down Expand Up @@ -59,13 +59,22 @@ static esp_err_t remove_route_entry(esp_route_entry_t * route_entry)
static void route_timeout_handler(void * arg)
{
esp_route_entry_t * route = (esp_route_entry_t *) arg;

remove_route_entry(route);
if (route->lifetime_seconds <= LWIP_MAX_TIMEOUT_SECONDS)
{
remove_route_entry(route);
}
else
{
route->lifetime_seconds -= LWIP_MAX_TIMEOUT_SECONDS;
sys_timeout(route->lifetime_seconds <= LWIP_MAX_TIMEOUT_SECONDS ? route->lifetime_seconds * 1000
: LWIP_MAX_TIMEOUT_SECONDS * 1000,
route_timeout_handler, route);
}
}

esp_route_entry_t * esp_route_table_add_route_entry(const esp_route_entry_t * route_entry)
{
if (route_entry == NULL || (route_entry->lifetime_seconds > MAX_RIO_TIMEOUT && route_entry->lifetime_seconds != UINT32_MAX))
if (route_entry == NULL)
{
return NULL;
}
Expand Down Expand Up @@ -96,9 +105,11 @@ esp_route_entry_t * esp_route_table_add_route_entry(const esp_route_entry_t * ro
}
entry->preference = route_entry->preference;
entry->lifetime_seconds = route_entry->lifetime_seconds;
if (entry->lifetime_seconds != UINT32_MAX)
if (entry->lifetime_seconds != LWIP_UINT32_MAX)
{
sys_timeout(entry->lifetime_seconds * 1000, route_timeout_handler, entry);
sys_timeout(entry->lifetime_seconds <= LWIP_MAX_TIMEOUT_SECONDS ? entry->lifetime_seconds * 1000
: LWIP_MAX_TIMEOUT_SECONDS * 1000,
route_timeout_handler, entry);
}

return entry;
Expand Down

0 comments on commit 1043211

Please sign in to comment.