Skip to content

Commit

Permalink
Mleid bbr fix (ARMmbed#1697)
Browse files Browse the repository at this point in the history
route source added and route info autofree implemented.
  • Loading branch information
deepakvenugopal committed May 9, 2018
1 parent 1fc81fc commit 3569c8a
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 24 deletions.
56 changes: 47 additions & 9 deletions source/6LoWPAN/Thread/thread_bbr_api.c
Expand Up @@ -91,6 +91,14 @@ typedef struct {
ns_list_link_t link;
} thread_bbr_t;

/*
* Thread PBBR ML-EID map structure
*/
typedef struct {
uint8_t mleid_ptr[8];
uint32_t last_contact_time;
} thread_bbr_mleid_map_t;

/* Neighbor discovery options according to RFC6106 (rfc4861) */
#define RFC6106_RECURSIVE_DNS_SERVER_OPTION 25
#define RFC6106_DNS_SEARCH_LIST_OPTION 31
Expand Down Expand Up @@ -955,18 +963,18 @@ static int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 1
return 0;

}
int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info, const uint8_t *mleid_ptr) {
(void) mleid_ptr;

int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info)
{
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
if (!this || this->backbone_interface_id < 0) {
tr_err("bbr not ready");
return -1;
}
ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_HOST, info, 0, lifetime, 0);
// We are using route info field to store sequence number
if (!route) {
// Direct route to host allows ND proxying to work
tr_err("out of resources");
tr_err("bbr out of resources");
return -2;
}
// send NA
Expand All @@ -975,14 +983,44 @@ int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,
return 0;
}

int thread_bbr_nd_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_HOST ) {
//Not found
int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr)
{
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
if (!this || this->backbone_interface_id < 0) {
return -1;
}
//TODO get information to route to parameters eq mleid, timeout
thread_bbr_mleid_map_t *map = ns_dyn_mem_alloc(sizeof(thread_bbr_mleid_map_t));
if (!map) {
goto error;
}
memcpy(map->mleid_ptr, mleid_ptr, 8);
map->last_contact_time = protocol_core_monotonic_time;

// We are using route info field to store BBR MLEID map
ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0);
if (!route) {
// Direct route to host allows ND proxying to work
ns_dyn_mem_free(map);
goto error;
}
// Route info autofreed
route->info_autofree = true;
// send NA
thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr);

return 0;
error:
tr_err("out of resources");
return -2;
}

ipv6_route_info_t *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST ) {
//Not found
return NULL;
}
return route->info.info;
}

int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status)
Expand Down
19 changes: 14 additions & 5 deletions source/6LoWPAN/Thread/thread_bbr_api_internal.h
Expand Up @@ -36,6 +36,7 @@

#include "net_interface.h"
#ifdef HAVE_THREAD_ROUTER

/**
* \brief Initialize Thread Commissioner relay for BBR and Routers
*
Expand Down Expand Up @@ -98,23 +99,31 @@ void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
/**
* \brief Add new nd entry to bbr
*
* \param interface_id addr_data_ptr lifetime info
*/
int thread_bbr_nd_entry_add(int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info);

/**
* \brief Add new dua entry to bbr
*
* \param interface_id addr_data_ptr lifetime info mleid_ptr
*/
int thread_bbr_nd_entry_add(int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info, const uint8_t *mleid_ptr);
int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr);

/**
* \brief Find if bbr has nd entry
* \brief Find if bbr has dua entry
*
* \param interface_id addr_data_ptr
*/
int thread_bbr_nd_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr);
ipv6_route_info_t *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr);

#else
#define thread_bbr_proxy_state_update(caller_interface_id , handler_interface_id, status) (NULL)
#define thread_bbr_routing_enabled(cur) false
#define thread_bbr_network_data_update_notify(cur)
#define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info, mleid_ptr) (0)
#define thread_bbr_nd_entry_find(interface_id, addr_data_ptr) (0)
#define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info) (0)
#define thread_bbr_dua_entry_add(interface_id, addr_data_ptr, lifetime, mleid_ptr) (0)
#define thread_bbr_dua_entry_find(interface_id, addr_data_ptr) (NULL)
#endif //HAVE_THREAD_BORDER_ROUTER


