From 6dd01c679db4deb0a4a2c55832f3abe7b19bc51b Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Nov 2018 17:08:28 +0200 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 2535a6c..ccd30a3 ccd30a3 Merge branch 'release_internal' into release_external a9d7c1b Use BSD3 license for Thread files (#1898) 2b1d298 Link request retransmission delay changed (#1895) 06bd60a Remove ws resources from Nanostack ad8577d Remove new test files 4453f82 Merge branch 'release_internal' into release_external acbf1ac Add missing function macros (#1897) dae82f6 implemented wisun routing cost calculation f919fd1 Fix warning found by PVS-studio (#1891) 399f02f Additional time for distribution of dataset added (#1892) dde9e61 Reverted commit #1888 and fixed thread_bbr_dua_entry_find (#1893) 628fa27 Merge pull request #1885 from ARMmbed/IOTTHD-2752 cfea7b2 BBR route for added with preference. Route info updated. (#1888) dc404c4 Fix issues found by coverity (#1889) c81e59c Fixes for Wi-SUN bbr behaviour c941fe6 Adjust COAP callback return values (#1886) 7ef4775 Fix for multicast ping forwarding before adding MPL header(#1883) 766e305 FHSS: fixed missing us convert ef38363 FHSS: Traces in set parent 296e455 FHSS: Time unit defines added 724696c FHSS: changed traces to use timestamp from MAC 3deb08c FHSS: use divider function in ufsi calculation 74c7f37 FHSS: function to check if remaining slots is negative 654dd44 Merge pull request #1879 from ARMmbed/IOTTHD-2752 1ef5062 Address registration fix (#1882) 4c74f96 FHSS unit tests: Fixed tr51 tests 4cf7fdf FHSS: fixed tr51 channel table size a1d8b3d FHSS unit tests: Fixed tr51 tests 7e622b3 FHSS: Allocate TR51 channel tables when FHSS enabled e7a8d45 link-local multicast group registration (#1880) d4c95f2 Clear COAP retransmissions in partition change (#1872) bf36b91 Added generation of mac address if not set 990f4f1 Merge pull request #1877 from ARMmbed/dhcpv6_server_fix 6cbe7c5 Fix wrong link type to correct one DHCPV6_DUID_HARDWARE_EUI64_TYPE -> DHCPV6_DUID_HARDWARE_EUI48_TYPE fd6c1c8 Merge pull request #1876 from ARMmbed/thread_dhcpv6_server_trace_fix 3f83bd1 Added trace about prefered timeout for fix CI test 4331ea1 added support for multicast forwarding 7327652 bbr start called after seq number updated. (#1875) 98be8b2 Merge pull request #1868 from ARMmbed/IOTTHD-2863 23296c1 Merge pull request #1871 from ARMmbed/ws_config_handler 2188fd2 FHSS: Fixed negative remaining time in ufsi calculation 5b70440 announce reattach fix (#1873) fc11a7a Merge pull request #1869 from ARMmbed/dhcpv6_server_update a156355 WS PAN config message handler update 5e45c40 Thread dhcpv6 server update fe9ba3b Wi-sun border router enable global prefix with DHCP address allocation. 6d2af0b Dhcpv6 server update ab1260a added possibility to set next sequence number on PBBR. (#1867) 6679db4 WS bootstrap: traces to hop calculation 1cc4aff Merge pull request #1865 from ARMmbed/dhcpv6_client_ws_integration c2d0e14 Enable wi-sun dhcp relay service. 70e56b1 Wi-sun DHCP client support and RPL prefix learn Callback 3389b46 Merge pull request #1866 from ARMmbed/dhcp_relay_fix 9aa6a95 Address registration changes for MED and SED (#1863) 16359eb Fix compile problem 1472b02 Removed duplcate line. 67ea075 Wi-SUN node init API change b906861 Fixed DHCP relay bugs bcffa5f FHSS: Fixed setting parent synch e0276f6 FHSS: Configure in critical state d74d5ff Merge pull request #1862 from ARMmbed/dhcp_client_generic_update 999bbc3 Copied memory fix from PR #1858 6500fcf DHCPv6 client Generic API for all stacks. 2ec9b6e Fix memory leak if dhcp renew send fails (#1858) cbf99e7 Merge pull request #1861 from ARMmbed/ws_dhcp_support 08155b1 DHCPv6 service relay support 62812ab Libdhcpv6 Relay support 0eea30d delay Join_ent.ntf sending by 50 ms (#1860) dac1d99 Merge pull request #1857 from ARMmbed/mac_enhanced_ack b819fa8 Fix bbr start 514bb58 Merge pull request #1836 from ARMmbed/IOTTHD-2828 b074d0e Merge pull request #1845 from ARMmbed/IOTTHD-2839 20b5e57 Enhanced ACK tx fix caf53d1 Merge pull request #1846 from ARMmbed/IOTTHD-2824 9b5e1c9 added payload length for Max child timeout tlv (#1856) 3c1864b address registration tlv check only for MTDs (#1855) 942d8e7 Diagnostic TLV added (#1854) f2b38cf Check for mandatory Address registration tlv (#1853) ce8d5b7 Valdations for Child update response added: (#1852) e373545 Added Wi-SUN border router implementation 1f7c040 Merge pull request #1849 from ARMmbed/mac_asynch_fix 33afc9c FHSS: Added force synch boolean in parent set 5ddf5fa FHSS: prevent unicast on broadcast channel in tx handle f17e6cd FHSS: Check TX/RX slot in tx handle 3082407 FHSS: implemented divide function cebdaf4 Update stoip6 prototype to tests (#1851) 279c708 Trig a new back off period for pending TX if ACK tx is active f1e7f06 Fix broken unit test. 1d8e3d7 MAC Asynch Data request update cca9879 Merge pull request #1848 from ARMmbed/iotthd-2788 fe84585 Merge pull request #1847 from ARMmbed/eAck_mac_timer_fix c1c5926 Dynamic parent selection delay based on trickle i_min. 68bad00 MAC: Stop active MAC timer before sending enhanced Ack 4a204bd MAC: set new MAC channel only if RF returns success 9d79ca9 FHSS: Added minimum synch interval a35b702 FHSS: Increased min random of tx poll db6dc6b MAC: Fixed enhanced ack TX time 5836b50 Merge pull request #1844 from ARMmbed/fix_ack_tx_fail_handling d9e2ea6 MAC: Fixed handling of the failed Ack transmission f43e285 Merge pull request #1843 from ARMmbed/address_reg_fix 0b4aa78 Parent Broadcast synch fix and TR51CF slot define fix d6b4111 fix for valgrind reported error. (#1842) 8160d86 Added support for wisun multicast 1f4625e Call ws_secondary_parent_update inside primary set for reduce code size. 35b39f4 Merge pull request #1840 from ARMmbed/address_register cfb2426 bbr memory leak during keep alive fixed. (#1839) a8aafe4 Stub update c244ad8 Enable 6-bit path control for give better compare between parent's. eac63d2 FHSS and address registration update c14343a valgrind and coverity reported errors fixed. (#1838) 9b14b83 additional thread prefixes in network data (#1833) fb07086 Merge pull request #1837 from ARMmbed/llc_parent_synch bf55180 Fixed failing unit test. 5e7a493 Update brodcast synch when here data from primary parent. 9e22831 Merge pull request #1834 from ARMmbed/enable_bt_ie_ulad 02af1a8 Thread extension commission updates (#1835) dd082a0 Fix ws_llc_data_send unit test validation with new bt-ie lement length. ae6554d Revert "Disable wi-sun features temporary". 927c329 Thread extension commissioning updates (#1828) 160ef0a Merge pull request #1829 from ARMmbed/IOTTHD-2821 576f2bf FHSS unit tests: Fixed channel function variable name f33d163 WS: Removed backward compatibility defines 9c88a7f WS: fixed overwriting fixed channel with random efd77f1 Clean thread_routing test stub (#1832) 2b8a011 Remove recursion from MAC layer #2 (#1830) 2f5a2ce Remove recursion from MAC layer (#1826) 06e3243 propagation of reserved bit in network data implemented. (#1827) e7fa605 Merge pull request #1823 from ARMmbed/IOTTHD-2782 89001d1 Merge pull request #1825 from ARMmbed/IOTTHD-2816 9c78a95 MAC: Static CSMA period when using FHSS 3d1c8a0 FHSS: Stop unicast schedule when fixed channel or no dwell interval d6086d0 Merge pull request #1818 from ARMmbed/nud_statemachine a2b8491 Wi-sun Border router and NUD process updates 60e1545 Disable wi-sun features temporary 7e3c16c Wi-sun LLC Data request IE update a27076f Fixed Pan informatio IE read bug bb1aeac Fixed Fragmentation init failure problem. 02fce65 Parent select and pan config handler update a2ef56a wi-sun update: ca9fd4f Disabled Wi-sun border router version number update. 231daf7 Wi-sun NUD State Machine update e7d551c Commissioner fixes (#1824) 62ffba3 keepalive for on mesh commissioner sent to leader aloc. (#1821) f846823 Coverity reported error fixes: (#1822) 708e8d3 Merge pull request #1820 from ARMmbed/IOTTHD-2735 b2e7efc FHSS WS: Get MAC channel from FHSS when starting RF interface fe2b448 Merge pull request #1819 from ARMmbed/fixed_bad_channel 7c13c3c commissioner updates. (#1812) 4c7d4f2 FHSS: Fixed bad channel check with fixed channel configuration 40b2eec Set global address flag to follow address state b46eacc updated channel plan settings 4a1d595 Merge pull request #1815 from ARMmbed/iotthd-2745 5a37354 Primary Parent Update Hook to Wi-sun for synch broadcast schedule. 98b0e23 Fix memory leak when advertising route (#1814) b5d276d refactored trickkle running checks 61ff793 Merge pull request #1807 from ARMmbed/rpl_parent_candidate a7a1ab3 Updated to NUD probability from 10% to 1%. 89b8eeb Merge pull request #1810 from ARMmbed/IOTTHD-2734 b99d497 Modify NUD operation propability. 4bb8b54 Wi-sun Probe update 2183869 FHSS Ack tx done fix fb4309d Mac Asynch and Ack validation update 2695601 FHSS parent synch fix. b50abb0 RPL, FHSS and Wisun Update a40e012 Check MAC status when purging indirect queue (#1811) b68f394 WS bootstrap: Updated channel function set apis 42b2e7c Unit tests: channel function tests updated b6236f9 WS bootstrap: Separated unicast and broadcast channel functions 6fe5ea5 Fix Thread DHCPv6-client memory leak (#1808) bbc0d77 WS bootstrap: renamed channel_function to uc_channel_function 7dbad5e Parent sends full network data in response to data request (#1806) cbe45b4 Merge pull request #1805 from ARMmbed/IOTTHD-2733 8956418 FHSS unit tests: Fixed broadcast handler tests e7aa893 FHSS: Define to make outdated application work 9fd804b FHSS: Separated broadcast schedule channel function 327c310 Merge pull request #1804 from ARMmbed/fhss_ws_cs e7ae8ce FHSS unit tests: Fixed missing platform stub 9cbd2b7 FHSS: added critical states 51f8328 Merge pull request #1803 from ARMmbed/IOTTHD-2736 537b60d FHSS unit tests: Fixed missing stub 43bc93d FHSS: Poll TX queue on every TX slot c6e2457 Merge pull request #1802 from ARMmbed/asynch_channel_plan_filter c851b07 Wi-sun bootstrap verify channel plan component against own configured ones. 1bdc4e6 Merge pull request #1800 from ARMmbed/IOTTHD-2504 6ed53e6 FHSS unit tests: Fixed timestamp stub return value f43b3af FHSS unit tests: Fixed missing timestamp read function f27a29c Merge pull request #1801 from ARMmbed/rf_driver_start_fix c2bc561 Add MAC TX active FLAG to active before write function return value. 08d3e12 Merge pull request #1799 from ARMmbed/several_bug_fixs 65d96c4 FHSS: Fixed calculating UFSI eedd746 FHSS: Compensate delay from platform driver when starting timeout 7d537ea FHSS: Read timestamp from MAC/PHY instead of using FHSS own timestamp 0206fc8 FHSS: Added callbacks for debugging purposes 63d8a41 Added Packet rebuild for extented driver after Driver Busy error. 607da3e Bug fixes: f39312b REED and FED links removed (#1796) b162d7b added support for modifying fhss configuration after initial startup 88e239d Merge pull request #1798 from ARMmbed/enhanced_ack_send 11fb5fa MAC Enhanced ACK TX fix: 08d5584 Merge pull request #1794 from ARMmbed/rpl_address_learn 5bbc86f fed advertisement fix (#1795) a48254c Wi-sun Address registration update: 5db8037 RPL Local Repair, SLAAC prefix update and Dodag Prefix proces update: b3139c8 Adjust Thread BBR neighbor/destination cache size (#1793) 21deb75 Registered neighbour cache entries are not reregistered. (#1792) d93b9e4 Added empty function for ws public api 1a09af7 Updated management api f52289f Merge pull request #1790 from ARMmbed/ws_llc_neigh_update_fix b954e56 WS neighbor refresh update 0b2736f Thread address registration improvements (#1779) 931a17d Merge pull request #1789 from ARMmbed/iotthd-2693 90c6a8a Removed unnecessary Decrypt Fail debug trace. b425f4b Adapatation neighbor validation update: 06255ee Merge pull request #1787 from ARMmbed/iottthd-2692 e98c182 MAC report unknow neighbour COMM status at Packet TX process not detetct destination. be0aa9c Merge pull request #1786 from ARMmbed/iotthd-2695 42122b7 Added support to report Driver if FHSS return unknow neighbor error. eb5ba30 Fixed Driver Tx done callback missing error return values. 1a9acbd Wi-SUN fhss refactor 0ca78d6 Merge pull request #1784 from ARMmbed/iotthd-2533 9b37c24 Fixed Unicast and Broadcast MAC packet request types. 0ddff57 Fix PAN-id read bug when received 2015 frame version's. git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: ccd30a3b7a718710090606b6d6add8dfd1c86159 --- nanostack/dhcp_service_api.h | 13 +- nanostack/fhss_api.h | 11 +- nanostack/fhss_config.h | 13 +- nanostack/fhss_ws_extension.h | 5 +- nanostack/mac_api.h | 3 +- nanostack/net_fhss.h | 3 +- nanostack/thread_bbr_api.h | 15 + nanostack/thread_commissioning_api.h | 14 + nanostack/thread_diagcop_lib.h | 3 +- .../Bootstraps/Generic/protocol_6lowpan.c | 15 +- .../Generic/protocol_6lowpan_bootstrap.c | 6 +- source/6LoWPAN/MAC/mpx_api.h | 3 +- source/6LoWPAN/Thread/thread_bbr_api.c | 65 ++-- .../6LoWPAN/Thread/thread_bbr_api_internal.h | 8 - source/6LoWPAN/Thread/thread_bootstrap.c | 84 +++-- source/6LoWPAN/Thread/thread_bootstrap.h | 4 +- .../6LoWPAN/Thread/thread_border_router_api.c | 38 ++- .../thread_border_router_api_internal.h | 9 + .../6LoWPAN/Thread/thread_commissioning_api.c | 276 +++++++++++++--- source/6LoWPAN/Thread/thread_common.c | 184 ++++++++++- source/6LoWPAN/Thread/thread_common.h | 10 +- source/6LoWPAN/Thread/thread_config.h | 11 + source/6LoWPAN/Thread/thread_constants.h | 1 + source/6LoWPAN/Thread/thread_dhcpv6_client.h | 98 ------ source/6LoWPAN/Thread/thread_dhcpv6_server.c | 114 +++++++ source/6LoWPAN/Thread/thread_dhcpv6_server.h | 39 +++ source/6LoWPAN/Thread/thread_diagnostic.c | 19 +- source/6LoWPAN/Thread/thread_extension.h | 44 ++- source/6LoWPAN/Thread/thread_extension_bbr.h | 4 + .../Thread/thread_extension_bootstrap.h | 2 + source/6LoWPAN/Thread/thread_host_bootstrap.c | 25 +- .../Thread/thread_joiner_application.c | 5 +- source/6LoWPAN/Thread/thread_leader_service.c | 13 +- source/6LoWPAN/Thread/thread_management_api.c | 1 - .../6LoWPAN/Thread/thread_management_client.c | 57 ++-- .../6LoWPAN/Thread/thread_management_client.h | 21 +- source/6LoWPAN/Thread/thread_management_if.c | 23 +- .../6LoWPAN/Thread/thread_management_server.c | 42 ++- .../6LoWPAN/Thread/thread_management_server.h | 7 + .../Thread/thread_mle_message_handler.c | 61 ++++ source/6LoWPAN/Thread/thread_nd.c | 5 +- .../Thread/thread_network_data_storage.c | 39 ++- .../Thread/thread_network_data_storage.h | 4 +- source/6LoWPAN/Thread/thread_nvm_store.c | 12 +- .../6LoWPAN/Thread/thread_resolution_client.c | 8 +- .../6LoWPAN/Thread/thread_resolution_server.c | 6 +- .../6LoWPAN/Thread/thread_router_bootstrap.c | 93 +++++- .../6LoWPAN/Thread/thread_router_bootstrap.h | 7 +- source/6LoWPAN/adaptation_interface.c | 94 +++--- source/6LoWPAN/ws/ws_bootstrap.h | 19 +- source/6LoWPAN/ws/ws_common.h | 33 +- source/6LoWPAN/ws/ws_common_defines.h | 26 +- source/6LoWPAN/ws/ws_neighbor_class.h | 5 + source/Common_Protocols/ipv6.c | 22 +- source/DHCPv6_Server/DHCPv6_Server_service.c | 197 +++--------- source/DHCPv6_Server/DHCPv6_server_service.h | 26 +- source/DHCPv6_client/dhcpv6_client_api.h | 88 ++++++ .../dhcpv6_client_service.c} | 111 +++---- source/MAC/IEEE802_15_4/mac_defines.h | 14 +- source/MAC/IEEE802_15_4/mac_fhss_callbacks.c | 13 +- source/MAC/IEEE802_15_4/mac_fhss_callbacks.h | 1 + .../mac_header_helper_functions.c | 49 ++- .../mac_header_helper_functions.h | 4 +- source/MAC/IEEE802_15_4/mac_indirect_data.c | 2 +- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 238 ++++++++------ source/MAC/IEEE802_15_4/mac_mcps_sap.h | 22 +- source/MAC/IEEE802_15_4/mac_mlme.c | 24 +- source/MAC/IEEE802_15_4/mac_mlme.h | 2 +- source/MAC/IEEE802_15_4/mac_pd_sap.c | 140 ++++++--- source/MAC/IEEE802_15_4/mac_pd_sap.h | 2 + source/MAC/IEEE802_15_4/sw_mac.c | 27 +- source/MPL/mpl.c | 58 ++-- source/RPL/rpl_control.c | 43 +-- source/RPL/rpl_control.h | 9 +- source/RPL/rpl_downward.c | 4 +- source/RPL/rpl_structures.h | 1 + source/RPL/rpl_upward.c | 43 ++- source/RPL/rpl_upward.h | 2 +- source/Service_Libs/etx/etx.c | 3 + source/Service_Libs/etx/etx.h | 1 + source/Service_Libs/fhss/channel_functions.h | 23 +- source/Service_Libs/fhss/channel_list.c | 13 + source/Service_Libs/fhss/channel_list.h | 10 + source/Service_Libs/fhss/fhss.c | 23 +- source/Service_Libs/fhss/fhss_common.c | 21 +- source/Service_Libs/fhss/fhss_common.h | 2 + .../fhss/fhss_configuration_interface.c | 4 +- source/Service_Libs/fhss/fhss_ws.h | 10 +- .../fhss/fhss_ws_empty_functions.c | 2 +- .../mac_neighbor_table/mac_neighbor_table.c | 12 + .../mac_neighbor_table/mac_neighbor_table.h | 2 + source/Service_Libs/mdns/ns_fnet_port.c | 3 +- source/ipv6_stack/ipv6_routing_table.c | 1 + source/ipv6_stack/protocol_ipv6.c | 14 +- source/libDHCPv6/dhcp_service_api.c | 296 +++++++++++++++++- source/libDHCPv6/libDHCPv6.c | 39 +++ source/libDHCPv6/libDHCPv6.h | 19 +- source/libDHCPv6/libDHCPv6_server.c | 16 +- source/libDHCPv6/libDHCPv6_server.h | 19 +- source/nsconfig.h | 6 + sources.mk | 3 +- 101 files changed, 2460 insertions(+), 944 deletions(-) delete mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_client.h create mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_server.c create mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_server.h create mode 100644 source/DHCPv6_client/dhcpv6_client_api.h rename source/{6LoWPAN/Thread/thread_dhcpv6_client.c => DHCPv6_client/dhcpv6_client_service.c} (74%) diff --git a/nanostack/dhcp_service_api.h b/nanostack/dhcp_service_api.h index d8b9b5b1168..3efae996b45 100644 --- a/nanostack/dhcp_service_api.h +++ b/nanostack/dhcp_service_api.h @@ -69,7 +69,8 @@ typedef enum dhcp_instance_type { DHCP_INSTANCE_CLIENT, - DHCP_INSTANCE_SERVER + DHCP_INSTANCE_SERVER, + DHCP_INTANCE_RELAY_AGENT } dhcp_instance_type_e; /** @@ -124,6 +125,16 @@ typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb); +/** +* \brief Enable DHCPv6 Relay Agent to server. +* +* +* \param instance The instance ID of the registered server. +* \param server_address global server IPv6 address +*/ +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address); + + /** * \brief Deletes a server instance. * diff --git a/nanostack/fhss_api.h b/nanostack/fhss_api.h index 16820aeaaee..0f0774cd024 100644 --- a/nanostack/fhss_api.h +++ b/nanostack/fhss_api.h @@ -132,8 +132,9 @@ typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_ * @param api FHSS instance. * @param fhss_state FHSS state (FHSS states are defined by FHSS api). * @param pan_id PAN id of the network FHSS synchronizes with. + * @return -1 when failed, otherwise current MAC channel. */ -typedef void fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); +typedef int16_t fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); /** * @brief Read timestamp. @@ -215,6 +216,13 @@ typedef int mac_read_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_addres */ typedef uint32_t mac_read_datarate(const fhss_api_t *fhss_api); +/** + * @brief Read 32-bit timestamp. + * @param fhss_api FHSS instance. + * @return Timestamp. + */ +typedef uint32_t mac_read_timestamp(const fhss_api_t *fhss_api); + /** * @brief Change channel. * @param fhss_api FHSS instance. @@ -287,6 +295,7 @@ struct fhss_callback { mac_read_tx_queue_size *read_tx_queue_size; /**< Read MAC TX queue size. */ mac_read_mac_address *read_mac_address; /**< Read MAC address. */ mac_read_datarate *read_datarate; /**< Read PHY datarate. */ + mac_read_timestamp *read_timestamp; /**< Read timestamp. */ mac_change_channel *change_channel; /**< Change channel. */ mac_send_fhss_frame *send_fhss_frame; /**< Send FHSS frame. */ mac_synch_lost_notification *synch_lost_notification; /**< Send notification when FHSS synchronization is lost. */ diff --git a/nanostack/fhss_config.h b/nanostack/fhss_config.h index 5695367659f..6a1cf3507ab 100644 --- a/nanostack/fhss_config.h +++ b/nanostack/fhss_config.h @@ -96,8 +96,11 @@ typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uin */ typedef struct fhss_ws_configuration { - /** WS channel function. */ - fhss_ws_channel_functions ws_channel_function; + /** WS unicast channel function. */ + fhss_ws_channel_functions ws_uc_channel_function; + + /** WS broadcast channel function. */ + fhss_ws_channel_functions ws_bc_channel_function; /** Broadcast schedule identifier. */ uint16_t bsi; @@ -111,6 +114,12 @@ typedef struct fhss_ws_configuration /** Broadcast dwell interval. Range: 15-250 milliseconds. */ uint8_t fhss_bc_dwell_interval; + /** Unicast fixed channel */ + uint8_t unicast_fixed_channel; + + /** Broadcast fixed channel */ + uint8_t broadcast_fixed_channel; + /** Channel mask. */ uint32_t channel_mask[8]; diff --git a/nanostack/fhss_ws_extension.h b/nanostack/fhss_ws_extension.h index c440451204d..44d86d1f6d9 100644 --- a/nanostack/fhss_ws_extension.h +++ b/nanostack/fhss_ws_extension.h @@ -37,6 +37,7 @@ typedef struct unicast_timing_info { unsigned unicast_channel_function:3; /**< Unicast schedule channel function */ uint8_t unicast_dwell_interval; /**< Unicast dwell interval */ uint16_t unicast_number_of_channels; /**< Unicast number of channels */ + uint16_t fixed_channel; /**< Unicast fixed channel*/ uint_fast24_t ufsi; /**< Unicast fractional sequence interval */ uint32_t utt_rx_timestamp; /**< UTT-IE reception timestamp */ } unicast_timing_info_t; @@ -47,6 +48,7 @@ typedef struct unicast_timing_info { typedef struct broadcast_timing_info { unsigned broadcast_channel_function:3; /**< Broadcast schedule channel function */ uint8_t broadcast_dwell_interval; /**< Broadcast dwell interval */ + uint16_t fixed_channel; /**< Broadcast fixed channel*/ uint16_t broadcast_slot; /**< Broadcast slot number */ uint16_t broadcast_schedule_id; /**< Broadcast schedule identifier */ uint_fast24_t broadcast_interval_offset; /**< Broadcast interval offset */ @@ -78,9 +80,10 @@ typedef fhss_ws_neighbor_timing_info_t *fhss_get_neighbor_info(const fhss_api_t * @param fhss_api FHSS instance. * @param eui64 EUI-64 address of parent. * @param bc_timing_info Pointer to parent broadcast timing/hopping schedule info. + * @param force_synch If false, synchronization is done only if minimum (internal) synchronization interval is exceed. * @return 0 on success, -1 on fail. */ -extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); +extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch); /** * @brief Remove parent which was set by ns_fhss_ws_set_parent function. diff --git a/nanostack/mac_api.h b/nanostack/mac_api.h index b889ee25a73..33c954bf980 100644 --- a/nanostack/mac_api.h +++ b/nanostack/mac_api.h @@ -137,8 +137,9 @@ typedef void mcps_data_request_ext(const mac_api_t* api, const mcps_data_req_t * * @brief mcps_purge_request MCPS_PURGE request call * @param api API to handle the request * @param data MCPS-PURGE.request specific values + * @return 0 in case of success, non-zero otherwise */ -typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data); +typedef uint8_t mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data); //Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it) diff --git a/nanostack/net_fhss.h b/nanostack/net_fhss.h index 2223a5af3bf..b201420e14f 100644 --- a/nanostack/net_fhss.h +++ b/nanostack/net_fhss.h @@ -39,10 +39,9 @@ extern "C" { extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics); /** - * @brief TODO: description. + * @brief Creates FHSS WS API instance which will be registered to software MAC. * @param fhss_configuration Basic FHSS configuration. * @param fhss_timer FHSS platform timer interface and configuration. - * @param fhss_statistics FHSS statistics storage. * @return New FHSS instance if successful, NULL otherwise. */ extern fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); diff --git a/nanostack/thread_bbr_api.h b/nanostack/thread_bbr_api.h index 91e697baad5..55a8e9f97da 100644 --- a/nanostack/thread_bbr_api.h +++ b/nanostack/thread_bbr_api.h @@ -75,6 +75,7 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id); * */ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); + /** * Set prefix to be used as combining multiple thread networks on backbone. * @@ -89,6 +90,20 @@ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t tim */ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); +/** + * Set sequence number to be used by bbr + * + * update sequence number value + * + * \param interface_id interface ID of the Thread network. + * \param sequence_number value that needs to be set on bbr + * + * \return 0 on success + * \return <0 in case of errors + * + */ +int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number); + /** * Set the Thread validation interface destination address. * diff --git a/nanostack/thread_commissioning_api.h b/nanostack/thread_commissioning_api.h index 85923328c8e..6495786534b 100644 --- a/nanostack/thread_commissioning_api.h +++ b/nanostack/thread_commissioning_api.h @@ -189,8 +189,10 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh typedef struct thread_commissioning_link_configuration { uint8_t name[16]; /**< Name of the Thread network. utf8 string nul terminated if shorter than 16. */ + uint8_t destination_address[16]; /**index); // If primary parent has changed clears priority from previous parent if (entry->link_role != PRIORITY_PARENT_NEIGHBOUR) { + new_primary = true; protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST); } entry->link_role = PRIORITY_PARENT_NEIGHBOUR; @@ -501,6 +504,10 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t if (etx_entry) { protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4); } + + if (new_primary) { + ws_primary_parent_update(cur, entry); + } return 1; } else { return 0; @@ -519,9 +526,11 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type); if (entry) { + bool new_secondary = false; etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index); // If secondary parent has changed clears priority from previous parent if (entry->link_role != SECONDARY_PARENT_NEIGHBOUR) { + new_secondary = true; protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND); } entry->link_role = SECONDARY_PARENT_NEIGHBOUR; @@ -529,6 +538,9 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr if (etx_entry) { protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4); } + if (new_secondary) { + ws_secondary_parent_update(cur); + } return 1; } else { return 0; @@ -557,7 +569,6 @@ void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_ } } -#endif #endif #endif diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index e8f4fe95771..4e8cec5ba1b 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1786,7 +1786,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode */ if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) { //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } #endif cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED; @@ -2073,6 +2073,8 @@ static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *han tr_error("RPL Local repair fail-->interface to idle"); nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur); break; + default: + break; } } @@ -2179,7 +2181,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t * // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } // Send unicast DIS to coordinator nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); diff --git a/source/6LoWPAN/MAC/mpx_api.h b/source/6LoWPAN/MAC/mpx_api.h index a61e3e00537..739b07b3307 100644 --- a/source/6LoWPAN/MAC/mpx_api.h +++ b/source/6LoWPAN/MAC/mpx_api.h @@ -39,9 +39,10 @@ typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s * @param api API to handle the request * @param purge MCPS-purge request * @param user_id MPX user ID + * @return 0 if purge requst was OK, non-zero otherwise * */ -typedef void mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); +typedef uint8_t mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); /** * @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request diff --git a/source/6LoWPAN/Thread/thread_bbr_api.c b/source/6LoWPAN/Thread/thread_bbr_api.c index 6c0b09a2c0f..9064b890d29 100644 --- a/source/6LoWPAN/Thread/thread_bbr_api.c +++ b/source/6LoWPAN/Thread/thread_bbr_api.c @@ -40,12 +40,16 @@ #include "common_functions.h" #include "thread_border_router_api.h" #include "thread_bbr_api.h" +#include "net_ipv6_api.h" +#include "NWK_INTERFACE/Include/protocol.h" #include "Common_Protocols/ipv6_constants.h" #include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_dhcpv6_server.h" #include "thread_management_if.h" #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_common.h" +#include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_extension.h" #include "6LoWPAN/Thread/thread_extension_bbr.h" @@ -96,7 +100,6 @@ typedef struct { #define RFC6106_DNS_SEARCH_LIST_OPTION 31 static NS_LIST_DEFINE(bbr_instance_list, thread_bbr_t, link); - static thread_bbr_t *thread_bbr_find_by_interface(int8_t interface_id) { thread_bbr_t *this = NULL; @@ -579,7 +582,7 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], // delete old prefix memset(this->bbr_prefix,0,8); // create new prefix - if (DHCPv6_server_service_init(this->interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + if (thread_dhcp6_server_init(this->interface_id, prefix, eui64, THREAD_MIN_PREFIX_LIFETIME) != 0) { tr_warn("DHCP server alloc fail"); // set 20 seconds delay before next process this->br_delay_timer = 20; @@ -587,8 +590,6 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], } memcpy(this->bbr_prefix,prefix,8); - DHCPv6_server_service_set_address_validlifetime(this->interface_id, this->bbr_prefix, THREAD_MIN_PREFIX_LIFETIME); - br_info.P_default_route = true; br_info.P_dhcp = true; br_info.P_on_mesh = true; @@ -724,7 +725,7 @@ static bool thread_bbr_activated(thread_bbr_t *this, uint32_t seconds) return true; } - if (cur->thread_info->routerIdReqCoapID) { + if (cur->thread_info->routerIdRequested) { // Router id reguest pending we need to wait for response return false; } @@ -978,25 +979,31 @@ int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_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) { thread_bbr_t *this = thread_bbr_find_by_interface(interface_id); + thread_pbbr_dua_info_t *map; if (!this || this->backbone_interface_id < 0) { return -1; } - thread_pbbr_dua_info_t *map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t)); - if (!map) { - goto error; + ipv6_route_t *route = ipv6_route_lookup_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, NULL, 0); + if (!route){ + map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t)); + if (!map) { + goto error; + } + // We are using route info field to store BBR MLEID map + 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; } + map = route->info.info; memcpy(map->mleid_ptr, mleid_ptr, 8); map->last_contact_time = protocol_core_monotonic_time; + route->info.info = map; - // 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); @@ -1006,15 +1013,6 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, return -2; } -struct ipv6_route *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; -} - int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id); @@ -1099,7 +1097,11 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id) // By default multicast forwarding is not enabled as it causes multicast loops multicast_fwd_set_forwarding(this->interface_id, false); + // Adjust BBR neighbor and destination cache size + arm_nwk_ipv6_max_cache_entries(THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE); + thread_extension_bbr_init(interface_id,backbone_interface_id); + return 0; #else return -1; @@ -1131,6 +1133,17 @@ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix) #endif // HAVE_THREAD_BORDER_ROUTER } +int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number) +{ + (void) interface_id; + (void) sequence_number; +#ifdef HAVE_THREAD_BORDER_ROUTER + return thread_extension_bbr_sequence_number_set(interface_id, sequence_number); +#else + return -1; +#endif // HAVE_THREAD_BORDER_ROUTER +} + int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port) { (void) interface_id; diff --git a/source/6LoWPAN/Thread/thread_bbr_api_internal.h b/source/6LoWPAN/Thread/thread_bbr_api_internal.h index dd05ca7525b..9e434990331 100644 --- a/source/6LoWPAN/Thread/thread_bbr_api_internal.h +++ b/source/6LoWPAN/Thread/thread_bbr_api_internal.h @@ -67,7 +67,6 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t tics); */ int thread_bbr_commissioner_proxy_service_update(int8_t interface_id); - #else #define thread_bbr_init(interface_id, external_commisssioner_port) #define thread_bbr_delete(interface_id) @@ -118,12 +117,6 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, */ int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16]); -/** - * \brief Find if bbr has dua entry - * - * \param interface_id addr_data_ptr - */ -struct ipv6_route *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) @@ -131,7 +124,6 @@ struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t #define thread_bbr_network_data_update_notify(cur) #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) #define thread_bbr_na_send(interface_id, target) (0) #endif //HAVE_THREAD_BORDER_ROUTER diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 0e26b643edf..f16ece331a6 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -86,7 +86,7 @@ #include "MPL/mpl.h" #include "MLE/mle.h" #include "MLE/mle_tlv.h" -#include "thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "thread_config.h" #include "thread_meshcop_lib.h" #include "multicast_api.h" @@ -136,8 +136,6 @@ static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void * static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { - - // Sleepy host protocol_interface_info_entry_t *cur_interface = user_data; if (thread_am_router(cur_interface)) { @@ -676,8 +674,6 @@ static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t * // Generate new ML64 address thread_generate_ml64_address(cur); - // Generate new domain address - thread_extension_address_generate(cur); // Register multicast addresses thread_bootstrap_all_nodes_multicast_register(cur); @@ -698,8 +694,6 @@ int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, l //Define Default Contexts lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true); - thread_extension_activate(cur); - thread_extension_bbr_route_update(cur); blacklist_clear(); @@ -896,7 +890,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur) { thread_discovery_reset(cur->id); thread_routing_set_mesh_callbacks(cur); - thread_dhcp_client_init(cur->id); + dhcp_client_init(cur->id); thread_management_client_init(cur->id); thread_address_registration_init(); cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT; @@ -1069,9 +1063,7 @@ void thread_tasklet(arm_event_s *event) case THREAD_CHILD_UPDATE: tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); - if (thread_info(cur)->thread_endnode_parent) { - thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); - } + thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); break; case THREAD_ANNOUNCE_ACTIVE: { tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); @@ -1178,6 +1170,10 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) thread_leader_service_generate_network_data(cur); } + if (thread_addresses_needs_to_be_registered(cur)) { + thread_info(cur)->childUpdateReqTimer = 1; + } + cur->bootsrap_state_machine_cnt = 0; mac_data_poll_protocol_poll_mode_decrement(cur); } @@ -1194,6 +1190,31 @@ void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur) } } +void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur) +{ + mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; + + if (thread_i_am_router(cur)) { + return; + } + + if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || + thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { + return; + } + + if (!thread_info(cur)->thread_endnode_parent) { + return; + } + ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { + // do not remove parent entry + if (memcmp(cur_entry->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) != 0) { + tr_debug("Free short addr: %x", cur_entry->mac16); + mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry); + } + } +} + void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur) { uint8_t static_address[16]; @@ -1612,7 +1633,6 @@ void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur) if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE || cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { thread_meshlocal_route_set(cur); - thread_extension_route_set(cur); // FEDs and routers (REEDs) perform their own address resolution thread_nd_service_activate(cur->id); } else { @@ -1627,7 +1647,7 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; cur->bootsrap_state_machine_cnt = 10; - cur->thread_info->routerIdReqCoapID = 0; + cur->thread_info->routerIdRequested = false; cur->thread_info->networkDataRequested = false; clear_power_state(ICMP_ACTIVE); @@ -1644,8 +1664,6 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) thread_generate_ml16_address(cur); //GENERATE ML-EID64 thread_generate_ml64_address(cur); - // Generate new domain address - thread_extension_address_generate(cur); thread_bootstrap_routing_activate(cur); thread_bootstrap_network_data_update(cur); // After successful attach if there is announcement info present, send announcement back to previous channel @@ -1823,8 +1841,7 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[ tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); if (prefix && dhcp_addr) { tr_debug("Delete Current Server data"); - thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix); - //TODO shuold we try again or select new Server + dhcp_client_global_address_delete(interface, dhcp_addr, prefix); } } } @@ -1964,6 +1981,10 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_ config_ptr[n].rfChannel = cur_class->channel; memcpy(config_ptr[n].name, cur_class->network_name, 16); memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8); + memcpy(config_ptr[n].destination_address, ADDR_LINK_LOCAL_PREFIX, 8); + memcpy(&config_ptr[n].destination_address[8], cur_class->extented_mac, 8); + config_ptr[n].destination_address[8] ^= 2; + config_ptr[n].destination_port = cur_class->commissioner_port; n++; } @@ -2023,7 +2044,7 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_ interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; - interface->thread_info->routerIdReqCoapID = 0; + interface->thread_info->routerIdRequested = false; interface->thread_info->networkDataRequested = false; interface->bootsrap_state_machine_cnt = 10; @@ -2128,6 +2149,12 @@ static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entr uint16_t my_short_address; uint8_t parent_mac64[8]; + // link sync is allowed only once in bootstrap start and we might get here in other cases also + if (!cur->thread_info->link_sync_allowed) { + return false; + } + cur->thread_info->link_sync_allowed = false; + int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address); if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err); @@ -2136,7 +2163,7 @@ static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entr link_info_err = thread_nvm_store_link_info_clear(); if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { tr_warning("thread_nvm_store_link_info_clear returned %d", link_info_err); - } + } if (thread_is_router_addr(my_short_address)) { thread_info(cur)->routerShortAddress = my_short_address; thread_dynamic_storage_build_mle_table(cur->id); @@ -2278,7 +2305,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur) 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); - thread_dhcp_client_delete(cur->id); + dhcp_client_delete(cur->id); thread_nd_service_delete(cur->id); thread_child_id_request_entry_clean(cur); thread_registered_mcast_addr_entry_clean(cur); @@ -2356,6 +2383,7 @@ static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cu if (cid == 16) { return -1; } + context.cid = cid; context.compression = true; context.stableData = stableData; @@ -2499,6 +2527,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1); genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1); genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1); + genericService.P_res1 = ((flags >> THREAD_P_ND_RES_BIT_MOVE) & 1); if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) { if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) { if (!genericService.P_slaac) { @@ -2525,7 +2554,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); common_write_16_bit(genericService.routerID, &addr[14]); tr_debug("Delete DHCPv6 given address"); - thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); + dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); } } @@ -2702,6 +2731,8 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) thread_border_router_network_data_update_notify(cur); thread_bbr_network_data_update_notify(cur); + thread_maintenance_timer_set(cur, THREAD_MAINTENANCE_TIMER_INTERVAL); + return 0; } @@ -2744,7 +2775,6 @@ int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thr return 0; } - void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur) { // Route prefix is variable-length, so need to zero pad for ip6tos @@ -2794,6 +2824,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) { // don't add tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); + } else if (curBorderRouter->P_res1) { + ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, 0xffffffff, 0); } else { //add tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); @@ -2818,8 +2850,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); /* Do not allow multiple DHCP solicits from one prefix => delete previous */ - thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); - if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { + dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); + if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { tr_debug("GP Address Requested"); } } @@ -2839,6 +2871,10 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); } } + // generate address based on res1 bit + if (curBorderRouter->P_res1) { + thread_extension_dua_address_generate(cur,curPrefix->servicesPrefix,64); + } } // for each borderRouterList diff --git a/source/6LoWPAN/Thread/thread_bootstrap.h b/source/6LoWPAN/Thread/thread_bootstrap.h index 212f1ca0449..e45bb99a6f4 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_bootstrap.h @@ -106,6 +106,9 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, void thread_bootstrap_ready(struct protocol_interface_info_entry *cur); int thread_bootstrap_reset(struct protocol_interface_info_entry *cur); void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur); + +/* Function to remove linked neighbours for REEDs and FEDs */ +void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur); bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address); bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mac_neighbor_table_entry *entry_temp); void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur); @@ -191,7 +194,6 @@ int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period); void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp); - #else #define thread_interface_up(cur) ((void) 0) #define thread_bootstrap_state_machine(cur) ((void)0) diff --git a/source/6LoWPAN/Thread/thread_border_router_api.c b/source/6LoWPAN/Thread/thread_border_router_api.c index 8ca402db62b..83385243ce2 100644 --- a/source/6LoWPAN/Thread/thread_border_router_api.c +++ b/source/6LoWPAN/Thread/thread_border_router_api.c @@ -42,6 +42,7 @@ #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_common.h" +#include "6LoWPAN/Thread/thread_extension_bbr.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_storage.h" #include "6LoWPAN/Thread/thread_management_client.h" @@ -591,6 +592,15 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent thread_border_router_network_data_appl_callback(cur); } + +void thread_border_router_old_partition_data_clean(int8_t interface_id) +{ + thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); + if (this) { + coap_service_request_delete_by_service_id(this->coap_service_id); + } + thread_extension_bbr_old_partition_data_clean(interface_id); +} #endif // HAVE_THREAD_ROUTER /*External APIs*/ @@ -837,7 +847,6 @@ int thread_border_router_dns_search_list_option_set(int8_t interface_id, uint8_t static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len) { protocol_interface_info_entry_t *cur; - (void) status; (void) data_len; (void) data_ptr; @@ -846,7 +855,7 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st return; } - cur->thread_info->localServerDataBase.publish_active = false; + cur->thread_info->localServerDataBase.publish_coap_req_id = 0; tr_debug("BR a/sd response status: %s, addr: %x",status?"Fail":"OK", cur->thread_info->localServerDataBase.registered_rloc16); @@ -855,9 +864,11 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st thread_border_router_publish(cur->id); } - // always update RLOC to new one. If COAP response fails then resubmit timer will trigger new a/sd - cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); - cur->thread_info->localServerDataBase.release_old_address = false; + if (status == 0) { + // If request was successful, then update RLOC to new one. + cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); + cur->thread_info->localServerDataBase.release_old_address = false; + } } #endif @@ -884,21 +895,20 @@ int thread_border_router_publish(int8_t interface_id) rloc16 = mac_helper_mac16_address_get(cur); tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16); - if (cur->thread_info->localServerDataBase.publish_active) { + if (cur->thread_info->localServerDataBase.publish_coap_req_id) { if (rloc16 != cur->thread_info->localServerDataBase.registered_rloc16) { /* - * Device short address has changed, cancel previous a/sd and a/as requests + * Device short address has changed, cancel previous a/sd requests * and start resubmit timer * */ - tr_debug("address changed, kill pending reuqests"); - thread_management_client_pending_coap_request_kill(cur->id); + tr_debug("RLOC changed, kill pending a/sd request"); + thread_management_client_coap_message_delete(cur->id, cur->thread_info->localServerDataBase.publish_coap_req_id); thread_border_router_resubmit_timer_set(interface_id, 5); - return 0; } else { cur->thread_info->localServerDataBase.publish_pending = true; tr_debug("Activate pending status for publish"); - return 0; } + return 0; } //Allocate Memory for Data @@ -926,8 +936,10 @@ int thread_border_router_publish(int8_t interface_id) if (payload_ptr) { ns_dyn_mem_free(payload_ptr); } - if (ret_val == 0) { - cur->thread_info->localServerDataBase.publish_active = true; + if (ret_val > 0) { + // a/sd request successful, save coap request id + cur->thread_info->localServerDataBase.publish_coap_req_id = (uint16_t)ret_val; + ret_val = 0 ; } thread_border_router_resubmit_timer_set(interface_id, -1); diff --git a/source/6LoWPAN/Thread/thread_border_router_api_internal.h b/source/6LoWPAN/Thread/thread_border_router_api_internal.h index 9d7694a23e2..c1227173dd7 100644 --- a/source/6LoWPAN/Thread/thread_border_router_api_internal.h +++ b/source/6LoWPAN/Thread/thread_border_router_api_internal.h @@ -85,6 +85,14 @@ void thread_border_router_network_data_appl_callback(protocol_interface_info_ent * */ void thread_border_router_network_data_update_notify(protocol_interface_info_entry_t *cur); + +/** + * \brief Clear data related to old partition. + * + * \param interface_id Network interface ID. + */ +void thread_border_router_old_partition_data_clean(int8_t interface_id); + #else #define thread_border_router_init(interface_id) #define thread_border_router_delete(interface_id) @@ -92,6 +100,7 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent #define thread_border_router_resubmit_timer_set(interface_id, seconds) #define thread_border_router_network_data_appl_callback(cur) #define thread_border_router_network_data_update_notify(cur) +#define thread_border_router_old_partition_data_clean(interface_id) #endif #endif /* THREAD_BORDER_ROUTER_API_INTERNAL_H_ */ diff --git a/source/6LoWPAN/Thread/thread_commissioning_api.c b/source/6LoWPAN/Thread/thread_commissioning_api.c index a80a5ad58f1..f5815360ac7 100644 --- a/source/6LoWPAN/Thread/thread_commissioning_api.c +++ b/source/6LoWPAN/Thread/thread_commissioning_api.c @@ -35,6 +35,7 @@ #include "ns_list.h" #include "ns_trace.h" #include "nsdynmemLIB.h" +#include "randLIB.h" #include "common_functions.h" #include "ns_sha256.h" @@ -74,6 +75,8 @@ typedef NS_LIST_HEAD(device_t, link) device_list_t; typedef struct commissioner_entry { device_list_t device_list; uint8_t destination_address[16]; + uint8_t final_dest_address[16]; // Relay message final destination + uint8_t leader_address[16]; // leader ALOC for contacting the leader uint8_t PSKc_ptr[16]; thread_commissioning_status_cb *status_cb_ptr; uint16_t destination_port; @@ -82,7 +85,8 @@ typedef struct commissioner_entry { int8_t interface_id; int8_t coap_service_id; int8_t coap_secure_service_id; - int8_t coap_virtual_service_id; + int8_t coap_secure_virtual_service_id; + int8_t coap_udp_proxy_service_id; bool registered: 1; bool native_commissioner: 1; @@ -167,7 +171,7 @@ static commissioner_t *commissioner_find_by_service(int8_t service_id) { commissioner_t *this = NULL; ns_list_foreach(commissioner_t, cur_ptr, &instance_list) { - if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id) { + if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_secure_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id || cur_ptr->coap_udp_proxy_service_id == service_id) { this = cur_ptr; break; } @@ -237,12 +241,46 @@ static int commission_finalisation_resp_send(int8_t coap_service_id, device_t *d * Callback functions */ +static int thread_commissioning_active_get_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) +{ + commissioner_t *this = commissioner_find_by_service(service_id); + commissioning_state_e state = COMMISSIONING_STATE_REJECT;// Default is accept if we get error it is rejected + uint8_t *ptr; + uint16_t len; + (void) source_address; + (void) source_port; + + /* Transaction failed */ + if (!response_ptr) { + return -1; + } + + tr_debug("management get response from comm module"); + if (!this) { + return -2; + } + + if ((len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr)) > 0) { + state = COMMISSIONING_STATE_ACCEPT; + tr_debug(" TLV ml prefix=%s\r\n", trace_array(ptr, len)); + memcpy(this->leader_address, ptr, 8); + memcpy(this->leader_address + 8, ADDR_SHORT_ADR_SUFFIC, 6); + common_write_16_bit(0xfc00, this->leader_address + 14); + } + + if (this->status_cb_ptr) { + this->status_cb_ptr(this->interface_id, this->session_id, state); + } + return 0; +} + static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) { commissioner_t *this = commissioner_find_by_service(service_id); commissioning_state_e state = COMMISSIONING_STATE_REJECT; uint16_t session_id = 0; - uint8_t *ptr; + uint8_t *ptr = NULL; + char *uri_ptr = THREAD_URI_ACTIVE_GET; (void) source_address; (void) source_port; @@ -267,6 +305,16 @@ static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t sour } tr_debug("petition response session_id: %d state:%d",session_id, state); + // if registered and native commissioner send ACTIVE_GET to BBR to get mesh parameters + // if not native set leader ALOC from stack + if (this->native_commissioner) { + coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb); + return 0; + } else { + thread_management_get_leader_aloc(this->interface_id, this->leader_address); + } + user_response: if (state == COMMISSIONING_STATE_REJECT) { thci_trace("commissionerPetitionRejected"); @@ -376,10 +424,54 @@ static int commission_dataset_changed_notify_recv_cb(int8_t service_id, uint8_t (void)source_port; tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address)); + commissioner_t *this = commissioner_find_by_service(service_id); + + if (!this) { + return -1; + } + + coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ACTIVE_GET, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb); + coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0); return 0; } +static int thread_commission_udp_proxy_receive_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) +{ + tr_debug("Recv UDP_RX.ntf"); + + commissioner_t *this = commissioner_find_by_service(service_id); + uint8_t *udp_encapsulation_ptr, *udp_tmf_ptr; + uint16_t udp_encapsulation_len, udp_tmf_len; + uint8_t *ipv6_addr_ptr; + uint16_t ipv6_addr_len; + uint16_t dest_port; + + (void) source_port; + + if (!this || !source_address || !request_ptr) { + return -1; // goto error response + } + + udp_encapsulation_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_UDP_ENCAPSULATION, &udp_encapsulation_ptr); + ipv6_addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_IPV6_ADDRESS, &ipv6_addr_ptr); + + if (udp_encapsulation_len == 0 || ipv6_addr_len < 16) { + tr_warn("Corrupted UDP_RX.ntf received (%d, %d)", udp_encapsulation_len, ipv6_addr_len); + return -1; + } + + dest_port = common_read_16_bit(udp_encapsulation_ptr + 2); + udp_tmf_len = udp_encapsulation_len - 4; + udp_tmf_ptr = udp_encapsulation_ptr + 4; + + tr_debug("UDP_RX tmf: %s", trace_array(udp_tmf_ptr, udp_tmf_len)); + + coap_service_virtual_socket_recv(this->coap_udp_proxy_service_id, ipv6_addr_ptr, dest_port, udp_tmf_ptr, udp_tmf_len); + + return -1; // no response sent +} static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t device_list, int *steering_tlv_max_length) { @@ -403,6 +495,35 @@ static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t d return bloom_filter_ptr; } +static int thread_commissioner_set_steering_data(commissioner_t *this, uint16_t session_id, uint8_t *steering_data_ptr, uint8_t steering_data_len) +{ + uint8_t payload[24];/* 4 + 16 + 4*/ + uint8_t *ptr; + int8_t coap_service_id; + if (!this || steering_data_len > 16) { + return -1; + } + + ptr = payload; + ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_STEERING_DATA, steering_data_len, steering_data_ptr); + ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id); + + tr_debug("thread commissioner set steering data %s", trace_array(steering_data_ptr, steering_data_len)); + memcpy(this->final_dest_address, this->leader_address,16); + //default uri for thread version 1.1 + char *uri = THREAD_URI_COMMISSIONER_SET; + + if (this->native_commissioner) { + coap_service_id = this->coap_udp_proxy_service_id; + } else { + coap_service_id = this->coap_service_id; + } + + coap_service_request_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL); + + return 0; +} static int commission_steering_data_update(commissioner_t *this) { @@ -414,7 +535,7 @@ static int commission_steering_data_update(commissioner_t *this) //bloom filter calculation function call bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length); tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16)); - ret = thread_management_set_steering_data(this->management_instance, this->session_id,bloom_filter_ptr, steering_tlv_length, NULL); + ret = thread_commissioner_set_steering_data(this, this->session_id,bloom_filter_ptr, steering_tlv_length); if (ret) { tr_warn("Steering data set failed %d", ret); return -1; @@ -475,7 +596,7 @@ static int commission_relay_rx_recv_cb(int8_t service_id, uint8_t source_address tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8)); } device_ptr->joiner_router_rloc = joiner_router_rloc; - coap_service_virtual_socket_recv(this->coap_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); + coap_service_virtual_socket_recv(this->coap_secure_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); return -1; // no response sent } @@ -616,20 +737,55 @@ static int commissioner_br_security_done_cb(int8_t service_id, uint8_t address[1 return 0; } -static int thread_commissioning_remote_addr_set(commissioner_t *this) +static int thread_commission_udp_proxy_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len) { - if (0 == thread_management_get_leader_address(this->interface_id, this->destination_address)) { - tr_debug("on-mesh commissioner"); - this->destination_port = THREAD_MANAGEMENT_PORT; - this->native_commissioner = false; - } else if (0 == thread_commissioning_native_commissioner_get_connection_info(this->interface_id, - this->destination_address, &this->destination_port)) { - tr_debug("native commissioner"); - this->native_commissioner = true; - } else { - tr_error("No remote address"); + (void) port; + uint8_t *payload_ptr; + uint8_t *ptr; + uint16_t payload_len; + uint16_t source_port; + + commissioner_t *this = commissioner_find_by_service(service_id); + if (!this) { + return -1; + } + + tr_debug("UDP_TX.ntf tmf: %s", trace_array(data_ptr, data_len)); + if (!this || !destination_addr_ptr || !data_ptr) { return -1; } + + payload_len = 2 + THREAD_IPV6_ADDRESS_TLV_LENGTH + 4 + 4 + data_len; // MESHCOP_TLV_IPV6_ADDRESS + MESHCOP_TLV_UDP_ENCAPSULATION + + payload_ptr = ns_dyn_mem_alloc(payload_len); + if (!payload_ptr) { + return -3; + } + + ptr = payload_ptr; + + tr_debug("br_address %s final dest_address %s and port %d", trace_ipv6(this->destination_address), + trace_ipv6(this->final_dest_address), this->destination_port); + + /* MESHCOP_TLV_IPV6_ADDRESS */ + ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_IPV6_ADDRESS, THREAD_IPV6_ADDRESS_TLV_LENGTH, this->final_dest_address); + + /* MESHCOP_TLV_UDP_ENCAPSULATION */ + *ptr++ = MESHCOP_TLV_UDP_ENCAPSULATION; + *ptr++ = 0xff; + ptr = common_write_16_bit(2 + 2 + data_len, ptr); // length (Port x 2 + TMF message) + source_port = randLIB_get_16bit(); // ephemeral port, 16-bit number + ptr = common_write_16_bit(source_port, ptr); // source port, + ptr = common_write_16_bit(THREAD_MANAGEMENT_PORT, ptr); // destination port + memcpy(ptr, data_ptr, data_len); + ptr += data_len; + + /* Send UDP_TX.ntf */ + coap_service_request_send(this->coap_secure_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_UDP_TRANSMIT_NOTIFICATION, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); + + ns_dyn_mem_free(payload_ptr); + return 0; } @@ -638,16 +794,17 @@ Public api functions */ int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) { - if (commissioner_find(interface_id)) { - return -1; + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + this = commissioner_create(interface_id); } - commissioner_t *this = commissioner_create(interface_id); if (!this) { return -2; } memcpy(this->PSKc_ptr,PSKc,16); - - this->management_instance = thread_management_register(interface_id); + if (this->registered) { + return 0; + } this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb); @@ -655,10 +812,15 @@ int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb); coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); + coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_UDP_RECVEIVE_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_commission_udp_proxy_receive_cb); + + this->coap_secure_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb); + coap_service_register_uri(this->coap_secure_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb); + coap_service_virtual_socket_set_cb(this->coap_secure_virtual_service_id, commission_virtual_socket_send_cb); + + this->coap_udp_proxy_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, NULL, NULL); + coap_service_virtual_socket_set_cb(this->coap_udp_proxy_service_id, thread_commission_udp_proxy_virtual_socket_send_cb); - this->coap_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb); - coap_service_register_uri(this->coap_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb); - coap_service_virtual_socket_set_cb(this->coap_virtual_service_id, commission_virtual_socket_send_cb); return 0; } @@ -672,11 +834,11 @@ int thread_commissioning_unregister(int8_t interface_id) // Unregister the commissioner thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT); } - thread_management_unregister(this->management_instance); coap_service_delete(this->coap_service_id); coap_service_delete(this->coap_secure_service_id); - coap_service_delete(this->coap_virtual_service_id); + coap_service_delete(this->coap_secure_virtual_service_id); + coap_service_delete(this->coap_udp_proxy_service_id); commissioner_delete(this); return 0; @@ -690,7 +852,6 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_ uint8_t service_id; uint8_t *ptr; char *uri_ptr; - this = commissioner_find(interface_id); if (!this) { @@ -705,16 +866,14 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_ return -3; } - if (thread_commissioning_remote_addr_set(this)) { - return -4; - } - if (this->native_commissioner) { uri_ptr = THREAD_URI_COMMISSIONER_PETITION; service_id = this->coap_secure_service_id; } else { uri_ptr = THREAD_URI_LEADER_PETITION; service_id = this->coap_service_id; + thread_management_get_leader_aloc(this->interface_id, this->destination_address); + this->destination_port = THREAD_MANAGEMENT_PORT; } this->status_cb_ptr = status_cb_ptr; @@ -747,16 +906,13 @@ int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_ return -1; } - if (thread_commissioning_remote_addr_set(this)) { - return -4; - } - if (this->native_commissioner) { uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE; service_id = this->coap_secure_service_id; } else { uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE; service_id = this->coap_service_id; + thread_management_get_leader_aloc(this->interface_id, this->destination_address); } ptr = payload; @@ -867,6 +1023,20 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh return cur_ptr; } +int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port) +{ + tr_debug("start ethernet commissioner attach"); + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + return -1; + } + memcpy(this->destination_address, destination_address,16); + this->destination_port = destination_port; + this->native_commissioner = true; + return 0; + +} + int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr) { protocol_interface_info_entry_t *cur; @@ -909,6 +1079,18 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread return -2; } *cur->thread_info->native_commissioner_link = *link_ptr; + + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + this = commissioner_create(interface_id); + } + if (!this) { + return -3; + } + + this->native_commissioner = true; + memcpy(this->destination_address, link_ptr->destination_address,16); + this->destination_port = link_ptr->destination_port; //TODO check that we are scanning for networks and reset backup timers return 0; @@ -916,22 +1098,15 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port) { - protocol_interface_info_entry_t *cur; - cur = protocol_stack_interface_info_get_by_id(interface_id); + commissioner_t *this = commissioner_find(interface_id); tr_debug("get native connection info"); - if(!cur || !cur->thread_info) { + if (!this) { return -1; } - if (thread_attach_ready(cur) != 0) { - return -2; - } - if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, address_ptr) != 0) { - return -1; - } - if (port) { - *port = cur->thread_info->native_commissioner_port; - } + memcpy(address_ptr,this->destination_address,16); + + *port = this->destination_port; return 0; } @@ -1031,4 +1206,11 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread return -1; } +int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port) { + (void)interface_id; + (void)destination_address; + (void)destination_port; + return -1; +} + #endif diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 0716d79cf7a..567851ecb4b 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -44,9 +44,11 @@ #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_beacon.h" +#include "6LoWPAN/Thread/thread_diagnostic.h" +#include "6LoWPAN/Thread/thread_extension_bbr.h" #include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_routing.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_router_bootstrap.h" @@ -60,6 +62,7 @@ #include "6LoWPAN/Thread/thread_management_internal.h" #include "6LoWPAN/Thread/thread_management_client.h" #include "6LoWPAN/Thread/thread_management_server.h" +#include "6LoWPAN/Thread/thread_resolution_server.h" #include "6LoWPAN/Thread/thread_resolution_client.h" #include "6LoWPAN/Thread/thread_address_registration_client.h" #include "6LoWPAN/Thread/thread_resolution_client.h" @@ -226,6 +229,7 @@ int8_t thread_bootstrap_up(protocol_interface_info_entry_t *cur) ret_val = nwk_6lowpan_up(cur); cur->nwk_nd_re_scan_count = 0; + cur->thread_info->link_sync_allowed = true; return ret_val; } @@ -258,9 +262,11 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur) thread_leader_mleid_rloc_map_to_nvm_write(cur); thread_bootstrap_stop(cur); mle_service_interface_unregister(cur->id); + thread_diagnostic_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id + thread_management_client_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id + thread_nd_service_disable(cur->id); // delete before thread_management_server_delete as they share same coap_service id thread_management_server_delete(cur->id); thread_joiner_application_deinit(cur->id); - thread_management_client_delete(cur->id); //free network Data thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage); //free local also here @@ -451,7 +457,7 @@ void thread_data_base_init(thread_info_t *thread_info, int8_t interfaceId) thread_leader_commissioner_create(thread_info); thread_info->rfc6775 = false; thread_info->threadPrivatePrefixInfo.ulaValid = false; - thread_info->routerIdReqCoapID = 0; + thread_info->routerIdRequested = false; thread_info->networkDataRequested = false; thread_info->proactive_an_timer = 0; @@ -905,6 +911,7 @@ static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur, if (cur->thread_info->childUpdateReqTimer == -1) { return; } + if (cur->thread_info->childUpdateReqTimer > seconds) { cur->thread_info->childUpdateReqTimer -= seconds; } else { @@ -945,6 +952,20 @@ static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16 } } +static void thread_maintenance_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) +{ + if (thread_info(cur)->thread_maintenance_timer) { + if (thread_info(cur)->thread_maintenance_timer > seconds) { + thread_info(cur)->thread_maintenance_timer -= seconds; + return; + } + } + + thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL ; + + thread_bootstrap_network_data_activate(cur); +} + void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) { uint8_t leader_address[16]; @@ -1003,6 +1024,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) } thread_router_bootstrap_timer(cur, ticks); + thread_maintenance_timer(cur, ticks); thread_border_router_seconds_timer(cur->id, ticks); thread_bbr_seconds_timer(cur->id, ticks); thread_lowpower_timer(cur, ticks); @@ -1720,9 +1742,105 @@ uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entr return ptr; } +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return false; + } + + // check for addresses + ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { + if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL + && !thread_addr_is_mesh_local_16(e->address, cur))) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (!ctx) { + return true; + } + if (ctx->cid != 0) { + return true; + + } + } + } + + // check for multicast groups + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); + ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) + { + if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) { + /* Skip solicited node multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { + /* Skip well-known realm-local all Thread nodes multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) { + /* Skip well-known link-local all Thread nodes multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { + /* Skip All MPL Forwarders address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_NODES)) { + /* Skip Mesh local all nodes */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_ROUTERS)) { + /* Skip Mesh local all routers */ + continue; + } + return true; + } + return false; +} + +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t *address_len_ptr; + + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return ptr; + } + *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION; + address_len_ptr = ptr++; + + *address_len_ptr = 0; + + ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { + + if (*address_len_ptr > 148 ) { + // Maximum length of address registrations + continue; + } + if (!thread_addr_is_mesh_local_16(e->address, cur)) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (ctx && ctx->cid == 0) { + //Write TLV to list + *ptr++ = (ctx->cid | 0x80); + memcpy(ptr, e->address + 8, 8); + ptr += 8; + *address_len_ptr += 9; + } + } + } + return ptr; +} + uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) { uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; lowpan_context_t *ctx; uint8_t *address_len_ptr; @@ -1738,7 +1856,6 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_ // Register all global addressess ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { - if (*address_len_ptr > 148 ) { // Maximum length of address registrations continue; @@ -1762,23 +1879,27 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_ } /* Registers multicast addresses to the parent */ - thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); - + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) { if (*address_len_ptr > 148) { // Maximum length of address registrations continue; } - if (addr_ipv6_multicast_scope(entry->group) < IPV6_SCOPE_REALM_LOCAL) { - /* Skip Link Local multicast address */ + + if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) { + /* Skip solicited node multicast address */ continue; } - if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { /* Skip well-known realm-local all Thread nodes multicast address */ continue; } + if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) { + /* Skip well-known link-local all Thread nodes multicast address */ + continue; + } if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { /* Skip All MPL Forwarders address */ continue; @@ -1935,9 +2056,34 @@ static void thread_address_notification_cb(struct protocol_interface_info_entry } } -void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added) +static bool thread_mcast_should_register_address(struct protocol_interface_info_entry *cur, uint8_t *addr) { + uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); + if (addr_ipv6_multicast_scope(addr) >= IPV6_SCOPE_LINK_LOCAL) { + if (memcmp(addr, ADDR_MULTICAST_SOLICITED, 13) == 0) { + return false; + } + if (memcmp(addr, thread_realm_local_mcast_addr, 16) == 0) { + return false; + } + if (memcmp(addr, thread_ll_unicast_prefix_based_mcast_addr, 16) == 0) { + return false; + } + if (memcmp(addr, ADDR_LINK_LOCAL_ALL_NODES, 16) == 0) { + return false; + } + if (memcmp(addr, ADDR_LINK_LOCAL_ALL_ROUTERS, 16) == 0) { + return false; + } + } + return true; +} +void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added) +{ if (thread_attach_ready(interface) != 0) { return; } @@ -1946,7 +2092,7 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if (thread_bootstrap_should_register_address(interface)) { /* Trigger Child Update Request only if MTD child's multicast address change */ - if (addr_ipv6_multicast_scope(group->group) > IPV6_SCOPE_LINK_LOCAL) { + if (thread_mcast_should_register_address(interface, group->group)) { interface->thread_info->childUpdateReqTimer = 1; } } else { @@ -1956,10 +2102,16 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface, } } +static void thread_old_partition_data_clean(int8_t interface_id) +{ + thread_management_client_old_partition_data_clean(interface_id); + thread_border_router_old_partition_data_clean(interface_id); +} + void thread_partition_data_purge(protocol_interface_info_entry_t *cur) { /* Partition has been changed. Wipe out data related to old partition */ - thread_management_client_pending_coap_request_kill(cur->id); + thread_old_partition_data_clean(cur->id); /* Reset previous routing information */ thread_routing_reset(&cur->thread_info->routing); @@ -1967,6 +2119,9 @@ void thread_partition_data_purge(protocol_interface_info_entry_t *cur) /* Flush address cache */ ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); + /* Remove linked neighbours for REEDs and FEDs */ + thread_reed_fed_neighbour_links_clean(cur); + } bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) @@ -1997,5 +2152,10 @@ void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index); } +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay) +{ + thread_info(cur)->thread_maintenance_timer = delay; +} + #endif diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 09ffce3900f..6e849529875 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -309,10 +309,10 @@ typedef struct thread_info_s { uint16_t routerShortAddress; uint16_t reedJitterTimer; uint16_t reedMergeAdvTimer; - uint16_t routerIdReqCoapID; // COAP msg id of RouterID request int16_t childUpdateReqTimer; uint16_t childUpdateReqMsgId; uint16_t proactive_an_timer; + uint16_t thread_maintenance_timer; //uint8_t lastValidRouteMask[8]; int8_t interface_id; //Thread Interface ID uint8_t version; @@ -322,11 +322,13 @@ typedef struct thread_info_s { bool rfc6775: 1; bool requestFullNetworkData: 1; bool leaderCab: 1; + bool routerIdRequested: 1; bool releaseRouterId: 1; bool networkSynch: 1; bool networkDataRequested: 1; bool end_device_link_synch: 1; bool router_mc_addrs_registered: 1; + bool link_sync_allowed:1; bool leader_synced:1; // flag used by leader after restart } thread_info_t; @@ -397,6 +399,11 @@ void thread_child_mcast_entries_remove(protocol_interface_info_entry_t *cur, con uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur); uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); + +// returns true if SED/MED needs to register additional address to parent +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur); +// write mesh local address tlv +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64); thread_leader_info_t *thread_allocate_and_init_leader_private_data(void); thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality); @@ -441,6 +448,7 @@ bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_ void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index); bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf); +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay); #else // HAVE_THREAD NS_DUMMY_DEFINITIONS_OK diff --git a/source/6LoWPAN/Thread/thread_config.h b/source/6LoWPAN/Thread/thread_config.h index 0db796cd5d9..cd7406d6eba 100644 --- a/source/6LoWPAN/Thread/thread_config.h +++ b/source/6LoWPAN/Thread/thread_config.h @@ -326,6 +326,17 @@ */ #define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST +/* + * Number of destination and neighbor cache entries assuming 250 thread devices (worst case) connecting to cloud service. + * Six entries reserved for backbone devices. + */ +#define THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE 256 + +/* + * Timeout to solicit address from DHCP if previous request fails. + */ +#define THREAD_MAINTENANCE_TIMER_INTERVAL 300 + /** * Build time flag to enable THCI special traces for test harness purposes */ diff --git a/source/6LoWPAN/Thread/thread_constants.h b/source/6LoWPAN/Thread/thread_constants.h index 4150f4cc237..971a1fa1c97 100644 --- a/source/6LoWPAN/Thread/thread_constants.h +++ b/source/6LoWPAN/Thread/thread_constants.h @@ -145,6 +145,7 @@ #define THREAD_DEFAULT_KEY_SWITCH_GUARD_TIME 624 // Hours #define THREAD_DEFAULT_KEY_ROTATION 672 // Hours #define THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL 50000 // Default thread commissioner keep-alive message interval (milliseconds) +#define THREAD_DELAY_JOIN_ENT 50 // Minimum delay for Joiner router before sending joiner entrust (milliseconds) #define THREAD_FAILED_CHILD_TRANSMISSIONS 4 #define THREAD_FAILED_ROUTER_TRANSMISSIONS 4 diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_client.h b/source/6LoWPAN/Thread/thread_dhcpv6_client.h deleted file mode 100644 index cc97006e05a..00000000000 --- a/source/6LoWPAN/Thread/thread_dhcpv6_client.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2014-2015, 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ -#define SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ - -#include - -/* Thread DHCP client implementation. - * - * Responsibilities of this module are: - * - send router id address request and receive new router address and inform it to thread bootstrap. - * - handle Global address queries and refresh inside thread network. - * - */ - -/* Initialize dhcp thread dhcp client. - * - * This instance needs to bee initialized once for each thread network interface. - * if only one thread instance is supported this is needed to call only once. - * - * /param interface interface id of this thread instance. - * - */ - -void thread_dhcp_client_init(int8_t interface); - -/* Delete dhcp thread dhcp client. - * - * When this is called all addressed assigned by this module are removed from stack. - */ -void thread_dhcp_client_delete(int8_t interface); - -/* Global address handler. - * - * This module updates the addresses from dhcp server and sets them in stack. - * this module makes refresh of address when needed. - * - */ - - -/* give dhcp server and prefix for global address assignment - * - * /param interface interface where address is got - * /param dhcp_addr dhcp server ML16 address where address is registered. - * /param prefix dhcp server ML16 address where address is registered. - * /param mac64 64 bit mac address for identifieng client. - * /param error_cb error callback that is called if address cannot be created or becomes invalid. - * /param register_status true if address registered. - * - */ -typedef void (thread_dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status); - -int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb); - -/* Renew all leased adddresses might be used when short address changes - * - * /param interface interface where address is got - */ -void thread_dhcp_client_global_address_renew(int8_t interface); - -/* Delete address from device - * if prefix is NULL all are deleted - * - * /param interface interface where address is got - * /param prefix dhcp server ML16 address where address is registered. - * - */ -void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]); - -#endif /* SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ */ diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_server.c b/source/6LoWPAN/Thread/thread_dhcpv6_server.c new file mode 100644 index 00000000000..f0c8f6dafe2 --- /dev/null +++ b/source/6LoWPAN/Thread/thread_dhcpv6_server.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "nsconfig.h" +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) +#include +#include +#include "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "common_functions.h" +#include "ns_trace.h" +#include "NWK_INTERFACE/Include/protocol.h" +#include "ipv6_stack/protocol_ipv6.h" +#include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ipv6.h" +#include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_bbr_api_internal.h" + +#define TRACE_GROUP "thds" + +static void thread_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress) +{ + ipv6_neighbour_t *neighbour_entry; + + neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress); + if (neighbour_entry) { + tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress)); + ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); + } +} + +static void thread_dhcp_address_prefer_remove_cb(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info) +{ + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId); + if (!curPtr) { + return; + } + if (!targetAddress) { + //Clear All targets routes + ipv6_route_table_remove_info(interfaceId, ROUTE_THREAD_PROXIED_HOST,prefix_info); + } else { + tr_debug("Address Preferred Timeout"); + ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST); + thread_service_remove_GUA_from_neighcache(curPtr, targetAddress); + + } + +} + +static bool thread_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src) +{ + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId); + if (!curPtr) { + return false; + } + + // If this is solicit from existing address, flush ND cache. + if (address_info->allocatedNewAddress) { + // coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return + thread_service_remove_GUA_from_neighcache(curPtr, address_info->allocatedAddress); + } + + if (thread_bbr_nd_entry_add(interfaceId,address_info->allocatedAddress, address_info->validLifeTime, route_src) == -1) { + // No nanostack BBR present we will put entry for application implemented BBR + ipv6_route_t *route = ipv6_route_add_with_info(address_info->allocatedAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,route_src,0, address_info->validLifeTime, 0); + if (!route) { + return false; + } + + } + return true; +} + +int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne) +{ + if (DHCPv6_server_service_init(interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + return -1; + } + //Register Callbacks + DHCPv6_server_service_callback_set(interface_id, prefix, thread_dhcp_address_prefer_remove_cb, thread_dhcp_address_add_cb); + //SET Timeout + DHCPv6_server_service_set_address_validlifetime(interface_id, prefix, validLifeTimne); + + return 0; +} + +#endif diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_server.h b/source/6LoWPAN/Thread/thread_dhcpv6_server.h new file mode 100644 index 00000000000..b8e56a63f0b --- /dev/null +++ b/source/6LoWPAN/Thread/thread_dhcpv6_server.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREAD_DHCPV6_SERVER_H_ +#define THREAD_DHCPV6_SERVER_H_ +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) +int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne); +#else +#define thread_dhcp6_server_init(interface_id, prefix, eui64, validLifeTimne) (-1) +#endif + + +#endif /* THREAD_DHCPV6_SERVER_H_ */ diff --git a/source/6LoWPAN/Thread/thread_diagnostic.c b/source/6LoWPAN/Thread/thread_diagnostic.c index fdce83ece82..33e1b419c3d 100644 --- a/source/6LoWPAN/Thread/thread_diagnostic.c +++ b/source/6LoWPAN/Thread/thread_diagnostic.c @@ -35,6 +35,7 @@ #include "nsdynmemLIB.h" #include "net_interface.h" #include "thread_management_if.h" +#include "thread_management_server.h" #include "thread_common.h" #include "thread_joiner_application.h" #include "thread_leader_service.h" @@ -229,6 +230,10 @@ static int thread_diagnostic_configuration_calc(protocol_interface_info_entry_t payload_len += 2+1; break; + case DIAGCOP_TLV_MAX_CHILD_TIMEOUT: + payload_len += 2 + 4; + break; + default: // todo: Other TLV's not supported atm break; @@ -254,6 +259,7 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur uint8_t *ptr; int written_address_count = 0; uint16_t ipv6_address_count = 0; + uint32_t max_child_timeout = 0; uint8_t extended_address[8] = {0}; arm_net_interface_address_list_size(cur->id, &ipv6_address_count); @@ -352,6 +358,12 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_CHANNEL_PAGES, 0); break; + case DIAGCOP_TLV_MAX_CHILD_TIMEOUT: + if (thread_router_bootstrap_child_max_timeout_get(cur, &max_child_timeout) == 0) { + response_ptr = thread_diagcop_tlv_data_write_uint32(response_ptr, DIAGCOP_TLV_MAX_CHILD_TIMEOUT, max_child_timeout); + } + break; + default: break; @@ -532,7 +544,7 @@ int thread_diagnostic_init(int8_t interface_id) this->interface_id = interface_id; - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); if (this->coap_service_id < 0) { tr_error("Thread diagnostic init failed"); ns_dyn_mem_free(this); @@ -556,8 +568,9 @@ int thread_diagnostic_delete(int8_t interface_id) if (!this) { return -1; } - - coap_service_delete(this->coap_service_id); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_REQUEST); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_RESET); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_QUERY); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); return 0; diff --git a/source/6LoWPAN/Thread/thread_extension.h b/source/6LoWPAN/Thread/thread_extension.h index 671ea9823c8..b6f64d1e909 100644 --- a/source/6LoWPAN/Thread/thread_extension.h +++ b/source/6LoWPAN/Thread/thread_extension.h @@ -46,19 +46,15 @@ void thread_extension_allocate(protocol_interface_info_entry_t *cur); void thread_extension_free(protocol_interface_info_entry_t *cur); void thread_extension_init(int8_t interface_id, int8_t coap_service_id); void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur); -int thread_extension_network_prefix_get(int8_t interface_id, uint8_t *options_ptr, uint8_t *prefix_ptr, uint8_t *prefix_len); void thread_extension_network_data_process(struct protocol_interface_info_entry *cur); int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr); void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected); -void thread_extension_address_generate(protocol_interface_info_entry_t *cur); +void thread_extension_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len); void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur); bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16); void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t *interface); void thread_extension_address_registration_trigger(protocol_interface_info_entry_t *interface); -void thread_extension_route_set(protocol_interface_info_entry_t *cur); -void thread_extension_activate(protocol_interface_info_entry_t *cur); bool thread_extension_enabled(protocol_interface_info_entry_t *cur); -bool thread_extension_context_can_delete(int8_t id, uint8_t servicesPrefix[16], uint8_t context_prefix_length); bool thread_extension_version_check(uint8_t version); void thread_extension_discover_response_read(struct discovery_response_list *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len); void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy); @@ -70,35 +66,31 @@ uint8_t thread_extension_discover_response_len(protocol_interface_info_entry_t * uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr); #else -#define thread_extension_joining_enabled(interface_id) false -#define thread_extension_discover_response_len(cur) 0 +#define thread_extension_joining_enabled(interface_id) (false) +#define thread_extension_discover_response_len(cur) (0) #define thread_extension_discover_response_write(cur, ptr) (ptr) #endif //HAVE_THREAD_ROUTER #else -#define thread_extension_allocate(cur) -#define thread_extension_free(cur) -#define thread_extension_init(interface_id,coap_service_id) -#define thread_extension_network_prefix_get(interface_id,options_ptr,prefix_ptr,prefix_len) (-1) -#define thread_extension_network_data_process(cur) +#define thread_extension_allocate(cur) ((void) 0) +#define thread_extension_free(cur) ((void) 0) +#define thread_extension_init(interface_id,coap_service_id) ((void) 0) +#define thread_extension_network_data_process(cur) ((void) 0) #define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1) -#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) -#define thread_extension_address_generate(cur) -#define thread_extension_aloc_generate(cur) -#define thread_extension_aloc_map(cur, addr16) false -#define thread_extension_mcast_subscrition_change(interface) -#define thread_extension_route_set(cur) -#define thread_extension_activate(cur) +#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) ((void) 0) +#define thread_extension_aloc_generate(cur) ((void) 0) +#define thread_extension_aloc_map(cur, addr16) (false) +#define thread_extension_mcast_subscrition_change(interface) ((void) 0) #define thread_extension_enabled(cur) (false) #define thread_extension_version_check(version) (false) -#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) -#define thread_extension_discover_response_tlv_write(data, version, extension_bit) (data) -#define thread_extension_service_init(cur) 0 -#define thread_extension_joining_enabled(interface_id) false -#define thread_extension_discover_response_len(cur) 0 +#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) ((void) 0) +#define thread_extension_discover_response_tlv_write(data, version, securityPolicy) ((void) 0) +#define thread_extension_service_init(cur) (0) +#define thread_extension_joining_enabled(interface_id) (false) +#define thread_extension_discover_response_len(cur) (0) #define thread_extension_discover_response_write(cur, ptr) (ptr) -#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) -#define thread_extension_context_can_delete(id, servicesPrefix, context_prefix_length) false +#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) ((void) 0) +#define thread_extension_dua_address_generate(cur, domain_prefix, domain_prefix_len) ((void) 0) #endif #ifdef __cplusplus diff --git a/source/6LoWPAN/Thread/thread_extension_bbr.h b/source/6LoWPAN/Thread/thread_extension_bbr.h index cad08464b09..153a82bac22 100644 --- a/source/6LoWPAN/Thread/thread_extension_bbr.h +++ b/source/6LoWPAN/Thread/thread_extension_bbr.h @@ -52,10 +52,12 @@ int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_ void thread_extension_bbr_delete(int8_t interface_id); bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc); void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds); +int thread_extension_bbr_sequence_number_set(int8_t interface_id, uint8_t seq_number); int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port); void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur); int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); +void thread_extension_bbr_old_partition_data_clean(int8_t interface_id); #else @@ -67,7 +69,9 @@ int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); #define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay) #define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1) #define thread_extension_bbr_route_update(cur) +#define thread_extension_bbr_sequence_number_set(interface_id, seq_number) (-1) #define thread_extension_bbr_prefix_set(interface_id, prefix) 0 +#define thread_extension_bbr_old_partition_data_clean(interface_id) #endif #ifdef __cplusplus diff --git a/source/6LoWPAN/Thread/thread_extension_bootstrap.h b/source/6LoWPAN/Thread/thread_extension_bootstrap.h index e83b3d359cd..e6132ccdd99 100644 --- a/source/6LoWPAN/Thread/thread_extension_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_extension_bootstrap.h @@ -45,6 +45,8 @@ extern "C" { #define thread_extension_bootstrap_thread_name_length_get(cur) (0) #define thread_extension_bootstrap_thread_name_ptr_get(cur) (NULL) #define thread_extension_bootstrap_network_certificate_enable(cur, coap_service_id) (NULL) +#define thread_extension_bootstrap_reenrollment_start(cur, service_id, pbbr_addr) (-1) +#define thread_extension_bootstrap_network_reattach(interface_id, timeout) (-1) #ifdef __cplusplus } diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index 50366616120..a6cb6b5dbf4 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -121,11 +121,11 @@ static void thread_network_data_clean(protocol_interface_info_entry_t *cur) static void thread_merge_prepare(protocol_interface_info_entry_t *cur) { + thread_partition_data_purge(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; } @@ -305,6 +305,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent uint16_t address16; uint32_t llFrameCounter; thread_leader_data_t leaderData; + mle_tlv_info_t addressRegisteredTlv; mac_neighbor_table_entry_t *entry_temp; bool new_entry_created; @@ -320,6 +321,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent // Address // MLE_TYPE_SRC_ADDRESS // MLE_TYPE_LEADER_DATA + // MLE_TYPE_ADDRESS_REGISTRATION if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) || @@ -329,6 +331,25 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent return -1; } + if (!(mode & THREAD_DEVICE_FED)) { + // check for presence of Address registration TLV for MTDs + if (!mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, ptr, data_length, &addressRegisteredTlv) || + (addressRegisteredTlv.tlvLen == 0)) { + tr_debug("MTD missed address registration TLV - reattach"); + return -1; + } + } + + // check if the source address is a router address + if (!thread_is_router_addr(srcAddress)) { + return -1; + } + + // check if the address16 is a valid child address + if (!thread_addr_is_child(srcAddress, address16)) { + return -1; + } + if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource)); // if learning key sequence from link sync actual guard timer value is not known @@ -1103,7 +1124,7 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t //Add ML-EID if ((mode & MLE_FFD_DEV) == 0) { - ptr = thread_address_registration_tlv_write(ptr, cur); + ptr = thread_ml_address_tlv_write(ptr,cur); } reqTlvCnt = 2; diff --git a/source/6LoWPAN/Thread/thread_joiner_application.c b/source/6LoWPAN/Thread/thread_joiner_application.c index 5bc1b784936..65ecc0af52c 100644 --- a/source/6LoWPAN/Thread/thread_joiner_application.c +++ b/source/6LoWPAN/Thread/thread_joiner_application.c @@ -54,6 +54,7 @@ #include "thread_management_if.h" #include "thread_common.h" #include "thread_bootstrap.h" +#include "thread_router_bootstrap.h" #include "thread_network_synch.h" #include "thread_network_data_lib.h" #include "thread_joiner_application.h" @@ -1140,7 +1141,7 @@ void thread_joiner_pending_config_activate(int8_t interface_id) this->active_configuration_ptr->timestamp = pending_active_timestamp; // All information is copied from old configuration so if configuration is corrupt we dont change anything. this->pending_configuration_ptr = NULL; - (void)thread_nvm_store_pending_configuration_remove(); + thread_nvm_store_pending_configuration_remove(); configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr); link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length); link_configuration_trace(this->configuration_ptr); @@ -1922,6 +1923,8 @@ int thread_joiner_application_update_configuration(uint8_t interface_id, uint8_t } thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); link_configuration_update(this->configuration_ptr,msg_ptr,msg_len); + // allow 5 seconds delay before state change for data response propagation + thread_router_bootstrap_delay_reed_jitter(interface_id, 5); ns_dyn_mem_free(configuration_ptr); thread_joiner_application_configuration_nvm_save(interface_id); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index d2be5fd3ebf..a244c9cedcf 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -41,7 +41,7 @@ #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_bootstrap.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" @@ -305,7 +305,6 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint protocol_interface_info_entry_t *cur; link_configuration_s *linkConfiguration; - tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address)); linkConfiguration = thread_joiner_application_get_config(interface_id); if (!linkConfiguration) { @@ -341,6 +340,13 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint *session_id = cur->thread_info->registered_commissioner.session_id; } + if (memcmp(border_router_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 && + memcmp(border_router_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0 && + border_router_address[14] == 0xfc) { + // source address is ALOC + common_write_16_bit(cur->thread_info->routerShortAddress, &border_router_address[14]); + } + tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address)); //SET Border Router Locator memcpy(cur->thread_info->registered_commissioner.border_router_address, border_router_address, 16); cur->thread_info->registered_commissioner.commissioner_valid = true; @@ -1295,7 +1301,7 @@ static int thread_leader_service_leader_init(protocol_interface_info_entry_t *cu thread_routing_free(&thread_info->routing); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); - thread_dhcp_client_delete(cur->id); + dhcp_client_delete(cur->id); thread_nd_service_delete(cur->id); mpl_clear_realm_scope_seeds(cur); ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); @@ -1352,7 +1358,6 @@ static void thread_leader_service_interface_setup_activate(protocol_interface_in cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS; thread_bootstrap_update_ml16_address(cur, cur->thread_info->routerShortAddress); thread_generate_ml64_address(cur); - thread_extension_address_generate(cur); thread_bootstrap_routing_activate(cur); thread_routing_update_id_set(cur, private->maskSeq, private->master_router_id_mask); thread_routing_activate(&cur->thread_info->routing); diff --git a/source/6LoWPAN/Thread/thread_management_api.c b/source/6LoWPAN/Thread/thread_management_api.c index ff364157b10..ac16c1f6066 100644 --- a/source/6LoWPAN/Thread/thread_management_api.c +++ b/source/6LoWPAN/Thread/thread_management_api.c @@ -287,7 +287,6 @@ int thread_management_register(int8_t interface_id) this->get_response_cb_ptr = NULL; if (thread_management_get_remote_addr(this)) { - ns_dyn_mem_free(this); return -1; } diff --git a/source/6LoWPAN/Thread/thread_management_client.c b/source/6LoWPAN/Thread/thread_management_client.c index 0ccae5a3ac3..a5d1646b3a0 100644 --- a/source/6LoWPAN/Thread/thread_management_client.c +++ b/source/6LoWPAN/Thread/thread_management_client.c @@ -45,6 +45,7 @@ #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_tmfcop_lib.h" #include "6LoWPAN/Thread/thread_management_internal.h" +#include "6LoWPAN/Thread/thread_management_server.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_bootstrap.h" @@ -58,9 +59,8 @@ typedef struct thread_management { thread_management_client_router_id_cb *router_id_release_cb_ptr; thread_management_client_network_data_set_cb *network_data_set_cb_ptr; thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr; - uint16_t coap_asd_msg_id; // COAP msg id for a/sd int8_t interface_id; - int8_t coap_service_id; + int8_t coap_service_id; // COAP service ID from Management server ns_list_link_t link; } thread_management_t; @@ -150,9 +150,12 @@ void thread_management_client_init(int8_t interface_id) this->neighbor_discovery_cb_ptr = NULL; this->router_id_cb_ptr = NULL; this->interface_id = interface_id; - this->coap_asd_msg_id = 0; //TODO: Check if to use ephemeral port here - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + + this->coap_service_id = thread_management_server_service_id_get(interface_id); + if (this->coap_service_id < 0) { + tr_error("Failed to init COAP service"); + } ns_list_add_to_start(&instance_list, this); } return; @@ -165,19 +168,10 @@ void thread_management_client_delete(int8_t interface_id) return; } - coap_service_delete(this->coap_service_id); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); return; } -int8_t thread_management_client_service_id_get(int8_t interface_id) -{ - thread_management_t *this = thread_management_find(interface_id); - if (!this) { - return -1; - } - return this->coap_service_id; -} int thread_management_client_router_id_get(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb, uint8_t status) { @@ -251,8 +245,6 @@ static int thread_management_client_register_cb(int8_t service_id, uint8_t sourc return -1; } - this->coap_asd_msg_id = 0; //clear the coap message id - if (this->network_data_set_cb_ptr) { if (response_ptr) { // If we get response status is OK @@ -281,10 +273,8 @@ int thread_management_client_network_data_register(int8_t interface_id, uint8_t this->network_data_set_cb_ptr = set_cb; tr_debug("thread network data send to %s", trace_ipv6(destination)); - this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, - COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); - - return 0; + return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); } int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16) @@ -306,8 +296,8 @@ int thread_management_client_network_data_unregister(int8_t interface_id, uint16 tr_debug("thread network data unregister"); - this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, - COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); + coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); return 0; } @@ -616,26 +606,29 @@ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t ad payload, ptr - payload, thread_management_client_proactive_an_cb); } -void thread_management_client_pending_coap_request_kill(int8_t interface_id) +void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id) { thread_management_t *this = thread_management_find(interface_id); - protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!this || !cur) { + if (!this) { return; } - cur->thread_info->localServerDataBase.publish_active = false; + coap_service_request_delete(this->coap_service_id, coap_message_id); +} - if (this->coap_asd_msg_id != 0) { - coap_service_request_delete(this->coap_service_id, this->coap_asd_msg_id); - this->coap_asd_msg_id = 0; - } +void thread_management_client_old_partition_data_clean(int8_t interface_id) +{ + thread_management_t *this = thread_management_find(interface_id); + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (cur->thread_info->routerIdReqCoapID != 0) { - coap_service_request_delete(this->coap_service_id, cur->thread_info->routerIdReqCoapID); - cur->thread_info->routerIdReqCoapID = 0; + if (!this || !cur) { + return; } + + cur->thread_info->localServerDataBase.publish_coap_req_id = 0; + cur->thread_info->routerIdRequested = false; + coap_service_request_delete_by_service_id(this->coap_service_id); } #endif diff --git a/source/6LoWPAN/Thread/thread_management_client.h b/source/6LoWPAN/Thread/thread_management_client.h index 583b6fcec46..f2691278ab3 100644 --- a/source/6LoWPAN/Thread/thread_management_client.h +++ b/source/6LoWPAN/Thread/thread_management_client.h @@ -65,12 +65,6 @@ void thread_management_client_init(int8_t interface_id); */ void thread_management_client_delete(int8_t interface_id); -/** Get service id of management service. - * - * When using Coap Management port service this service is the only instance used to make client transactions. - */ -int8_t thread_management_client_service_id_get(int8_t interface_id); - /** Router id handler callback. * * callback to inform when new router id is received from leader. @@ -213,9 +207,20 @@ int thread_management_client_provision_request(int8_t interface_id, uint8_t *dst */ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t address[16], const uint16_t rloc, const uint8_t ml_eid[8], const uint8_t dst_addr[16]); -/** Kill pending COAP requests. +/** Delete COAP message . + * + * Delete COAP message that is sent to COAP service. + * + * \param interface_id interface id of this Thread instance. + * \param coap_message_id COAP message to be deleted. + */ +void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id); + +/** Clear old partition data. + * + * Clear data related to old partition, like pending COAP transactions. * * \param interface_id interface id of this Thread instance. */ -void thread_management_client_pending_coap_request_kill(int8_t interface_id); +void thread_management_client_old_partition_data_clean(int8_t interface_id); #endif /* THREAD_MANAGEMENT_CLIENT_H_ */ diff --git a/source/6LoWPAN/Thread/thread_management_if.c b/source/6LoWPAN/Thread/thread_management_if.c index 767bb355389..e22f94c9985 100644 --- a/source/6LoWPAN/Thread/thread_management_if.c +++ b/source/6LoWPAN/Thread/thread_management_if.c @@ -50,7 +50,7 @@ #include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_nd.h" #include "thread_diagnostic.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_network_synch.h" #include "6LoWPAN/Thread/thread_management_internal.h" @@ -63,6 +63,7 @@ #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_extension_bootstrap.h" #include "6LoWPAN/Thread/thread_extension.h" +#include "6LoWPAN/Thread/thread_bbr_api_internal.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up #include "MLE/mle.h" @@ -71,9 +72,8 @@ #include "thread_commissioning_if.h" #include "shalib.h" #include "Common_Protocols/icmpv6.h" -#include "libDHCPv6/libDHCPv6.h" -#include "libDHCPv6/libDHCPv6_server.h" #include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_dhcpv6_server.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/blacklist/blacklist.h" #include "6LoWPAN/MAC/mac_helper.h" @@ -606,7 +606,7 @@ int thread_management_get_ml_prefix_112(int8_t interface_id, uint8_t *prefix_ptr */ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_cnt, bool stableData) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) protocol_interface_info_entry_t *cur; thread_prefix_tlv_t prefixTlv; thread_border_router_tlv_entry_t service; @@ -622,7 +622,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t return -1; } - if (DHCPv6_server_service_init(interface_id, prefix_ptr, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + if (thread_dhcp6_server_init(interface_id, prefix_ptr, cur->mac, THREAD_MIN_PREFIX_LIFETIME) != 0) { tr_warn("SerVER alloc fail"); return -1; } @@ -637,14 +637,9 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t service.P_on_mesh = true; service.stableData = stableData; - //SET Timeout - DHCPv6_server_service_set_address_validlifetime(interface_id, prefix_ptr, THREAD_MIN_PREFIX_LIFETIME); - // SET maximum number of accepted clients DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_cnt); - //Enable Mapping - //DHCPv6_server_service_set_gua_address_mapping(interface_id,prefix_ptr, true, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix); tr_debug("GUA server Generate OK"); memcpy(ptr, prefix_ptr, 8); memset(ptr + 8, 0, 8); @@ -665,7 +660,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -681,7 +676,7 @@ int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -697,7 +692,7 @@ int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -715,7 +710,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t * int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) uint8_t temp[16]; protocol_interface_info_entry_t *cur; thread_prefix_tlv_t prefixTlv; diff --git a/source/6LoWPAN/Thread/thread_management_server.c b/source/6LoWPAN/Thread/thread_management_server.c index 8a4ae139fd6..8f0bc4a59d5 100644 --- a/source/6LoWPAN/Thread/thread_management_server.c +++ b/source/6LoWPAN/Thread/thread_management_server.c @@ -100,6 +100,9 @@ typedef struct announce { typedef struct thread_management_server { scan_query_t *scan_ptr; announce_t *announce_ptr; + timeout_t *join_ent_timer; + uint8_t destination_address[16]; + uint8_t one_time_key[16]; uint16_t relay_port_joiner; uint16_t external_commissioner_port; int8_t interface_id; @@ -994,7 +997,6 @@ static int thread_management_server_energy_scan_cb(int8_t service_id, uint8_t so return -1; } - static void thread_announce_timeout_cb(void* arg) { link_configuration_s *linkConfiguration; @@ -1132,6 +1134,9 @@ int thread_management_server_init(int8_t interface_id) this->relay_port_joiner = 0; this->scan_ptr = NULL; this->announce_ptr = NULL; + this->join_ent_timer = NULL; + memset(this->destination_address,0,16); + memset(this->one_time_key,0,16); this->external_commissioner_port = THREAD_COMMISSIONING_PORT; #ifdef HAVE_THREAD_ROUTER @@ -1147,13 +1152,13 @@ int thread_management_server_init(int8_t interface_id) #endif this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); if (this->coap_service_id < 0) { - tr_warn("Thread management init failed"); + tr_error("Thread management init failed"); ns_dyn_mem_free(this); return -3; } #ifdef HAVE_THREAD_ROUTER if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { - tr_warn("Thread leader service init failed"); + tr_error("Thread leader service init failed"); ns_dyn_mem_free(this); return -3; } @@ -1191,6 +1196,7 @@ void thread_management_server_delete(int8_t interface_id) coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); coap_service_delete(this->coap_service_id); + ns_list_remove(&instance_list, this); if (this->announce_ptr) { if (this->announce_ptr->timer) { @@ -1215,6 +1221,15 @@ void thread_management_server_delete(int8_t interface_id) return; } +int8_t thread_management_server_service_id_get(int8_t interface_id) +{ + thread_management_server_t *this = thread_management_server_find(interface_id); + if (!this) { + return -1; + } + return this->coap_service_id; +} + int8_t thread_management_server_interface_id_get(int8_t coap_service_id) { thread_management_server_t *this = thread_management_find_by_service(coap_service_id); @@ -1312,6 +1327,19 @@ static int thread_management_server_entrust_send(thread_management_server_t *thi ns_dyn_mem_free(response_ptr); return 0; } + +static void thread_join_ent_timeout_cb(void *arg) +{ + thread_management_server_t *this = arg; + if(!this || !this->join_ent_timer) { + return; + } + + this->join_ent_timer = NULL; + thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); + return; +} + void joiner_router_recv_commission_msg(void *cb_res) { socket_callback_t *sckt_data = 0; @@ -1412,7 +1440,13 @@ static int thread_management_server_relay_tx_cb(int8_t service_id, uint8_t sourc if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { // KEK present in relay set pairwise key and send entrust tr_debug("Kek received"); - thread_management_server_entrust_send(this, destination_address.address, kek_ptr); + if (this->join_ent_timer) { + eventOS_timeout_cancel(this->join_ent_timer); + thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); + } + memcpy(this->destination_address, destination_address.address, 16); + memcpy(this->one_time_key, kek_ptr, 16); + this->join_ent_timer = eventOS_timeout_ms(thread_join_ent_timeout_cb, THREAD_DELAY_JOIN_ENT, this); } tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); thci_trace("joinerrouterJoinerDataRelayedOutbound"); diff --git a/source/6LoWPAN/Thread/thread_management_server.h b/source/6LoWPAN/Thread/thread_management_server.h index 88be72814a0..b7ca9fb5c1b 100644 --- a/source/6LoWPAN/Thread/thread_management_server.h +++ b/source/6LoWPAN/Thread/thread_management_server.h @@ -99,6 +99,13 @@ int thread_management_server_joiner_router_init(int8_t interface_id); * */ void thread_management_server_joiner_router_deinit(int8_t interface_id); + +/** Get service id of management service. + * + * When using Coap Management port service this service is the only instance used to make client transactions. + */ +int8_t thread_management_server_service_id_get(int8_t interface_id); + int8_t thread_management_server_interface_id_get(int8_t coap_service_id); int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data); diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 2c108ee6e88..4ff0a64038d 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -30,6 +30,7 @@ #ifdef HAVE_THREAD #include "ns_trace.h" +#include "string.h" #include "common_functions.h" #include "NWK_INTERFACE/Include/protocol.h" #include @@ -53,6 +54,7 @@ #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_data_poll.h" +#include "Common_Protocols/ipv6.h" #include "MLE/mle.h" #include "mac_api.h" #define TRACE_GROUP "thmh" @@ -699,6 +701,54 @@ static int thread_host_child_update_response_send(protocol_interface_info_entry_ return 0; } +static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info) +{ + uint8_t context; + uint16_t length = tlv_info->tlvLen; + uint8_t *ptr = tlv_info->dataPtr; + + while (length) { + context = *ptr++; + if (context & 0x80) { + if (memcmp(ptr, entry->address + 8, 8) == 0) { + return true; + } + ptr += 8; + length -= 9; + } else { + if (memcmp(ptr, entry->address, 16) == 0) { + return true; + } + ptr += 16; + length -= 17; + } + } + + return false; + +} + +static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info) +{ + bool ret_val = true; + + ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { + if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL && + !thread_addr_is_mesh_local_16(e->address, cur))) { + + if (thread_address_registration_tlv_search(e, tlv_info) == false) { + tr_debug("Address %s registration to parent failed", trace_ipv6(e->address)); + addr_set_preferred_lifetime(cur, e, 0); // deprecate address + ret_val = false; + } else if (e->preferred_lifetime == 0) { + addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite + } + } + } + + return ret_val; +} + static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) { thread_leader_data_t leaderData; @@ -710,6 +760,7 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent uint64_t pending_timestamp = 0;// means no pending timestamp mac_neighbor_table_entry_t *entry_temp; bool data_request_needed = false; + mle_tlv_info_t tlv_info = {0}; tr_debug("Child update request"); entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); @@ -738,6 +789,11 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent thread_bootstrap_network_data_update(cur); } + // Check Address Registration TLV + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { // version numbers not in sync need to send data request @@ -776,6 +832,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * thread_leader_data_t leaderData = {0}; uint8_t status; bool leader_data_received; + mle_tlv_info_t tlv_info = {0}; if (cur->thread_info->thread_endnode_parent == NULL) { return; @@ -822,6 +879,10 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * tr_debug("Setting child timeout, value=%"PRIu32, timeout); } + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + tr_debug("Keep-Alive -->Respond from Parent"); mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); diff --git a/source/6LoWPAN/Thread/thread_nd.c b/source/6LoWPAN/Thread/thread_nd.c index 717e757bffd..85020a37705 100644 --- a/source/6LoWPAN/Thread/thread_nd.c +++ b/source/6LoWPAN/Thread/thread_nd.c @@ -294,7 +294,7 @@ static void thread_nd_address_error(int8_t interface_id, const uint8_t ip_addr[1 if_address_entry_t *addr_entry = addr_get_entry(cur, ip_addr); if (addr_entry && memcmp(ml_eid, cur->iid_slaac, 8)) { addr_duplicate_detected(cur, ip_addr); - thread_extension_address_generate(cur); + thread_extension_dua_address_generate(cur, ip_addr, 64); } /* Scan IPv6 neighbour cache for registered entries of children */ @@ -547,8 +547,7 @@ int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const u } uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh); - if (neigh->state != IP_NEIGHBOUR_NEW && memcmp(nce_eui64, mac64, 8) != 0) - { + if (neigh->type == IP_NEIGHBOUR_REGISTERED && memcmp(nce_eui64, mac64, 8) != 0) { return -2; } diff --git a/source/6LoWPAN/Thread/thread_network_data_storage.c b/source/6LoWPAN/Thread/thread_network_data_storage.c index 0947cf4564b..e5ef23aa26b 100755 --- a/source/6LoWPAN/Thread/thread_network_data_storage.c +++ b/source/6LoWPAN/Thread/thread_network_data_storage.c @@ -48,7 +48,7 @@ #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_storage.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "thread_management_if.h" #include "thread_meshcop_lib.h" @@ -193,6 +193,7 @@ static uint16_t thread_nd_service_border_router_flags_read(thread_network_server flags |= (cur->P_default_route << THREAD_P_DEF_ROUTE_BIT_MOVE); flags |= (cur->P_on_mesh << THREAD_P_ON_MESH_BIT_MOVE); flags |= (cur->P_nd_dns << THREAD_P_ND_DNS_BIT_MOVE); + flags |= (cur->P_res1 << THREAD_P_ND_RES_BIT_MOVE); return flags; } @@ -872,6 +873,7 @@ static int thread_service_data_delete_mark_by_router_id(thread_network_data_serv static int thread_server_context_clean(int8_t id, thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list) { + (void) id; int retVal = -1; (void) prefixEntry; ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { @@ -881,9 +883,7 @@ static int thread_server_context_clean(int8_t id, thread_network_data_cache_entr cachePtr->stableUpdatePushed = true; } // Set context lifetime to 0 to delete - if (thread_extension_context_can_delete(id, prefixEntry->servicesPrefix, cur->contextPrefixLength)) { - lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); - } + lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); ns_list_remove(listPtr, cur); ns_dyn_mem_free(cur); retVal = 0; @@ -930,11 +930,18 @@ static bool thread_server_data_clean_by_router_id(thread_network_data_cache_entr if (cur->P_dhcp) { tr_debug("Delete DHCPv6 given address"); - thread_dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix); - } else { + dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix); + } + + if (cur->P_slaac) { tr_debug("Delete SLAAC address"); addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_SLAAC); } + + if (cur->P_res1) { + tr_debug("Delete thread domain address"); + addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_THREAD_DOMAIN); + } } ns_list_remove(listPtr, cur); @@ -995,7 +1002,7 @@ void thread_network_local_server_data_base_init(thread_network_local_data_cache_ ns_list_init(&cachePtr->service_list); cachePtr->registered_rloc16 = 0xffff; cachePtr->release_old_address = false; - cachePtr->publish_active = false; + cachePtr->publish_coap_req_id = 0; cachePtr->publish_pending = false; } @@ -1077,6 +1084,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list) { + (void) id; ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList) { ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) { if (!curContext->compression) { @@ -1090,9 +1098,7 @@ void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_d cachePtr->temporaryUpdatePushed = true; } // Set context lifetime to 0 to delete - if (thread_extension_context_can_delete(id, cur->servicesPrefix,curContext->contextPrefixLength)) { - lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); - } + lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); ns_dyn_mem_free(curContext); } } @@ -1162,7 +1168,7 @@ void thread_network_local_data_free_and_clean(thread_network_local_data_cache_en } cachePtr->publish_pending = false; - cachePtr->publish_active = false; + cachePtr->publish_coap_req_id = 0; cachePtr->release_old_address = false; } @@ -1628,6 +1634,7 @@ int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *n server_entry->P_nd_dns = service->P_nd_dns; trigDataPropagate = true; } + } if (trigDataPropagate) { @@ -1707,9 +1714,9 @@ int thread_nd_local_list_del_on_mesh_server(thread_network_data_cache_entry_t *n int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) { int retVal = -1; - tr_debug("Add prefix: %s prf:%d %s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, + tr_debug("Add prefix: %s prf:%d %s%s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, service->P_default_route?"Default Route ":"",service->P_dhcp?"DHCPv6 Server ":"", service->P_configure?"DHCPv6 Configuration ":"", - service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":""); + service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":"",service->P_res1?"P_res1 ":""); if (networkDataList) { thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv); @@ -2341,7 +2348,9 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_ if (curService->S_id != S_id) { continue; } - ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) { + /* any server will do - take first from the list */ + thread_network_data_service_server_entry_t *curServiceServer = ns_list_get_first(&curService->server_list); + if (curServiceServer) { *rlocAddress = curServiceServer->router_id; return true; } @@ -2352,7 +2361,7 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_ bool thread_nd_on_mesh_address_valid(thread_network_server_data_entry_t *curRoute) { bool onMeshActive = false; - if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred) { + if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred || curRoute->P_on_mesh) { onMeshActive = true; } diff --git a/source/6LoWPAN/Thread/thread_network_data_storage.h b/source/6LoWPAN/Thread/thread_network_data_storage.h index 10dbd298f16..b5924535a62 100644 --- a/source/6LoWPAN/Thread/thread_network_data_storage.h +++ b/source/6LoWPAN/Thread/thread_network_data_storage.h @@ -187,8 +187,8 @@ typedef struct thread_network_local_data_cache_entry_s { thread_network_data_prefix_list_t prefix_list; /*!< Local parsed or generated service list */ thread_network_data_service_list_t service_list; uint16_t registered_rloc16;/*!< Address used for latest registration */ + uint16_t publish_coap_req_id;/*!< Non-zero when publish is active */ bool release_old_address:1;/*!< true if network data can be released from old address */ - bool publish_active:1;/*!< true when publish is active */ bool publish_pending:1;/*!< true when publish attempt made during active publish */ } thread_network_local_data_cache_entry_t; @@ -344,7 +344,7 @@ uint8_t *thread_network_data_prefix_set_write(thread_network_data_cache_entry_t uint8_t *thread_network_data_service_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr); bool thread_network_data_service_hosted_by_this_router_id(thread_network_data_service_cache_entry_t *dataList, uint16_t router_id); uint16_t thread_network_data_service_child_id_from_networkdata_get(thread_network_data_cache_entry_t *networkDataList, uint16_t router_short_addr); - +thread_network_data_prefix_cache_entry_t *thread_prefix_entry_find(thread_network_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv); uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_entry_t *serverDataList, uint8_t *ptr, uint16_t routerID); uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_entry_t *serverDataList); diff --git a/source/6LoWPAN/Thread/thread_nvm_store.c b/source/6LoWPAN/Thread/thread_nvm_store.c index 0aa4657f687..18a1918b04b 100644 --- a/source/6LoWPAN/Thread/thread_nvm_store.c +++ b/source/6LoWPAN/Thread/thread_nvm_store.c @@ -292,7 +292,11 @@ int thread_nvm_store_active_configuration_remove(void) } char ac_data_path[ACTIVE_CONF_STRING_LEN]; thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); - return remove(ac_data_path); + int status = remove(ac_data_path); + if (status != 0) { + return THREAD_NVM_FILE_REMOVE_ERROR; + } + return THREAD_NVM_FILE_SUCCESS; } int thread_nvm_store_pending_configuration_remove(void) @@ -302,7 +306,11 @@ int thread_nvm_store_pending_configuration_remove(void) } char ac_data_path[PENDING_CONF_STRING_LEN]; thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE); - return remove(ac_data_path); + int status = remove(ac_data_path); + if (status != 0) { + return THREAD_NVM_FILE_REMOVE_ERROR; + } + return THREAD_NVM_FILE_SUCCESS; } diff --git a/source/6LoWPAN/Thread/thread_resolution_client.c b/source/6LoWPAN/Thread/thread_resolution_client.c index 9ea5aeaa63c..58bb6cf3255 100644 --- a/source/6LoWPAN/Thread/thread_resolution_client.c +++ b/source/6LoWPAN/Thread/thread_resolution_client.c @@ -39,6 +39,7 @@ #include "coap_service_api.h" #include "thread_config.h" +#include "thread_management_server.h" #include "thread_resolution_client.h" #define TRACE_GROUP TRACE_GROUP_THREAD_RESOLUTION_CLIENT @@ -294,7 +295,7 @@ void thread_resolution_client_init(int8_t interface_id) this->error_cb_ptr = NULL; ns_list_init(&this->queries); //TODO: Check if to use ephemeral port here - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); ns_list_add_to_start(&instance_list, this); coap_service_register_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_resolution_client_notification_post_cb); @@ -309,7 +310,7 @@ void thread_resolution_client_delete(int8_t interface_id) } coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION); - coap_service_delete(this->coap_service_id); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_ERROR); ns_list_foreach_safe(address_query_t, query, &this->queries) { ns_list_remove(&this->queries, query); ns_dyn_mem_free(query); @@ -465,6 +466,7 @@ void thread_resolution_client_timer(int8_t interface_id, uint16_t seconds) } } } - } + #endif // HAVE_THREAD_NEIGHBOR_DISCOVERY + diff --git a/source/6LoWPAN/Thread/thread_resolution_server.c b/source/6LoWPAN/Thread/thread_resolution_server.c index 362f96aa7cd..e20541eb2bf 100644 --- a/source/6LoWPAN/Thread/thread_resolution_server.c +++ b/source/6LoWPAN/Thread/thread_resolution_server.c @@ -47,6 +47,7 @@ #include "thread_config.h" #include "thread_tmfcop_lib.h" #include "thread_management_if.h" +#include "thread_management_server.h" #include "thread_commissioning_if.h" @@ -170,9 +171,9 @@ int thread_resolution_server_init(int8_t interface_id, thread_resolution_server_ } this->interface_id = interface_id; - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); if (this->coap_service_id < 0) { - tr_warn("Thread resolution init failed"); + tr_warn("Thread resolution srv init failed"); ns_dyn_mem_free(this); return -3; } @@ -193,7 +194,6 @@ void thread_resolution_server_delete(int8_t interface_id) coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_QUERY_REQUEST); - coap_service_delete(this->coap_service_id); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); } diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 0c00650f7fd..b16287a042a 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -78,7 +78,7 @@ #include "Service_Libs/nd_proxy/nd_proxy.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/blacklist/blacklist.h" -#include "thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "mac_api.h" #include "6LoWPAN/MAC/mac_data_poll.h" @@ -1027,10 +1027,10 @@ static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t sta if (!cur) { return; } - if (!cur->thread_info->routerIdReqCoapID) { + if (!cur->thread_info->routerIdRequested) { return; } - cur->thread_info->routerIdReqCoapID = 0; + cur->thread_info->routerIdRequested = false; if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER || cur->thread_info->leader_private_data ) { @@ -1088,15 +1088,15 @@ void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t * { int router_id_req_status; tr_debug("Router ID Request"); - if (cur->thread_info->routerIdReqCoapID) { + if (cur->thread_info->routerIdRequested) { tr_warn("Router ID already requested"); return; } router_id_req_status = thread_management_client_router_id_get(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_cb, status); - tr_debug("Coap address req, ID=%d", router_id_req_status); + tr_debug("RouterIDReq COAP ID=%d", router_id_req_status); if (router_id_req_status > 0) { - cur->thread_info->routerIdReqCoapID = (uint16_t)router_id_req_status; + cur->thread_info->routerIdRequested = true; } } @@ -1196,6 +1196,32 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c } + +int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout) +{ + uint16_t router_address = thread_info(cur)->routerShortAddress; + uint32_t max_timeout = 0; + if (router_address >= 0xfffe) { + router_address = mac_helper_mac16_address_get(cur); + } + if (router_address & THREAD_CHILD_MASK) { + return -1; //I am child + } + if (router_address >= 0xfffe) { + return -1; + } + mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; + + ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { + if (thread_router_addr_from_addr(cur_entry->mac16) == router_address && + !cur_entry->ffd_device && cur_entry->lifetime > max_timeout) { + max_timeout = cur_entry->lifetime; + } + } + *max_child_timeout = max_timeout; + return 0; +} + uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur) { uint16_t child_count = 0; @@ -1277,7 +1303,7 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c bool new_neigbour = false; if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) { - if (!cur->thread_info->routerIdReqCoapID) { + if (!cur->thread_info->routerIdRequested) { tr_info("Upgrade REED to Router"); thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST); } @@ -1366,7 +1392,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le uint8_t tempIPv6Address[16]; uint8_t ctxId; bool new_neighbour_created; - + thread_child_mcast_entries_remove(cur,mac64); while (data_length) { //Read ctxId = *ptr++; @@ -1389,8 +1415,8 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le tr_debug("Register %s", trace_ipv6(ptr)); if (addr_is_ipv6_multicast(ptr)) { - // Register multicast address (higher scope than link-local) - if (addr_ipv6_multicast_scope(ptr) > IPV6_SCOPE_LINK_LOCAL) { + // Register multicast address (link-local & higher) + if (addr_ipv6_multicast_scope(ptr) >= IPV6_SCOPE_LINK_LOCAL) { addr_add_group(cur, ptr); if (thread_child_mcast_entry_get(cur, ptr, mac64)) { tr_debug("Added sleepy multicast registration entry."); @@ -1665,6 +1691,11 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t * } } + if (!(id_req->mode & MLE_FFD_DEV) && addressRegisteredTlv.tlvLen == 0) { + tr_debug("No address registration TLV in MTD child id request"); + thread_child_id_request_entry_remove(cur, id_req); + return; + } id_req->keyId = security_headers->KeyIndex; id_req->keySeq = common_read_32_bit(security_headers->Keysource); @@ -1991,10 +2022,22 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t * if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) { return; } + + uint8_t mode = mle_mode_write_from_mac_entry(entry_temp); + /* check if thread neighbor class is not initialized */ + if ((thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0) && + (thread_neighbor_last_communication_time_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0)) { + /* + * Thread neighbor class is not yet initialized and we receive data_request from such child. + * Always send full network data in this case + */ + mode |= MLE_THREAD_REQ_FULL_DATA_SET | MLE_THREAD_SECURED_DATA_REQUEST; + } else { + mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index); + } + thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false); thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index); - uint8_t mode = mle_mode_write_from_mac_entry(entry_temp); - mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index); mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode); } break; @@ -2026,8 +2069,9 @@ static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info tr_debug("Buffer overflow at message write"); } - timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; - timeout.timeout_init = 1; + // timeout set to two seconds, no retries + timeout.retrans_max = 1; + timeout.timeout_init = 2; timeout.timeout_max = 3; timeout.delay = MLE_NO_DELAY; @@ -2325,7 +2369,6 @@ static uint32_t thread_reed_timeout_calculate(thread_router_select_t *routerSele static int thread_reed_advertise (protocol_interface_info_entry_t *cur) { uint32_t keySequence; - tr_debug("MLE REED ADVERTISEMENT STARTED"); struct link_configuration *linkConfiguration; linkConfiguration = thread_joiner_application_get_config(cur->id); if (!linkConfiguration) { @@ -2336,11 +2379,17 @@ static int thread_reed_advertise (protocol_interface_info_entry_t *cur) return -1; } + // FED not allowed to send advertisements + if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { + return -1; + } + uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT); if (bufId == 0) { return -1; } + tr_debug("MLE REED ADVERTISEMENT STARTED"); thread_management_get_current_keysequence(cur->id, &keySequence); mle_service_msg_update_security_params(bufId, 5, 2, keySequence); @@ -2734,4 +2783,18 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY; } +void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay) +{ + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return; + } + if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) { + return; + } + // delay reed jitter timer to allow for settings changes to distribute + thread_info(cur)->reedJitterTimer += delay; + return; +} + #endif /* HAVE_THREAD_ROUTER */ diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.h b/source/6LoWPAN/Thread/thread_router_bootstrap.h index 0143ce1e30c..6874a01b0bb 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.h @@ -52,6 +52,9 @@ int thread_router_bootstrap_mle_advertise(struct protocol_interface_info_entry * void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur); int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child); uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur); + +// max_child_timeout is longest MLE Timeout a router has registered for all of its active MTD children +int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout); void thread_router_bootstrap_child_id_handler(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_child_id_reject(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_router_id_request(struct protocol_interface_info_entry *cur, uint8_t status); @@ -73,6 +76,7 @@ void thread_router_bootstrap_anycast_address_register(protocol_interface_info_en void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur); bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur); +void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay); #else @@ -81,6 +85,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ #define thread_router_bootstrap_child_information_clear(cur) #define thread_router_bootstrap_child_count_get(cur) 0 +#define thread_router_bootstrap_child_max_timeout_get(cur, max_child_timeout) 0 #define thread_router_bootstrap_child_id_handler(cur) #define thread_router_bootstrap_child_id_reject(cur) #define thread_router_bootstrap_router_id_request(cur, status) @@ -104,7 +109,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ #define thread_router_bootstrap_routing_allowed(cur) false #define thread_router_bootstrap_address_change_notify_send(cur) #define thread_router_bootstrap_reed_merge_advertisement(cur) - +#define thread_router_bootstrap_delay_reed_jitter(interface_id, delay) #endif/*HAVE_THREAD_ROUTER*/ #endif /* THREAD_ROUTER_BOOTSTRAP_H_ */ diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 226ed6f9642..4392f993ac1 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -43,7 +43,6 @@ #ifdef HAVE_RPL #include "RPL/rpl_data.h" #endif -#include "6LoWPAN/ws/ws_common.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/ws/ws_common.h" @@ -72,7 +71,7 @@ typedef struct { bool fragmented_data:1; bool first_fragment:1; bool indirect_data:1; - bool indirect_data_cached:1; /* Data cached for delayed transmission as mac request is already active */ + bool indirect_data_cached:1; /*!< Data cached for delayed transmission as mac request is already active */ buffer_t *buf; uint8_t *fragmenter_buf; ns_list_link_t link; /*!< List link entry */ @@ -132,7 +131,7 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr); /* Fragmentation local functions */ static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr); static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq); -static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); +static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); @@ -613,40 +612,35 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_ { mac_neighbor_table_entry_t *neigh_entry_ptr = NULL; + //Validate is link known and set indirect, datareq and security key id mode if (buf->dst_sa.addr_type == ADDR_NONE) { goto tx_error_handler; } - /* If MLE is enabled, we will talk if we have an MLE association */ - if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG ) { - neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); + if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK ) { + buf->dst_sa.addr_type = ADDR_802_15_4_SHORT; + buf->dst_sa.address[2] = 0xff; + buf->dst_sa.address[3] = 0xff; + buf->link_specific.ieee802_15_4.indirectTxProcess = false; + buf->link_specific.ieee802_15_4.requestAck = false; + } else { - } else if(buf->dst_sa.addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa.address + 2)) != 0xffff) { neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); - } - //Validate neighbour - if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) { + //Validate neighbour + if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) { - if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device) { + if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device) { - } else { - //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); + } else { + //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); + goto tx_error_handler; + } + } else if (ws_info(cur) && !neigh_entry_ptr) { + //Do not accept to send unknow device goto tx_error_handler; } - } - - //Check indirect - - - if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK) { - buf->dst_sa.addr_type = ADDR_802_15_4_SHORT; - buf->dst_sa.address[2] = 0xff; - buf->dst_sa.address[3] = 0xff; - buf->link_specific.ieee802_15_4.indirectTxProcess = false; - buf->link_specific.ieee802_15_4.requestAck = false; - } else { buf->link_specific.ieee802_15_4.requestAck = true; buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr); } @@ -755,7 +749,7 @@ static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_ent ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { if (fragmenter_tx_entry->indirect_data_cached) { if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { - tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); + tr_debug_extra("Pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); fragmenter_tx_entry->indirect_data_cached = false; lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr); return true; @@ -805,7 +799,12 @@ static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type); if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) { if (++count >= interface_ptr->max_indirect_small_packets_per_child) { - lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); + tr_debug_extra("Purge seq: %d", tx_entry->buf->seq); + if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) { + /* entry could not be purged from mac, try next entry */ + tr_debug_extra("Purge failed, try next"); + count--; + } } } } @@ -822,8 +821,12 @@ static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) { if (++count >= interface_ptr->max_indirect_big_packets_total) { - tr_debug_extra("free seq: %d", tx_entry->buf->seq); - lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); + tr_debug_extra("Purge seq: %d", tx_entry->buf->seq); + if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) { + tr_debug("Purge failed, try next entry"); + /* entry could not be purged from mac, try next entry */ + count--; + } } } } @@ -911,6 +914,8 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff if (indirect) { ns_dyn_mem_free(tx_ptr->fragmenter_buf); ns_dyn_mem_free(tx_ptr); + } else { + tx_ptr->buf = NULL; } goto tx_error_handler; } @@ -1281,29 +1286,44 @@ static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *addres return true; } -static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) +static bool lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) { mcps_purge_t purge_req; purge_req.msduHandle = msduhandle; + bool mac_purge_success = false; if (interface_ptr->mpx_api) { - interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id); + if (interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id) == 0) { + mac_purge_success = true; + } } else { if (cur->mac_api->mcps_purge_req) { - cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req); + if (cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req) == 0) { + mac_purge_success = true; + } } } + + return mac_purge_success; } -static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) +static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) { - tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq); - lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq); + tr_debug("Purge from indirect handle %u, cached %d", tx_ptr->buf->seq, tx_ptr->indirect_data_cached); + if (tx_ptr->indirect_data_cached == false) { + if (lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq) == false) { + // MAC purge failed + return false; + } + } + lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL); + + return true; } void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) { - //Free firts by defined short address + //Free first by defined short address if (entry_ptr->mac16 < 0xfffe) { uint8_t temp_address[2]; common_write_16_bit(entry_ptr->mac16, temp_address); @@ -1323,7 +1343,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr //Check first indirect queue ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) { - if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { //Purge from mac lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); @@ -1331,7 +1350,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr } return 0; - } int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child) diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 4cd3316e5a8..c967b1c86c5 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -35,6 +35,8 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode); void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur); +int ws_bootstrap_restart(int8_t interface_id); + /*State machine transactions*/ void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur); @@ -50,12 +52,27 @@ void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *c void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); -void ws_bootstrap_trigle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); +void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); + +void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor); + +void ws_secondary_parent_update(protocol_interface_info_entry_t *interface); + +void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor); + +void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); + +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local); + +void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix); #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) #define ws_bootstrap_state_machine(cur) +#define ws_bootstrap_restart(cur) +#define ws_primary_parent_update(interface, neighbor) +#define ws_secondary_parent_update(interface) #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index dc02f6938a8..70d48cb40a6 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -20,11 +20,13 @@ #include "ns_types.h" +#include "ns_list.h" #include "fhss_api.h" #include "fhss_config.h" #include "net_fhss.h" #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_neighbor_class.h" +#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" struct ws_pan_information_s; struct ws_neighbor_class_s; @@ -40,6 +42,17 @@ typedef struct parent_info_s { uint32_t timestamp; /**< Timestamp when packet was received */ }parent_info_t; +typedef struct ws_nud_table_entry { + void *neighbor_info; + uint16_t timer; /*!< Timer which resolution is 100ms*/ + unsigned retry_count:2; + bool wait_response:1; /*!< True when NS is sended and wait NA, False when random timer is active*/ + bool nud_process; + ns_list_link_t link; +} ws_nud_table_entry_t; + +typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; + typedef struct ws_info_s { char network_name[33]; // Network name max 32 octets + terminating 0. uint16_t network_pan_id; @@ -54,8 +67,24 @@ typedef struct ws_info_s { uint32_t pan_version_timer; /**< border router version udate timeout */ uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ uint8_t gtkhash[32]; + bool address_registration_event_active : 1; bool configuration_learned:1; - + bool trickle_pas_running:1; + bool trickle_pa_running:1; + bool trickle_pcs_running:1; + bool trickle_pc_running:1; + // default fhss parameters for this device + uint8_t fhss_uc_dwell_interval; + uint8_t fhss_bc_dwell_interval; + uint32_t fhss_bc_interval; + uint8_t fhss_uc_channel_function; + uint8_t fhss_bc_channel_function; + uint16_t fhss_uc_fixed_channel; + uint16_t fhss_bc_fixed_channel; + uint32_t fhss_channel_mask[8]; + ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX]; + ws_nud_table_list_t active_nud_process; + ws_nud_table_list_t free_nud_entries; struct ws_pan_information_s pan_information; ws_hopping_schedule_t hopping_schdule; struct ws_neighbor_class_s neighbor_storage; @@ -65,6 +94,8 @@ typedef struct ws_info_s { #ifdef HAVE_WS +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain); + int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 4b4c067f70f..ae6fb036146 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -73,12 +73,14 @@ typedef struct ws_hopping_schedule_s { uint8_t operating_class; /**< PHY operating class default to 1 */ uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */ uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */ - uint8_t channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ + uint8_t uc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ + uint8_t bc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ uint8_t channel_spacing; /**< derived from regulatory domain. 0:200k, 1:400k, 2:600k, 3:100k */ uint8_t number_of_channels; /**< derived from regulatory domain */ uint8_t clock_drift; uint8_t timing_accurancy; - uint16_t fixed_channel; + uint16_t uc_fixed_channel; + uint16_t bc_fixed_channel; uint16_t fhss_bsi; uint32_t fhss_broadcast_interval; uint32_t channel_mask[8]; @@ -182,9 +184,19 @@ typedef struct ws_bs_ie { #define WS_FAN_VERSION_1_0 1 -#define WS_NEIGHBOR_LINK_TIMEOUT 240 +#define WS_NEIGHBOR_LINK_TIMEOUT 2200 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 +#define WS_NEIGBOR_ETX_SAMPLE_MAX 3 + +#define WS_PROBE_INIT_BASE_SECONDS 8 + +#define WS_NUD_RAND_PROBABILITY 1 + +#define WS_NUD_RANDOM_SAMPLE_LENGTH WS_NEIGHBOR_NUD_TIMEOUT / 2 + +#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100 + /* * Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set */ @@ -203,4 +215,12 @@ typedef struct ws_bs_ie { */ #define WS_RPL_DIS_TIMEOUT 1800 +/* Default FHSS timing information + * + */ +#define WS_FHSS_UC_DWELL_INTERVAL 250; +#define WS_FHSS_BC_INTERVAL 800; +#define WS_FHSS_BC_DWELL_INTERVAL 200; + + #endif /* WS_COMMON_DEFINES_H_ */ diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index c05964f00b0..5be662f3a45 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -21,11 +21,16 @@ #include "fhss_ws_extension.h" #include "6LoWPAN/ws/ws_common_defines.h" +#define RSL_UNITITIALIZED 0x7fff + typedef struct ws_neighbor_class_entry { fhss_ws_neighbor_timing_info_t fhss_data; uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/ uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/ + uint16_t routing_cost; /*!< ETX to border Router. */ bool candidate_parent:1; + bool broadcast_timing_info_stored:1; + bool broadcast_shedule_info_stored:1; } ws_neighbor_class_entry_t; /** diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index af3ca814f49..ea441ea4490 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -583,6 +583,24 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_NO_ROUTE, 0); } + /* Consider multicast forwarding /before/ calling routing code to modify + * extension headers - if that actually decides to tunnel it will + * overwrite the buffer's src_sa and dst_sa, when we want to consider + * forwarding the inner packet. This ordering works out for our only + * header-modifying multicast case of MPL: + * 1) We never want to forward packets with MPL headers, which means the + * outer packet in a tunnel gets ignored anyway. + * 2) This also means we don't have to worry that we're forwarding packets + * with the extension header not filled in yet. + * If we ever do have a multicast system where we are working with + * extension headers and forwarding those across interfaces, ipv6_get_exthdrs + * system will need a rework - probably split the "try MODIFY" call from the + * subsequent "give me tunnel parameters" part. + */ + if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) { + buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true); + } + /* Allow routing code to update extension headers */ int16_t exthdr_result; buf = ipv6_get_exthdrs(buf, IPV6_EXTHDR_MODIFY, &exthdr_result); @@ -593,10 +611,6 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) goto drop; } - if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) { - buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true); - } - /* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */ if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) { /* Avoid an infinite loop in the event of routing code failure - never diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index 26b7b3a7963..1049fe0cdd3 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -34,7 +34,6 @@ #include "DHCPv6_Server/DHCPv6_server_service.h" #include "common_functions.h" #include "NWK_INTERFACE/Include/protocol.h" -#include "6LoWPAN/Thread/thread_bbr_api_internal.h" #include "Common_Protocols/icmpv6.h" #include "dhcp_service_api.h" @@ -57,9 +56,6 @@ static int8_t dhcpv6_service_tasklet = -1; static arm_event_storage_t *dhcp_timer_storage = NULL; -static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress); - - static bool DHCP_server_service_timer_start(void) { if(!dhcp_timer_storage) { @@ -101,19 +97,16 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r nonTemporalAddress.validLifeTime = dhcp_allocated_address->lifetime; nonTemporalAddress.preferredLifeTime = dhcp_allocated_address->preferredLifetime; - // If this is solicit from existing address, flush ND cache. - if (allocateNew) { - // 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) == -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) { + if (serverBase->addCb) { + dhcp_address_cache_update_t update_info; + update_info.allocatedAddress = dhcp_allocated_address->nonTemporalAddress; + update_info.allocatedNewAddress = allocateNew; + update_info.validLifeTime = nonTemporalAddress.validLifeTime; + + if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) { address_allocated = false; libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress); } - } } @@ -213,30 +206,6 @@ void DHCPv6_server_service_tasklet(arm_event_s *event) } } -static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress) -{ - ipv6_neighbour_t *neighbour_entry; - - neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress); - if (neighbour_entry) { - tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress)); - ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); - } -} - -void DHCPv6_server_service_address_preferred_timeout_handler(int8_t interfaceId, uint8_t *targetAddress) -{ - tr_warn("Address Preferred Timeout"); - protocol_interface_info_entry_t *cur = 0; - //allocate Socket Service - - cur = protocol_stack_interface_info_get_by_id(interfaceId); - if (cur) { - ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST); - DHCPV6_server_service_remove_GUA_from_neighcache(cur, targetAddress); - } -} - static int8_t dhcpv6_server_service_tasklet_generated(void) { if (dhcpv6_service_tasklet == -1) { @@ -267,28 +236,21 @@ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], u //allocate Socket Service socketInstance = dhcp_service_init(interface, DHCP_INSTANCE_SERVER, DHCPV6_server_service_request_handler); cur = protocol_stack_interface_info_get_by_id(interface); - if (cur) { - if (dhcpv6_server_service_tasklet_generated() < 0) { - retVal = -2; - } else if (!DHCP_server_service_timer_start()) { - retVal = -2; - } else { - //allocate server - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE, DHCPv6_server_service_address_preferred_timeout_handler); - if (serverInfo) { - //if_address_entry_t *def_address = NULL; - uint8_t temp[16]; - uint8_t *ptr = temp; - //define address & Route advert's - memcpy(ptr, guaPrefix, 8); - ptr += 8; - memcpy(ptr, cur->iid_slaac, 8); - - serverInfo->socketInstance_id = socketInstance; - socketInstance = 0; - //Generate Address for current interface - retVal = 0; - } + if (!cur) { + return -1; + } + + if (dhcpv6_server_service_tasklet_generated() < 0) { + retVal = -2; + } else if (!DHCP_server_service_timer_start()) { + retVal = -2; + } else { + //allocate server + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE); + if (serverInfo) { + serverInfo->socketInstance_id = socketInstance; + socketInstance = 0; + retVal = 0; } } if (socketInstance > 0) { @@ -303,25 +265,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) libdhcpv6_gua_servers_time_update(timeUpdateInSeconds); } -void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping) -{ - uint8_t ml64[16]; - uint8_t *ptr = ml64; - memcpy(ptr, meshLocalPrefix, 8); - ptr += 8; - memcpy(ptr, clientEUID64, 8); - *ptr ^= 2; - //Generate Route Info - if (deleteMapping) { - ipv6_route_delete(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC); - } else if (ipv6_route_add(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC, 0xffffffff, 0) == 0) { - tr_debug("Route ADD OK"); - } else { - tr_warn("Route Add fail"); - } - -} - /* Delete dhcp thread dhcp router ID server. * * When this is called it close selected service and free all allocated memory. @@ -332,30 +275,32 @@ void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAd */ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses) { - protocol_interface_info_entry_t *curPtr = 0; - //allocate Socket Service - - curPtr = protocol_stack_interface_info_get_by_id(interface); - if (curPtr) { - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - //Delete Server data base - DHCPV6_server_service_remove_GUA_from_neighcache(curPtr, cur->nonTemporalAddress); + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (serverInfo) { + ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + //Delete Server data base + if (serverInfo->removeCb) { + serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL); } + } + if (serverInfo->removeCb) { // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server - ipv6_route_table_remove_info(curPtr->id, ROUTE_THREAD_PROXIED_HOST,serverInfo->guaPrefix); - dhcp_service_delete(serverInfo->socketInstance_id); + serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix); } + dhcp_service_delete(serverInfo->socketInstance_id); + } - if (delete_gua_addresses) { + if (delete_gua_addresses) { + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interface); + if (curPtr) { protocol_core_dhcpv6_allocated_address_remove(curPtr, guaPrefix); } + } - libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); + libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); + + DHCP_server_service_timer_stop(); - DHCP_server_service_timer_stop(); - } } /* Control GUA address for client by DUI.Default value is true @@ -379,33 +324,15 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu return retVal; } -/* Enable or disable GUA64 Address mapping to ML64 - * - * - * /param interface interface id of this thread instance. - * /param guaPrefix Prefix which will be removed - * /param mode - * /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64 - */ -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]) +void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb) { - int retVal = -1; - dhcpv6_gua_server_entry_s *serverInfo; - - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - if (mode == true && meshLocalPrefix == NULL) { - retVal = -2; - } else { - serverInfo->enableAddressMapping = mode; - if (meshLocalPrefix) { - memcpy(serverInfo->meshLocalPrefix, meshLocalPrefix, 8); - } - retVal = 0; - } + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return; } - return retVal; + serverInfo->addCb = add_cb; + serverInfo->removeCb = remove_cb; } /* SET max accepted clients to server, Default is 200 @@ -453,21 +380,6 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu } return retVal; } - -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64) -{ - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, targetGUA); - if (serverInfo) { - dhcpv6_alloacted_address_entry_t *entry = libdhcpv6_address_get_from_allocated_list(serverInfo, targetGUA); - if (entry) { - if (entry->preferredLifetime && (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE)) { - memcpy(targetEUI64, entry->linkId, 8); - return 0; - } - } - } - return -1; -} #else int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) @@ -497,15 +409,6 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu return -1; } -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]) -{ - (void) interface; - (void) guaPrefix; - (void) mode; - (void) meshLocalPrefix; - - return -1; -} int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) { (void) interface; @@ -522,13 +425,5 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu return -1; } -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64) -{ - (void) interfaceId; - (void) targetGUA; - (void) targetEUI64; - - return -1; -} #endif diff --git a/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 50f535f7a74..d2ba01068f4 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/source/DHCPv6_Server/DHCPv6_server_service.h @@ -23,6 +23,10 @@ #ifndef DHCPV6_SERVER_SERVICE_H_ #define DHCPV6_SERVER_SERVICE_H_ +#ifdef HAVE_DHCPV6_SERVER +#include "libDHCPv6/libDHCPv6.h" +#include "libDHCPv6/libDHCPv6_server.h" + /* Initialize dhcp Global address server. * * This instance needs to bee initialized once for each thread network interface. @@ -38,6 +42,10 @@ */ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType); + +void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb); + + /* Delete dhcp thread dhcp router ID server. * * When this is called it close selected service and free all allocated memory. @@ -51,8 +59,6 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16] void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); -//void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping); - /* Control GUA address for client by DUI.Default value is true * * @@ -63,16 +69,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode); -/* Enable or disable GUA64 Address mapping to ML64 - * - * - * /param interface interface id of this thread instance. - * /param guaPrefix Prefix which will be removed - * /param mode - * /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64 - */ -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]); - /* SET max accepted clients to server, Default is 200 * * @@ -91,7 +87,7 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ * /param validLifeTimne in seconds */ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne); - - -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64); +#else +#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses) +#endif #endif /* DHCPV6_SERVER_SERVICE_H_ */ diff --git a/source/DHCPv6_client/dhcpv6_client_api.h b/source/DHCPv6_client/dhcpv6_client_api.h new file mode 100644 index 00000000000..69ae1ddd20d --- /dev/null +++ b/source/DHCPv6_client/dhcpv6_client_api.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DHCPV6_CLIENT_API_H_ +#define DHCPV6_CLIENT_API_H_ +#include + +/* DHCP client implementation. + * + * Responsibilities of this module are: + * - handle Global address queries and refresh inside network. + * + */ + +/* Initialize dhcp client. + * + * This instance needs to bee initialized once for each network interface. + * if only one thread instance is supported this is needed to call only once. + * + * /param interface interface id of this instance. + * + */ + +void dhcp_client_init(int8_t interface); + +/* Delete dhcp client. + * + * When this is called all addressed assigned by this module are removed from stack. + */ +void dhcp_client_delete(int8_t interface); + +/* Global address handler. + * + * This module updates the addresses from dhcp server and sets them in stack. + * this module makes refresh of address when needed. + * + */ + + +/* give dhcp server and prefix for global address assignment + * + * /param interface interface where address is got + * /param dhcp_addr dhcp server ML16 address where address is registered. + * /param prefix dhcp server ML16 address where address is registered. + * /param mac64 64 bit mac address for identifieng client. + * /param error_cb error callback that is called if address cannot be created or becomes invalid. + * /param register_status true if address registered. + * + */ +typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status); + +int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb); + +/* Renew all leased adddresses might be used when short address changes + * + * /param interface interface where address is got + */ +void dhcp_client_global_address_renew(int8_t interface); + +/* Delete address from device + * if prefix is NULL all are deleted + * + * /param interface interface where address is got + * /param prefix dhcp server ML16 address where address is registered. + * + */ +void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]); + + +void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]); + + + +#endif /* DHCPV6_CLIENT_API_H_ */ diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_client.c b/source/DHCPv6_client/dhcpv6_client_service.c similarity index 74% rename from source/6LoWPAN/Thread/thread_dhcpv6_client.c rename to source/DHCPv6_client/dhcpv6_client_service.c index a49054e3ed0..06be8c8374c 100644 --- a/source/6LoWPAN/Thread/thread_dhcpv6_client.c +++ b/source/DHCPv6_client/dhcpv6_client_service.c @@ -1,34 +1,21 @@ /* - * Copyright (c) 2013-2018, Arm Limited and affiliates. - * SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "nsconfig.h" -#ifdef HAVE_THREAD #include #include #include @@ -36,31 +23,30 @@ #include "ns_list.h" #include "common_functions.h" - +#ifdef HAVE_DHCPV6 #include "dhcp_service_api.h" -#include "thread_dhcpv6_client.h" +#include "dhcpv6_client_api.h" #include "libDHCPv6/libDHCPv6.h" #include "NWK_INTERFACE/Include/protocol.h" -#include "6LoWPAN/Thread/thread_common.h" -#include "6LoWPAN/Thread/thread_bootstrap.h" -#define TRACE_GROUP "TDHP" +#define TRACE_GROUP "DHP" typedef struct { - thread_dhcp_client_global_adress_cb *global_address_cb; + dhcp_client_global_adress_cb *global_address_cb; uint16_t service_instance; + uint16_t relay_instance; uint8_t libDhcp_instance; int8_t interface; -} thread_dhcp_client_class_t; +} dhcp_client_class_t; -thread_dhcp_client_class_t dhcp_client; +static dhcp_client_class_t dhcp_client; -void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr); +void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr); -void thread_dhcp_client_init(int8_t interface) +void dhcp_client_init(int8_t interface) { - // No support for multible thread instances yet. + // No support for multible instances yet. dhcp_client.service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL); dhcp_client.interface = interface; dhcp_client.libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id(); @@ -68,7 +54,13 @@ void thread_dhcp_client_init(int8_t interface) return; } -void thread_dhcp_client_delete(int8_t interface) +void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]) +{ + dhcp_client.relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL); + dhcp_service_relay_instance_enable(dhcp_client.relay_instance, border_router_address); +} + +void dhcp_client_delete(int8_t interface) { protocol_interface_info_entry_t *cur = NULL; dhcpv6_client_server_data_t *srv_data_ptr; @@ -96,7 +88,7 @@ void thread_dhcp_client_delete(int8_t interface) } -void thread_dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) +void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) { if (srv_data_ptr != NULL) { @@ -159,12 +151,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime; memcpy(srv_data_ptr->serverLinkId, serverId.linkID, 8); srv_data_ptr->serverLinkType = serverId.linkType; - srv_data_ptr->serverLinkType = serverId.linkType; srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0; srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1; srv_data_ptr->iaNonTemporalStructValid = true; - thread_dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr); + dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr); if (dhcp_client.global_address_cb) { @@ -172,11 +163,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin } return RET_MSG_ACCEPTED; error_exit: - thread_dhcpv6_client_send_error_cb(srv_data_ptr); + dhcpv6_client_send_error_cb(srv_data_ptr); return RET_MSG_ACCEPTED; } -int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb) +int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb) { dhcpv6_solication_base_packet_s solPacket = {0}; dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; @@ -190,16 +181,19 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st } srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr); + if (!srv_data_ptr) { + tr_error("OOM srv_data_ptr"); + return -1; + } payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); - - if (payload_ptr == NULL || srv_data_ptr == NULL) { - ns_dyn_mem_free(payload_ptr); + if (!payload_ptr) { libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr); - tr_error("Out of memory"); + tr_error("OOM payload_ptr"); return -1; } + dhcp_client.global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code. srv_data_ptr->GlobalAddress = true; // Build solicit @@ -214,17 +208,22 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st // send solicit srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb); - return srv_data_ptr->transActionId ? 0 : -1; + if (srv_data_ptr->transActionId == 0) { + ns_dyn_mem_free(payload_ptr); + libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr); + return -1; + } + + return 0; } -void thread_dhcp_client_global_address_renew(int8_t interface) +void dhcp_client_global_address_renew(int8_t interface) { - // only prepared for changes in thread specifications (void)interface; return; } -void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]) +void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]) { protocol_interface_info_entry_t *cur; dhcpv6_client_server_data_t *srv_data_ptr; @@ -249,7 +248,7 @@ void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_add return; } -void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) +void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) { dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; dhcp_link_options_params_t serverLink; @@ -275,7 +274,7 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_ payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); if (payload_ptr == NULL) { - addr->state_timer = 200;//Retry after? should there be maximum 20 second retry + addr->state_timer = 200; //Retry after 20 seconds tr_error("Out of memory"); return ; } @@ -299,9 +298,14 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_ libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &serverLink); // send solicit srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, srv_data_ptr->server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb); + if (srv_data_ptr->transActionId == 0) { + ns_dyn_mem_free(payload_ptr); + addr->state_timer = 200; //Retry after 20 seconds + tr_error("DHCP renew send failed"); + } } -void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr) +void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr) { protocol_interface_info_entry_t *cur = NULL; if_address_entry_t *address_entry = NULL; @@ -335,6 +339,7 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_ } } address_entry->state_timer = renewTimer; - address_entry->cb = thread_dhcpv6_renew; + address_entry->cb = dhcpv6_renew; } + #endif diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 9315d36e95c..8a1c2edc9d6 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -37,7 +37,9 @@ typedef enum mac_event_t { MAC_TIMER_ACK, MAC_TIMER_CCA, MAC_TX_FAIL, - MAC_TX_TIMEOUT + MAC_TX_TIMEOUT, + MAC_UNKNOWN_DESTINATION, + MAC_TX_PRECOND_FAIL } mac_event_t; typedef enum mac_tx_status_type_t { @@ -89,8 +91,12 @@ typedef enum arm_nwk_mlme_event_type { ARM_NWK_MAC_MLME_INDIRECT_DATA_POLL_AFTER_DATA = 5, } arm_nwk_mlme_event_type_e; +#define ENHANCED_ACK_MAX_LENGTH 255 + typedef struct dev_driver_tx_buffer { uint8_t *buf; + uint8_t *enhanced_ack_buf; + uint16_t ack_len; uint16_t len; unsigned priority:2; } dev_driver_tx_buffer_s; @@ -134,6 +140,11 @@ typedef struct mac_tx_status_t { uint8_t retry; } mac_tx_status_t; +typedef struct mac_mcps_data_conf_fail_s { + uint8_t msduHandle; /**< Handle associated with MSDU */ + uint8_t status; /**< Status of the failing MSDU transmission */ +} mac_mcps_data_conf_fail_t; + typedef struct protocol_interface_rf_mac_setup { int8_t mac_interface_id; bool macUpState; @@ -229,6 +240,7 @@ typedef struct protocol_interface_rf_mac_setup { uint8_t max_ED; uint16_t mlme_ED_counter; mac_tx_status_t mac_tx_status; + mac_mcps_data_conf_fail_t mac_mcps_data_conf_fail; struct cca_structure_s *cca_structure; /* MAC Security components */ struct mlme_device_descriptor_s *device_description_table; diff --git a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c index d326aaa078a..3f09ca01baf 100644 --- a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c +++ b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c @@ -65,13 +65,24 @@ uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api) return datarate; } +uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api) +{ + protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api); + if (!mac_setup) { + return 0; + } + uint32_t timestamp; + mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)×tamp); + return timestamp; +} + int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number) { protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api); if (!mac_setup) { return -1; } - if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && mac_setup->active_pd_data_request->asynch_request)) { + if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && (mac_setup->active_pd_data_request->asynch_request || mac_setup->timer_mac_event == MAC_TIMER_ACK))) { return -1; } return mac_mlme_rf_channel_change(mac_setup, channel_number); diff --git a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h index 431cd9cd1ae..364c94339f7 100644 --- a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h +++ b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h @@ -21,6 +21,7 @@ uint16_t mac_read_tx_queue_sizes(const fhss_api_t *fhss_api, bool broadcast_queue); int mac_read_64bit_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address); uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api); +uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api); int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number); int mac_fhss_frame_tx(const fhss_api_t *fhss_api, int frame_type); int mac_synch_lost(const fhss_api_t *fhss_api); diff --git a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c index 2867513170f..39711c22b54 100644 --- a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c +++ b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c @@ -337,16 +337,16 @@ void mac_header_security_components_read(mac_pre_parsed_frame_t *buffer, mlme_se } -uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) +static bool mac_header_pan_full_compressed(const mac_fcf_sequence_t *header) { - - if (!header->SrcPanPresents) { - if (!header->DstPanPresents) { - return 0xffff; - } - return mac_header_get_dst_panid(header, ptr); + if (header->frameVersion == MAC_FRAME_VERSION_2015 && (!header->DstPanPresents && !header->SrcPanPresents) && header->intraPan) { + return true; } + return false; +} +static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) +{ ptr += mac_fcf_lenght(header);//Skip FCF + DSN ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address @@ -354,15 +354,42 @@ uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_ return common_read_16_bit_inverse(ptr); } -uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) +static uint16_t mac_header_read_dst_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) +{ + ptr += mac_fcf_lenght(header);//Skip FCF + DSN + + return common_read_16_bit_inverse(ptr); +} + +uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id) +{ + if (mac_header_pan_full_compressed(header)) { + return configured_pan_id; + } + + if (!header->SrcPanPresents) { + if (!header->DstPanPresents) { + return 0xffff; + } + return mac_header_read_dst_pan(header, ptr); + } + + return mac_header_read_src_pan(header, ptr); +} + +uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id) { + if (mac_header_pan_full_compressed(header)) { + return configured_pan_id; + } if (!header->DstPanPresents) { + if (header->SrcPanPresents && header->frameVersion == MAC_FRAME_VERSION_2015 && header->DstAddrMode == MAC_ADDR_MODE_NONE) { + return mac_header_read_src_pan(header, ptr); + } return 0xffff; } - ptr += mac_fcf_lenght(header);//Skip FCF + DSN - - return common_read_16_bit_inverse(ptr); + return mac_header_read_dst_pan(header, ptr); } void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr) diff --git a/source/MAC/IEEE802_15_4/mac_header_helper_functions.h b/source/MAC/IEEE802_15_4/mac_header_helper_functions.h index 4231f398209..5ce872323f8 100644 --- a/source/MAC/IEEE802_15_4/mac_header_helper_functions.h +++ b/source/MAC/IEEE802_15_4/mac_header_helper_functions.h @@ -59,8 +59,8 @@ uint16_t mac_buffer_total_payload_length(struct mac_pre_build_frame *buffer); /** * Next function should only call when address mode is not MAC_ADDR_MODE_NONE and parsed proper header! */ -uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); -uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); +uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id); +uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id); void mac_header_get_src_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); void mac_header_get_dst_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); uint8_t mac_address_length(uint8_t address_mode); diff --git a/source/MAC/IEEE802_15_4/mac_indirect_data.c b/source/MAC/IEEE802_15_4/mac_indirect_data.c index 3820c16e8d2..db09d73f1be 100644 --- a/source/MAC/IEEE802_15_4/mac_indirect_data.c +++ b/source/MAC/IEEE802_15_4/mac_indirect_data.c @@ -134,7 +134,7 @@ uint8_t mac_indirect_data_req_handle(mac_pre_parsed_frame_t *buf, protocol_inter comm_status.status = MLME_DATA_POLL_NOTIFICATION; //Call com status - comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), mac_ptr->pan_id); comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index cfe56837606..f118770c330 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -70,6 +70,7 @@ static void mac_set_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup static void mac_clear_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static bool mac_read_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer); +static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup); static int8_t mac_tasklet_event_handler = -1; @@ -87,47 +88,18 @@ static uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s return timestamp; } -static void mac_data_request_init(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) -{ - rf_mac_setup->active_pd_data_request = buffer; - if (buffer->asynch_request) { - buffer->asynch_channel = rf_mac_setup->mac_channel; //Store Original channel - uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list); - if (channel <= 0xff) { - uint8_t switch_channel = channel; - if (rf_mac_setup->mac_channel != switch_channel) { - mac_mlme_mac_radio_disabled(rf_mac_setup); - rf_mac_setup->mac_channel = channel; - mac_mlme_mac_radio_enable(rf_mac_setup); - } - } - } -} - static bool mac_data_request_confirmation_finnish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) { if (!buffer->asynch_request) { return true; } - uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list); - uint8_t switch_channel; - bool return_value; - - if (channel > 0x00ff) { - return_value = true; - switch_channel = buffer->asynch_channel; - } else { - switch_channel = channel; - return_value = false; - } - //Set original Channel back if channel is switched - if (rf_mac_setup->mac_channel != switch_channel) { - mac_mlme_mac_radio_disabled(rf_mac_setup); - rf_mac_setup->mac_channel = switch_channel; - mac_mlme_mac_radio_enable(rf_mac_setup); + if (mlme_scan_analyze_next_channel(&buffer->asynch_channel_list, false) > 0x00ff) { + mac_mlme_rf_channel_change(rf_mac_setup, buffer->asynch_channel); + return true; } - return return_value; + + return false; } @@ -145,7 +117,6 @@ static void mac_data_poll_radio_disable_check(protocol_interface_rf_mac_setup_s static void mcps_data_confirm_cb(protocol_interface_rf_mac_setup_s *rf_mac_setup, mcps_data_conf_t *confirm, mac_pre_parsed_frame_t *ack_buf) { - mac_data_poll_radio_disable_check(rf_mac_setup); if( get_sw_mac_api(rf_mac_setup) ) { @@ -363,13 +334,14 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set verify_status: if (status != MLME_SUCCESS){ - mcps_data_conf_t confirm; - memset(&confirm, 0, sizeof(mcps_data_conf_t)); - confirm.msduHandle = data_req->msduHandle; - confirm.status = status; tr_debug("DATA REQ Fail %u", status); + rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = data_req->msduHandle; + rf_mac_setup->mac_mcps_data_conf_fail.status = status; mcps_sap_prebuild_frame_buffer_free(buffer); - mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); + if (mcps_sap_pd_confirm_failure(rf_mac_setup) != 0) { + // event sending failed, calling handler directly + mac_pd_data_confirm_failure_handle(rf_mac_setup); + } } } @@ -568,7 +540,7 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme //READ SRC Address - uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b)); + uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b), rf_mac_setup->pan_id); mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address); neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode; neighbour_validation.keyId = security_params->KeyIndex; @@ -670,10 +642,11 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme static void mcps_comm_status_indication_generate(uint8_t status, mac_pre_parsed_frame_t *buf, mac_api_t * mac) { mlme_comm_status_t comm_status; + protocol_interface_rf_mac_setup_s *rf_ptr = buf->mac_class_ptr; memset(&comm_status,0 ,sizeof(mlme_comm_status_t) ); comm_status.status = status; //Call com status - comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_ptr->pan_id); comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; @@ -723,12 +696,14 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte //Parse data data_ind->DSN = buf->fcf_dsn.DSN; data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode; - data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr); data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode; - data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->SrcAddr); + data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); + data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); + data_ind->mpduLinkQuality = buf->LQI; data_ind->signal_dbm = buf->dbm; data_ind->timestamp = buf->timestamp; @@ -739,7 +714,6 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte if (buf->fcf_dsn.securityEnabled) { status = mac_data_interface_decrypt_packet(buf, &data_ind->Key); if (status != MLME_SUCCESS) { - tr_debug("Decrypt fail, %d", status); mcps_comm_status_indication_generate(status, buf, mac); goto DROP_PACKET; } @@ -772,6 +746,12 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte ie_list.payloadIeListLength = buf->payloadsIeLength; ie_list.headerIeList = buf->headerIePtr; ie_list.headerIeListLength = buf->headerIeLength; + //Swap compressed address to broadcast when dst Address is elided + if (buf->fcf_dsn.DstAddrMode == MAC_ADDR_MODE_NONE) { + data_ind->DstAddrMode = MAC_ADDR_MODE_16_BIT; + data_ind->DstAddr[0] = 0xff; + data_ind->DstAddr[1] = 0xff; + } mac->data_ind_ext_cb(mac, data_ind, &ie_list); } else { @@ -796,7 +776,7 @@ static void mac_lib_res_no_data_to_req(mac_pre_parsed_frame_t *buffer, protocol_ buf->fcf_dsn.SrcAddrMode = buffer->fcf_dsn.DstAddrMode; buf->fcf_dsn.DstAddrMode = buffer->fcf_dsn.SrcAddrMode; //SET PANID - buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer)); + buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), rf_mac_setup->pan_id); buf->DstPANId = buf->SrcPANId; mac_header_get_dst_address(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), buf->SrcAddr); @@ -910,7 +890,7 @@ static void mac_data_interface_parse_beacon(mac_pre_parsed_frame_t *buf, protoco uint8_t *pending_address_list = NULL; uint8_t SuperframeSpec[2]; - uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); //validate beacon pan-id and filter other network out if (rf_mac_setup->pan_id < 0xffff && (rf_mac_setup->pan_id != src_pan_id && !rf_mac_setup->macAcceptAnyBeacon)) { @@ -1045,6 +1025,14 @@ static void mac_data_interface_frame_handler(mac_pre_parsed_frame_t *buf) } +static void mac_mcps_asynch_finish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) +{ + if (buffer->asynch_request && rf_mac_setup->fhss_api) { + // Must return to scheduled channel after asynch process by calling TX done + rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); + } +} + void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_setup) { if (!rf_mac_setup) { @@ -1064,9 +1052,10 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false); if (buffer) { - mac_data_request_init(rf_mac_setup, buffer); + rf_mac_setup->active_pd_data_request = buffer; if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { rf_mac_setup->active_pd_data_request = NULL; + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { return; @@ -1077,7 +1066,6 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s } } - static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_interface_rf_mac_setup_s *rf_mac_setup) { //allocate Data ind primitiv and parse packet to that @@ -1106,20 +1094,18 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter return 0; } -static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) { - +static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) +{ if (rf_mac_setup->active_pd_data_request) { mac_pre_build_frame_t *buffer = rf_mac_setup->active_pd_data_request; if (mac_data_request_confirmation_finnish(rf_mac_setup, buffer) ) { rf_mac_setup->active_pd_data_request = NULL; - if (buffer->asynch_request && rf_mac_setup->fhss_api) { - // Must return to scheduled channel after asynch process by calling TX done - rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); - } + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { rf_mac_setup->active_pd_data_request = NULL; + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { return; @@ -1130,9 +1116,17 @@ static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac mac_mcps_trig_buffer_from_queue(rf_mac_setup); } +static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) +{ + mcps_data_conf_t mcps_data_conf; + memset(&mcps_data_conf, 0, sizeof(mcps_data_conf_t)); + mcps_data_conf.msduHandle = rf_mac_setup->mac_mcps_data_conf_fail.msduHandle; + mcps_data_conf.status = rf_mac_setup->mac_mcps_data_conf_fail.status; + mcps_data_confirm_cb(rf_mac_setup, &mcps_data_conf, NULL); +} -static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { - +static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) +{ protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr; if (!rf_mac_setup->active_pd_data_request) { @@ -1147,10 +1141,6 @@ static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { } rf_mac_setup->active_pd_data_request = NULL; - if (buffer->asynch_request && rf_mac_setup->fhss_api) { - // Must return to scheduled channel after asynch process by calling TX done - rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); - } mcps_data_confirm_handle(rf_mac_setup, buffer, buf); mcps_sap_pre_parsed_frame_buffer_free(buf); @@ -1177,6 +1167,10 @@ static void mac_mcps_sap_data_tasklet(arm_event_s *event) mac_pd_data_confirm_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr); break; + case MCPS_SAP_DATA_CNF_FAIL_EVENT: + mac_pd_data_confirm_failure_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr); + break; + case MCPS_SAP_DATA_ACK_CNF_EVENT: mac_pd_data_ack_handler((mac_pre_parsed_frame_t*)event->data_ptr); break; @@ -1277,14 +1271,8 @@ static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_ if (buffer->fcf_dsn.DstAddrMode && buffer->fcf_dsn.ackRequested) { device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode); if (!device_description) { - - if (rf_ptr->mac_security_bypass_unknow_device && (buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT - && buffer->aux_header.securityLevel > AES_SECURITY_LEVEL_ENC)) { - - } else { - buffer->status = MLME_UNAVAILABLE_KEY; - return false; - } + buffer->status = MLME_UNAVAILABLE_KEY; + return false; } } nonce_ext_64_ptr = rf_ptr->mac64; @@ -1350,7 +1338,11 @@ static void mac_common_data_confirmation_handle (protocol_interface_rf_mac_setup //Enable Radio mac_mlme_mac_radio_enable(rf_mac_setup); buf->status = MLME_TRANSACTION_EXPIRED; - } + } else if (m_event == MAC_UNKNOWN_DESTINATION) { + buf->status = MLME_UNAVAILABLE_KEY; + }/** else if (m_event == MAC_TX_PRECOND_FAIL) { + * Nothing to do, status already set to buf->status. + }**/ } } @@ -1419,7 +1411,7 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, sw_mac_stats_update(rf_ptr, STAT_MAC_TX_CCA_ATT, rf_ptr->mac_tx_status.cca_cnt); sw_mac_stats_update(rf_ptr, STAT_MAC_TX_RETRY, rf_ptr->mac_tx_status.retry); mcps_data_conf_t confirm; - if (rf_ptr->fhss_api) { + if (rf_ptr->fhss_api && !buffer->asynch_request) { // FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) { if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) { @@ -1615,6 +1607,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m buffer->fcf_dsn.frameVersion = fcf->frameVersion; buffer->fcf_dsn.framePending = rf_ptr->mac_frame_pending; buffer->fcf_dsn.DSN = fcf->DSN; + buffer->fcf_dsn.intraPan = fcf->intraPan; buffer->fcf_dsn.sequenceNumberSuppress = fcf->sequenceNumberSuppress; buffer->fcf_dsn.DstPanPresents = fcf->DstPanPresents; buffer->fcf_dsn.SrcAddrMode = fcf->DstAddrMode; @@ -1628,9 +1621,8 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn); - buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr); - buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr); - + buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr, rf_ptr->pan_id); + buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr, rf_ptr->pan_id); mac_header_get_src_address(fcf, data_ptr, buffer->DstAddr); mac_header_get_dst_address(fcf, data_ptr, buffer->SrcAddr); @@ -1696,7 +1688,15 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m //Add MHR length to total length frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len; - if ((frame_length) > dev_driver->phy_MTU - 2) { + uint16_t ack_mtu_size; + if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_MTU) { + ack_mtu_size = dev_driver->phy_MTU; + } else { + ack_mtu_size = ENHANCED_ACK_MAX_LENGTH; + } + + + if ((frame_length) > ack_mtu_size - 2) { buffer->status = MLME_FRAME_TOO_LONG; if (buffer->fcf_dsn.securityEnabled) { @@ -1708,14 +1708,14 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m } rf_ptr->mac_tx_status.length = frame_length; - uint8_t *ptr = tx_buf->buf; + uint8_t *ptr = tx_buf->enhanced_ack_buf; if (dev_driver->phy_header_length) { ptr += dev_driver->phy_header_length; } - tx_buf->len = frame_length; + tx_buf->ack_len = frame_length; uint8_t *mhr_start = ptr; - buffer->tx_time = rx_time + 196; //Send 196 us later + buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later ptr = mac_generic_packet_write(rf_ptr, ptr, buffer); @@ -1731,9 +1731,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m csma_params.cca_enabled = false; rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t*) &csma_params); if (rf_ptr->active_pd_data_request) { + timer_mac_stop(rf_ptr); mac_pd_sap_set_phy_tx_time(rf_ptr, 0, false); } - return mcps_pd_data_cca_trig(rf_ptr, buffer); } @@ -1803,6 +1803,7 @@ static int8_t mcps_generic_packet_rebuild(protocol_interface_rf_mac_setup_s *rf_ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer) { + platform_enter_critical(); mac_mlme_mac_radio_enable(rf_ptr); rf_ptr->macTxProcessActive = true; if (rf_ptr->rf_csma_extension_supported) { @@ -1810,18 +1811,35 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m bool cca_enabled; if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { cca_enabled = false; + rf_ptr->mac_ack_tx_active = true; } else { + if (rf_ptr->mac_ack_tx_active) { + mac_csma_backoff_start(rf_ptr); + platform_exit_critical(); + return -1; + } cca_enabled = true; } mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled); if (mac_plme_cca_req(rf_ptr) != 0) { - rf_ptr->macTxProcessActive = false; - return -1; + if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { + rf_ptr->mac_ack_tx_active = false; + // For Ack, stop the active TX process + rf_ptr->macTxProcessActive = false; + // If MAC had TX process active before Ack transmission, + // the TX process has to be restarted in case the Ack transmission failed. + if (rf_ptr->active_pd_data_request) { + mac_csma_backoff_start(rf_ptr); + } + platform_exit_critical(); + return -1; + } + mac_csma_backoff_start(rf_ptr); } } else { timer_mac_start(rf_ptr, MAC_TIMER_CCA, (uint16_t)(buffer->tx_time / 50)); } - + platform_exit_critical(); return 0; } @@ -1891,19 +1909,18 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup } } //Start TX process immediately - mac_data_request_init(rf_mac_setup, buffer); + rf_mac_setup->active_pd_data_request = buffer; if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { - rf_mac_setup->active_pd_data_request = NULL; - mcps_data_conf_t confirm; - memset(&confirm, 0, sizeof(mcps_data_conf_t)); - confirm.msduHandle = buffer->msduHandle; - confirm.status = buffer->status; - bool requested_from_up = buffer->upper_layer_request; - mcps_sap_prebuild_frame_buffer_free(buffer); - if (requested_from_up) { - mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); + rf_mac_setup->mac_tx_result = MAC_TX_PRECOND_FAIL; + rf_mac_setup->macTxRequestAck = false; + if (mcps_sap_pd_confirm(rf_mac_setup) != 0) { + // can't send event, try calling error handler directly + rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = buffer->msduHandle; + rf_mac_setup->mac_mcps_data_conf_fail.status = buffer->status; + mcps_sap_prebuild_frame_buffer_free(buffer); + rf_mac_setup->active_pd_data_request = NULL; + mac_pd_data_confirm_failure_handle(rf_mac_setup); } - //Call } return; @@ -1981,7 +1998,7 @@ static mac_pre_build_frame_t * mcps_sap_pd_req_queue_read(protocol_interface_rf_ // With FHSS, check TX conditions if (rf_mac_setup->fhss_api) { while (buffer) { - if ((flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer), + if (buffer->asynch_request || (flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer), buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length, rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true)) { break; @@ -2083,10 +2100,10 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer) return eventOS_event_send(&event); } -void mcps_sap_pd_confirm(void *mac_ptr) +int8_t mcps_sap_pd_confirm(void *mac_ptr) { if (mac_tasklet_event_handler < 0 || !mac_ptr) { - return; + return -2; } arm_event_s event = { .receiver = mac_tasklet_event_handler, @@ -2097,8 +2114,24 @@ void mcps_sap_pd_confirm(void *mac_ptr) .priority = ARM_LIB_HIGH_PRIORITY_EVENT, }; - eventOS_event_send(&event); + return eventOS_event_send(&event); +} +int8_t mcps_sap_pd_confirm_failure(void *mac_ptr) +{ + if (mac_tasklet_event_handler < 0 || !mac_ptr) { + return -2; + } + arm_event_s event = { + .receiver = mac_tasklet_event_handler, + .sender = 0, + .event_id = 0, + .data_ptr = mac_ptr, + .event_type = MCPS_SAP_DATA_CNF_FAIL_EVENT, + .priority = ARM_LIB_HIGH_PRIORITY_EVENT, + }; + + return eventOS_event_send(&event); } void mcps_sap_pd_ack(void *ack_ptr) @@ -2226,17 +2259,14 @@ static bool mcps_sap_purge_req_from_queue(protocol_interface_rf_mac_setup_s *rf_ uint8_t status = false; rf_mac_setup->pd_data_request_queue_to_go = mcps_sap_purge_from_list(rf_mac_setup->pd_data_request_queue_to_go, msduhandle, &status); - if (status) { - return true; + if (!status) { + rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status); } - rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status); - return status; - } -void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req) +uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req) { mcps_purge_conf_t confirmation; confirmation.msduHandle = purge_req->msduHandle; @@ -2250,4 +2280,6 @@ void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, if( get_sw_mac_api(rf_mac_setup) ) { get_sw_mac_api(rf_mac_setup)->purge_conf_cb(get_sw_mac_api(rf_mac_setup), &confirmation); } + + return confirmation.status; } diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.h b/source/MAC/IEEE802_15_4/mac_mcps_sap.h index 59d14cdbf76..2e88e69c53f 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.h +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.h @@ -48,14 +48,14 @@ typedef enum { #define MAC_PD_DATA_MEDIUM_PRIORITY 1 //Indirect Data which is polled #define MAC_PD_DATA_HIGH_PRIOTITY 2 //Beacon request Beacon response -#define MCPS_SAP_DATA_IND_EVENT 1 -#define MCPS_SAP_DATA_CNF_EVENT 2 -#define MAC_MLME_EVENT_HANDLER 3 -#define MAC_MCPS_INDIRECT_TIMER_CB 4 -#define MAC_MLME_SCAN_CONFIRM_HANDLER 5 -#define MAC_SAP_TRIG_TX 6 -#define MCPS_SAP_DATA_ACK_CNF_EVENT 7 - +#define MCPS_SAP_DATA_IND_EVENT 1 +#define MCPS_SAP_DATA_CNF_EVENT 2 +#define MCPS_SAP_DATA_CNF_FAIL_EVENT 3 +#define MAC_MLME_EVENT_HANDLER 4 +#define MAC_MCPS_INDIRECT_TIMER_CB 5 +#define MAC_MLME_SCAN_CONFIRM_HANDLER 6 +#define MAC_SAP_TRIG_TX 7 +#define MCPS_SAP_DATA_ACK_CNF_EVENT 8 /** * @brief struct mac_aux_security_header_t MAC auxiliarity security header structure @@ -180,7 +180,9 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer); /** * MAC MCPS SAP layer data confirmation event trig */ -void mcps_sap_pd_confirm(void *mac_ptr); +int8_t mcps_sap_pd_confirm(void *mac_ptr); + +int8_t mcps_sap_pd_confirm_failure(void *mac_ptr); void mcps_sap_pd_ack(void *ack_ptr); @@ -200,7 +202,7 @@ int mac_convert_frame_type_to_fhss(uint8_t frame_type); void mcps_sap_trig_tx(void *mac_ptr); -void mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req); +uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req); int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer); diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index bdf1c049690..51c63f329f0 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -85,7 +85,7 @@ static void mac_mlme_energy_scan_start(protocol_interface_rf_mac_setup_s *rf_mac rf_mac_setup->macRfRadioTxActive = false; } -uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list) +uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list, bool clear_channel) { uint8_t i, j = 0, k = 1; uint32_t mask = 1; @@ -101,7 +101,9 @@ uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list) { if (*channel_mask & mask) { - *channel_mask &= ~mask; + if (clear_channel) { + *channel_mask &= ~mask; + } return (i+j*32); } mask <<= 1; @@ -280,7 +282,7 @@ static void mac_mlme_scan_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) { uint8_t channel; - channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); + channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true); mac_mlme_scan_init(channel, rf_mac_setup); } @@ -400,14 +402,14 @@ int8_t mac_mlme_start_req(const mlme_start_t *s, struct protocol_interface_rf_ma tr_debug("MAC: Start network %u channel %x panid", s->LogicalChannel, s->PANId); mac_mlme_set_panid(rf_mac_setup, s->PANId); + // Synchronize FHSS if (rf_mac_setup->fhss_api) { - rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId); - } - - if (!rf_mac_setup->fhss_api) { + rf_mac_setup->mac_channel = rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId); + } else { rf_mac_setup->mac_channel = s->LogicalChannel; } + mac_mlme_start_request(rf_mac_setup); if (s->PANCoordinator) { //tr_debug("Cordinator"); @@ -795,7 +797,7 @@ static void mlme_scan_operation(protocol_interface_rf_mac_setup_s *rf_mac_setup) resp->ResultListSize++; } - channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); + channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true); if (channel > 0xff || rf_mac_setup->mac_mlme_scan_resp->ResultListSize == MLME_MAC_RES_SIZE_MAX) { resp->status = MLME_SUCCESS; tr_debug("Scan Complete..Halt MAC"); @@ -981,6 +983,7 @@ void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_ma eventOS_callback_timer_unregister(rf_mac->mac_mcps_timer); ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.buf); + ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.enhanced_ack_buf); ns_dyn_mem_free(rf_mac->mac_beacon_payload); mac_sec_mib_deinit(rf_mac); @@ -1510,8 +1513,9 @@ int8_t mac_mlme_rf_channel_change(protocol_interface_rf_mac_setup_s *rf_mac_setu return 0; } platform_enter_critical(); - rf_mac_setup->mac_channel = new_channel; - rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &rf_mac_setup->mac_channel); + if (rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &new_channel) == 0) { + rf_mac_setup->mac_channel = new_channel; + } platform_exit_critical(); return 0; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.h b/source/MAC/IEEE802_15_4/mac_mlme.h index 41f29601596..5878f702707 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.h +++ b/source/MAC/IEEE802_15_4/mac_mlme.h @@ -125,6 +125,6 @@ int8_t mac_mlme_beacon_tx(struct protocol_interface_rf_mac_setup *rf_ptr); uint8_t mac_mlme_beacon_req_tx(struct protocol_interface_rf_mac_setup *rf_ptr); int8_t mac_mlme_virtual_confirmation_handle(int8_t driver_id, const uint8_t *data_ptr, uint16_t length); -uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list); +uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list, bool clear_channel); #endif /* MAC_MLME_H_ */ diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 98586cf813a..8f71f73b309 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -38,8 +38,13 @@ /* Define TX Timeot Period */ // Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout #define NWKTX_TIMEOUT_PERIOD (1200*20) +// Measured 3750us with 1280 byte secured packet from calculating TX time to starting CSMA timer on PHY. +// Typically varies from 500us to several milliseconds depending on packet size and the platform. +// MAC should learn and make this dynamic by sending first few packets with predefined CSMA period. +#define MIN_FHSS_CSMA_PERIOD_US 4000 static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry); +static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr); void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup) { @@ -64,7 +69,7 @@ static uint16_t mac_csma_backoff_period_convert_to50us(uint8_t random, uint8_t b return (random * backoff_period_in_10us) / 5; } -static void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) +void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) { uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup); uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff, rf_mac_setup->backoff_period_in_10us); @@ -90,6 +95,13 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (backoff_in_us == 0) { backoff_in_us = 1; } + if (rf_mac_setup->fhss_api) { + // Synchronization error when backoff time is shorter than allowed. + // TODO: Make this dynamic. + if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) { + backoff_in_us += MIN_FHSS_CSMA_PERIOD_US; + } + } return backoff_in_us; } @@ -136,21 +148,31 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup) { dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer; phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver; - + rf_mac_setup->macRfRadioTxActive = true; if (dev_driver->arm_net_virtual_tx_cb) { if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { - rf_mac_setup->macRfRadioTxActive = true; timer_mac_start(rf_mac_setup, MAC_TX_TIMEOUT, NWKTX_TIMEOUT_PERIOD); /*Start Timeout timer for virtual packet loss*/ } else { + rf_mac_setup->macRfRadioTxActive = false; mac_data_interface_tx_to_cb(rf_mac_setup); } return 0; } - if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { - rf_mac_setup->macRfRadioTxActive = true; + uint8_t *buffer; + uint16_t length; + if (rf_mac_setup->mac_ack_tx_active) { + buffer = tx_buf->enhanced_ack_buf; + length = tx_buf->ack_len; + } else { + buffer = tx_buf->buf; + length = tx_buf->len; + } + if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) { return 0; } + + rf_mac_setup->macRfRadioTxActive = false; return -1; } @@ -219,6 +241,12 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (rf_mac_setup->macUpState && rf_mac_setup->macTxProcessActive) { if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) { + + if (rf_mac_setup->rf_csma_extension_supported) { + mac_sap_cca_fail_cb(rf_mac_setup); + return; + } + if (rf_mac_setup->fhss_api) { uint8_t *synch_info = NULL; mac_pre_build_frame_t *active_buf = rf_mac_setup->active_pd_data_request; @@ -254,6 +282,9 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (tx_handle_retval == -3) { mac_tx_done_state_set(rf_mac_setup, MAC_CCA_FAIL); return; + } else if (tx_handle_retval == -2) { + mac_tx_done_state_set(rf_mac_setup, MAC_UNKNOWN_DESTINATION); + return; } } if (mac_plme_cca_req(rf_mac_setup) != 0) { @@ -267,16 +298,24 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) } } -static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) { - rf_ptr->macRfRadioTxActive = false; - if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { - //Send MAC_CCA_FAIL - mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); +static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) +{ + if (rf_ptr->mac_ack_tx_active) { + if (rf_ptr->active_pd_data_request) { + mac_csma_backoff_start(rf_ptr); + } } else { - timer_mac_stop(rf_ptr); - mac_csma_BE_update(rf_ptr); - if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request) ) { + + rf_ptr->macRfRadioTxActive = false; + if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { + //Send MAC_CCA_FAIL mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + } else { + timer_mac_stop(rf_ptr); + mac_csma_BE_update(rf_ptr); + if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request) ) { + mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + } } } } @@ -322,6 +361,20 @@ static bool mac_data_counter_too_small(uint32_t current_counter, uint32_t packet } +static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *active_buf) +{ + if (!active_buf || !active_buf->asynch_request) { + return false; + } + active_buf->asynch_channel = rf_ptr->mac_channel; //Store Original channel + uint16_t channel = mlme_scan_analyze_next_channel(&active_buf->asynch_channel_list, true); + if (channel <= 0xff) { + mac_mlme_rf_channel_change(rf_ptr, channel); + + } + return true; +} + static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry) { @@ -330,10 +383,16 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r } if (status == PHY_LINK_CCA_PREPARE) { + + if (rf_ptr->mac_ack_tx_active) { + return 0; + } + + if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request) ) { + return 0; + } + if (rf_ptr->fhss_api) { - if (rf_ptr->mac_ack_tx_active) { - return 0; - } mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request; if (!active_buf) { return -1; @@ -345,25 +404,28 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r uint8_t *synch_info = tx_buf->buf + rf_ptr->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH; rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, synch_info, 0, FHSS_SYNCH_FRAME, 0); } - if (active_buf->asynch_request == false) { - // Change to destination channel and write synchronization info to Beacon frames here - int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf), - active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype), - active_buf->mac_payload_length, rf_ptr->dev_driver->phy_driver->phy_header_length, - rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); - // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer - if (tx_handle_retval == -1) { - mac_sap_cca_fail_cb(rf_ptr); - return -2; - } - // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back - // to queue by using CCA fail event - if (tx_handle_retval == -3) { - mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); - return -3; - } + + // Change to destination channel and write synchronization info to Beacon frames here + int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf), + active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype), + active_buf->mac_payload_length, rf_ptr->dev_driver->phy_driver->phy_header_length, + rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); + // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer + if (tx_handle_retval == -1) { + mac_sap_cca_fail_cb(rf_ptr); + return -2; + } + // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back + // to queue by using CCA fail event + if (tx_handle_retval == -3) { + mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + return -3; + } else if (tx_handle_retval == -2) { + mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION); + return -2; } } + return 0; } @@ -373,6 +435,10 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r if (rf_ptr->mac_ack_tx_active) { rf_ptr->mac_ack_tx_active = false; + if (rf_ptr->fhss_api) { + //SET tx completed false because ack isnot never queued + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff); + } if (rf_ptr->active_pd_data_request) { if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) { @@ -450,7 +516,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf) { - if (!rf_ptr->macRfRadioTxActive) { + if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) { return -1; } @@ -465,9 +531,7 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set mcps_sap_pd_ack(buf); if (rf_ptr->fhss_api) { - if (rf_ptr->active_pd_data_request->asynch_request == false) { - rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); - } + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); } return 0; } @@ -611,8 +675,6 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) if (mcps_generic_ack_build(rf_ptr, &fcf_read, pd_data_ind->data_ptr, &ack_payload, time_stamp) !=0) { return -1; } - - rf_ptr->mac_ack_tx_active = true; } } diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.h b/source/MAC/IEEE802_15_4/mac_pd_sap.h index f975f039522..d6364ba5274 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.h +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.h @@ -48,6 +48,8 @@ int8_t mac_pd_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *message); void mac_csma_param_init(struct protocol_interface_rf_mac_setup *rf_mac_setup); uint32_t mac_csma_backoff_get(struct protocol_interface_rf_mac_setup *rf_mac_setup); + +void mac_csma_backoff_start(struct protocol_interface_rf_mac_setup *rf_mac_setup); /** * Run Mac data interface state Machine. * diff --git a/source/MAC/IEEE802_15_4/sw_mac.c b/source/MAC/IEEE802_15_4/sw_mac.c index 45fbfc2ca06..3c8dee0721c 100644 --- a/source/MAC/IEEE802_15_4/sw_mac.c +++ b/source/MAC/IEEE802_15_4/sw_mac.c @@ -54,7 +54,7 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication static void mlme_req(const mac_api_t* api, mlme_primitive id, const void *data); static void mcps_req(const mac_api_t* api, const mcps_data_req_t *data); static void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list); -static void purge_req(const mac_api_t* api, const mcps_purge_t *data); +static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data); static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64); static int8_t macext_mac64_address_get( const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf); @@ -176,6 +176,7 @@ int ns_sw_mac_fhss_register(mac_api_t *mac_api, fhss_api_t *fhss_api) fhss_callback_t callbacks; callbacks.read_tx_queue_size = &mac_read_tx_queue_sizes; callbacks.read_datarate = &mac_read_phy_datarate; + callbacks.read_timestamp = &mac_read_phy_timestamp; callbacks.read_mac_address = &mac_read_64bit_mac_address; callbacks.change_channel = &mac_set_channel; callbacks.send_fhss_frame = &mac_fhss_frame_tx; @@ -251,6 +252,22 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication cur->data_ind_ext_cb = data_ind_cb; cur->enhanced_ack_data_req_cb = ack_data_req_cb; if (data_cnf_cb && data_ind_cb && ack_data_req_cb) { + arm_device_driver_list_s *dev_driver = mac_store.setup->dev_driver; + ns_dyn_mem_free(mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf); + + uint16_t total_length; + if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_driver->phy_MTU) { + total_length = dev_driver->phy_driver->phy_MTU; + } else { + total_length = ENHANCED_ACK_MAX_LENGTH; + } + + total_length += (dev_driver->phy_driver->phy_header_length + dev_driver->phy_driver->phy_tail_length); + mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf = ns_dyn_mem_alloc(total_length); + if (!mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf) { + return -2; + } + mac_store.setup->mac_extension_enabled = true; } else { mac_store.setup->mac_extension_enabled = false; @@ -509,11 +526,12 @@ void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_ } -static void purge_req(const mac_api_t* api, const mcps_purge_t *data) +static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data) { if (mac_store.mac_api == api) { - mcps_sap_purge_reg_handler(mac_store.setup , data ); + return mcps_sap_purge_reg_handler(mac_store.setup , data ); } + return MLME_INVALID_HANDLE; } static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64) @@ -587,8 +605,7 @@ static int8_t sw_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_li phy_msg.message.mac15_4_pd_sap_confirm.cca_retry = cca_retry; phy_msg.message.mac15_4_pd_sap_confirm.tx_retry = tx_retry; - mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg); - return 0; + return mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg); } static void bc_enable_timer_cb(int8_t timer_id, uint16_t slots) diff --git a/source/MPL/mpl.c b/source/MPL/mpl.c index 13ad35e10e6..f1c809fb9dd 100644 --- a/source/MPL/mpl.c +++ b/source/MPL/mpl.c @@ -1011,17 +1011,41 @@ void mpl_clear_realm_scope_seeds(protocol_interface_info_entry_t *cur) static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, int16_t *result) { mpl_domain_t *domain = mpl_domain_lookup_with_realm_check(buf->interface, buf->dst_sa.address); - if (!domain) { - // We need to tunnel - if (stage != IPV6_EXTHDR_MODIFY) { - *result = 0; + /* Deal with simpler modify-already-created-header case first. Note that no error returns. */ + if (stage == IPV6_EXTHDR_MODIFY) { + if (!domain) { + *result = IPV6_EXTHDR_MODIFY_TUNNEL; + memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16); + buf->src_sa.addr_type = ADDR_NONE; // force auto-selection return buf; } - *result = IPV6_EXTHDR_MODIFY_TUNNEL; - memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16); - buf->src_sa.addr_type = ADDR_NONE; // force auto-selection + if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) { + /* We assume we created this, therefore our option is in place + * in the expected place. Sequence is set now, AFTER + * fragmentation. + */ + uint8_t *iphdr = buffer_data_pointer(buf); + uint8_t *ext = iphdr + IPV6_HDRLEN; + if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) { + tr_err("modify"); + return buffer_free(buf); + } + /* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */ + ext[5] = domain->sequence++; + buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED; + buf->mpl_option_data_offset = IPV6_HDRLEN + 4; + mpl_forwarder_process_message(buf, domain, true); + } + *result = 0; + return buf; + } + + /* Rest of code deals with header insertion */ + if (!domain) { + // We will need to tunnel - do nothing on the inner packet + *result = 0; return buf; } @@ -1112,26 +1136,6 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i buf->options.ip_extflags |= IPEXT_HBH_MPL | IPEXT_HBH_MPL_UNFILLED; return buf; } - case IPV6_EXTHDR_MODIFY: - if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) { - /* We assume we created this, therefore our option is in place - * in the expected place. Sequence is set now, AFTER - * fragmentation. - */ - uint8_t *iphdr = buffer_data_pointer(buf); - uint8_t *ext = iphdr + IPV6_HDRLEN; - if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) { - tr_err("modify"); - return buffer_free(buf); - } - /* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */ - ext[5] = domain->sequence++; - buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED; - buf->mpl_option_data_offset = IPV6_HDRLEN + 4; - mpl_forwarder_process_message(buf, domain, true); - } - *result = 0; - return buf; default: return buffer_free(buf); } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index e95865bfad7..8239bc0fdd2 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -348,9 +348,10 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c } } -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle) +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle) { domain->callback = callback; + domain->prefix_cb = prefix_learn_cb; domain->cb_handle = cb_handle; } @@ -677,28 +678,22 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t * const uint8_t *prefix = ptr + 16; if (!pref_parent || neighbour == pref_parent) { - //Check is L Flag active - if (flags & PIO_L) { - //define ONLink Route Information - //tr_debug("Register On Link Prefix to routing table"); - ipv6_route_add(prefix, prefix_len, cur->id, NULL, ROUTE_RADV, valid, 0); - } - /* Check if A-Flag. - * A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC) - * from a prefix advertised by a parent. - */ - if (pref_parent && (flags & PIO_A)) { - if (icmpv6_slaac_prefix_update(cur, prefix, prefix_len, valid, preferred) != 0) { - ipv6_interface_slaac_handler(cur, prefix, prefix_len, valid, preferred); - } - } /* Store prefixes for possible forwarding */ /* XXX if leaf - don't bother? Or do we want to remember them for * when we switch DODAG, as mentioned above? */ - rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); + prefix_entry_t *prefix_entry = rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); + if (prefix_entry && pref_parent) { + rpl_control_process_prefix_option(prefix_entry, cur); + rpl_domain_t *domain = cur->rpl_domain; + if (domain && domain->prefix_cb) { + uint8_t ll_address[16]; + memcpy(ll_address, rpl_neighbour_ll_address(pref_parent), 16); + domain->prefix_cb(prefix_entry, domain->cb_handle,ll_address); + } + } } if ((flags & PIO_R) && !router_addr_set) { @@ -715,6 +710,18 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t * } } +void rpl_control_process_prefix_option(prefix_entry_t *prefix, protocol_interface_info_entry_t *cur) +{ + //Check is L Flag active + if (prefix->options & PIO_L) { + //define ONLink Route Information + //tr_debug("Register On Link Prefix to routing table"); + ipv6_route_add(prefix->prefix, prefix->prefix_len, cur->id, NULL, ROUTE_RADV, prefix->lifetime, 0); + } + +} + + /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -1004,7 +1011,7 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r rpl_instance_consistent_rx(instance); } - rpl_instance_neighbours_changed(instance); + rpl_instance_neighbours_changed(instance, dodag); return buffer_free(buf); diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 72f77885514..c924750d796 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -29,15 +29,19 @@ struct rpl_dodag; struct buffer; struct protocol_interface_info_entry; struct rpl_dodag_info_t; +struct prefix_entry_t; typedef enum rpl_event { RPL_EVENT_DAO_DONE, /* Simplistic trigger for bootstrap advance - a DAO registration completed */ RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/ RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */ + RPL_EVENT_DAO_PARENT_SWITCH, /* RPL indicate that DAO downward Parent state have been updated */ } rpl_event_t; typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); +typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local); + typedef struct rpl_domain { NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; @@ -50,6 +54,7 @@ typedef struct rpl_domain /* As part of shutdown, we can force entering leaf mode */ bool force_leaf; rpl_domain_callback_t *callback; + rpl_prefix_callback_t *prefix_cb; void *cb_handle; } rpl_domain_t; @@ -100,6 +105,7 @@ void rpl_control_transmit_dio(struct rpl_domain *domain, struct protocol_interfa bool rpl_control_transmit_dao(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, struct rpl_instance *instance, uint8_t instance_id, uint8_t dao_sequence, const uint8_t dodagid[16], const uint8_t *opts, uint16_t opts_size, const uint8_t *dst); void rpl_control_disable_ra_routes(struct rpl_domain *domain); void rpl_control_event(struct rpl_domain *domain, rpl_event_t event); +void rpl_control_process_prefix_option(struct prefix_entry_t *prefix, struct protocol_interface_info_entry *cur); /*********************** RPL control API to rest of system *******************/ @@ -138,7 +144,7 @@ rpl_domain_t *rpl_control_create_domain(void); void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle); +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); @@ -160,7 +166,6 @@ const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance * const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global); uint16_t rpl_control_current_rank(const struct rpl_instance *instance); - #else /* HAVE_RPL */ #define rpl_control_fast_timer(ticks) ((void) 0) diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 8e040e5c67e..d99c3e1c2fe 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -243,6 +243,8 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance) } } } + //GENERATE PARENT Update event + rpl_control_event(instance->domain, RPL_EVENT_DAO_PARENT_SWITCH); rpl_instance_dao_trigger(instance, 0); } } @@ -588,7 +590,7 @@ void rpl_instance_send_address_registration(protocol_interface_info_entry_t *int aro.status = ARO_SUCCESS; aro.present = true; - aro.lifetime = addr->preferred_lifetime; + aro.lifetime = addr->valid_lifetime; memcpy(aro.eui64, interface->mac, 8); // go through neighbour list, and send to all assigned parents. diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 0e518d029f9..4210442fdf8 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -134,6 +134,7 @@ typedef struct rpl_dao_non_root uint32_t refresh_timer; /* Refresh timer (seconds) - 0xFFFFFFFF = infinite, 0 = not yet set */ } rpl_dao_non_root_t; + /* Descriptor for a RPL DAO target */ struct rpl_dao_target { diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 126e195312e..fdc5f341bd4 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -427,7 +427,7 @@ void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour) } if (neighbour->dodag_parent) { rpl_instance_remove_system_routes_through_parent(instance, neighbour); - rpl_instance_neighbours_changed(instance); + rpl_instance_neighbours_changed(instance, NULL); } rpl_free(neighbour, sizeof *neighbour); @@ -1171,13 +1171,18 @@ bool rpl_instance_purge(rpl_instance_t *instance) return false; } -void rpl_instance_neighbours_changed(rpl_instance_t *instance) +void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag) { instance->neighbours_changed = true; - if (!rpl_instance_preferred_parent(instance)) { - rpl_instance_set_local_repair(instance, true); + uint16_t delay = rpl_policy_dio_parent_selection_delay(instance->domain); + if (dodag) { + //Convert imin 100ms tick to seconds + uint16_t i_min_delay = dodag->dio_timer_params.Imin / 10; + if (i_min_delay > delay) { + delay = i_min_delay; + } } - rpl_instance_trigger_parent_selection(instance, rpl_policy_dio_parent_selection_delay(instance->domain)); + rpl_instance_trigger_parent_selection(instance, delay); } static void rpl_instance_remove_parents(rpl_instance_t *instance) @@ -1366,7 +1371,18 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) } } - rpl_instance_set_local_repair(instance, preferred_parent == NULL); + //Control Local repair state + if (preferred_parent) { + // Always stop repair if we find a parent + rpl_instance_set_local_repair(instance, false); + } else if (original_preferred) { + // Only start repair if we just lost a parent + rpl_instance_set_local_repair(instance, true); + } else { + // !preferred_parent && !original_preferred - didn't have a parent, + // still don't. Leave repair flag as-is (would be off on initial start + // up, may be on if having problems mid-session). + } if (rpl_instance_mop(instance) != RPL_MODE_NO_DOWNWARD) { rpl_downward_process_dao_parent_changes(instance); @@ -1384,6 +1400,20 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) rpl_control_print(trace_info_print); /* Changing DODAG version is an inconsistency */ if (original_version != instance->current_dodag_version) { + //learn Routes an Prefixes + if (preferred_parent && instance->current_dodag_version) { + rpl_dodag_t *dodag = instance->current_dodag_version->dodag; + protocol_interface_info_entry_t *rpl_interface = protocol_stack_interface_info_get_by_id(preferred_parent->interface_id); + if (rpl_interface) { + ns_list_foreach(prefix_entry_t, prefix, &dodag->prefixes) { + rpl_control_process_prefix_option(prefix, rpl_interface); + if (instance->domain->prefix_cb) { + instance->domain->prefix_cb(prefix, rpl_interface, preferred_parent->ll_address); + } + } + } + } + rpl_instance_inconsistency(instance); return; } @@ -1536,6 +1566,7 @@ void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds) } } + void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) { rpl_dodag_version_t *dodag_version = instance->current_dodag_version; diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index 1718d753739..1225e285495 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -135,7 +135,7 @@ void rpl_neighbour_update_dodag_version(rpl_neighbour_t *neighbour, rpl_dodag_ve bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn); rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour); -void rpl_instance_neighbours_changed(rpl_instance_t *instance); +void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag); void rpl_instance_run_parent_selection(rpl_instance_t *instance); void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn); diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 981ab71ad8e..084ffaafed6 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -81,6 +81,9 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ if (!entry) { return; } + if (entry->etx_samples < 7) { + entry->etx_samples++; + } accumulated_failures = entry->accumulated_failures; diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index 12b1ee6117c..a0216b4a382 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -38,6 +38,7 @@ typedef struct etx_storage_s { unsigned accumulated_failures: 5; unsigned tmp_etx: 1; unsigned linkIdr: 4; + unsigned etx_samples: 3; } etx_storage_t; /** diff --git a/source/Service_Libs/fhss/channel_functions.h b/source/Service_Libs/fhss/channel_functions.h index 990a7ac90e6..f6ceab73bb8 100644 --- a/source/Service_Libs/fhss/channel_functions.h +++ b/source/Service_Libs/fhss/channel_functions.h @@ -17,25 +17,44 @@ #ifndef CHANNEL_FUNC_H_ #define CHANNEL_FUNC_H_ +/** + * @brief Function calculates nearest (higher) prime number for given start value. + * @param start_value Start value. + * @return Calculated prime number. + */ +uint16_t tr51_calc_nearest_prime_number(uint16_t start_value); + +/** + * @brief Initialize channel table for TR51 channel function. + * @param channel_table Channel table to be initialized. + * @param number_of_channels Number of channels. + * @return 0 Success, -1 Failure. + */ +int tr51_init_channel_table(int16_t *channel_table, int16_t number_of_channels); + /** * @brief Compute the unicast schedule channel index using tr51 channel function. + * @param channel_table Channel table. + * @param output_table Table used to generate output channel. * @param slot_number Current slot number. * @param mac MAC address of the node for which the index is calculated. * @param number_of_channels Number of channels. * @param excluded_channels Excluded channels. * @return Channel index. */ -int32_t tr51_get_uc_channel_index(uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels); +int32_t tr51_get_uc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels); /** * @brief Compute the broadcast schedule channel index using tr51 channel function. + * @param channel_table Channel table. + * @param output_table Table used to generate output channel. * @param slot_number Current slot number. * @param bsi Broadcast schedule identifier of the node for which the index is calculated. * @param number_of_channels Number of channels. * @param excluded_channels Excluded channels. * @return Channel index. */ -int32_t tr51_get_bc_channel_index(uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels); +int32_t tr51_get_bc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels); /** * @brief Compute the unicast schedule channel index using direct hash channel function. diff --git a/source/Service_Libs/fhss/channel_list.c b/source/Service_Libs/fhss/channel_list.c index 7d22696bd95..eab1e85c65d 100644 --- a/source/Service_Libs/fhss/channel_list.c +++ b/source/Service_Libs/fhss/channel_list.c @@ -88,6 +88,19 @@ uint8_t channel_list_get_channel(const uint32_t* list, int current_index) return found_index; } +void channel_list_set_channel(uint32_t* list, int channel, bool active) +{ + if (channel >= CHANNEL_LIST_SIZE_IN_BITS) { + return; + } + if (active) { + list[channel/32] |= (1 << channel % 32); + } else { + list[channel/32] &= ~(1 << channel % 32); + } + return; +} + // count the amount of channels enabled in a list int channel_list_count_channels(const uint32_t* list) { diff --git a/source/Service_Libs/fhss/channel_list.h b/source/Service_Libs/fhss/channel_list.h index 5e3a2139e0d..65a16c68089 100644 --- a/source/Service_Libs/fhss/channel_list.h +++ b/source/Service_Libs/fhss/channel_list.h @@ -31,6 +31,16 @@ extern "C" { * @return channel number */ uint8_t channel_list_get_channel(const uint32_t* list, int current_index); +/** + * set matching bit on in in channel mask. + * + * @param list channel mask + * @param channel channel number + * @param active set the channel on if true, disable channel if false. + * + * @return channel number + */ +void channel_list_set_channel(uint32_t* list, int channel, bool active); /** * Count the amount of channels enabled in a list. diff --git a/source/Service_Libs/fhss/fhss.c b/source/Service_Libs/fhss/fhss.c index 5e898153a46..bf4e763b038 100644 --- a/source/Service_Libs/fhss/fhss.c +++ b/source/Service_Libs/fhss/fhss.c @@ -34,6 +34,7 @@ #define TRACE_GROUP "fhss" +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); static int fhss_reset(fhss_structure_t *fhss_structure); static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure); static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length); @@ -67,6 +68,7 @@ fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t * } memset(fhss_struct->bs, 0, sizeof(fhss_bs_t)); + fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); fhss_struct->bs->fhss_configuration = *fhss_configuration; fhss_struct->bs->fhss_stats_ptr = fhss_statistics; fhss_struct->number_of_channels = channel_count; @@ -99,6 +101,15 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure) return true; } +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) +{ + (void) slots; + fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); + if (fhss_structure) { + fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); + } +} + static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) { if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) { @@ -689,16 +700,16 @@ static void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, } } -static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) +static int16_t fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { - return; + return -1; } // State is already set if (fhss_structure->fhss_state == fhss_state) { tr_debug("Synch same state %u", fhss_state); - return; + return -1; } if (fhss_state == FHSS_UNSYNCHRONIZED) { @@ -712,7 +723,7 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs // Do not synchronize to current pan if (fhss_structure->bs->synch_panid == pan_id) { tr_debug("Synch same panid %u", pan_id); - return; + return -1; } fhss_generate_scramble_table(fhss_structure); @@ -737,11 +748,11 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs fhss_start_timer(fhss_structure, fhss_structure->bs->synch_configuration.fhss_superframe_length, fhss_superframe_handler); } else { tr_error("Synch info not found"); - return; + return -1; } } fhss_structure->fhss_state = fhss_state; - return; + return fhss_structure->rx_channel; } static void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer) diff --git a/source/Service_Libs/fhss/fhss_common.c b/source/Service_Libs/fhss/fhss_common.c index 592a0b557da..583f87e241d 100644 --- a/source/Service_Libs/fhss/fhss_common.c +++ b/source/Service_Libs/fhss/fhss_common.c @@ -34,8 +34,6 @@ static fhss_structure_t *fhss_struct = NULL; -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); @@ -52,7 +50,6 @@ fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_ memset(fhss_struct, 0, sizeof(fhss_structure_t)); fhss_struct->fhss_api = fhss_api; fhss_struct->platform_functions = *fhss_timer; - fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); if (!fhss_struct->platform_functions.fhss_resolution_divider) { fhss_struct->platform_functions.fhss_resolution_divider = 1; } @@ -69,16 +66,7 @@ int8_t fhss_free_instance(fhss_api_t *fhss_api) return 0; } -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) -{ - (void) slots; - fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); - if (fhss_structure) { - fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); - } -} - -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) +fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) { if (timer_id < 0 || !fhss_struct) { return NULL; @@ -142,6 +130,13 @@ void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*ca } } +void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t)) +{ + if (callback){ + fhss_structure->platform_functions.fhss_timer_stop(callback, fhss_structure->fhss_api); + } +} + int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) { if (!fhss_structure) { diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h index 144e089019a..1c635d2062d 100644 --- a/source/Service_Libs/fhss/fhss_common.h +++ b/source/Service_Libs/fhss/fhss_common.h @@ -54,6 +54,7 @@ struct fhss_structure uint8_t synch_parent[8]; }; +fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_t *fhss_timer); int8_t fhss_free_instance(fhss_api_t *fhss_api); int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate); @@ -61,6 +62,7 @@ fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api); void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); int8_t fhss_disable(fhss_structure_t *fhss_structure); void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); +void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time); int fhss_timeout_stop(fhss_structure_t *fhss_structure); int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure); diff --git a/source/Service_Libs/fhss/fhss_configuration_interface.c b/source/Service_Libs/fhss/fhss_configuration_interface.c index 0c7567e5169..c1acfc38ac3 100644 --- a/source/Service_Libs/fhss/fhss_configuration_interface.c +++ b/source/Service_Libs/fhss/fhss_configuration_interface.c @@ -62,13 +62,13 @@ fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, return this; } -int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) +int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); if (!fhss_structure || !eui64 || !bc_timing_info) { return -1; } - return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info); + return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info, force_synch); } int ns_fhss_ws_remove_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8]) diff --git a/source/Service_Libs/fhss/fhss_ws.h b/source/Service_Libs/fhss/fhss_ws.h index 03befff9f8f..cf4af1040cb 100644 --- a/source/Service_Libs/fhss/fhss_ws.h +++ b/source/Service_Libs/fhss/fhss_ws.h @@ -23,6 +23,8 @@ #define WS_NUMBER_OF_CHANNEL_RETRIES 4 //TX/RX slot length in milliseconds #define WS_MAX_TXRX_SLOT_LEN_MS 100 +// Default minimum broadcast synchronization interval in seconds +#define DEFAULT_MIN_SYNCH_INTERVAL 60 typedef struct fhss_ws fhss_ws_t; struct fhss_ws @@ -30,6 +32,12 @@ struct fhss_ws uint8_t bc_channel; uint16_t uc_slot; uint16_t bc_slot; + uint16_t min_synch_interval; + uint32_t txrx_slot_length_ms; + uint32_t synchronization_time; + int16_t *tr51_channel_table; + uint8_t *tr51_output_table; + bool unicast_timer_running; bool is_on_bc_channel; struct fhss_ws_configuration fhss_configuration; const struct broadcast_timing_info *parent_bc_info; @@ -38,7 +46,7 @@ struct fhss_ws fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure); -int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); +int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch); int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]); int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration); int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count); diff --git a/source/Service_Libs/fhss/fhss_ws_empty_functions.c b/source/Service_Libs/fhss/fhss_ws_empty_functions.c index df6bc4813cf..07597662f93 100644 --- a/source/Service_Libs/fhss/fhss_ws_empty_functions.c +++ b/source/Service_Libs/fhss/fhss_ws_empty_functions.c @@ -46,7 +46,7 @@ int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure) return -1; } -int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) +int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch) { (void) fhss_structure; (void) eui64; diff --git a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c index 6b1e548212c..60352bec4fd 100644 --- a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c +++ b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c @@ -192,6 +192,9 @@ void mac_neighbor_table_neighbor_connected(mac_neighbor_table_t *table_class, ma void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device) { (void)table_class; + if (!neighbor_entry->trusted_device && trusted_device) { + neighbor_entry->lifetime = neighbor_entry->link_lifetime; + } neighbor_entry->trusted_device = trusted_device; } @@ -271,4 +274,13 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t return mac_neighbor_table_entry_allocate(table_class, mac64); } +mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class) +{ + ns_list_foreach(mac_neighbor_table_entry_t, entry, &table_class->neighbour_list) { + if (entry->link_role == PRIORITY_PARENT_NEIGHBOUR) { + return entry; + } + } + return NULL; +} diff --git a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h index edd10a974d9..c2bd7ef4f7a 100644 --- a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h +++ b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h @@ -202,4 +202,6 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_ll64(mac_neighbor_table_t mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t *table_class, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated); +mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class); + #endif /* MAC_NEIGHBOR_TABLE_H_ */ diff --git a/source/Service_Libs/mdns/ns_fnet_port.c b/source/Service_Libs/mdns/ns_fnet_port.c index 63e904b1911..346f6f3f8b4 100644 --- a/source/Service_Libs/mdns/ns_fnet_port.c +++ b/source/Service_Libs/mdns/ns_fnet_port.c @@ -72,10 +72,9 @@ fnet_bool_t fnet_netif_get_ip6_addr (fnet_netif_desc_t netif_desc, fnet_index_t addr_info->type = FNET_NETIF_IP_ADDR_TYPE_AUTOCONFIGURABLE; /* How the address was acquired.*/ result = FNET_TRUE; } + FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr)); } - FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr)); - return result; } diff --git a/source/ipv6_stack/ipv6_routing_table.c b/source/ipv6_stack/ipv6_routing_table.c index 0b47ed5b72c..484a41097b6 100644 --- a/source/ipv6_stack/ipv6_routing_table.c +++ b/source/ipv6_stack/ipv6_routing_table.c @@ -1589,6 +1589,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i route->metric = metric; changed_info = UPDATED; } + } if (changed_info != UNCHANGED) { diff --git a/source/ipv6_stack/protocol_ipv6.c b/source/ipv6_stack/protocol_ipv6.c index 7f01fbbe51f..59394310443 100644 --- a/source/ipv6_stack/protocol_ipv6.c +++ b/source/ipv6_stack/protocol_ipv6.c @@ -394,14 +394,14 @@ void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint return; } + if (addr_interface_gp_prefix_compare(cur, address) == 0) { + return; + } - - if (addr_interface_gp_prefix_compare(cur, address) != 0) { - ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) { - if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) { - cur_prefix->routePrefer = routePrefer; - return; - } + ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) { + if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) { + cur_prefix->routePrefer = routePrefer; + return; } } diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index 3027046fcc8..c000b581e17 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -53,6 +53,16 @@ typedef struct { } server_instance_t; typedef NS_LIST_HEAD(server_instance_t, link) server_instance_list_t; + +typedef struct { + uint16_t instance_id; + int8_t interface_id; + uint8_t server_address[16]; + bool relay_activated; + ns_list_link_t link; +} relay_instance_t; +typedef NS_LIST_HEAD(relay_instance_t, link) relay_instance_list_t; + typedef struct { ns_address_t addr; dhcp_service_receive_resp_cb *recv_resp_cb; @@ -71,6 +81,7 @@ typedef struct { uint8_t retrans; uint8_t *msg_ptr; uint16_t msg_len; + uint8_t *relay_start; ns_list_link_t link; } msg_tr_t; typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; @@ -78,9 +89,11 @@ typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; typedef struct { ns_address_t src_address; server_instance_list_t srv_list; + relay_instance_list_t relay_list; tr_list_t tr_list; int8_t dhcp_server_socket; int8_t dhcp_client_socket; + int8_t dhcp_relay_socket; int8_t dhcpv6_socket_service_tasklet; } dhcp_service_class_t; @@ -120,9 +133,11 @@ bool dhcp_service_allocate(void) dhcp_service = ns_dyn_mem_alloc(sizeof(dhcp_service_class_t)); if (dhcp_service) { ns_list_init(&dhcp_service->srv_list); + ns_list_init(&dhcp_service->relay_list); ns_list_init(&dhcp_service->tr_list); dhcp_service->dhcp_client_socket = -1; dhcp_service->dhcp_server_socket = -1; + dhcp_service->dhcp_relay_socket = -1; dhcp_service->dhcpv6_socket_service_tasklet = eventOS_event_handler_create(DHCPv6_socket_service_tasklet, DHCPV6_SOCKET_SERVICE_TASKLET_INIT); if (dhcp_service->dhcpv6_socket_service_tasklet < 0) { ns_dyn_mem_free(dhcp_service); @@ -229,13 +244,50 @@ server_instance_t *dhcp_service_client_find(uint16_t instance_id) } +static uint16_t dhcp_service_relay_interface_get(int8_t interface_id) +{ + ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) { + if (cur_ptr->interface_id == interface_id && cur_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) { + return cur_ptr->instance_id; + } + } + + return 0; +} + + + +static relay_instance_t *dhcp_service_relay_find(uint16_t instance_id) +{ + relay_instance_t *result = NULL; + ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) { + if (cur_ptr->instance_id == instance_id) { + result = cur_ptr; + } + } + return result; +} + +static relay_instance_t *dhcp_service_relay_interface(int8_t interface_id) +{ + relay_instance_t *result = NULL; + ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) { + if (cur_ptr->interface_id == interface_id) { + result = cur_ptr; + } + } + return result; +} + + void recv_dhcp_server_msg(void *cb_res) { socket_callback_t *sckt_data; server_instance_t *srv_ptr = NULL; msg_tr_t *msg_tr_ptr; - uint8_t *msg_ptr; + uint8_t *msg_ptr, *allocated_ptr; uint16_t msg_len; + dhcpv6_relay_msg_t relay_msg; sckt_data = cb_res; @@ -245,12 +297,33 @@ void recv_dhcp_server_msg(void *cb_res) tr_debug("dhcp Server recv request"); msg_tr_ptr = dhcp_tr_create(); msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len); + allocated_ptr = msg_ptr; if (msg_ptr == NULL || msg_tr_ptr == NULL) { // read actual message tr_error("Out of resources"); goto cleanup; } msg_len = socket_read(sckt_data->socket_id, &msg_tr_ptr->addr, msg_ptr, sckt_data->d_len); + + uint8_t msg_type = *msg_ptr; + if (msg_type == DHCPV6_RELAY_FORWARD) { + if ( !libdhcpv6_relay_msg_read(msg_ptr, msg_len, &relay_msg) ) { + tr_error("Relay forward not correct"); + goto cleanup; + } + //Update Source and data + msg_tr_ptr->relay_start = msg_ptr; + memcpy(msg_tr_ptr->addr.address,relay_msg.peer_address , 16); + msg_ptr = relay_msg.relay_options.msg_ptr; + msg_len = relay_msg.relay_options.len; + msg_type = *msg_ptr; + + + } else if (msg_type == DHCPV6_RELAY_REPLY) { + tr_error("Relay reply drop at server"); + goto cleanup; + } + //TODO use real function from lib also call validity check msg_tr_ptr->message_tr_id = common_read_24_bit(&msg_ptr[1]); @@ -265,7 +338,7 @@ void recv_dhcp_server_msg(void *cb_res) msg_tr_ptr->instance_id = cur_ptr->instance_id; msg_tr_ptr->interface_id = sckt_data->interface_id; if ((RET_MSG_ACCEPTED == - cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, *msg_ptr, msg_ptr + 4, msg_len - 4))) { + cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, msg_type, msg_ptr + 4, msg_len - 4))) { // should not modify pointers but library requires. msg_tr_ptr = NULL; srv_ptr = cur_ptr; @@ -276,7 +349,7 @@ void recv_dhcp_server_msg(void *cb_res) cleanup: dhcp_tr_delete(msg_tr_ptr); - ns_dyn_mem_free(msg_ptr); + ns_dyn_mem_free(allocated_ptr); if (srv_ptr == NULL) { //no owner found tr_warn("No handler for this message found"); @@ -285,6 +358,118 @@ void recv_dhcp_server_msg(void *cb_res) return; } +void recv_dhcp_relay_msg(void *cb_res) +{ + socket_callback_t *sckt_data; + uint16_t msg_len; + + sckt_data = cb_res; + + if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) { + return; + } + + protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(sckt_data->interface_id); + + relay_instance_t *relay_srv =dhcp_service_relay_interface(sckt_data->interface_id); + + if (!interface_ptr || !relay_srv || !relay_srv->relay_activated) { + return; + } + ns_address_t src_address; + + uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4]; + ns_iovec_t msg_iov[2]; + msg_iov[0].iov_base = relay_frame; + msg_iov[0].iov_len = 34; + msg_iov[1].iov_base = ns_dyn_mem_temporary_alloc(sckt_data->d_len); + msg_iov[1].iov_len = sckt_data->d_len; + if (msg_iov[1].iov_base == NULL ) { + // read actual message + tr_error("Out of resources"); + goto cleanup; + } + + ns_msghdr_t msghdr; + //Set messages name buffer + msghdr.msg_name = &src_address; + msghdr.msg_namelen = sizeof(src_address); + msghdr.msg_iov = &msg_iov[1]; + msghdr.msg_iovlen = 1; + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + + msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); + + + tr_debug("dhcp Relay recv msg"); + + //Parse type + uint8_t *ptr = msg_iov[1].iov_base; + uint8_t msg_type = *ptr; + + + if (msg_type == DHCPV6_RELAY_FORWARD) { + tr_error("Drop not supported DHCPv6 forward at Agent"); + goto cleanup; + + } else if (msg_type == DHCPV6_RELAY_REPLY) { + //Parse and validate Relay + dhcpv6_relay_msg_t relay_msg; + if (!libdhcpv6_relay_msg_read(ptr, msg_len, &relay_msg) ) { + tr_error("Not valid relay"); + goto cleanup; + } + if (0 != libdhcpv6_message_malformed_check(relay_msg.relay_options.msg_ptr, relay_msg.relay_options.len)) { + tr_error("Malformed packet"); + goto cleanup; + } + //Copy DST address + memcpy(src_address.address, relay_msg.peer_address, 16); + src_address.type = ADDRESS_IPV6; + src_address.identifier = DHCPV6_CLIENT_PORT; + msghdr.msg_iov = &msg_iov[0]; + msghdr.msg_iovlen = 1; + msg_iov[0].iov_base = relay_msg.relay_options.msg_ptr; + msg_iov[0].iov_len = relay_msg.relay_options.len; + tr_debug("Forward Original relay msg to client"); + + } else { + if (0 != libdhcpv6_message_malformed_check(ptr, msg_len)) { + tr_error("Malformed packet"); + goto cleanup; + } + uint8_t gp_address[16]; + //Get blobal address from interface + if (arm_net_address_get(sckt_data->interface_id, ADDR_IPV6_GP, gp_address) != 0) { + // No global prefix available + tr_error("No GP address"); + goto cleanup; + } + + //Build + libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address); + libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len); + + //Copy DST address + memcpy(src_address.address, relay_srv->server_address, 16); + src_address.type = ADDRESS_IPV6; + src_address.identifier = DHCPV6_SERVER_PORT; + //ADD relay frame vector front of original data + msghdr.msg_iov = &msg_iov[0]; + msghdr.msg_iovlen = 2; + msg_iov[0].iov_base = relay_frame; + msg_iov[0].iov_len = 38; + msg_iov[1].iov_len = msg_len; + tr_debug("Forward Client msg to server"); + } + socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); +cleanup: + ns_dyn_mem_free(msg_iov[1].iov_base); + + return; +} + void recv_dhcp_client_msg(void *cb_res) { ns_address_t address; @@ -351,8 +536,19 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty return 0; } if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) { + if (dhcp_service->dhcp_relay_socket >= 0) { + tr_error("dhcp Server socket can't open because Agent open already"); + } dhcp_service->dhcp_server_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_server_msg); } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT && dhcp_service->dhcp_relay_socket < 0) { + if (dhcp_service->dhcp_server_socket >= 0) { + tr_error("dhcp Relay agent can't open because server open already"); + } + dhcp_service->dhcp_relay_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_relay_msg); + } + if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) { dhcp_service->dhcp_client_socket = socket_open(SOCKET_UDP, DHCPV6_CLIENT_PORT, recv_dhcp_client_msg); } @@ -364,6 +560,18 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty tr_error("No sockets available for DHCP client"); return 0; } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT) { + if (dhcp_service->dhcp_relay_socket < 0) { + tr_error("No sockets available for DHCP server"); + } + + uint16_t temp_id = dhcp_service_relay_interface_get(interface_id); + if (temp_id) { + return temp_id; + } + } + for (; id < MAX_SERVERS; id++) { if (dhcp_service_client_find(id) == NULL) { break; @@ -375,6 +583,22 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty ns_dyn_mem_free(srv_ptr); return 0; } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT) { + //Allocate Realay Agent + relay_instance_t *relay_srv = ns_dyn_mem_alloc(sizeof(relay_instance_t)); + if (!relay_srv) { + tr_error("Out of realy instances"); + ns_dyn_mem_free(srv_ptr); + return 0; + } + ns_list_add_to_start(&dhcp_service->relay_list, relay_srv); + relay_srv->instance_id = id; + relay_srv->interface_id = interface_id; + relay_srv->relay_activated = false; + + } + ns_list_add_to_start(&dhcp_service->srv_list, srv_ptr); srv_ptr->instance_id = id; srv_ptr->instance_type = instance_type; @@ -383,6 +607,15 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty return srv_ptr->instance_id; } +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address) +{ + relay_instance_t * realay_srv = dhcp_service_relay_find(instance); + if (realay_srv) { + realay_srv->relay_activated = true; + memcpy(realay_srv->server_address, server_address, 16); + } +} + void dhcp_service_delete(uint16_t instance) { server_instance_t *srv_ptr; @@ -393,7 +626,16 @@ void dhcp_service_delete(uint16_t instance) //TODO delete all transactions if (srv_ptr != NULL) { ns_list_remove(&dhcp_service->srv_list, srv_ptr); + if (srv_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) { + //Free relay service + relay_instance_t *relay = dhcp_service_relay_find(instance); + if (relay) { + ns_list_remove(&dhcp_service->relay_list, relay); + ns_dyn_mem_free(relay); + } + } ns_dyn_mem_free(srv_ptr); + } ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) { if (cur_ptr->instance_id == instance) { @@ -401,17 +643,19 @@ void dhcp_service_delete(uint16_t instance) } } - int8_t server_instances = 0, client_instances = 0; + int8_t server_instances = 0, client_instances = 0, relay_instances = 0; ns_list_foreach(server_instance_t, srv, &dhcp_service->srv_list) { if (srv->instance_type == DHCP_INSTANCE_SERVER) { ++server_instances; } else if (srv->instance_type == DHCP_INSTANCE_CLIENT) { ++client_instances; + } else if (srv->instance_type == DHCP_INTANCE_RELAY_AGENT) { + ++relay_instances; } } - if (server_instances == 0 && dhcp_service->dhcp_server_socket > -1) { + if ((server_instances == 0 && relay_instances == 0) && dhcp_service->dhcp_server_socket > -1) { socket_close(dhcp_service->dhcp_server_socket); dhcp_service->dhcp_server_socket = -1; } @@ -458,7 +702,7 @@ uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, msg_tr_ptr = dhcp_tr_create(); if (msg_tr_ptr == NULL || srv_ptr == NULL || msg_ptr == NULL || receive_resp_cb == NULL || msg_len < 5) { - tr_error("request sending failed"); + tr_error("Request sending failed"); return 0; } @@ -530,7 +774,38 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) } socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hop_limit, sizeof multicast_hop_limit); socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &msg_tr_ptr->interface_id, sizeof(int8_t)); - retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); + + if (msg_tr_ptr->relay_start) { + //Build Relay Reply only server do this + ns_iovec_t data_vector[2]; + ns_msghdr_t msghdr; + memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16); + msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT; + //SET IOV vectors + //Relay Reply + data_vector[0].iov_base = (void *) msg_tr_ptr->relay_start; + data_vector[0].iov_len = DHCPV6_RELAY_LENGTH + 4; + //DHCPV normal message vector + data_vector[1].iov_base = (void *) msg_tr_ptr->msg_ptr; + data_vector[1].iov_len = msg_tr_ptr->msg_len; + + //Set message name + msghdr.msg_name = (void *) &msg_tr_ptr->addr; + msghdr.msg_namelen = sizeof(ns_address_t); + msghdr.msg_iov = &data_vector[0]; + msghdr.msg_iovlen = 2; + //No ancillary data + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + + uint8_t *ptr = msg_tr_ptr->relay_start; + *ptr = DHCPV6_RELAY_REPLY; + libdhcpv6_dhcp_option_header_write(ptr +34, msg_tr_ptr->msg_len); + retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0); + + } else { + retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); + } if (retval != 0) { tr_warn("dhcp service socket_sendto fails: %i", retval); } @@ -588,6 +863,12 @@ void dhcp_service_delete(uint16_t instance) (void)instance; } +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address) +{ + (void)instance; + (void)server_address; +} + int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len) { (void)msg_tr_id; @@ -626,4 +907,5 @@ bool dhcp_service_timer_tick(uint16_t ticks) (void)ticks; return false; } + #endif diff --git a/source/libDHCPv6/libDHCPv6.c b/source/libDHCPv6/libDHCPv6.c index f89f66e5e3c..780d40afe8e 100644 --- a/source/libDHCPv6/libDHCPv6.c +++ b/source/libDHCPv6/libDHCPv6.c @@ -795,4 +795,43 @@ uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addre return length; } + +uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address) +{ + *ptr++ = type; + *ptr++ = hop_limit; + memcpy(ptr, link_address, 16); + ptr += 16; + memcpy(ptr, peer_addres, 16); + ptr += 16; + return ptr; +} + +uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length) +{ + ptr = common_write_16_bit(DHCPV6_OPTION_RELAY, ptr); + ptr = common_write_16_bit(length, ptr); + return ptr; +} + +bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg) +{ + if (length < DHCPV6_RELAY_LENGTH + 4) { + return false; + } + // Relay message base first + relay_msg->type = *ptr++; + relay_msg->hop_limit = *ptr++; + relay_msg->link_address = ptr; + relay_msg->peer_address = ptr + 16; + ptr += 32; + //Discover + if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_RELAY, &relay_msg->relay_options) != 0) { + return false; + } + + + return true; +} + #endif diff --git a/source/libDHCPv6/libDHCPv6.h b/source/libDHCPv6/libDHCPv6.h index f13a24887d5..d5a522a6cb5 100644 --- a/source/libDHCPv6/libDHCPv6.h +++ b/source/libDHCPv6/libDHCPv6.h @@ -112,6 +112,14 @@ typedef struct dhcpv6_client_server_entry_s { typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_entry_s; +typedef struct dhcpv6_relay_msg { + uint8_t type; + uint8_t hop_limit; + uint8_t *link_address; + uint8_t *peer_address; + dhcp_options_msg_t relay_options; +} dhcpv6_relay_msg_t; + /** UDP Port Number definition */ #define DHCPV6_SERVER_PORT 547 #define DHCPV6_CLIENT_PORT 546 @@ -123,6 +131,8 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent #define DHCPV6_RENEW_TYPE 5 #define DHCPV6_REPLY_TYPE 7 #define DHCPV6_RELEASE_TYPE 8 +#define DHCPV6_RELAY_FORWARD 12 +#define DHCPV6_RELAY_REPLY 13 #define DHCPV6_LEASEQUERY_TYPE 14 #define DHCPV6_LEASEQUERY_REPLY_TYPE 15 @@ -209,6 +219,11 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent #define DHCPV6_OPTION_CLT_TIME 0x002e +#define DHCPV6_RELAY_LENGTH 34 +#define DHCPV6_OPTION_RELAY 0x0009 + + + /** DHCPv6 client Nontemporal address and server data allocate, free and search */ dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address); void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry); @@ -259,7 +274,8 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t s uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink); uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData); - +uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address); +uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length); int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params); int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type , dhcp_link_options_params_t *params); @@ -347,5 +363,6 @@ int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_le int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length); bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length); bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length); +bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg); #endif /* LIBDHCPV6_H_ */ diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index a70fd001da1..bac446af7a9 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -43,11 +43,12 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s)); if (entry) { entry->clientIdSequence = 0; - entry->enableAddressMapping = false; entry->enableAddressAutonous = true; entry->clientIdDefaultSuffics = 0x0000000; entry->maxSuppertedClients = 200; entry->validLifetime = 7200; + entry->removeCb = NULL; + entry->addCb = NULL; ns_list_init(&entry->allocatedAddressList); } return entry; @@ -62,7 +63,7 @@ static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dh if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { memcpy(ptr, entry->linkId, 8); *ptr ^= 2; - } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { + } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { *ptr++ = entry->linkId[0] ^ 2; *ptr++ = entry->linkId[1]; *ptr++ = entry->linkId[2]; @@ -96,7 +97,9 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) //Stop use this address for leasequery and delete Route or address map address->preferredLifetime = 0; - cur->timeoutCb(cur->interfaceId, address->nonTemporalAddress); + if (cur->removeCb) { + cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix); + } } else { address->preferredLifetime -= timeUpdateInSeconds; } @@ -137,17 +140,16 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstanc } -dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb) +dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType) { - dhcpv6_gua_server_entry_s *entry = NULL; - if (libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix) == NULL) { + dhcpv6_gua_server_entry_s *entry = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); + if (entry == NULL) { entry = libdhcpv6_server_entry_allocate(); if (entry) { memcpy(entry->guaPrefix, prefix, 8); memcpy(entry->serverDUID, serverDUID, 8); entry->serverLinkType = serverDUIDType; entry->interfaceId = interfaceId; - entry->timeoutCb = prefered_timeout_cb; ns_list_add_to_end(&dhcpv6_gua_server_list, entry); } } diff --git a/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index 9f47aff2437..6e9412e4789 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/source/libDHCPv6/libDHCPv6_server.h @@ -26,7 +26,7 @@ #ifdef HAVE_DHCPV6_SERVER #include "ns_list.h" -typedef void (dhcp_address_prefer_timeout_cb)(int8_t interfaceId, uint8_t *targetAddress); +typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info); typedef struct dhcpv6_alloacted_address_entry_s { uint8_t nonTemporalAddress[16]; @@ -50,10 +50,16 @@ typedef struct thread_dhcpv6_server_data_s { ns_list_link_t link; /*!< List link entry */ } dhcpv6_server_data_entry_t; +typedef struct dhcp_address_cache_update{ + uint8_t *allocatedAddress; + bool allocatedNewAddress; + uint32_t validLifeTime; +} dhcp_address_cache_update_t; + +typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src); + typedef struct dhcpv6_gua_server_entry_s { int8_t interfaceId; - bool enableAddressMapping; - uint8_t meshLocalPrefix[8]; bool enableAddressAutonous; uint16_t socketInstance_id; uint8_t guaPrefix[8]; @@ -63,13 +69,14 @@ typedef struct dhcpv6_gua_server_entry_s { uint32_t clientIdDefaultSuffics; uint32_t clientIdSequence; /*!< Define */ uint32_t validLifetime; - dhcp_address_prefer_timeout_cb *timeoutCb; + dhcp_address_prefer_remove_cb *removeCb; + dhcp_address_add_notify_cb *addCb; dhcpv6_alloacted_address_list_t allocatedAddressList; ns_list_link_t link; /*!< List link entry */ } dhcpv6_gua_server_entry_s; bool libdhcpv6_gua_server_list_empty(void); -dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb); +dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType); void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId); void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds); void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); @@ -81,7 +88,7 @@ dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_g #define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL #define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance, prefixPtr) NULL -#define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType, prefered_timeout_cb) NULL +#define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType) NULL #define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) ((void)0) #define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) ((void)0) #define libdhcpv6_gua_server_free_by_interfaceid(interfaceId) ((void)0) diff --git a/source/nsconfig.h b/source/nsconfig.h index bd7df30a632..59e3dc1a6fc 100644 --- a/source/nsconfig.h +++ b/source/nsconfig.h @@ -57,6 +57,12 @@ #endif #endif /* HAVE_THREAD */ +#if defined(HAVE_WS) +#ifndef HAVE_DHCPV6 +#define HAVE_DHCPV6 +#endif +#endif /* HAVE_WS */ + #endif // ifndef _NANOSTACK_SOURCE_CONFIG_H diff --git a/sources.mk b/sources.mk index 0217a539d46..e6461345da5 100644 --- a/sources.mk +++ b/sources.mk @@ -124,9 +124,9 @@ SRCS += \ source/6LoWPAN/Thread/thread_management_client.c \ source/6LoWPAN/Thread/thread_network_synch.c \ source/6LoWPAN/Thread/thread_bootstrap.c \ + source/6LoWPAN/Thread/thread_dhcpv6_server.c \ source/6LoWPAN/Thread/thread_host_bootstrap.c \ source/6LoWPAN/Thread/thread_router_bootstrap.c \ - source/6LoWPAN/Thread/thread_dhcpv6_client.c \ source/6LoWPAN/Thread/thread_discovery.c \ source/6LoWPAN/Thread/thread_commissioning_if.c \ source/6LoWPAN/Thread/thread_net_config_api.c \ @@ -143,6 +143,7 @@ SRCS += \ source/6LoWPAN/Thread/thread_lowpower_private_api.c \ source/6LoWPAN/Thread/thread_nvm_store.c \ source/DHCPv6_Server/DHCPv6_Server_service.c \ + source/DHCPv6_client/dhcpv6_client_service.c \ source/libDHCPv6/dhcp_service_api.c \ source/libDHCPv6/libDHCPv6.c \ source/libDHCPv6/libDHCPv6_server.c \