Expand Down
1 change: 1 addition & 0 deletions source/6LoWPAN/Thread/thread_bootstrap.c
Expand Up @@ -2242,6 +2242,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
thread_leader_service_leader_data_free(cur->thread_info);
thread_bootstrap_all_nodes_multicast_unregister(cur);
thread_data_base_init(cur->thread_info, cur->id);
Expand Down
20 changes: 13 additions & 7 deletions source/6LoWPAN/Thread/thread_extension_bbr.c
Expand Up @@ -460,7 +460,7 @@ static int thread_pbbr_bb_qry_cb(int8_t service_id, uint8_t source_address[16],
return 0;
}
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, this->interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_HOST ) {
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST ) {
//address not in mesh
return 0;
}
Expand Down Expand Up @@ -493,7 +493,7 @@ static int thread_pbbr_dua_duplicate_address_detection(int8_t service_id, uint8_
}

ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, this->interface_id, NULL);
if (!route || route->prefix_len != 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_HOST) {
if (!route || route->prefix_len != 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST) {
// Not found
tr_debug("route not found");
return 0;
Expand All @@ -509,7 +509,7 @@ static int thread_pbbr_dua_duplicate_address_detection(int8_t service_id, uint8_
tr_debug("Remove from neigh Cache: %s", tr_ipv6(tr_ptr->target_eid));
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
}
ipv6_route_delete(route->prefix, route->prefix_len, this->interface_id, route->info.next_hop_addr, ROUTE_THREAD_PROXIED_HOST);
ipv6_route_delete(route->prefix, route->prefix_len, this->interface_id, route->info.next_hop_addr, ROUTE_THREAD_PROXIED_DUA_HOST);
}
return 0;

Expand All @@ -528,6 +528,8 @@ static int thread_pbbr_bb_ans_cb(int8_t service_id, uint8_t source_address[16],
uint8_t destination_address[16] = {0};
uint8_t *ml_eid_ptr;
uint32_t last_transaction_time;
uint8_t *network_name_ptr;
uint8_t network_name_len;
tr_info("Thread BBR BB_ANS.ntf receive");
thread_pbbr_t *this = thread_border_router_find_by_service(service_id);

Expand All @@ -544,10 +546,10 @@ static int thread_pbbr_bb_ans_cb(int8_t service_id, uint8_t source_address[16],
// Received from own address no need to process
return 0;
}

addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_TARGET_EID, &addr_data_ptr);
ml_eid_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_ML_EID, &ml_eid_ptr);
last_transaction_time_len = thread_meshcop_tlv_data_get_uint32(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_LAST_TRANSACTION_TIME, &last_transaction_time);
network_name_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_NETWORK_NAME, &network_name_ptr);

if ( addr_len < 16|| ml_eid_len < 8 || last_transaction_time_len < 4 ) {
tr_err("Invalid message");
Expand All @@ -560,6 +562,11 @@ static int thread_pbbr_bb_ans_cb(int8_t service_id, uint8_t source_address[16],

// If rloc16 is present then a/an is sent to the thread device with the rloc
if (thread_tmfcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_RLOC16, &rloc16) != 2) {
// this is Pro active ANS to inform that device has moved in new network
// This message was sent to multicast address
// in spec there is checks for Last transaction time, but we always know that this message has zero and we have lower
// TODO create function to process
// Delete route to DUA as it is moved
return 0;
}

Expand Down Expand Up @@ -781,11 +788,10 @@ static int thread_extension_bbr_dua_cb(int8_t service_id, uint8_t source_address

entry_keep_alive = false;
// TODO add ml_eid to structure saved in info pointer to detect duplicates
if (thread_bbr_nd_entry_find(this->interface_id, addr_data_ptr) == 0) {
if (thread_bbr_dua_entry_find(this->interface_id, addr_data_ptr) != NULL) {
entry_keep_alive = true;
}

if (thread_bbr_nd_entry_add(this->interface_id, addr_data_ptr, 0xFFFFFFFF, NULL, ml_eid_ptr) != 0) {
if (thread_bbr_dua_entry_add(this->interface_id, addr_data_ptr, 0xFFFFFFFF, ml_eid_ptr) != 0) {
bbr_status = THREAD_BBR_STATUS_RESOURCE_SHORTAGE;
goto send_response;
}
Expand Down
1 change: 1 addition & 0 deletions source/6LoWPAN/Thread/thread_host_bootstrap.c
Expand Up @@ -122,6 +122,7 @@ static void thread_merge_prepare(protocol_interface_info_entry_t *cur)
thread_clean_old_16_bit_address_based_addresses(cur);
mpl_clear_realm_scope_seeds(cur);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
thread_partition_data_purge(cur);
thread_network_data_clean(cur);
cur->nwk_mode = ARM_NWK_GP_IP_MODE;
Expand Down
3 changes: 1 addition & 2 deletions source/DHCPv6_Server/DHCPv6_Server_service.c
Expand Up @@ -106,15 +106,14 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
// coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return
DHCPV6_server_service_remove_GUA_from_neighcache(protocol_stack_interface_info_get_by_id(serverBase->interfaceId), nonTemporalAddress.requestedAddress);
}
if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix, NULL) == -1) {
if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix) == -1) {
// No nanostack BBR present we will put entry for application implemented BBR
ipv6_route_t *route = ipv6_route_add_with_info(dhcp_allocated_address->nonTemporalAddress, 128, serverBase->interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,serverBase->guaPrefix,0, nonTemporalAddress.validLifeTime, 0);
if (!route) {
address_allocated = false;
libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress);
}


}
}

Expand Down
8 changes: 7 additions & 1 deletion source/ipv6_stack/ipv6_routing_table.c
Expand Up @@ -1088,8 +1088,10 @@ static const char *route_src_names[] = {
[ROUTE_MPL] = "MPL",
[ROUTE_RIP] = "RIP",
[ROUTE_THREAD] = "Thread",
[ROUTE_THREAD_BORDER_ROUTER] = "Thread BR",
[ROUTE_THREAD_BORDER_ROUTER] = "Thread Network data",
[ROUTE_THREAD_PROXIED_HOST] = "Thread Proxy",
[ROUTE_THREAD_BBR] = "Thread BBR",
[ROUTE_THREAD_PROXIED_DUA_HOST] = "Thread DUA Proxy",
[ROUTE_REDIRECT] = "Redirect",
};

Expand Down Expand Up @@ -1199,6 +1201,9 @@ static void ipv6_route_entry_remove(ipv6_route_t *route)
#ifdef FEA_TRACE_SUPPORT
ipv6_route_print(route, trace_debug_print);
#endif
if (route->info_autofree) {
ns_dyn_mem_free(route->info.info);
}
if (protocol_core_buffers_in_event_queue > 0) {
// Alert any buffers in the queue already routed by this source
ipv6_route_source_invalidated[route->info.source] = true;
Expand Down Expand Up @@ -1548,6 +1553,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i
route->lifetime = lifetime;
route->metric = metric;
route->info.source = source;
route->info_autofree = false;
route->info.info = info;
route->info.source_id = source_id;
route->info.interface_id = interface_id;
Expand Down
3 changes: 3 additions & 0 deletions source/ipv6_stack/ipv6_routing_table.h
Expand Up @@ -82,6 +82,7 @@ typedef enum ipv6_route_src {
ROUTE_THREAD,
ROUTE_THREAD_BORDER_ROUTER,
ROUTE_THREAD_PROXIED_HOST,
ROUTE_THREAD_PROXIED_DUA_HOST,
ROUTE_THREAD_BBR,
ROUTE_REDIRECT, /* Only occurs in destination cache */
ROUTE_MAX,
Expand Down Expand Up @@ -215,13 +216,15 @@ void ipv6_destination_cache_timer(uint8_t ticks);
#ifdef HAVE_IPV6_ND
void ipv6_destination_redirect(const uint8_t *dest_addr, const uint8_t *sender_addr, const uint8_t *redirect_addr, int8_t interface_id, addrtype_t ll_type, const uint8_t *ll_address);
#endif

/* Combined Routing Table (RFC 4191) and Prefix List (RFC 4861) */
/* On-link prefixes have the on_link flag set and next_hop is unset */
typedef struct ipv6_route {
uint8_t prefix_len;
bool on_link: 1;
bool search_skip: 1;
bool probe: 1;
bool info_autofree:1;
uint8_t metric; // 0x40 = RFC 4191 pref high, 0x80 = default, 0xC0 = RFC 4191 pref low
ipv6_route_info_t info;
uint32_t lifetime; // (seconds); 0xFFFFFFFF means permanent
Expand Down

0 comments on commit 3569c8a

Please sign in to comment.