Merge pull request #13080 from artokin/nanostack_release_12_3_0_to_5_15

[mbed-os-5.15] Nanostack release v12.3.0
pull/13125/head
Anna Bridge 2020-06-12 14:47:34 +01:00 committed by GitHub
commit 82e2f9016c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
119 changed files with 6096 additions and 1566 deletions

View File

@ -70,9 +70,16 @@
#if !defined(TEST_PIN_SPARE_2) #if !defined(TEST_PIN_SPARE_2)
#define TEST_PIN_SPARE_2 D8 #define TEST_PIN_SPARE_2 D8
#endif #endif
#if !defined(SE2435L_CSD)
#define SE2435L_CSD D2
#endif
#if !defined(SE2435L_ANT_SEL)
#define SE2435L_ANT_SEL D8
#endif
class RFBits; class RFBits;
class TestPins; class TestPins;
class Se2435Pins;
class NanostackRfPhyAtmel : public NanostackRfPhy { class NanostackRfPhyAtmel : public NanostackRfPhy {
public: public:
@ -86,10 +93,13 @@ public:
virtual void set_mac_address(uint8_t *mac); virtual void set_mac_address(uint8_t *mac);
private: private:
#if !defined(DISABLE_AT24MAC)
AT24Mac _mac; AT24Mac _mac;
#endif
uint8_t _mac_addr[8]; uint8_t _mac_addr[8];
RFBits *_rf; RFBits *_rf;
TestPins *_test_pins; TestPins *_test_pins;
Se2435Pins *_se2435_pa_pins;
bool _mac_set; bool _mac_set;
const PinName _spi_mosi; const PinName _spi_mosi;

View File

@ -26,6 +26,7 @@ extern "C" {
#define RF24_IRQS 0x01 #define RF24_IRQS 0x01
#define BBC0_IRQS 0x02 #define BBC0_IRQS 0x02
#define BBC1_IRQS 0x03 #define BBC1_IRQS 0x03
#define RF_AUXS 0x01
#define RF_CFG 0x06 #define RF_CFG 0x06
#define RF_IQIFC1 0x0B #define RF_IQIFC1 0x0B
#define RF_PN 0x0D #define RF_PN 0x0D
@ -47,6 +48,8 @@ extern "C" {
#define RF_EDV 0x10 #define RF_EDV 0x10
#define RF_TXCUTC 0x12 #define RF_TXCUTC 0x12
#define RF_TXDFE 0x13 #define RF_TXDFE 0x13
#define RF_PAC 0x14
#define RF_PADFE 0x16
#define BBC_IRQM 0x00 #define BBC_IRQM 0x00
#define BBC_PC 0x01 #define BBC_PC 0x01
#define BBC_RXFLL 0x04 #define BBC_RXFLL 0x04
@ -55,6 +58,9 @@ extern "C" {
#define BBC_TXFLH 0x07 #define BBC_TXFLH 0x07
#define BBC_FBLL 0x08 #define BBC_FBLL 0x08
#define BBC_FBLH 0x09 #define BBC_FBLH 0x09
#define BBC_OFDMPHRTX 0x0C
#define BBC_OFDMC 0x0E
#define BBC_OFDMSW 0x0F
#define BBC_OQPSKC0 0x10 #define BBC_OQPSKC0 0x10
#define BBC_OQPSKC1 0x11 #define BBC_OQPSKC1 0x11
#define BBC_OQPSKC2 0x12 #define BBC_OQPSKC2 0x12
@ -82,6 +88,20 @@ extern "C" {
#define BBC1_FBRXS 0x3000 #define BBC1_FBRXS 0x3000
#define BBC1_FBTXS 0x3800 #define BBC1_FBTXS 0x3800
// RF_AUXS
#define EXTLNABYP (1 << 7)
#define AGCMAP 0x60
#define AGCMAP_2 (2 << 5)
#define AVEN (1 << 3)
// RF_PAC
#define TXPWR 0x1F
#define TXPWR_11 (11 << 0)
// RF_PADFE
#define PADFE 0xC0
#define RF_FEMODE3 (3 << 6)
// RF_AGCC // RF_AGCC
#define AGCI (1 << 6) #define AGCI (1 << 6)
#define AVGS 0x30 #define AVGS 0x30
@ -90,7 +110,7 @@ extern "C" {
// RF_AGCS // RF_AGCS
#define TGT 0xE0 #define TGT 0xE0
#define TGT_1 (1 << 5) #define TGT_1 (1 << 5)
#define TGT_3 (3 << 5)
// RF_RXBWC // RF_RXBWC
#define BW 0x0F #define BW 0x0F
@ -131,6 +151,7 @@ extern "C" {
// RF_TXDFE, RF_RXDFE // RF_TXDFE, RF_RXDFE
#define RCUT 0xE0 #define RCUT 0xE0
#define RCUT_4 (4 << 5) #define RCUT_4 (4 << 5)
#define RCUT_3 (3 << 5)
#define RCUT_2 (2 << 5) #define RCUT_2 (2 << 5)
#define RCUT_1 (1 << 5) #define RCUT_1 (1 << 5)
#define RCUT_0 (0 << 5) #define RCUT_0 (0 << 5)
@ -144,6 +165,41 @@ extern "C" {
#define SR_2 (2 << 0) #define SR_2 (2 << 0)
#define SR_1 (1 << 0) #define SR_1 (1 << 0)
// BBC_OFDMPHRTX
#define MCS 0x07
#define MCS_0 (0 << 0)
#define MCS_1 (1 << 0)
#define MCS_2 (2 << 0)
#define MCS_3 (3 << 0)
#define MCS_4 (4 << 0)
#define MCS_5 (5 << 0)
#define MCS_6 (6 << 0)
// BBC_OFDMC
#define SSRX 0xC0
#define SSRX_0 (0 << 6)
#define SSRX_1 (1 << 6)
#define SSRX_2 (2 << 6)
#define SSRX_3 (3 << 6)
#define SSTX 0x30
#define SSTX_0 (0 << 4)
#define SSTX_1 (1 << 4)
#define SSTX_2 (2 << 4)
#define SSTX_3 (3 << 4)
#define LFO (1 << 3)
#define POI (1 << 2)
#define OPT 0x03
#define OPT_1 (0 << 0)
#define OPT_2 (1 << 0)
#define OPT_3 (2 << 0)
#define OPT_4 (3 << 0)
// BBC_OFDMSW
#define OFDM_PDT 0xE0
#define OFDM_PDT_5 (5 << 5)
#define OFDM_PDT_4 (4 << 5)
#define OFDM_PDT_3 (3 << 5)
// BBC_FSKC0 // BBC_FSKC0
#define BT 0xC0 #define BT 0xC0
#define BT_20 (3 << 6) #define BT_20 (3 << 6)

View File

@ -48,6 +48,7 @@ extern "C" {
#define PART_AT86RF212 0x07 #define PART_AT86RF212 0x07
#define PART_AT86RF233 0x0B #define PART_AT86RF233 0x0B
#define PART_AT86RF215 0x34 #define PART_AT86RF215 0x34
#define PART_AT86RF215M 0x36
#define VERSION_AT86RF212 0x01 #define VERSION_AT86RF212 0x01
#define VERSION_AT86RF212B 0x03 #define VERSION_AT86RF212B 0x03

View File

@ -23,6 +23,7 @@
#include "platform/mbed_wait_api.h" #include "platform/mbed_wait_api.h"
#include "nanostack/platform/arm_hal_phy.h" #include "nanostack/platform/arm_hal_phy.h"
#include "NanostackRfPhyAtmel.h" #include "NanostackRfPhyAtmel.h"
#include "AT86RFReg.h"
#include "AT86RF215Reg.h" #include "AT86RF215Reg.h"
#include "mbed_trace.h" #include "mbed_trace.h"
#include "common_functions.h" #include "common_functions.h"
@ -99,6 +100,7 @@ static int rf_set_channel(uint16_t channel, rf_modules_e module);
static int rf_set_ch0_frequency(uint32_t frequency, rf_modules_e module); static int rf_set_ch0_frequency(uint32_t frequency, rf_modules_e module);
static int rf_set_channel_spacing(uint32_t channel_spacing, rf_modules_e module); static int rf_set_channel_spacing(uint32_t channel_spacing, rf_modules_e module);
static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules_e module); static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules_e module);
static int rf_configure_by_ofdm_bandwidth_option(uint8_t option, uint32_t data_rate, rf_modules_e module);
static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation); static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation);
static void rf_conf_set_cca_threshold(uint8_t percent); static void rf_conf_set_cca_threshold(uint8_t percent);
// Defined register read/write functions // Defined register read/write functions
@ -164,6 +166,7 @@ using namespace rtos;
#include "rfbits.h" #include "rfbits.h"
static RFBits *rf; static RFBits *rf;
static TestPins *test_pins; static TestPins *test_pins;
static Se2435Pins *se2435_pa_pins = NULL;
#define MAC_FRAME_TYPE_MASK 0x07 #define MAC_FRAME_TYPE_MASK 0x07
#define MAC_TYPE_ACK (2) #define MAC_TYPE_ACK (2)
@ -300,6 +303,9 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt
case PHY_EXTENSION_SET_CCA_THRESHOLD: case PHY_EXTENSION_SET_CCA_THRESHOLD:
rf_conf_set_cca_threshold(*data_ptr); rf_conf_set_cca_threshold(*data_ptr);
break; break;
case PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD:
cca_threshold = (int8_t) *data_ptr; // *NOPAD*
break;
case PHY_EXTENSION_SET_802_15_4_MODE: case PHY_EXTENSION_SET_802_15_4_MODE:
mac_mode = (phy_802_15_4_mode_t) *data_ptr; // *NOPAD* mac_mode = (phy_802_15_4_mode_t) *data_ptr; // *NOPAD*
if (mac_mode == IEEE_802_15_4_2011) { if (mac_mode == IEEE_802_15_4_2011) {
@ -378,7 +384,8 @@ static void rf_init(void)
static void rf_init_registers(rf_modules_e module) static void rf_init_registers(rf_modules_e module)
{ {
// O-QPSK configuration using IEEE Std 802.15.4-2011 // O-QPSK configuration using IEEE Std 802.15.4-2011
// FSK configuration using IEEE Std 802.15.4g-2012 // FSK/OFDM configuration using IEEE Std 802.15.4g-2012
// OFDM configuration is experimental only
if (mac_mode == IEEE_802_15_4_2011) { if (mac_mode == IEEE_802_15_4_2011) {
device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
// 16-bit FCS // 16-bit FCS
@ -405,12 +412,13 @@ static void rf_init_registers(rf_modules_e module)
rf_write_bbc_register_field(BBC_AFFTM, module, TYPE_2, TYPE_2); rf_write_bbc_register_field(BBC_AFFTM, module, TYPE_2, TYPE_2);
} else if (mac_mode == IEEE_802_15_4G_2012) { } else if (mac_mode == IEEE_802_15_4G_2012) {
device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE; device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
// Enable FSK
rf_write_bbc_register_field(BBC_PC, module, PT, BB_MRFSK);
// Disable auto ack // Disable auto ack
rf_write_bbc_register_field(BBC_AMCS, module, AACK, 0); rf_write_bbc_register_field(BBC_AMCS, module, AACK, 0);
// Disable address filter unit 0 // Disable address filter unit 0
rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, 0); rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, 0);
// Enable FSK
if (phy_current_config.modulation == M_2FSK) {
rf_write_bbc_register_field(BBC_PC, module, PT, BB_MRFSK);
// Set bandwidth time product // Set bandwidth time product
rf_write_bbc_register_field(BBC_FSKC0, module, BT, BT_20); rf_write_bbc_register_field(BBC_FSKC0, module, BT, BT_20);
// Disable interleaving // Disable interleaving
@ -438,8 +446,38 @@ static void rf_init_registers(rf_modules_e module)
preamble_len = 12; preamble_len = 12;
} }
rf_write_bbc_register(BBC_FSKPLL, module, preamble_len); rf_write_bbc_register(BBC_FSKPLL, module, preamble_len);
// Set preamble detector threshold
rf_write_bbc_register_field(BBC_FSKC3, module, PDT, PDT_6); rf_write_bbc_register_field(BBC_FSKC3, module, PDT, PDT_6);
} else if (phy_current_config.modulation == M_OFDM) {
rf_write_bbc_register_field(BBC_PC, module, PT, BB_MROFDM);
// Set TX scrambler seed
rf_write_bbc_register_field(BBC_OFDMC, module, SSTX, SSTX_0);
// Set RX scrambler seed
rf_write_bbc_register_field(BBC_OFDMC, module, SSRX, SSRX_0);
// Set phyOFDMInterleaving
rf_write_bbc_register_field(BBC_OFDMC, module, POI, 0);
// Set low frequency offset bit
rf_write_bbc_register_field(BBC_OFDMC, module, LFO, 0);
// Configure using bandwidth option
rf_configure_by_ofdm_bandwidth_option(4, 300000, module);
// Set Gain control settings
rf_write_rf_register_field(RF_AGCC, module, AVGS, AVGS_8_SAMPLES);
rf_write_rf_register_field(RF_AGCC, module, AGCI, 0);
rf_write_rf_register_field(RF_AGCS, module, TGT, TGT_3);
} }
}
if (se2435_pa_pins) {
// Wakeup SE2435L
se2435_pa_pins->CSD = 1;
// Antenna port selection: (0 - port 1, 1 - port 2)
se2435_pa_pins->ANT_SEL = 0;
// Enable external front end with configuration 3
rf_write_rf_register_field(RF_PADFE, module, PADFE, RF_FEMODE3);
// Output power at 900MHz: 0 dBm with FSK/QPSK, less than -5 dBm with OFDM
rf_write_rf_register_field(RF_PAC, module, TXPWR, TXPWR_11);
}
// Enable analog voltage regulator
rf_write_rf_register_field(RF_AUXS, module, AVEN, AVEN);
// Disable filtering FCS // Disable filtering FCS
rf_write_bbc_register_field(BBC_PC, module, FCSFE, 0); rf_write_bbc_register_field(BBC_PC, module, FCSFE, 0);
// Set channel spacing // Set channel spacing
@ -488,9 +526,10 @@ static int8_t rf_start_csma_ca(uint8_t *data_ptr, uint16_t data_length, uint8_t
tx_sequence = *(data_ptr + 2); tx_sequence = *(data_ptr + 2);
} }
rf_write_tx_buffer(data_ptr, data_length, rf_module); rf_write_tx_buffer(data_ptr, data_length, rf_module);
if (phy_current_config.modulation == M_OQPSK) { // Add CRC bytes
if (mac_mode == IEEE_802_15_4_2011) {
data_length += 2; data_length += 2;
} else if (phy_current_config.modulation == M_2FSK) { } else {
data_length += 4; data_length += 4;
} }
rf_write_tx_packet_length(data_length, rf_module); rf_write_tx_packet_length(data_length, rf_module);
@ -614,9 +653,10 @@ static void rf_handle_rx_done(void)
rf_handle_ack(rx_buffer[2], rx_buffer[0] & MAC_DATA_PENDING); rf_handle_ack(rx_buffer[2], rx_buffer[0] & MAC_DATA_PENDING);
} else { } else {
int8_t rssi = (int8_t) rf_read_rf_register(RF_EDV, rf_module); int8_t rssi = (int8_t) rf_read_rf_register(RF_EDV, rf_module);
if (phy_current_config.modulation == M_OQPSK) { // Cut CRC bytes
if (mac_mode == IEEE_802_15_4_2011) {
cur_rx_packet_len -= 2; cur_rx_packet_len -= 2;
} else if (phy_current_config.modulation == M_2FSK) { } else {
cur_rx_packet_len -= 4; cur_rx_packet_len -= 4;
} }
device_driver.phy_rx_cb(rx_buffer, cur_rx_packet_len, 0xf0, rssi, rf_radio_driver_id); device_driver.phy_rx_cb(rx_buffer, cur_rx_packet_len, 0xf0, rssi, rf_radio_driver_id);
@ -1055,6 +1095,75 @@ static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules
return 0; return 0;
} }
static int rf_configure_by_ofdm_bandwidth_option(uint8_t option, uint32_t data_rate, rf_modules_e module)
{
if (!option || option > 4) {
return -1;
}
uint32_t datarate_tmp = 100000 >> (option - 1);
// Set modulation and coding scheme
if (data_rate == datarate_tmp) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_0);
} else if (data_rate == datarate_tmp * 2) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_1);
} else if (data_rate == datarate_tmp * 4) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_2);
} else if (data_rate == datarate_tmp * 8) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_3);
} else if (data_rate == datarate_tmp * 12) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_4);
} else if (data_rate == datarate_tmp * 16) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_5);
} else if (data_rate == datarate_tmp * 24) {
rf_write_bbc_register_field(BBC_OFDMPHRTX, module, MCS, MCS_6);
} else {
return -1;
}
if (option == 1) {
rf_write_bbc_register_field(BBC_OFDMC, module, OPT, OPT_1);
rf_write_rf_register_field(RF_TXDFE, module, SR, SR_3);
rf_write_rf_register_field(RF_RXDFE, module, SR, SR_3);
rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_4);
rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_4);
rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC800KHZ);
rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW1250KHZ_IF2000KHZ);
rf_write_rf_register_field(RF_RXBWC, module, IFS, IFS);
rf_write_bbc_register_field(BBC_OFDMSW, module, OFDM_PDT, OFDM_PDT_5);
} else if (option == 2) {
rf_write_bbc_register_field(BBC_OFDMC, module, OPT, OPT_2);
rf_write_rf_register_field(RF_TXDFE, module, SR, SR_3);
rf_write_rf_register_field(RF_RXDFE, module, SR, SR_3);
rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_3);
rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_2);
rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC500KHZ);
rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW800KHZ_IF1000KHZ);
rf_write_rf_register_field(RF_RXBWC, module, IFS, IFS);
rf_write_bbc_register_field(BBC_OFDMSW, module, OFDM_PDT, OFDM_PDT_5);
} else if (option == 3) {
rf_write_bbc_register_field(BBC_OFDMC, module, OPT, OPT_3);
rf_write_rf_register_field(RF_TXDFE, module, SR, SR_6);
rf_write_rf_register_field(RF_RXDFE, module, SR, SR_6);
rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_3);
rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_2);
rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC250KHZ);
rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW400KHZ_IF500KHZ);
rf_write_rf_register_field(RF_RXBWC, module, IFS, 0);
rf_write_bbc_register_field(BBC_OFDMSW, module, OFDM_PDT, OFDM_PDT_4);
} else if (option == 4) {
rf_write_bbc_register_field(BBC_OFDMC, module, OPT, OPT_4);
rf_write_rf_register_field(RF_TXDFE, module, SR, SR_6);
rf_write_rf_register_field(RF_RXDFE, module, SR, SR_6);
rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_2);
rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1);
rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC160KHZ);
rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW250KHZ_IF250KHZ);
rf_write_rf_register_field(RF_RXBWC, module, IFS, 1);
rf_write_bbc_register_field(BBC_OFDMSW, module, OFDM_PDT, OFDM_PDT_3);
}
return 0;
}
static void rf_conf_set_cca_threshold(uint8_t percent) static void rf_conf_set_cca_threshold(uint8_t percent)
{ {
uint8_t step = (MAX_CCA_THRESHOLD - MIN_CCA_THRESHOLD); uint8_t step = (MAX_CCA_THRESHOLD - MIN_CCA_THRESHOLD);
@ -1094,10 +1203,28 @@ int RFBits::init_215_driver(RFBits *_rf, TestPins *_test_pins, const uint8_t mac
test_pins = _test_pins; test_pins = _test_pins;
irq_thread_215.start(mbed::callback(this, &RFBits::rf_irq_task)); irq_thread_215.start(mbed::callback(this, &RFBits::rf_irq_task));
rf->spi.frequency(25000000); rf->spi.frequency(25000000);
/* Atmel AT86RF215 Device Family datasheet:
* Errata #9: RF215M device has a wrong part number
* Description:
* The RF215M device part number is 0x34 instead of 0x36 (register RF_PN.PN).
*/
#if !defined(HAVE_AT86RF215M)
*rf_part_num = rf_read_common_register(RF_PN); *rf_part_num = rf_read_common_register(RF_PN);
#else
*rf_part_num = PART_AT86RF215M;
// AT86RF215M is Sub-GHz only transceiver. Change default settings.
rf_module = RF_09;
mac_mode = IEEE_802_15_4G_2012;
#endif
rf_version_num = rf_read_common_register(RF_VN); rf_version_num = rf_read_common_register(RF_VN);
tr_info("RF version number: %x", rf_version_num); tr_info("RF version number: %x", rf_version_num);
return rf_device_register(mac); return rf_device_register(mac);
} }
int RFBits::init_se2435_pa(Se2435Pins *_se2435_pa_pins)
{
se2435_pa_pins = _se2435_pa_pins;
return 0;
}
#endif // MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI && DEVICE_INTERRUPTIN && defined(MBED_CONF_RTOS_PRESENT) #endif // MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI && DEVICE_INTERRUPTIN && defined(MBED_CONF_RTOS_PRESENT)

View File

@ -275,8 +275,15 @@ TestPins::TestPins(PinName test_pin_1, PinName test_pin_2, PinName test_pin_3, P
{ {
} }
Se2435Pins::Se2435Pins(PinName csd_pin, PinName ant_sel_pin)
: CSD(csd_pin),
ANT_SEL(ant_sel_pin)
{
}
static RFBits *rf; static RFBits *rf;
static TestPins *test_pins; static TestPins *test_pins;
static Se2435Pins *se2435_pa_pins;
static uint8_t rf_part_num = 0; static uint8_t rf_part_num = 0;
/*TODO: RSSI Base value setting*/ /*TODO: RSSI Base value setting*/
static int8_t rf_rssi_base_val = -91; static int8_t rf_rssi_base_val = -91;
@ -2168,7 +2175,11 @@ static uint8_t rf_scale_lqi(int8_t rssi)
NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso, NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso,
PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq,
PinName i2c_sda, PinName i2c_scl) PinName i2c_sda, PinName i2c_scl)
: _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _test_pins(NULL), _mac_set(false), :
#if !defined(DISABLE_AT24MAC)
_mac(i2c_sda, i2c_scl),
#endif
_mac_addr(), _rf(NULL), _test_pins(NULL), _se2435_pa_pins(NULL), _mac_set(false),
_spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk), _spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk),
_spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq) _spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq)
{ {
@ -2176,6 +2187,9 @@ NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso,
#ifdef TEST_GPIOS_ENABLED #ifdef TEST_GPIOS_ENABLED
_test_pins = new TestPins(TEST_PIN_TX, TEST_PIN_RX, TEST_PIN_CSMA, TEST_PIN_SPARE_1, TEST_PIN_SPARE_2); _test_pins = new TestPins(TEST_PIN_TX, TEST_PIN_RX, TEST_PIN_CSMA, TEST_PIN_SPARE_1, TEST_PIN_SPARE_2);
#endif #endif
#ifdef SE2435L_PA
_se2435_pa_pins = new Se2435Pins(SE2435L_CSD, SE2435L_ANT_SEL);
#endif
} }
NanostackRfPhyAtmel::~NanostackRfPhyAtmel() NanostackRfPhyAtmel::~NanostackRfPhyAtmel()
@ -2200,19 +2214,29 @@ int8_t NanostackRfPhyAtmel::rf_register()
// Read the mac address if it hasn't been set by a user // Read the mac address if it hasn't been set by a user
rf = _rf; rf = _rf;
test_pins = _test_pins; test_pins = _test_pins;
se2435_pa_pins = _se2435_pa_pins;
if (!_mac_set) { if (!_mac_set) {
// Unless AT24MAC is available, using randomly generated MAC address
#if !defined(DISABLE_AT24MAC)
int ret = _mac.read_eui64((void *)_mac_addr); int ret = _mac.read_eui64((void *)_mac_addr);
if (ret < 0) { if (ret < 0) {
rf = NULL; rf = NULL;
rf_if_unlock(); rf_if_unlock();
return -1; return -1;
} }
#else
randLIB_seed_random();
randLIB_get_n_bytes_random(_mac_addr, 8);
_mac_addr[0] |= 2; //Set Local Bit
_mac_addr[0] &= ~1; //Clear multicast bit
#endif
} }
/*Reset RF module*/ /*Reset RF module*/
rf_if_reset_radio(); rf_if_reset_radio();
rf_part_num = rf_if_read_part_num(); rf_part_num = rf_if_read_part_num();
int8_t radio_id = -1; int8_t radio_id = -1;
if (rf_part_num != PART_AT86RF231 && rf_part_num != PART_AT86RF233 && rf_part_num != PART_AT86RF212) { if (rf_part_num != PART_AT86RF231 && rf_part_num != PART_AT86RF233 && rf_part_num != PART_AT86RF212) {
rf->init_se2435_pa(_se2435_pa_pins);
// Register RF type 215. Jumps to AT86RF215 driver. // Register RF type 215. Jumps to AT86RF215 driver.
radio_id = rf->init_215_driver(_rf, _test_pins, _mac_addr, &rf_part_num); radio_id = rf->init_215_driver(_rf, _test_pins, _mac_addr, &rf_part_num);
} else { } else {

View File

@ -51,6 +51,7 @@ public:
Timeout cca_timer; Timeout cca_timer;
Timer tx_timer; Timer tx_timer;
int init_215_driver(RFBits *_rf, TestPins *_test_pins, const uint8_t mac[8], uint8_t *rf_part_num); int init_215_driver(RFBits *_rf, TestPins *_test_pins, const uint8_t mac[8], uint8_t *rf_part_num);
int init_se2435_pa(Se2435Pins *_se2435_pa_pins);
#ifdef MBED_CONF_RTOS_PRESENT #ifdef MBED_CONF_RTOS_PRESENT
Thread irq_thread; Thread irq_thread;
Thread irq_thread_215; Thread irq_thread_215;
@ -70,4 +71,11 @@ public:
DigitalOut TEST5; DigitalOut TEST5;
}; };
class Se2435Pins {
public:
Se2435Pins(PinName csd_pin, PinName ant_sel_pin);
DigitalOut CSD;
DigitalOut ANT_SEL;
};
#endif /* RFBITS_H_ */ #endif /* RFBITS_H_ */

View File

@ -1,6 +1,7 @@
/*! /*!
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* *
* \file MCR20Drv.c * \file MCR20Drv.c
* *
@ -114,9 +115,7 @@ void MCR20Drv_Init
xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000); xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
gXcvrDeassertCS_d(); gXcvrDeassertCS_d();
#if !defined(TARGET_KW24D)
MCR20Drv_RST_B_Deassert(); MCR20Drv_RST_B_Deassert();
#endif
RF_IRQ_Init(); RF_IRQ_Init();
RF_IRQ_Disable(); RF_IRQ_Disable();
mPhyIrqDisableCnt = 1; mPhyIrqDisableCnt = 1;
@ -639,7 +638,6 @@ void MCR20Drv_RESET
void void
) )
{ {
#if !defined(TARGET_KW24D)
volatile uint32_t delay = 1000; volatile uint32_t delay = 1000;
//assert RST_B //assert RST_B
MCR20Drv_RST_B_Assert(); MCR20Drv_RST_B_Assert();
@ -648,7 +646,6 @@ void MCR20Drv_RESET
//deassert RST_B //deassert RST_B
MCR20Drv_RST_B_Deassert(); MCR20Drv_RST_B_Deassert();
#endif
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------

View File

@ -1,6 +1,7 @@
/*! /*!
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* *
* \file MCR20Drv.h * \file MCR20Drv.h
* *

View File

@ -1,6 +1,7 @@
/*! /*!
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* *
* \file MCR20Overwrites.h * \file MCR20Overwrites.h
* Description: Overwrites header file for MCR20 Register values * Description: Overwrites header file for MCR20 Register values

View File

@ -1,6 +1,7 @@
/*! /*!
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* *
* \file MCR20reg.h * \file MCR20reg.h
* MCR20 Registers * MCR20 Registers

View File

@ -61,11 +61,7 @@ extern "C" {
#define gCcaCCA_MODE1_c 1 #define gCcaCCA_MODE1_c 1
#define gXcvrRunState_d gXcvrPwrAutodoze_c #define gXcvrRunState_d gXcvrPwrAutodoze_c
#if !defined(TARGET_KW24D)
#define gXcvrLowPowerState_d gXcvrPwrHibernate_c #define gXcvrLowPowerState_d gXcvrPwrHibernate_c
#else
#define gXcvrLowPowerState_d gXcvrPwrAutodoze_c
#endif
namespace { namespace {
@ -504,9 +500,7 @@ static void rf_init(void)
/* Disable Tristate on MISO for SPI reads */ /* Disable Tristate on MISO for SPI reads */
MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02); MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02);
/* Set XCVR clock output settings */ /* Set XCVR clock output settings */
#if !defined(TARGET_KW24D)
MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d); MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d);
#endif
/* Set default XCVR power state */ /* Set default XCVR power state */
rf_set_power_state(gXcvrRunState_d); rf_set_power_state(gXcvrRunState_d);
@ -1758,7 +1752,7 @@ void NanostackRfPhyMcr20a::_pins_clear()
irq_thread = NULL; irq_thread = NULL;
} }
#if MBED_CONF_MCR20A_PROVIDE_DEFAULT || TARGET_KW24D #if MBED_CONF_MCR20A_PROVIDE_DEFAULT
NanostackRfPhy &NanostackRfPhy::get_default_instance() NanostackRfPhy &NanostackRfPhy::get_default_instance()
{ {

View File

@ -1,6 +1,7 @@
/*! /*!
* Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* *
* \file XcvrSpi.h * \file XcvrSpi.h
* *

View File

@ -1,14 +1,73 @@
{ {
"name": "s2lp", "name": "s2lp",
"config": { "config": {
"SPI_SDI": {
"help": "SPI_SDI pin for SPI connection. D11 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_SDO": {
"help": "SPI_SDO pin for SPI connection. D12 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_SCLK": {
"help": "SPI_SCLK pin for SPI connection, D13 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_CS": {
"help": "SPI_CS pin for SPI connection, A1 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_SDN": {
"help": "SPI_SDN pin for SPI connection, D7 assumed, needs to be set/overwritten otherwise",
"value": null
},
"TEST_PIN_TX": {
"help": "TEST_PIN_TX pin for serial connection, D6 assumed, needs to be set/overwritten otherwise",
"value": null
},
"TEST_PIN_RX": {
"help": "TEST_PIN_RX pin for serial connection, D5 assumed, needs to be set/overwritten otherwise",
"value": null
},
"TEST_PIN_CSMA": {
"help": "TEST_PIN_CSMA pin for CSMA, D4 assumed, needs to be set/overwritten otherwise",
"value": null
},
"TEST_PIN_SPARE_1": {
"help": "TEST_PIN_SPARE_1 pin for testing, D2 assumed, needs to be set/overwritten otherwise",
"value": null
},
"TEST_PIN_SPARE_2": {
"help": "TEST_PIN_SPARE_2 pin for testing, D8 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_GPIO0": {
"help": "SPI_GPIO0 pin for GPIO testing, A0 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_GPIO1": {
"help": "SPI_GPIO1 pin for GPIO testing, A2 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_GPIO2": {
"help": "SPI_GPIO2 pin for GPIO testing, A3 assumed, needs to be set/overwritten otherwise",
"value": null
},
"SPI_GPIO3": {
"help": "SPI_GPIO3 pin for GPIO testing, A5 assumed, needs to be set/overwritten otherwise",
"value": null
},
"I2C_SDA": {
"help": "I2C_SDA pin for I2C SDA, null assumed, needs to be set/overwritten otherwise",
"value": null
},
"I2C_SCL": {
"help": "I2C_SCL pin for I2C SCL, null assumed, needs to be set/overwritten otherwise",
"value": null
},
"provide-default": { "provide-default": {
"help": "Provide default NanostackRfpy. [true/false]", "help": "Provide default NanostackRfpy. [true/false]",
"value": false "value": false
},
"target_overrides": {
"MTB_STM_S2LP": {
"s2lp.provide-default": true
}
} }
} }
} }

View File

@ -182,7 +182,9 @@ static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *
static void rf_cca_timer_start(uint32_t slots); static void rf_cca_timer_start(uint32_t slots);
static RFPins *rf; static RFPins *rf;
#ifdef TEST_GPIOS_ENABLED
static TestPins_S2LP *test_pins; static TestPins_S2LP *test_pins;
#endif
static phy_device_driver_s device_driver; static phy_device_driver_s device_driver;
static int8_t rf_radio_driver_id = -1; static int8_t rf_radio_driver_id = -1;
static uint8_t *tx_data_ptr; static uint8_t *tx_data_ptr;
@ -207,6 +209,7 @@ static uint8_t s2lp_short_address[2];
static uint8_t s2lp_MAC[8]; static uint8_t s2lp_MAC[8];
static rf_mode_e rf_mode = RF_MODE_NORMAL; static rf_mode_e rf_mode = RF_MODE_NORMAL;
static bool rf_update_config = false; static bool rf_update_config = false;
static bool rf_update_cca_threshold = false;
static uint16_t cur_packet_len = 0xffff; static uint16_t cur_packet_len = 0xffff;
static uint32_t receiver_ready_timestamp; static uint32_t receiver_ready_timestamp;
static int16_t rssi_threshold = RSSI_THRESHOLD; static int16_t rssi_threshold = RSSI_THRESHOLD;
@ -704,6 +707,13 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt
rf_receive(rf_rx_channel); rf_receive(rf_rx_channel);
} }
break; break;
case PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD:
if ((rssi_threshold != (int8_t)*data_ptr) && (rf_state != RF_RX_STARTED)) {
rssi_threshold = (int8_t)*data_ptr; // *NOPAD*
rf_update_cca_threshold = true;
rf_receive(rf_rx_channel);
}
break;
default: default:
break; break;
} }
@ -752,9 +762,9 @@ static void rf_tx_sent_handler(void)
TEST_TX_DONE TEST_TX_DONE
rf_backup_timer_stop(); rf_backup_timer_stop();
rf_disable_interrupt(TX_DATA_SENT); rf_disable_interrupt(TX_DATA_SENT);
rf_update_tx_active_time();
if (rf_state != RF_TX_ACK) { if (rf_state != RF_TX_ACK) {
tx_finnish_time = rf_get_timestamp(); tx_finnish_time = rf_get_timestamp();
rf_update_tx_active_time();
rf_state = RF_IDLE; rf_state = RF_IDLE;
rf_receive(rf_rx_channel); rf_receive(rf_rx_channel);
if (device_driver.phy_tx_done_cb) { if (device_driver.phy_tx_done_cb) {
@ -821,7 +831,6 @@ static void rf_cca_timer_interrupt(void)
} }
rf_flush_tx_fifo(); rf_flush_tx_fifo();
tx_finnish_time = rf_get_timestamp(); tx_finnish_time = rf_get_timestamp();
rf_update_tx_active_time();
if (device_driver.phy_tx_done_cb) { if (device_driver.phy_tx_done_cb) {
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
} }
@ -955,7 +964,6 @@ static void rf_handle_ack(uint8_t seq_number, uint8_t pending)
phy_link_tx_status_e phy_status; phy_link_tx_status_e phy_status;
if (tx_sequence == (uint16_t)seq_number) { if (tx_sequence == (uint16_t)seq_number) {
tx_finnish_time = rf_get_timestamp(); tx_finnish_time = rf_get_timestamp();
rf_update_tx_active_time();
if (pending) { if (pending) {
phy_status = PHY_LINK_TX_DONE_PENDING; phy_status = PHY_LINK_TX_DONE_PENDING;
} else { } else {
@ -1047,6 +1055,12 @@ static void rf_receive(uint8_t rx_channel)
rf_update_config = false; rf_update_config = false;
rf_set_channel_configuration_registers(); rf_set_channel_configuration_registers();
} }
if (rf_update_cca_threshold == true) {
rf_update_cca_threshold = false;
uint8_t rssi_th;
rf_conf_calculate_rssi_threshold_registers(rssi_threshold, &rssi_th);
rf_write_register(RSSI_TH, rssi_th);
}
if (rx_channel != rf_rx_channel) { if (rx_channel != rf_rx_channel) {
rf_write_register(CHNUM, rx_channel * rf_channel_multiplier); rf_write_register(CHNUM, rx_channel * rf_channel_multiplier);
rf_rx_channel = rf_new_channel = rx_channel; rf_rx_channel = rf_new_channel = rx_channel;
@ -1280,7 +1294,9 @@ int8_t NanostackRfPhys2lp::rf_register()
} }
rf = _rf; rf = _rf;
#ifdef TEST_GPIOS_ENABLED
test_pins = _test_pins; test_pins = _test_pins;
#endif
int8_t radio_id = rf_device_register(_mac_addr); int8_t radio_id = rf_device_register(_mac_addr);
if (radio_id < 0) { if (radio_id < 0) {
@ -1303,9 +1319,9 @@ void NanostackRfPhys2lp::rf_unregister()
} }
NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn
,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 , PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3
#ifdef AT24MAC #ifdef AT24MAC
,PinName i2c_sda, PinName i2c_scl , PinName i2c_sda, PinName i2c_scl
#endif //AT24MAC #endif //AT24MAC
) )
: :
@ -1424,9 +1440,9 @@ static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *
NanostackRfPhy &NanostackRfPhy::get_default_instance() NanostackRfPhy &NanostackRfPhy::get_default_instance()
{ {
static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN
,S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3 , S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3
#ifdef AT24MAC #ifdef AT24MAC
,S2LP_I2C_SDA, S2LP_I2C_SCL , S2LP_I2C_SDA, S2LP_I2C_SCL
#endif //AT24MAC #endif //AT24MAC
); );
return rf_phy; return rf_phy;

View File

@ -157,7 +157,7 @@ void rf_conf_calculate_rx_filter_bandwidth_registers(uint32_t rx_bandwidth, uint
int16_t rf_conf_cca_threshold_percent_to_rssi(uint8_t percent) int16_t rf_conf_cca_threshold_percent_to_rssi(uint8_t percent)
{ {
uint8_t step = (MAX_RSSI_THRESHOLD-MIN_RSSI_THRESHOLD); uint8_t step = (MAX_RSSI_THRESHOLD - MIN_RSSI_THRESHOLD);
return MIN_RSSI_THRESHOLD + (step * percent) / 100; return MIN_RSSI_THRESHOLD + (step * percent) / 100;
} }

View File

@ -25,87 +25,100 @@
#include "InterruptIn.h" #include "InterruptIn.h"
#include "SPI.h" #include "SPI.h"
// Uncomment to use testing gpios attached to TX/RX processes #if defined(MBED_CONF_S2LP_SPI_SDI)
// #define TEST_GPIOS_ENABLED #define S2LP_SPI_SDI MBED_CONF_S2LP_SPI_SDI
#if defined(TARGET_MTB_STM_S2LP)
#if !defined(S2LP_SPI_SDI)
#define S2LP_SPI_SDI PA_7
#endif
#if !defined(S2LP_SPI_SDO)
#define S2LP_SPI_SDO PA_6
#endif
#if !defined(S2LP_SPI_SCLK)
#define S2LP_SPI_SCLK PA_5
#endif
#if !defined(S2LP_SPI_CS)
#define S2LP_SPI_CS PC_0
#endif
#if !defined(S2LP_SPI_SDN)
#define S2LP_SPI_SDN PF_13
#endif
#if !defined(S2LP_SPI_GPIO0)
#define S2LP_SPI_GPIO0 PA_3
#endif
#if !defined(S2LP_SPI_GPIO1)
#define S2LP_SPI_GPIO1 PC_3
#endif
#if !defined(S2LP_SPI_GPIO2)
#define S2LP_SPI_GPIO2 PF_3
#endif
#if !defined(S2LP_SPI_GPIO3)
#define S2LP_SPI_GPIO3 PF_10
#endif
#if !defined(S2LP_I2C_SDA)
#define S2LP_I2C_SDA PB_7
#endif
#if !defined(S2LP_I2C_SCL)
#define S2LP_I2C_SCL PB_6
#endif
#define AT24MAC
#else #else
#if !defined(S2LP_SPI_SDI)
#define S2LP_SPI_SDI D11 #define S2LP_SPI_SDI D11
#endif #endif
#if !defined(S2LP_SPI_SDO)
#if defined(MBED_CONF_S2LP_SPI_SDO)
#define S2LP_SPI_SDO MBED_CONF_S2LP_SPI_SDO
#else
#define S2LP_SPI_SDO D12 #define S2LP_SPI_SDO D12
#endif #endif
#if !defined(S2LP_SPI_SCLK)
#if defined(MBED_CONF_S2LP_SPI_SCLK)
#define S2LP_SPI_SCLK MBED_CONF_S2LP_SPI_SCLK
#else
#define S2LP_SPI_SCLK D13 #define S2LP_SPI_SCLK D13
#endif #endif
#if !defined(S2LP_SPI_CS)
#if defined(MBED_CONF_S2LP_SPI_CS)
#define S2LP_SPI_CS MBED_CONF_S2LP_SPI_CS
#else
#define S2LP_SPI_CS A1 #define S2LP_SPI_CS A1
#endif #endif
#if !defined(S2LP_SPI_SDN)
#if defined(MBED_CONF_S2LP_SPI_SDN)
#define S2LP_SPI_SDN MBED_CONF_S2LP_SPI_SDN
#else
#define S2LP_SPI_SDN D7 #define S2LP_SPI_SDN D7
#endif #endif
#if !defined(TEST_PIN_TX)
#define TEST_PIN_TX D6 #if defined(MBED_CONF_S2LP_TEST_PIN_TX)
#define S2LP_TEST_PIN_TX MBED_CONF_S2LP_TEST_PIN_TX
#else
#define S2LP_TEST_PIN_TX D6
#endif #endif
#if !defined(TEST_PIN_RX)
#define TEST_PIN_RX D5 #if defined(MBED_CONF_S2LP_TEST_PIN_RX)
#define S2LP_TEST_PIN_RX MBED_CONF_S2LP_TEST_PIN_RX
#else
#define S2LP_TEST_PIN_RX D5
#endif #endif
#if !defined(TEST_PIN_CSMA)
#define TEST_PIN_CSMA D4 #if defined(MBED_CONF_S2LP_TEST_PIN_CSMA)
#define S2LP_TEST_PIN_CSMA MBED_CONF_S2LP_TEST_PIN_CSMA
#else
#define S2LP_TEST_PIN_CSMA D4
#endif #endif
#if !defined(TEST_PIN_SPARE_1)
#define TEST_PIN_SPARE_1 D2 #if defined(MBED_CONF_S2LP_TEST_PIN_SPARE_1)
#define S2LP_TEST_PIN_SPARE_1 MBED_CONF_S2LP_TEST_PIN_SPARE_1
#else
#define S2LP_TEST_PIN_SPARE_1 D2
#endif #endif
#if !defined(TEST_PIN_SPARE_2)
#define TEST_PIN_SPARE_2 D8 #if defined(MBED_CONF_S2LP_TEST_PIN_SPARE_2)
#define S2LP_TEST_PIN_SPARE_2 MBED_CONF_S2LP_TEST_PIN_SPARE_2
#else
#define S2LP_TEST_PIN_SPARE_2 D8
#endif #endif
#if !defined(S2LP_SPI_GPIO0)
#if defined(MBED_CONF_S2LP_SPI_GPIO0)
#define S2LP_SPI_GPIO0 MBED_CONF_S2LP_SPI_GPIO0
#else
#define S2LP_SPI_GPIO0 A0 #define S2LP_SPI_GPIO0 A0
#endif #endif
#if !defined(S2LP_SPI_GPIO1)
#if defined(MBED_CONF_S2LP_SPI_GPIO1)
#define S2LP_SPI_GPIO1 MBED_CONF_S2LP_SPI_GPIO1
#else
#define S2LP_SPI_GPIO1 A2 #define S2LP_SPI_GPIO1 A2
#endif #endif
#if !defined(S2LP_SPI_GPIO2)
#if defined(MBED_CONF_S2LP_SPI_GPIO2)
#define S2LP_SPI_GPIO2 MBED_CONF_S2LP_SPI_GPIO2
#else
#define S2LP_SPI_GPIO2 A3 #define S2LP_SPI_GPIO2 A3
#endif #endif
#if !defined(S2LP_SPI_GPIO3)
#if defined(MBED_CONF_S2LP_SPI_GPIO3)
#define S2LP_SPI_GPIO3 MBED_CONF_S2LP_SPI_GPIO3
#else
#define S2LP_SPI_GPIO3 A5 #define S2LP_SPI_GPIO3 A5
#endif #endif
#if defined(MBED_CONF_S2LP_I2C_SDA)
#define S2LP_I2C_SDA MBED_CONF_S2LP_I2C_SDA
#else
#define S2LP_I2C_SDA null
#endif
#if defined(MBED_CONF_S2LP_I2C_SCL)
#define S2LP_I2C_SCL MBED_CONF_S2LP_I2C_SCL
#else
#define S2LP_I2C_SCL null
#endif #endif
#include "at24mac_s2lp.h" #include "at24mac_s2lp.h"
@ -116,9 +129,9 @@ class TestPins_S2LP;
class NanostackRfPhys2lp : public NanostackRfPhy { class NanostackRfPhys2lp : public NanostackRfPhy {
public: public:
NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn
,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 , PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3
#ifdef AT24MAC #ifdef AT24MAC
,PinName i2c_sda, PinName i2c_scl , PinName i2c_sda, PinName i2c_scl
#endif //AT24MAC #endif //AT24MAC
); );
virtual ~NanostackRfPhys2lp(); virtual ~NanostackRfPhys2lp();

View File

@ -509,9 +509,7 @@ COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros(uint8_t value)
COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t value) COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t value)
{ {
#ifdef __CC_ARM #if defined __GNUC__
return value ? __clz((unsigned int) value << 24) : 8;
#elif defined __GNUC__
return value ? __builtin_clz((unsigned int) value << 24) : 8; return value ? __builtin_clz((unsigned int) value << 24) : 8;
#else #else
uint_fast8_t cnt = 0; uint_fast8_t cnt = 0;
@ -536,9 +534,7 @@ COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t value)
COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_16(uint16_t value) COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_16(uint16_t value)
{ {
#ifdef __CC_ARM #if defined __GNUC__
return value ? __clz((unsigned int) value << 16) : 16;
#elif defined __GNUC__
return value ? __builtin_clz((unsigned int) value << 16) : 16; return value ? __builtin_clz((unsigned int) value << 16) : 16;
#else #else
uint_fast8_t cnt = 0; uint_fast8_t cnt = 0;
@ -567,9 +563,7 @@ COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_16(uint16_t value)
COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_32(uint32_t value) COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_32(uint32_t value)
{ {
#ifdef __CC_ARM #if defined __GNUC__
return __clz(value);
#elif defined __GNUC__
return value ? __builtin_clz(value) : 32; return value ? __builtin_clz(value) : 32;
#else #else
uint_fast8_t cnt = 0; uint_fast8_t cnt = 0;

View File

@ -106,8 +106,6 @@ typedef int_fast32_t int_fast24_t;
#define NS_NORETURN _Noreturn #define NS_NORETURN _Noreturn
#elif defined __GNUC__ #elif defined __GNUC__
#define NS_NORETURN __attribute__((__noreturn__)) #define NS_NORETURN __attribute__((__noreturn__))
#elif defined __CC_ARM
#define NS_NORETURN __declspec(noreturn)
#elif defined __IAR_SYSTEMS_ICC__ #elif defined __IAR_SYSTEMS_ICC__
#define NS_NORETURN __noreturn #define NS_NORETURN __noreturn
#else #else
@ -117,7 +115,7 @@ typedef int_fast32_t int_fast24_t;
/* C11's "alignas" macro, emulated for integer expressions if necessary */ /* C11's "alignas" macro, emulated for integer expressions if necessary */
#ifndef __alignas_is_defined #ifndef __alignas_is_defined
#if defined __CC_ARM || defined __TASKING__ #if defined __TASKING__
#define alignas(n) __align(n) #define alignas(n) __align(n)
#define __alignas_is_defined 1 #define __alignas_is_defined 1
#elif (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L) #elif (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L)
@ -149,7 +147,7 @@ typedef int_fast32_t int_fast24_t;
* static int foo(void) MAYBE_UNUSED; * static int foo(void) MAYBE_UNUSED;
* ~~~ * ~~~
*/ */
#if defined __CC_ARM || defined __GNUC__ #if defined __GNUC__
#define MAYBE_UNUSED __attribute__((unused)) #define MAYBE_UNUSED __attribute__((unused))
#else #else
#define MAYBE_UNUSED #define MAYBE_UNUSED
@ -219,7 +217,7 @@ typedef int_fast32_t int_fast24_t;
#else /* C */ #else /* C */
# if __STDC_VERSION__ >= 201112L # if __STDC_VERSION__ >= 201112L
# define NS_STATIC_ASSERT(test, str) _Static_assert(test, str); # define NS_STATIC_ASSERT(test, str) _Static_assert(test, str);
# elif defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM # elif defined __GNUC__ && NS_GCC_VERSION >= 40600
# ifdef _Static_assert # ifdef _Static_assert
/* /*
* Some versions of glibc cdefs.h (which comes in via <stdint.h> above) * Some versions of glibc cdefs.h (which comes in via <stdint.h> above)
@ -255,7 +253,7 @@ typedef int_fast32_t int_fast24_t;
/** \brief Pragma to suppress warnings about always true/false comparisons /** \brief Pragma to suppress warnings about always true/false comparisons
*/ */
#if defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM #if defined __GNUC__ && NS_GCC_VERSION >= 40600
#define NS_FUNNY_COMPARE_OK _Pragma("GCC diagnostic push") \ #define NS_FUNNY_COMPARE_OK _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") _Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
#define NS_FUNNY_COMPARE_RESTORE _Pragma("GCC diagnostic pop") #define NS_FUNNY_COMPARE_RESTORE _Pragma("GCC diagnostic pop")
@ -272,11 +270,7 @@ typedef int_fast32_t int_fast24_t;
* components should ensure this is not included by only using it in * components should ensure this is not included by only using it in
* a ifdef blocks providing dummy definitions. * a ifdef blocks providing dummy definitions.
*/ */
#ifdef __CC_ARM #if defined __IAR_SYSTEMS_ICC__
// statement is unreachable(111), controlling expression is constant(236), expression has no effect(174),
// function was declared but never referenced(177), variable was set but never used(550)
#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=111,236,174,177,550")
#elif defined __IAR_SYSTEMS_ICC__
// controlling expression is constant // controlling expression is constant
#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=Pe236") #define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=Pe236")
#else #else

View File

@ -3,37 +3,29 @@ ARM Mesh networking stack
This repository contains the ARM mesh networking stack that provides support for the following mesh protocols: This repository contains the ARM mesh networking stack that provides support for the following mesh protocols:
* 6LoWPAN with Neighbor Discovery (ND) and Mesh Link Establishment (MLE) * 6LoWPAN with Neighbor Discovery (ND) and Mesh Link Establishment (MLE)
* Thread * Wi-SUN
* Wi-SUN
All networking stacks are using IEEE 802.15.4 based radios. All networking stacks are using IEEE 802.15.4 based radios.
The full documentation is hosted in [Mbed OS documentation](https://os.mbed.com/docs/mbed-os/latest/reference/mesh-tech.html). The full documentation is hosted in [Mbed OS documentation](https://os.mbed.com/docs/mbed-os/latest/reference/mesh-tech.html).
On mbed OS, mesh networking stacks can be used through [Mbed Mesh API](https://os.mbed.com/docs/mbed-os/latest/apis/mesh-api.html) and [Network Socket API](https://os.mbed.com/docs/mbed-os/v5.11/apis/network-socket.html). On mbed OS, mesh networking stacks can be used through [Mbed Mesh API](https://os.mbed.com/docs/mbed-os/latest/apis/mesh-api.html) and [Network Socket API](https://os.mbed.com/docs/mbed-os/latest/apis/network-socket.html).
To see, how the mesh networking stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal). To see, how the mesh networking stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
##6LoWPAN with ND and MLE ## 6LoWPAN with ND and MLE
This networking stack is using standard 6LoWPAN and uses: This networking stack is using standard 6LoWPAN and uses:
* Neighbor Discovery Protocol ([RFC4861](https://tools.ietf.org/html/rfc4861)) to locate other devices in the mesh network. * Neighbor Discovery Protocol ([RFC4861](https://tools.ietf.org/html/rfc4861)) to locate other devices in the mesh network.
* Mesh-Link-Establishment ([draft-kelsey-intarea-mesh-link-establishment-06](https://tools.ietf.org/html/draft-kelsey-intarea-mesh-link-establishment-06)) is used for establishing and configuring secure radio links. * Mesh-Link-Establishment ([draft-kelsey-intarea-mesh-link-establishment-06](https://tools.ietf.org/html/draft-kelsey-intarea-mesh-link-establishment-06)) is used for establishing and configuring secure radio links.
##Thread
Thread is standardized by [Thread group](https://www.threadgroup.org/).
![](docs/img/thread_certified.png) ## Wi-SUN
mbed OS is now a Thread Certified Component. Using IPv6 with 6LoWPAN as the foundation, Thread technology provides a low-power, self-healing mesh network designed for the home.
##Wi-SUN
Wi-SUN (Smart Utility Networks) specification is standardized by [Wi-SUN Alliance](https://www.wi-sun.org/). Wi-SUN (Smart Utility Networks) specification is standardized by [Wi-SUN Alliance](https://www.wi-sun.org/).
Mbed OS release 5.12 contains the initial Mbed Wi-SUN FAN implementation. Functionality of the Mbed Wi-SUN network stack will be updated when the Wi-SUN protocol is specified further.
## License ## License

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -9,12 +9,6 @@
}, },
"macros": ["NS_USE_EXTERNAL_MBED_TLS"], "macros": ["NS_USE_EXTERNAL_MBED_TLS"],
"target_overrides": { "target_overrides": {
"KW24D": {
"nanostack.configuration": "lowpan_router"
},
"NCS36510": {
"nanostack.configuration": "lowpan_router"
},
"TB_SENSE_12": { "TB_SENSE_12": {
"nanostack.configuration": "lowpan_router" "nanostack.configuration": "lowpan_router"
}, },

View File

@ -88,6 +88,16 @@ typedef struct fhss_configuration {
*/ */
typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uint8_t eui64[8], uint16_t bsi, uint16_t number_of_channels); typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uint8_t eui64[8], uint16_t bsi, uint16_t number_of_channels);
/**
* \brief Struct fhss_config_parameters defines FHSS configuration parameters.
*
*/
typedef struct fhss_config_parameters {
/** Number of channel retries defines how many consecutive channels are used when retransmitting a frame after initial transmission channel. */
uint8_t number_of_channel_retries;
} fhss_config_parameters_t;
/** /**
* \brief Struct fhss_ws_configuration defines configuration of WS FHSS. * \brief Struct fhss_ws_configuration defines configuration of WS FHSS.
*/ */
@ -125,6 +135,9 @@ typedef struct fhss_ws_configuration {
/** Vendor defined channel function. */ /** Vendor defined channel function. */
fhss_vendor_defined_cf *vendor_defined_cf; fhss_vendor_defined_cf *vendor_defined_cf;
/** Configuration parameters. */
fhss_config_parameters_t config_parameters;
} fhss_ws_configuration_t; } fhss_ws_configuration_t;
/** /**

View File

@ -39,6 +39,17 @@ extern "C" {
*/ */
int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packet_length); int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packet_length);
/**
* \brief Set number of channel retries
*
* \param fhss_api FHSS instance.
* \param number_of_channel_retries Number of channel retries
*
* \return 0 Success
* \return -1 Failure
*/
int8_t fhss_set_number_of_channel_retries(const fhss_api_t *fhss_api, uint8_t number_of_channel_retries);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -264,6 +264,8 @@ typedef enum {
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/ macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
macDefaultKeySource = 0x7c, /*<Default key source*/ macDefaultKeySource = 0x7c, /*<Default key source*/
//NON standard extension //NON standard extension
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */
mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/ mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/
macDeviceDescriptionPanIDUpdate = 0xf7, /*<Thread pending link update case this will update device descrioton list pan-id to new one*/ macDeviceDescriptionPanIDUpdate = 0xf7, /*<Thread pending link update case this will update device descrioton list pan-id to new one*/
macTXPower = 0xf8, /*<TX output power*/ macTXPower = 0xf8, /*<TX output power*/

View File

@ -50,6 +50,109 @@ int ns_file_system_set_root_path(const char *root_path);
*/ */
char *ns_file_system_get_root_path(void); char *ns_file_system_get_root_path(void);
/**
* \brief NS file handle
*
*/
typedef void *NS_FILE;
/**
* File open callback
*
* Depending on underlying file system file open for read for non-existing
* files can return success. In that case file read will fail.
*
* \param filename filename
* \param mode can be either "r" or "w"
*
* \return file handle
* \return NULL on error
*
*/
typedef NS_FILE(*ns_file_open)(const char *filename, const char *mode);
/**
* File close callback
*
* \param handle file handle
*
* \return 0 on success
* \return < 0 in case of errors
*
*/
typedef int (*ns_file_close)(NS_FILE *handle);
/**
* File remove callback
*
* \param filename filename
*
* \return 0 on success
* \return < 0 in case of errors
*
*/
typedef int (*ns_file_remove)(const char *filename);
/**
* File write callback
*
* Write is not stream write. The whole file is written from start to end
* and if function is called again, previous file content is replaced with
* new content.
*
* \param handle file handle
* \param buffer buffer
* \param buffer buffer size
*
* \return bytes written
*
*/
typedef size_t (*ns_file_write)(NS_FILE *handle, const void *buffer, size_t size);
/**
* File read callback
*
* Read is not stream read. The whole file is read from start to end
* and if function is called again, read is started from start again.
*
* \param handle file handle
* \param buffer buffer
* \param size buffer size
*
* \return bytes written
*
*/
typedef size_t (*ns_file_read)(NS_FILE *handle, void *buffer, size_t size);
/**
* File size callback
*
* Reads file size.
*
* \param handle file handle
* \param size file size
*
* \return 0 on success
* \return < 0 in case of reading file size is not supported
*
*/
typedef int (*ns_file_size)(NS_FILE *handle, size_t *size);
/**
* File callbacks set
*
* Sets file handling callbacks to nanostack.
*
* \param open file open callback
* \param close file close callback
* \param remove file remove callback
* \param write file write callback
* \param read file read callback
* \param size file size callback
*
*/
void ns_file_system_callbacks_set(ns_file_open open, ns_file_close close, ns_file_remove remove, ns_file_write write, ns_file_read read, ns_file_size size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020, 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.
*/
/**
* \file ns_time_api.h
* \brief Nanostack time API
*
* This is Nanostack time API.
*
*/
#ifndef NS_TIME_API_H_
#define NS_TIME_API_H_
#include "ns_types.h"
/**
* System time callback.
*
* Callback shall return the system time in seconds after 1970.
*
* \param seconds system time in seconds
*
*/
typedef uint64_t ns_time_api_system_time_callback(void);
/**
* System time callback set.
*
* Sets callback for the system time.
*
* \param callback system time callback
*
*/
void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callback);
#endif /* NS_TIME_API_H_ */

View File

@ -80,6 +80,7 @@ typedef enum {
PHY_EXTENSION_FILTERING_SUPPORT, /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */ PHY_EXTENSION_FILTERING_SUPPORT, /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */
PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */ PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */
PHY_EXTENSION_SET_CCA_THRESHOLD, /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */ PHY_EXTENSION_SET_CCA_THRESHOLD, /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */
PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, /**< Set CCA threshold which is given as dBm. This value is set in PHY_LINK_CCA_PREPARE callback and PHY driver should update the CCA threshold configuration */
PHY_EXTENSION_SET_802_15_4_MODE /**< Set IEEE 802.15.4 mode as defined by phy_802_15_4_mode_t*/ PHY_EXTENSION_SET_802_15_4_MODE /**< Set IEEE 802.15.4 mode as defined by phy_802_15_4_mode_t*/
} phy_extension_type_e; } phy_extension_type_e;

View File

@ -30,6 +30,36 @@
#include "ns_types.h" #include "ns_types.h"
/**
* \brief Struct ws_statistics Border router dynamic information.
*/
typedef struct bbr_information {
/** Timestamp of the the device. Can be used as version number*/
uint64_t timestamp;
/** Border router dodag id */
uint8_t dodag_id[16];
/** Address prefix given to devices in network set to 0 if not available*/
uint8_t prefix[8];
/** Address IID of the border router set to 0 if not available*/
uint8_t IID[8];
/** Amount of devices in the network. */
uint16_t devices_in_network;
/** Border router instance identifier defined in RPL */
uint8_t instance_id;
/** RPL version number */
uint8_t version;
} bbr_information_t;
/**
* \brief Struct route_info is parent child relation structure.
*/
typedef struct bbr_route_info {
/** IID of target device public IPv6 address can be formed by combining prefix + IID*/
uint8_t target[8];
/** IID of parent*/
uint8_t parent[8];
} bbr_route_info_t;
/** /**
* Start backbone border router service. * Start backbone border router service.
* *
@ -83,6 +113,49 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options);
*/ */
void ws_bbr_stop(int8_t interface_id); void ws_bbr_stop(int8_t interface_id);
/**
* Get border router information
*
* \param interface_id interface ID of the Wi-SUN network
* \param info_ptr Structure given to stack where information is stored
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int ws_bbr_info_get(int8_t interface_id, bbr_information_t *info_ptr);
/**
* Routing table get
*
* Table is Parent child relation using the Global address IID of the devices
* To get the full IPv6 address of the device.
* IPv6 = Global Prefix + IID.
*
* Routing table is in the format: 18 bytes per entry
* | Node IID 8 bytes | parent IID 8 bytes |
* | 1122112211221122 | 1111111111111111 |
* | 1133113311331133 | 1111111111111111 |
* | 1144114411441144 | 1111111111111111 |
* | 1155115511551155 | 1122112211221122 |
* | 1166116611661166 | 1122112211221122 |
* | 1177117711771177 | 1155115511551155 |
* | 1188118811881188 | 1177117711771177 |
*
* Order is not assured only parent child link is given in random order
*
* Return value is device amount in network divided by 16 bytes per route entry
*
* \param interface_id interface ID of the Wi-SUN network
* \param table_ptr Application allocated memory block where routing table is written.
* \param table_len Length of the table allocated by application given as amount of entries.
*
* \return 0 - x on success indicates amount of bytes written to the table_ptr
* \return <0 in case of errors
*
*/
int ws_bbr_routing_table_get(int8_t interface_id, bbr_route_info_t *table_ptr, uint16_t table_len);
/** /**
* Remove node's keys from border router * Remove node's keys from border router
* *
@ -243,4 +316,40 @@ int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id);
*/ */
int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id); int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id);
/**
* ws_bbr_key_storage_memory_set sets memory used for key storages
*
* This functions can be used to set memory used by EAPOL key storage. When memory
* areas are set, module does not allocate memory internally from heap.
*
* \param interface_id Network interface ID.
* \param key_storages_number number of memory areas.
* \param key_storage_size array of memory area sizes.
* \param key_storages array of memory area start pointers.
*
* \return < 0 failure
* \return >= 0 success
*
*/
int ws_bbr_key_storage_memory_set(int8_t interface_id, uint8_t key_storages_number, const uint16_t *key_storage_size, void **key_storages);
/**
* ws_bbr_key_storage_settings_set sets key storage settings
*
* This functions can be used to set the settings of EAPOL key storage.
* Allocation max number and allocation size sets the settings that are used when key storage
* memory is allocated dynamically from heap. These settings must be set before (first) interface
* up and shall not be set if key storage memory is set by ws_pae_key_storage_memory_set() call.
*
* \param interface_id Network interface ID.
* \param alloc_max_number maximum number of allocation made to dynamic memory.
* \param alloc_size size of each allocation.
* \param storing_interval interval in which the check to store to NVM is made.
*
* \return < 0 failure
* \return >= 0 success
*
*/
int ws_bbr_key_storage_settings_set(int8_t interface_id, uint8_t alloc_max_number, uint16_t alloc_size, uint16_t storing_interval);
#endif /* WS_BBR_API_H_ */ #endif /* WS_BBR_API_H_ */

View File

@ -75,10 +75,16 @@ extern "C" {
#define CHANNEL_SPACING_100 0x03 // 100 khz #define CHANNEL_SPACING_100 0x03 // 100 khz
#define CHANNEL_SPACING_250 0x04 // 250 khz #define CHANNEL_SPACING_250 0x04 // 250 khz
#define NETWORK_SIZE_CERTIFICATE 0x00 /*
#define NETWORK_SIZE_SMALL 0x01 * Network Size definitions are device amount in hundreds of devices.
#define NETWORK_SIZE_MEDIUM 0x08 * These definitions are meant to give some estimates of sizes. Any value can be given as parameter
#define NETWORK_SIZE_LARGE 0x10 */
#define NETWORK_SIZE_CERTIFICATE 0x00 // Network configuration used in Wi-SUN certification
#define NETWORK_SIZE_SMALL 0x01 // Small networks
#define NETWORK_SIZE_MEDIUM 0x08 // 100 - 800 device networks are medium sized
#define NETWORK_SIZE_LARGE 0x0F // 800 - 1500 device networks are large
#define NETWORK_SIZE_XLARGE 0x19 // 2500+ devices
#define NETWORK_SIZE_AUTOMATIC 0xFF #define NETWORK_SIZE_AUTOMATIC 0xFF
/** Temporary API change flag. this will be removed when new version of API is implemented on applications /** Temporary API change flag. this will be removed when new version of API is implemented on applications
@ -229,9 +235,9 @@ int ws_management_regulatory_domain_validate(
* *
* timing parameters follows the specification example from Wi-SUN specification * timing parameters follows the specification example from Wi-SUN specification
* *
* Default value: medium * Default value: medium 100 - 800 device
* small network size: hundreds of devices * small network size: less than 100 devices
* Large network size: thousands of devices * Large network size: 800 - 1500 devices
* automatic: when discovering the network network size is learned * automatic: when discovering the network network size is learned
* from advertisements and timings adjusted accordingly * from advertisements and timings adjusted accordingly
* *

View File

@ -83,6 +83,9 @@
#define TRACE_GROUP_LOWPAN "6lo" #define TRACE_GROUP_LOWPAN "6lo"
#define TRACE_GROUP "6lo" #define TRACE_GROUP "6lo"
/* Data rate for application used in Stagger calculation */
#define STAGGER_DATARATE_FOR_APPL(n) ((n)*25/100)
#ifdef HAVE_RPL #ifdef HAVE_RPL
rpl_domain_t *protocol_6lowpan_rpl_domain; rpl_domain_t *protocol_6lowpan_rpl_domain;
/* Having to sidestep old rpl_dodag_t type for the moment */ /* Having to sidestep old rpl_dodag_t type for the moment */
@ -800,7 +803,7 @@ bool protocol_6lowpan_latency_estimate_get(int8_t interface_id, uint32_t *latenc
latency_estimate = 100; latency_estimate = 100;
} else if (thread_info(cur_interface)) { } else if (thread_info(cur_interface)) {
// thread network // thread network
latency_estimate = 1000; latency_estimate = 2000;
} else if (ws_info(cur_interface)) { } else if (ws_info(cur_interface)) {
latency_estimate = ws_common_latency_estimate_get(cur_interface); latency_estimate = ws_common_latency_estimate_get(cur_interface);
} else { } else {
@ -820,14 +823,13 @@ bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_am
{ {
size_t network_size; size_t network_size;
uint32_t datarate; uint32_t datarate;
uint32_t stagger_value;
protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id); protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur_interface) { if (!cur_interface) {
return false; return false;
} }
*stagger_min = 1;
if (cur_interface->eth_mac_api) { if (cur_interface->eth_mac_api) {
// either PPP or Ethernet interface. // either PPP or Ethernet interface.
network_size = 1; network_size = 1;
@ -849,16 +851,25 @@ bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_am
// If no data amount given, use 1kB // If no data amount given, use 1kB
data_amount = 1; data_amount = 1;
} }
/**Example:
* Maximum stagger value to send 1kB on 50 devices network using datarate 50000 kb/: /*
* (1 * 1024 * 8 * 50) / (50000/4)) = ~ 32s * Do not occupy whole bandwidth, leave space for network formation etc...
*
* devices: 50, datarate: 250kbps => stagger ~ 6s
* devices: 1000, datarate: 50kbps => stagger ~ 655s
*/ */
/* Do not occupy whole bandwidth, halve the theoretical datarate and reserve room for other channel usage */ datarate = STAGGER_DATARATE_FOR_APPL(datarate);
datarate = datarate / 4; stagger_value = 1 + ((data_amount * 1024 * 8 * network_size) / datarate);
*stagger_max = (uint16_t) * stagger_min + ((data_amount * 1024 * 8 * network_size) / datarate); /**
* Example:
* Maximum stagger value to send 1kB to 100 device network using data rate of 50kbs:
* 1 + (1 * 1024 * 8 * 100) / (50000*0.25) = 66s
*/
*stagger_min = stagger_value / 5; // Minimum stagger value is 1/5 of the max
if (stagger_value > 0xFFFF) {
*stagger_max = 0xFFFF;
} else {
*stagger_max = (uint16_t)stagger_value;
}
// Randomize stagger value // Randomize stagger value
*stagger_rand = randLIB_get_random_in_range(*stagger_min, *stagger_max); *stagger_rand = randLIB_get_random_in_range(*stagger_min, *stagger_max);

View File

@ -588,7 +588,7 @@ static void mle_neigh_entry_update_by_mle_tlv_list(int8_t interface_id, mac_neig
uint8_t link_idr; uint8_t link_idr;
uint8_t iop_flags; uint8_t iop_flags;
if (mle_link_quality_tlv_parse(mac64, short_address, mle_tlv_info.dataPtr, mle_tlv_info.tlvLen, &iop_flags, &link_idr)) { if (mle_link_quality_tlv_parse(mac64, short_address, mle_tlv_info.dataPtr, mle_tlv_info.tlvLen, &iop_flags, &link_idr)) {
etx_remote_incoming_idr_update(interface_id, link_idr, entry_temp->index); etx_remote_incoming_idr_update(interface_id, link_idr, entry_temp->index, entry_temp->mac64);
if ((iop_flags & MLE_NEIGHBOR_PRIORITY_LINK) == MLE_NEIGHBOR_PRIORITY_LINK) { if ((iop_flags & MLE_NEIGHBOR_PRIORITY_LINK) == MLE_NEIGHBOR_PRIORITY_LINK) {
entry_temp->link_role = CHILD_NEIGHBOUR; entry_temp->link_role = CHILD_NEIGHBOUR;
@ -965,9 +965,9 @@ int protocol_6lowpan_router_synch_to_new_router(protocol_interface_info_entry_t
static uint8_t mle_calculate_idr(int8_t interface_id, mle_message_t *mle_msg, mac_neighbor_table_entry_t *entry_temp) static uint8_t mle_calculate_idr(int8_t interface_id, mle_message_t *mle_msg, mac_neighbor_table_entry_t *entry_temp)
{ {
if (!entry_temp) { if (!entry_temp) {
return etx_lqi_dbm_update(-2, mle_msg->lqi, mle_msg->dbm, 0) >> 3; return etx_lqi_dbm_update(-2, mle_msg->lqi, mle_msg->dbm, 0, NULL) >> 3;
} }
return etx_lqi_dbm_update(interface_id, mle_msg->lqi, mle_msg->dbm, entry_temp->index) >> 3; return etx_lqi_dbm_update(interface_id, mle_msg->lqi, mle_msg->dbm, entry_temp->index, entry_temp->mac64) >> 3;
} }
@ -1609,7 +1609,7 @@ static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entr
} }
mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index, entry_ptr->mac64); mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index, entry_ptr->mac64);
//Removes ETX neighbor //Removes ETX neighbor
etx_neighbor_remove(cur_interface->id, entry_ptr->index); etx_neighbor_remove(cur_interface->id, entry_ptr->index, entry_ptr->mac64);
//Remove MLE frame counter info //Remove MLE frame counter info
mle_service_frame_counter_entry_delete(cur_interface->id, entry_ptr->index); mle_service_frame_counter_entry_delete(cur_interface->id, entry_ptr->index);

View File

@ -900,11 +900,13 @@ void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index,
set_req.attr_index = attribute_index; set_req.attr_index = attribute_index;
set_req.value_pointer = (void *)&device_desc; set_req.value_pointer = (void *)&device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t); set_req.value_size = sizeof(mlme_device_descriptor_t);
if (mac64) {
tr_debug("Unregister Device %u, mac64: %s", attribute_index, trace_array(mac64, 8)); tr_debug("Unregister Device %u, mac64: %s", attribute_index, trace_array(mac64, 8));
}
mac_api->mlme_req(mac_api, MLME_SET, &set_req); mac_api->mlme_req(mac_api, MLME_SET, &set_req);
} }
void mac_helper_device_description_write(protocol_interface_info_entry_t *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt) void mac_helper_device_description_write(protocol_interface_info_entry_t *cur, mlme_device_descriptor_t *device_desc, const uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt)
{ {
memcpy(device_desc->ExtAddress, mac64, 8); memcpy(device_desc->ExtAddress, mac64, 8);
device_desc->ShortAddress = mac16; device_desc->ShortAddress = mac16;
@ -914,14 +916,19 @@ void mac_helper_device_description_write(protocol_interface_info_entry_t *cur, m
} }
void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur, uint8_t attribute_index, uint8_t keyID, bool force_set) void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur, uint8_t attribute_index, uint8_t keyID, bool force_set)
{ {
if (!cur->mac_api) { if (!force_set && cur->mac_parameters->SecurityEnabled && cur->mac_parameters->mac_default_key_index != keyID) {
tr_debug("Do not set counter by index %u != %u", cur->mac_parameters->mac_default_key_index, keyID);
return; return;
} }
if (!force_set && cur->mac_parameters->SecurityEnabled && cur->mac_parameters->mac_default_key_index != keyID) { tr_debug("Register Device %u, mac16 %x mac64: %s, %"PRIu32, attribute_index, device_desc->ShortAddress, trace_array(device_desc->ExtAddress, 8), device_desc->FrameCounter);
tr_debug("Do not set counter by index %u != %u", cur->mac_parameters->mac_default_key_index, keyID); mac_helper_devicetable_direct_set(cur->mac_api, device_desc, attribute_index);
}
void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_device_descriptor_t *device_desc, uint8_t attribute_index)
{
if (!mac_api) {
return; return;
} }
@ -930,7 +937,20 @@ void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_desc, pro
set_req.attr_index = attribute_index; set_req.attr_index = attribute_index;
set_req.value_pointer = (void *)device_desc; set_req.value_pointer = (void *)device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t); set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("Register Device %u, mac16 %x mac64: %s, %"PRIu32, attribute_index, device_desc->ShortAddress, trace_array(device_desc->ExtAddress, 8), device_desc->FrameCounter); mac_api->mlme_req(mac_api, MLME_SET, &set_req);
}
void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur)
{
if (!cur->mac_api) {
return;
}
mlme_set_t set_req;
set_req.attr = macDevicePendingAckTrig;
set_req.attr_index = 0;
set_req.value_pointer = (void *)device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req); cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
} }

View File

@ -121,9 +121,14 @@ int8_t mac_helper_key_link_frame_counter_set(int8_t interface_id, uint32_t seq_p
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index, uint8_t *mac64); void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index, uint8_t *mac64);
void mac_helper_device_description_write(struct protocol_interface_info_entry *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt); void mac_helper_device_description_write(struct protocol_interface_info_entry *cur, mlme_device_descriptor_t *device_desc, const uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt);
void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, struct protocol_interface_info_entry *cur, uint8_t attribute_index, uint8_t keyID, bool force_set); void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, struct protocol_interface_info_entry *cur, uint8_t attribute_index, uint8_t keyID, bool force_set);
void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_device_descriptor_t *device_desc, uint8_t attribute_index);
void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, struct protocol_interface_info_entry *cur);
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set); int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id); int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id);

View File

@ -141,7 +141,7 @@ static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *
thread_reset_neighbour_info(cur, entry_ptr); thread_reset_neighbour_info(cur, entry_ptr);
//Removes ETX neighbor //Removes ETX neighbor
etx_neighbor_remove(cur->id, entry_ptr->index); etx_neighbor_remove(cur->id, entry_ptr->index, entry_ptr->mac64);
//Remove MLE frame counter info //Remove MLE frame counter info
mle_service_frame_counter_entry_delete(cur->id, entry_ptr->index); mle_service_frame_counter_entry_delete(cur->id, entry_ptr->index);
} }

View File

@ -34,7 +34,7 @@
#include "nsconfig.h" #include "nsconfig.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include "Service_Libs/utils/ns_file.h"
#include "Core/include/ns_address_internal.h" #include "Core/include/ns_address_internal.h"
#include "ns_file_system.h" #include "ns_file_system.h"
#include "thread_config.h" #include "thread_config.h"
@ -44,16 +44,13 @@
#define TRACE_GROUP "tnvm" #define TRACE_GROUP "tnvm"
const char *FAST_DATA_FILE = "f_d"; const char *FAST_DATA_FILE = "f_d";
#define FAST_DATA_VERSION 1
#define LINK_INFO_WRITE_DELAY 2 #define LINK_INFO_WRITE_DELAY 2
#define LINK_INFO_SHORT_ADDR_NOT_SET 0xffff #define LINK_INFO_SHORT_ADDR_NOT_SET 0xffff
#define LINK_INFO_WRITE_DONE 0xffff #define LINK_INFO_WRITE_DONE 0xffff
const char *LINK_INFO_FILE = "l_i"; const char *LINK_INFO_FILE = "l_i";
#define LINK_INFO_DATA_VERSION 1
const char *LEADER_INFO_FILE = "ld_i"; const char *LEADER_INFO_FILE = "ld_i";
#define LEADER_INFO_DATA_VERSION 1
typedef struct { typedef struct {
uint8_t mac[8]; uint8_t mac[8];
@ -67,18 +64,15 @@ typedef struct {
} thread_nvm_store_link_info_t; } thread_nvm_store_link_info_t;
const char *THREAD_NVM_ACTIVE_CONF_FILE = "a_c"; const char *THREAD_NVM_ACTIVE_CONF_FILE = "a_c";
#define ACTIVE_CONF_DATA_VERSION 1
const char *DEVICE_CONF_FILE = "s_d"; const char *DEVICE_CONF_FILE = "s_d";
#define DEVICE_CONF_VERSION 1
const char *THREAD_NVM_PENDING_CONF_FILE = "p_c"; const char *THREAD_NVM_PENDING_CONF_FILE = "p_c";
#define PENDING_CONF_DATA_VERSION 1
static const char *thread_nvm_store_get_root_path(void); static const char *thread_nvm_store_get_root_path(void);
static int root_path_valid(void); static int root_path_valid(void);
static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size, uint32_t *version); static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size);
static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size, uint32_t version); static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size);
static void thread_nvm_store_create_path(char *fast_data_path, const char *file_name); static void thread_nvm_store_create_path(char *fast_data_path, const char *file_name);
static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t *fast_data_to_set); static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t *fast_data_to_set);
static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t seq_counter); static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t seq_counter);
@ -131,13 +125,12 @@ int thread_nvm_store_mleid_rloc_map_write(thread_nvm_mleid_rloc_map *mleid_rloc_
} }
thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE);
tr_debug("writing to store rloc mapping info"); tr_debug("writing to store rloc mapping info");
return thread_nvm_store_write(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), LEADER_INFO_DATA_VERSION); return thread_nvm_store_write(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map));
} }
int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map) int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map)
{ {
char lc_data_path[LEADER_INFO_STRING_LEN]; char lc_data_path[LEADER_INFO_STRING_LEN];
uint32_t version;
if (NULL == mleid_rloc_map) { if (NULL == mleid_rloc_map) {
return THREAD_NVM_FILE_PARAMETER_INVALID; return THREAD_NVM_FILE_PARAMETER_INVALID;
} }
@ -146,7 +139,7 @@ int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_m
} }
thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE);
int ret = thread_nvm_store_read(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), &version); int ret = thread_nvm_store_read(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map));
if (THREAD_NVM_FILE_SUCCESS != ret) { if (THREAD_NVM_FILE_SUCCESS != ret) {
tr_info("Leader data map read failed"); tr_info("Leader data map read failed");
@ -154,12 +147,6 @@ int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_m
return ret; return ret;
} }
if (LEADER_INFO_DATA_VERSION != version) {
tr_info("Leader data map version mismatch %"PRIu32, version);
thread_nvm_store_mleid_rloc_map_remove();
return THREAD_NVM_FILE_VERSION_WRONG;
}
return ret; return ret;
} }
@ -191,7 +178,7 @@ int thread_nvm_store_device_configuration_write(uint8_t *mac_ptr, uint8_t *mleid
memcpy(d_c.mle_id, mleid_ptr, sizeof(d_c.mle_id)); memcpy(d_c.mle_id, mleid_ptr, sizeof(d_c.mle_id));
char device_conf_path[DEVICE_CONF_STRING_LEN]; char device_conf_path[DEVICE_CONF_STRING_LEN];
thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE);
return thread_nvm_store_write(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), DEVICE_CONF_VERSION); return thread_nvm_store_write(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t));
} }
int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_ptr) int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_ptr)
@ -202,19 +189,13 @@ int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_
} }
char device_conf_path[DEVICE_CONF_STRING_LEN]; char device_conf_path[DEVICE_CONF_STRING_LEN];
thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE);
uint32_t version;
thread_nvm_device_conf_t d_c; thread_nvm_device_conf_t d_c;
ret = thread_nvm_store_read(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), &version); ret = thread_nvm_store_read(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t));
if (THREAD_NVM_FILE_SUCCESS == ret) { if (THREAD_NVM_FILE_SUCCESS == ret) {
if (THREAD_NVM_FILE_SUCCESS == ret && DEVICE_CONF_VERSION != version) {
tr_info("fast data version mismatch %"PRIu32, version);
ret = THREAD_NVM_FILE_VERSION_WRONG;
} else {
memcpy(mac_ptr, d_c.mac, sizeof(d_c.mac)); memcpy(mac_ptr, d_c.mac, sizeof(d_c.mac));
memcpy(mleid_ptr, d_c.mle_id, sizeof(d_c.mle_id)); memcpy(mleid_ptr, d_c.mle_id, sizeof(d_c.mle_id));
} }
}
return ret; return ret;
} }
@ -228,13 +209,12 @@ int thread_nvm_store_pending_configuration_write(void *data, uint16_t size)
return THREAD_NVM_FILE_ROOT_PATH_INVALID; return THREAD_NVM_FILE_ROOT_PATH_INVALID;
} }
thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE); thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE);
return thread_nvm_store_write(pc_data_path, data, size, PENDING_CONF_DATA_VERSION); return thread_nvm_store_write(pc_data_path, data, size);
} }
int thread_nvm_store_pending_configuration_read(void *data, uint16_t size) int thread_nvm_store_pending_configuration_read(void *data, uint16_t size)
{ {
char pc_data_path[PENDING_CONF_STRING_LEN]; char pc_data_path[PENDING_CONF_STRING_LEN];
uint32_t version;
if (NULL == data) { if (NULL == data) {
return THREAD_NVM_FILE_PARAMETER_INVALID; return THREAD_NVM_FILE_PARAMETER_INVALID;
} }
@ -243,11 +223,7 @@ int thread_nvm_store_pending_configuration_read(void *data, uint16_t size)
} }
thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE); thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE);
int ret = thread_nvm_store_read(pc_data_path, data, size, &version); int ret = thread_nvm_store_read(pc_data_path, data, size);
if (THREAD_NVM_FILE_SUCCESS == ret && PENDING_CONF_DATA_VERSION != version) {
tr_info("Pending configuration version mismatch %"PRIu32, version);
return THREAD_NVM_FILE_VERSION_WRONG;
}
return ret; return ret;
} }
@ -262,13 +238,12 @@ int thread_nvm_store_active_configuration_write(void *data, uint16_t data_size)
} }
thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE);
return thread_nvm_store_write(ac_data_path, data, data_size, ACTIVE_CONF_DATA_VERSION); return thread_nvm_store_write(ac_data_path, data, data_size);
} }
int thread_nvm_store_active_configuration_read(void *data, uint16_t data_size) int thread_nvm_store_active_configuration_read(void *data, uint16_t data_size)
{ {
char ac_data_path[ACTIVE_CONF_STRING_LEN]; char ac_data_path[ACTIVE_CONF_STRING_LEN];
uint32_t version;
if (NULL == data) { if (NULL == data) {
return THREAD_NVM_FILE_PARAMETER_INVALID; return THREAD_NVM_FILE_PARAMETER_INVALID;
} }
@ -277,11 +252,7 @@ int thread_nvm_store_active_configuration_read(void *data, uint16_t data_size)
} }
thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE);
int ret = thread_nvm_store_read(ac_data_path, data, data_size, &version); int ret = thread_nvm_store_read(ac_data_path, data, data_size);
if (THREAD_NVM_FILE_SUCCESS == ret && ACTIVE_CONF_DATA_VERSION != version) {
tr_info("active configuration version mismatch %"PRIu32, version);
return THREAD_NVM_FILE_VERSION_WRONG;
}
return ret; return ret;
} }
@ -399,12 +370,7 @@ int thread_nvm_store_fast_data_read(thread_nvm_fast_data_t *fast_data)
if (root_path_valid()) { if (root_path_valid()) {
char fast_data_path[FAST_DATA_STRING_LEN]; char fast_data_path[FAST_DATA_STRING_LEN];
thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE);
uint32_t version; ret = thread_nvm_store_read(fast_data_path, fast_data, sizeof(thread_nvm_fast_data_t));
ret = thread_nvm_store_read(fast_data_path, fast_data, sizeof(thread_nvm_fast_data_t), &version);
if (THREAD_NVM_FILE_SUCCESS == ret && FAST_DATA_VERSION != version) {
tr_info("fast data version mismatch %"PRIu32, version);
return THREAD_NVM_FILE_VERSION_WRONG;
}
} else { } else {
fast_data->mac_frame_counter = cached_fast_data.mac_frame_counter; fast_data->mac_frame_counter = cached_fast_data.mac_frame_counter;
fast_data->mle_frame_counter = cached_fast_data.mle_frame_counter; fast_data->mle_frame_counter = cached_fast_data.mle_frame_counter;
@ -417,26 +383,19 @@ static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t *fast_data_to_
{ {
char fast_data_path[FAST_DATA_STRING_LEN]; char fast_data_path[FAST_DATA_STRING_LEN];
thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE);
return thread_nvm_store_write(fast_data_path, fast_data_to_set, sizeof(thread_nvm_fast_data_t), FAST_DATA_VERSION); return thread_nvm_store_write(fast_data_path, fast_data_to_set, sizeof(thread_nvm_fast_data_t));
} }
static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size, uint32_t version) static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size)
{ {
FILE *fp = fopen(file_name, "w"); NS_FILE *fp = ns_fopen(file_name, "w");
if (fp == NULL) { if (fp == NULL) {
tr_error("NVM open error: %s", file_name); tr_error("NVM open error: %s", file_name);
return THREAD_NVM_FILE_CANNOT_OPEN; return THREAD_NVM_FILE_CANNOT_OPEN;
} }
size_t n_bytes = fwrite(&version, 1, sizeof(uint32_t), fp); size_t n_bytes = ns_fwrite(fp, data, data_size);
if (n_bytes != sizeof(uint32_t)) { ns_fclose(fp);
tr_warning("NVM version write error");
fclose(fp);
return THREAD_NVM_FILE_WRITE_ERROR;
}
n_bytes = fwrite(data, 1, data_size, fp);
fclose(fp);
if (n_bytes != data_size) { if (n_bytes != data_size) {
tr_error("NVM write error %s", file_name); tr_error("NVM write error %s", file_name);
return THREAD_NVM_FILE_WRITE_ERROR; return THREAD_NVM_FILE_WRITE_ERROR;
@ -446,23 +405,16 @@ static int thread_nvm_store_write(const char *file_name, void *data, uint32_t da
} }
// returns 0 when ok // returns 0 when ok
static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size, uint32_t *version) static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size)
{ {
FILE *fp = fopen(file_name, "r"); NS_FILE *fp = ns_fopen(file_name, "r");
if (fp == NULL) { if (fp == NULL) {
tr_warning("File not found: %s", file_name); tr_warning("File not found: %s", file_name);
return THREAD_NVM_FILE_CANNOT_OPEN; return THREAD_NVM_FILE_CANNOT_OPEN;
} }
size_t n_bytes = fread(version, 1, sizeof(uint32_t), fp); size_t n_bytes = ns_fread(fp, data, data_size);
if (n_bytes != sizeof(uint32_t)) { ns_fclose(fp);
tr_warning("NVM version read error %s", file_name);
fclose(fp);
return THREAD_NVM_FILE_READ_ERROR;
}
n_bytes = fread(data, 1, data_size, fp);
fclose(fp);
if (n_bytes != data_size) { if (n_bytes != data_size) {
tr_error("NVM read error %s", file_name); tr_error("NVM read error %s", file_name);
return THREAD_NVM_FILE_READ_ERROR; return THREAD_NVM_FILE_READ_ERROR;
@ -488,8 +440,7 @@ int thread_nvm_store_link_info_read(void)
strcpy(link_info_path, thread_nvm_store_get_root_path()); strcpy(link_info_path, thread_nvm_store_get_root_path());
strcat(link_info_path, LINK_INFO_FILE); strcat(link_info_path, LINK_INFO_FILE);
uint32_t version = 0; status = thread_nvm_store_read(link_info_path, &nvm_link_info_tmp, sizeof(nvm_link_info_t));
status = thread_nvm_store_read(link_info_path, &nvm_link_info_tmp, sizeof(nvm_link_info_t), &version);
if (status != THREAD_NVM_FILE_SUCCESS) { if (status != THREAD_NVM_FILE_SUCCESS) {
if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) &&
@ -499,9 +450,6 @@ int thread_nvm_store_link_info_read(void)
return THREAD_NVM_FILE_READ_ERROR; return THREAD_NVM_FILE_READ_ERROR;
} }
return status; return status;
} else if (ACTIVE_CONF_DATA_VERSION != version) {
tr_info("link info version mismatch %"PRIu32, version);
return THREAD_NVM_FILE_VERSION_WRONG;
} }
memcpy(cached_link_info.nvm_link_info.mac, nvm_link_info_tmp.mac, 8); memcpy(cached_link_info.nvm_link_info.mac, nvm_link_info_tmp.mac, 8);
cached_link_info.nvm_link_info.short_addr = nvm_link_info_tmp.short_addr; cached_link_info.nvm_link_info.short_addr = nvm_link_info_tmp.short_addr;
@ -597,7 +545,7 @@ static void thread_nvm_store_link_info_delayed_write(uint32_t seconds)
strcpy(link_info_path, thread_nvm_store_get_root_path()); strcpy(link_info_path, thread_nvm_store_get_root_path());
strcat(link_info_path, LINK_INFO_FILE); strcat(link_info_path, LINK_INFO_FILE);
tr_info("link info write parent mac: %s parent short addr: %"PRIu16, trace_array(cached_link_info.nvm_link_info.mac, 8), cached_link_info.nvm_link_info.short_addr); tr_info("link info write parent mac: %s parent short addr: %"PRIu16, trace_array(cached_link_info.nvm_link_info.mac, 8), cached_link_info.nvm_link_info.short_addr);
thread_nvm_store_write(link_info_path, &cached_link_info.nvm_link_info, sizeof(nvm_link_info_t), LINK_INFO_DATA_VERSION); thread_nvm_store_write(link_info_path, &cached_link_info.nvm_link_info, sizeof(nvm_link_info_t));
} }
void thread_nvm_store_seconds_timer(uint32_t seconds) void thread_nvm_store_seconds_timer(uint32_t seconds)

View File

@ -155,7 +155,7 @@ static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur
// Gets table entry // Gets table entry
mac_neighbor_table_entry_t *neigh_table_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + PAN_ID_LEN, buf->dst_sa.addr_type); mac_neighbor_table_entry_t *neigh_table_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + PAN_ID_LEN, buf->dst_sa.addr_type);
if (neigh_table_ptr) { if (neigh_table_ptr) {
etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries, success, neigh_table_ptr->index); etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries, success, neigh_table_ptr->index, neigh_table_ptr->mac64);
// Updates ETX statistics // Updates ETX statistics
etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, neigh_table_ptr->index); etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, neigh_table_ptr->index);
if (etx_entry) { if (etx_entry) {

View File

@ -20,6 +20,7 @@
#include "ns_types.h" #include "ns_types.h"
#include "ns_trace.h" #include "ns_trace.h"
#include "net_interface.h" #include "net_interface.h"
#include "socket_api.h"
#include "eventOS_event.h" #include "eventOS_event.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
@ -28,6 +29,7 @@
#include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bootstrap.h" #include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/ws/ws_pae_key_storage.h"
#include "RPL/rpl_control.h" #include "RPL/rpl_control.h"
#include "RPL/rpl_data.h" #include "RPL/rpl_data.h"
#include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6.h"
@ -52,7 +54,6 @@ static uint8_t current_instance_id = RPL_INSTANCE_ID;
#define WS_ULA_LIFETIME 24*3600 #define WS_ULA_LIFETIME 24*3600
#define WS_ROUTE_LIFETIME WS_ULA_LIFETIME #define WS_ROUTE_LIFETIME WS_ULA_LIFETIME
#define WS_DHCP_ADDRESS_LIFETIME 2*3600
#define BBR_CHECK_INTERVAL 60 #define BBR_CHECK_INTERVAL 60
#define BBR_BACKUP_ULA_DELAY 300 #define BBR_BACKUP_ULA_DELAY 300
@ -68,7 +69,7 @@ static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x72, 0x83, 0x7e};
static uint8_t static_dodag_id_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d}; static uint8_t static_dodag_id_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
static uint8_t current_dodag_id[16] = {0}; static uint8_t current_dodag_id[16] = {0};
static uint8_t current_local_prefix[8] = {0}; static uint8_t current_local_prefix[8] = {0};
static uint8_t current_global_prefix[8] = {0}; static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay. static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
static uint32_t global_prefix_unavailable_timer = 0; // initial delay. static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
@ -94,7 +95,16 @@ static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur,
//stable version for RPL so slow timer update is ok //stable version for RPL so slow timer update is ok
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME; cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME;
} else { } else {
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART; if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) {
// handles also NETWORK_SIZE_CERTIFICATE
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_SMALL;
} else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM) {
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_MEDIUM;
} else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_LARGE) {
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_LARGE;
} else {
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_EXTRA_LARGE;
}
} }
} }
@ -137,6 +147,15 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8
} }
} }
void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint32_t dhcp_address_lifetime)
{
if (!cur) {
return;
}
// Change the setting if the border router is active
DHCPv6_server_service_set_address_validlifetime(cur->id, current_global_prefix, dhcp_address_lifetime);
}
static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t *dodag_id) static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t *dodag_id)
{ {
tr_info("RPL root start"); tr_info("RPL root start");
@ -223,7 +242,10 @@ static if_address_entry_t *ws_bbr_slaac_generate(protocol_interface_info_entry_t
static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix) static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix)
{ {
if (cur) {
icmpv6_slaac_prefix_update(cur, ula_prefix, 64, 0, 0); icmpv6_slaac_prefix_update(cur, ula_prefix, 64, 0, 0);
}
addr_policy_table_delete_entry(ula_prefix, 64); addr_policy_table_delete_entry(ula_prefix, 64);
} }
@ -328,7 +350,7 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
return true; return true;
} }
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id) static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id, uint32_t dhcp_address_lifetime)
{ {
uint8_t ll[16]; uint8_t ll[16];
memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8); memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8);
@ -344,7 +366,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb); DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
//Enable SLAAC mode to border router //Enable SLAAC mode to border router
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false); DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false);
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, dhcp_address_lifetime);
//SEt max value for not limiting address allocation //SEt max value for not limiting address allocation
DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE); DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE);
@ -352,6 +374,9 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
} }
static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id) static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
{ {
if (!cur) {
return;
}
uint8_t temp_address[16]; uint8_t temp_address[16];
memcpy(temp_address, global_id, 8); memcpy(temp_address, global_id, 8);
memset(temp_address + 8, 0, 8); memset(temp_address + 8, 0, 8);
@ -359,7 +384,6 @@ static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_
DHCPv6_server_service_delete(cur->id, global_id, false); DHCPv6_server_service_delete(cur->id, global_id, false);
//Delete Client //Delete Client
dhcp_client_global_address_delete(cur->id, NULL, temp_address); dhcp_client_global_address_delete(cur->id, NULL, temp_address);
} }
static void ws_bbr_routing_stop(protocol_interface_info_entry_t *cur) static void ws_bbr_routing_stop(protocol_interface_info_entry_t *cur)
@ -506,7 +530,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
return; return;
} }
} }
ws_bbr_dhcp_server_start(cur, global_prefix); ws_bbr_dhcp_server_start(cur, global_prefix, cur->ws_info->cfg->bbr.dhcp_address_lifetime);
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false); rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false);
// no check for failure should have // no check for failure should have
@ -623,6 +647,11 @@ uint16_t test_pan_size_override = 0xffff;
uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur) uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
{ {
uint16_t result = 0; uint16_t result = 0;
if (!cur || !cur->rpl_domain) {
return 0;
}
if (test_pan_size_override != 0xffff) { if (test_pan_size_override != 0xffff) {
return test_pan_size_override; return test_pan_size_override;
} }
@ -701,7 +730,6 @@ void ws_bbr_stop(int8_t interface_id)
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
ws_bbr_routing_stop(cur); ws_bbr_routing_stop(cur);
backbone_interface_id = -1; backbone_interface_id = -1;
current_instance_id++; current_instance_id++;
@ -728,6 +756,86 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options)
return -1; return -1;
#endif #endif
} }
int ws_bbr_info_get(int8_t interface_id, bbr_information_t *info_ptr)
{
#ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
rpl_dodag_info_t dodag_info;
if (!info_ptr) {
return -1;
}
if (!cur || !protocol_6lowpan_rpl_root_dodag) {
tr_warn("bbr not started");
return -1;
}
struct rpl_instance *instance = rpl_control_lookup_instance(protocol_6lowpan_rpl_domain, current_instance_id, current_dodag_id);
if (!instance) {
tr_warn("bbr instance not found");
return -2;
}
// Zero the structure
memset(info_ptr, 0, sizeof(bbr_information_t));
rpl_control_read_dodag_info(instance, &dodag_info);
memcpy(info_ptr->dodag_id, current_dodag_id, 16);
memcpy(info_ptr->prefix, current_global_prefix, 8);
// Get the Wi-SUN interface generated address that is used in the RF interface.
const uint8_t *wisun_if_addr = addr_select_with_prefix(cur, current_global_prefix, 64, SOCKET_IPV6_PREFER_SRC_PUBLIC);
if (wisun_if_addr) {
memcpy(info_ptr->IID, wisun_if_addr + 8, 8);
}
info_ptr->devices_in_network = ws_bbr_pan_size(cur);
info_ptr->instance_id = current_instance_id;
info_ptr->version = dodag_info.version_num;
info_ptr->timestamp = protocol_core_monotonic_time; // TODO switch to second timer
// consider DTSN included It can also be added for getting device information
// Consider own device API to get DTSN, DHCP lifetime values
return 0;
#else
(void) interface_id;
(void) info_ptr;
return -1;
#endif
}
int ws_bbr_routing_table_get(int8_t interface_id, bbr_route_info_t *table_ptr, uint16_t table_len)
{
#ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
int length;
if (!cur || !protocol_6lowpan_rpl_root_dodag) {
return -1;
}
struct rpl_instance *instance = rpl_control_lookup_instance(protocol_6lowpan_rpl_domain, current_instance_id, current_dodag_id);
if (!instance) {
tr_warn("bbr instance not found");
return -2;
}
memset(table_ptr, 0, table_len);
/* RPL structure must match the external structure so we dont need to make conversion.
*
*/
length = rpl_control_route_table_get(instance, current_global_prefix, (rpl_route_info_t *)table_ptr, table_len);
return length;
#else
(void) interface_id;
(void) table_ptr;
(void) table_len;
return -1;
#endif
}
int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64) int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
{ {
@ -782,8 +890,8 @@ int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uin
#ifdef HAVE_WS_BORDER_ROUTER #ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
ws_rpl_cfg_t cfg; ws_bbr_cfg_t cfg;
if (ws_cfg_rpl_get(&cfg, NULL) < 0) { if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
return -1; return -1;
} }
@ -797,7 +905,7 @@ int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uin
cfg.dio_redundancy_constant = dio_redundancy_constant; cfg.dio_redundancy_constant = dio_redundancy_constant;
} }
if (ws_cfg_rpl_set(cur, NULL, &cfg, 0) < 0) { if (ws_cfg_bbr_set(cur, NULL, &cfg, 0) < 0) {
return -2; return -2;
} }
@ -818,8 +926,8 @@ int ws_bbr_rpl_parameters_get(int8_t interface_id, uint8_t *dio_interval_min, ui
return -1; return -1;
} }
ws_rpl_cfg_t cfg; ws_bbr_cfg_t cfg;
if (ws_cfg_rpl_get(&cfg, NULL) < 0) { if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
return -2; return -2;
} }
@ -840,8 +948,8 @@ int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min
{ {
(void) interface_id; (void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER #ifdef HAVE_WS_BORDER_ROUTER
ws_rpl_cfg_t cfg; ws_bbr_cfg_t cfg;
if (ws_cfg_rpl_get(&cfg, NULL) < 0) { if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
return -2; return -2;
} }
@ -855,7 +963,7 @@ int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min
cfg.dio_redundancy_constant = dio_redundancy_constant; cfg.dio_redundancy_constant = dio_redundancy_constant;
} }
if (ws_cfg_rpl_validate(NULL, &cfg) < 0) { if (ws_cfg_bbr_validate(NULL, &cfg) < 0) {
return -3; return -3;
} }
@ -935,3 +1043,29 @@ int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id)
return -1; return -1;
#endif #endif
} }
int ws_bbr_key_storage_memory_set(int8_t interface_id, uint8_t key_storages_number, const uint16_t *key_storage_size, void **key_storages)
{
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
return ws_pae_key_storage_memory_set(key_storages_number, key_storage_size, key_storages);
#else
(void) key_storages_number;
(void) key_storage_size;
(void) key_storages;
return -1;
#endif
}
int ws_bbr_key_storage_settings_set(int8_t interface_id, uint8_t alloc_max_number, uint16_t alloc_size, uint16_t storing_interval)
{
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
return ws_pae_key_storage_settings_set(alloc_max_number, alloc_size, storing_interval);
#else
(void) alloc_max_number;
(void) alloc_size;
(void) storing_interval;
return -1;
#endif
}

View File

@ -31,6 +31,8 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur);
void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase); void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase);
void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint32_t dhcp_address_lifetime);
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur); bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
@ -40,6 +42,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
#define ws_bbr_pan_version_increase(cur) #define ws_bbr_pan_version_increase(cur)
#define ws_bbr_pan_size(cur) 0 #define ws_bbr_pan_size(cur) 0
#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase) #define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase)
#define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime)
#define ws_bbr_ready_to_start(cur) true #define ws_bbr_ready_to_start(cur) true
#endif //HAVE_WS_BORDER_ROUTER #endif //HAVE_WS_BORDER_ROUTER

View File

@ -95,14 +95,16 @@ static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index); static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot); static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot);
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot); static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot);
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64); static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64);
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id);
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur); static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor); static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor);
static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr); static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr);
static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data); static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]);
static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr, bool clear_list);
static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur);
static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create);
@ -146,14 +148,68 @@ mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interf
static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr) static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr)
{ {
mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index, entry_ptr->mac64); mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index, entry_ptr->mac64);
etx_neighbor_remove(interface->id, entry_ptr->index); etx_neighbor_remove(interface->id, entry_ptr->index, entry_ptr->mac64);
ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, entry_ptr->index); ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, entry_ptr->index);
} }
static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_info_entry *interface)
{
uint8_t mac_64[8];
memset(mac_64, 0, sizeof(mac_64));
mac_neighbor_table_entry_t *mac_entry = ws_bootstrap_mac_neighbor_add(interface, mac_64);
if (!mac_entry) {
return;
}
mac_entry->lifetime = 0xffffffff;
mac_entry->link_lifetime = 0xffffffff;
ws_neighbor_class_entry_t *ws_neigh = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, mac_entry->index);
if (!ws_neigh) {
return;
}
interface->ws_info->eapol_tx_index = mac_entry->index;
}
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(interface, &device_desc, src64, 0xffff, 0, false);
mac_helper_devicetable_ack_trig(&device_desc, interface);
}
ws_neighbor_class_entry_t *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
mlme_device_descriptor_t device_desc;
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_table_attribute_discover(mac_neighbor_info(interface), interface->ws_info->eapol_tx_index);
if (!mac_entry) {
return NULL;
}
memcpy(mac_entry->mac64, src64, 8);
mac_helper_device_description_write(interface, &device_desc, src64, 0xffff, 0, false);
mac_helper_devicetable_direct_set(interface->mac_api, &device_desc, interface->ws_info->eapol_tx_index);
return ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, mac_entry->index);
}
void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface)
{
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_table_attribute_discover(mac_neighbor_info(interface), interface->ws_info->eapol_tx_index);
if (!mac_entry) {
return;
}
memset(mac_entry->mac64, 0xff, 8);
mac_helper_devicetable_remove(interface->mac_api, interface->ws_info->eapol_tx_index, NULL);
}
static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface) static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface)
{ {
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(interface)); mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(interface));
//Allocate EAPOL TX temporary neigh entry
ws_bootstap_eapol_neigh_entry_allocate(interface);
} }
static void ws_address_reregister_trig(struct protocol_interface_info_entry *interface) static void ws_address_reregister_trig(struct protocol_interface_info_entry *interface)
@ -486,8 +542,8 @@ static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded
static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration)
{ {
ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
// using bitwise AND operation for user set channel mask to remove channels not allowed in this device // using bitwise AND operation for user set channel mask to remove channels not allowed in this device
for (uint8_t n = 0; n < 8; n++) { for (uint8_t n = 0; n < 8; n++) {
fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n]; fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n];
@ -510,6 +566,7 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_bc_channel_function; fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_bc_channel_function;
fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->cfg->fhss.fhss_bc_dwell_interval; fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->cfg->fhss.fhss_bc_dwell_interval;
fhss_configuration.fhss_broadcast_interval = cur->ws_info->cfg->fhss.fhss_bc_interval; fhss_configuration.fhss_broadcast_interval = cur->ws_info->cfg->fhss.fhss_bc_interval;
fhss_configuration.config_parameters.number_of_channel_retries = WS_NUMBER_OF_CHANNEL_RETRIES;
fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr);
if (!fhss_api) { if (!fhss_api) {
@ -1069,7 +1126,7 @@ static parent_info_t *ws_bootstrap_candidate_parent_allocate(protocol_interface_
return entry; return entry;
} }
static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, uint8_t *addr) static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, const uint8_t *addr)
{ {
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
if (memcmp(entry->addr, addr, 8) == 0) { if (memcmp(entry->addr, addr, 8) == 0) {
@ -1286,14 +1343,15 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter
* a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node. * a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node.
*/ */
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit); trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit);
/* /*
* Optimized PAN discovery to select faster the parent if we hear solicit from someone else * Optimized PAN discovery to select faster the parent if we hear solicit from someone else
*/ */
if (ws_bootstrap_state_discovery(cur) && if (ws_bootstrap_state_discovery(cur) && cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM &&
cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin + 50) { cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin * 2) {
cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin);
tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10));
} }
} }
@ -1347,6 +1405,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
tr_error("No broadcast schedule"); tr_error("No broadcast schedule");
return; return;
} }
llc_neighbour_req_t neighbor_info; llc_neighbour_req_t neighbor_info;
bool neighbour_pointer_valid; bool neighbour_pointer_valid;
@ -1362,7 +1421,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
} }
if (neighbour_pointer_valid) { if (neighbour_pointer_valid) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index); etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
//Update Neighbor Broadcast and Unicast Parameters //Update Neighbor Broadcast and Unicast Parameters
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
@ -1447,7 +1506,7 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
llc_neighbour_req_t neighbor_info; llc_neighbour_req_t neighbor_info;
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index); etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
} }
@ -1607,6 +1666,10 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) { ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, cur->index); ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, cur->index);
if (cur->index == interface->ws_info->eapol_tx_index) {
continue;
}
if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) { if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) {
//This is our primary parent we cannot delete //This is our primary parent we cannot delete
continue; continue;
@ -1758,7 +1821,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
return false; return false;
} }
if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) { if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, cur->ws_info->cfg->gen.rpl_parent_candidate_max)) {
//NUD Not needed for if neighbour is not parent candidate //NUD Not needed for if neighbour is not parent candidate
return false; return false;
} }
@ -1921,7 +1984,7 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
ret_val = -4; ret_val = -4;
goto init_fail; goto init_fail;
} }
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment) < 0) { if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated) < 0) {
ret_val = -4; ret_val = -4;
goto init_fail; goto init_fail;
} }
@ -1957,6 +2020,8 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
set_req.value_size = sizeof(bool); set_req.value_size = sizeof(bool);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req); cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
mac_helper_mac_mlme_max_retry_set(cur->id, WS_MAX_FRAME_RETRIES);
// Set the default parameters for MPL // Set the default parameters for MPL
cur->mpl_proactive_forwarding = true; cur->mpl_proactive_forwarding = true;
@ -2032,6 +2097,12 @@ int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_chan
set_request.value_pointer = &multi_csma_params; set_request.value_pointer = &multi_csma_params;
set_request.value_size = sizeof(mlme_multi_csma_ca_param_t); set_request.value_size = sizeof(mlme_multi_csma_ca_param_t);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
// Start automatic CCA threshold
uint8_t start_cca_thr[4] = {cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT};
set_request.attr = macCCAThresholdStart;
set_request.value_pointer = &start_cca_thr;
set_request.value_size = sizeof(start_cca_thr);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
return 0; return 0;
} }
@ -2205,8 +2276,8 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT); ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT);
// Set network information to PAE // Set network information to PAE
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name); ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name);
// Network key is valid // Network key is valid, indicate border router IID to controller
ws_pae_controller_nw_key_valid(cur); ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]);
// After successful DAO ACK connection to border router is verified // After successful DAO ACK connection to border router is verified
cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout;
@ -2308,20 +2379,22 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t
static bool ws_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) static bool ws_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance)
{ {
//If bootstrap active we not need any candidate filtering
if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) && (ws_info(cur)->cfg->gen.network_size == NETWORK_SIZE_CERTIFICATE)) {
return true;
}
//Already many candidates //Already many candidates
if (rpl_control_candidate_list_size(cur, instance) > cur->ws_info->cfg->rpl.rpl_parent_candidate_max) { uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance);
if (candidate_list_size >= cur->ws_info->cfg->gen.rpl_parent_candidate_max) {
return false; return false;
} }
uint16_t selected_parents = rpl_control_selected_parent_count(cur, instance);
//Already enough selected candidates //Already enough selected candidates
if (rpl_control_selected_parent_count(cur, instance) >= cur->ws_info->cfg->rpl.rpl_selected_parent_max) { if (selected_parents >= cur->ws_info->cfg->gen.rpl_selected_parent_max) {
candidate_list_size -= selected_parents;
if (candidate_list_size >= 2) {
//We have more candidates than selected
return false; return false;
} }
}
return true; return true;
} }
@ -2354,6 +2427,19 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle,
ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64);
if (!ws_rpl_candidate_soft_filtering(cur, instance)) { if (!ws_rpl_candidate_soft_filtering(cur, instance)) {
//Acept only better than own rank here
if (candidate_rank >= rpl_control_current_rank(instance)) {
//Do not accept no more siblings
return false;
}
uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance);
if (candidate_list_size > cur->ws_info->cfg->gen.rpl_parent_candidate_max + 1) {
//Accept only 1 better 1 time
return false;
}
if (!neigh_buffer.neighbor) { if (!neigh_buffer.neighbor) {
//Do not accept any new in that Place //Do not accept any new in that Place
return false; return false;
@ -2386,42 +2472,6 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle,
if (neigh_buffer.neighbor) { if (neigh_buffer.neighbor) {
return true; return true;
} }
#if 0
if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) {
return false;
}
// +2 Is for PAN ID space
memcpy(mac64 + 2, replacing + 8, 8);
mac64[2] ^= 2;
if (ws_etx_read(cur, ADDR_802_15_4_LONG, mac64) == 0xffff) {
//Not proped yet because ETX is 0xffff
return false;
}
uint16_t etx = 0;
if (neigh_buffer.neighbor) {
etx = etx_local_etx_read(cur->id, neigh_buffer.neighbor->index);
}
// Accept now only better one's when max candidates selected and max candidate list size is reached
if (!rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx)) {
return false;
}
//TODO if replacing has poor ETX, put it in blacklist as "poor ETX" to prevent reselection
//Mark That We can try remove replaced link
replace_ok = true;
neigh_create:
if (neigh_buffer.neighbor) {
//Use Already discovered entry
create_ok = true;
goto neigh_create_ok;
}
#endif
if (!entry) { if (!entry) {
//No Multicast Entry Available //No Multicast Entry Available
@ -2435,7 +2485,7 @@ neigh_create:
//Copy fhss temporary data //Copy fhss temporary data
*ws_neigh = entry->neigh_info_list; *ws_neigh = entry->neigh_info_list;
//ETX Create here //ETX Create here
etx_lqi_dbm_update(cur->id, entry->mpduLinkQuality, entry->signal_dbm, neigh_buffer.neighbor->index); etx_lqi_dbm_update(cur->id, entry->mpduLinkQuality, entry->signal_dbm, neigh_buffer.neighbor->index, neigh_buffer.neighbor->mac64);
mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true);
} }
ws_llc_free_multicast_temp_entry(cur, entry); ws_llc_free_multicast_temp_entry(cur, entry);
@ -2562,7 +2612,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
} }
// Discovery statemachine is checkked after we have sent the Solicit // Discovery statemachine is checkked after we have sent the Solicit
uint16_t time_to_solicit = 0; uint32_t time_to_solicit = 0;
if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) { if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) {
time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now; time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now;
} }
@ -2571,7 +2621,13 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k, cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k,
cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c); cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c);
cur->bootsrap_state_machine_cnt = time_to_solicit + cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; time_to_solicit += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin);
if (time_to_solicit > 0xffff) {
time_to_solicit = 0xffff;
}
cur->bootsrap_state_machine_cnt = time_to_solicit;
tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10));
} }
@ -2627,6 +2683,32 @@ static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *
mac_helper_key_link_frame_counter_read(cur->id, counter, slot); mac_helper_key_link_frame_counter_read(cur->id, counter, slot);
} }
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *cur, uint16_t pan_id, char *network_name)
{
/* For border router, the PAE controller reads pan_id and network name from storage.
* If they are set, takes them into use here.
*/
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
// Get pad_id and network name
ws_gen_cfg_t gen_cfg;
if (ws_cfg_gen_get(&gen_cfg, NULL) < 0) {
return;
}
// If pan_id has not been set, set it
if (gen_cfg.network_pan_id == 0xffff) {
gen_cfg.network_pan_id = pan_id;
}
// If network name has not been set, set it
if (strlen(gen_cfg.network_name) == 0) {
strncpy(gen_cfg.network_name, network_name, 32);
}
// Stores the settings
ws_cfg_gen_set(cur, NULL, &gen_cfg, 0);
}
}
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64) static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64)
{ {
(void) target_eui_64; (void) target_eui_64;
@ -2658,6 +2740,24 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_
} }
} }
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id)
{
ws_bootstrap_candidate_parent_free(cur, previous_eui_64);
// Gets best target
parent_info_t *parent_info = ws_bootstrap_candidate_parent_get_best(cur);
if (parent_info) {
/* On failure still continues with the new parent, and on next call,
will try to set the neighbor again */
ws_bootstrap_neighbor_set(cur, parent_info, true);
*pan_id = parent_info->pan_id;
return parent_info->addr;
}
// If no targets found, retries the last one
return previous_eui_64;
}
// Start configuration learning // Start configuration learning
static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur) static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur)
{ {
@ -2731,7 +2831,7 @@ static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asy
uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel; uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel;
async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32)); async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32));
} else { } else {
ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
} }
async_req->channel_list.channel_page = CHANNEL_PAGE_10; async_req->channel_list.channel_page = CHANNEL_PAGE_10;
@ -3047,6 +3147,36 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
} }
} }
static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr, bool clear_list)
{
uint16_t pan_id = cur->ws_info->network_pan_id;
// Add EAPOL neighbor
cur->ws_info->network_pan_id = parent_ptr->pan_id;
cur->ws_info->pan_information = parent_ptr->pan_information;
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
// If PAN ID changes, clear learned neighbors and activate FHSS
if (pan_id != cur->ws_info->network_pan_id) {
if (clear_list) {
ws_bootstrap_neighbor_list_clean(cur);
}
ws_bootstrap_fhss_activate(cur);
}
llc_neighbour_req_t neighbor_info;
if (!ws_bootstrap_neighbor_info_request(cur, parent_ptr->addr, &neighbor_info, true)) {
//Remove Neighbour and set Link setup back
ns_list_remove(&cur->ws_info->parent_list_reserved, parent_ptr);
ns_list_add_to_end(&cur->ws_info->parent_list_free, parent_ptr);
return -1;
}
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us);
return 0;
}
/* /*
* State machine * State machine
* *
@ -3067,29 +3197,21 @@ select_best_candidate:
// randomize new channel and start MAC // randomize new channel and start MAC
ws_bootstrap_fhss_activate(cur); ws_bootstrap_fhss_activate(cur);
// Next check will be after one trickle // Next check will be after one trickle
cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; uint32_t random_start = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin);
if (random_start > 0xffff) {
random_start = 0xffff;
}
cur->bootsrap_state_machine_cnt = random_start;
tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10));
return; return;
} }
tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id); tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id);
// Add EAPOL neighbour if (ws_bootstrap_neighbor_set(cur, selected_parent_ptr, false) < 0) {
cur->ws_info->network_pan_id = selected_parent_ptr->pan_id;
cur->ws_info->pan_information = selected_parent_ptr->pan_information;
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
ws_bootstrap_fhss_activate(cur);
llc_neighbour_req_t neighbor_info;
if (!ws_bootstrap_neighbor_info_request(cur, selected_parent_ptr->addr, &neighbor_info, true)) {
//Remove Neighbour and set Link setup back
ns_list_remove(&cur->ws_info->parent_list_reserved, selected_parent_ptr);
ns_list_add_to_end(&cur->ws_info->parent_list_free, selected_parent_ptr);
goto select_best_candidate; goto select_best_candidate;
} }
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_utt, selected_parent_ptr->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_us);
ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth
ws_bootstrap_event_authentication_start(cur); ws_bootstrap_event_authentication_start(cur);
return; return;
@ -3305,6 +3427,8 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s
} }
} }
ws_llc_timer_seconds(cur, seconds);
} }
void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor)

View File

@ -31,6 +31,7 @@ typedef enum {
struct llc_neighbour_req; struct llc_neighbour_req;
struct ws_us_ie; struct ws_us_ie;
struct ws_neighbor_class_entry;
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode); int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
@ -81,6 +82,12 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur,
bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur); bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur);
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
struct ws_neighbor_class_entry *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface);
#else #else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)

View File

@ -49,8 +49,9 @@
#define TRICKLE_IMIN_15_SECS 15 #define TRICKLE_IMIN_15_SECS 15
typedef struct ws_cfg_nw_size_s { typedef struct ws_cfg_nw_size_s {
ws_gen_cfg_t gen; /**< General configuration */
ws_timing_cfg_t timing; /**< Timing configuration */ ws_timing_cfg_t timing; /**< Timing configuration */
ws_rpl_cfg_t rpl; /**< RPL configuration */ ws_bbr_cfg_t bbr; /**< RPL configuration */
ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */ ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */
} ws_cfg_nw_size_t; } ws_cfg_nw_size_t;
@ -69,7 +70,7 @@ typedef union {
ws_gen_cfg_t gen; ws_gen_cfg_t gen;
ws_phy_cfg_t phy; ws_phy_cfg_t phy;
ws_timing_cfg_t timing; ws_timing_cfg_t timing;
ws_rpl_cfg_t rpl; ws_bbr_cfg_t bbr;
ws_fhss_cfg_t fhss; ws_fhss_cfg_t fhss;
ws_mpl_cfg_t mpl; ws_mpl_cfg_t mpl;
ws_sec_timer_cfg_t sec_timer; ws_sec_timer_cfg_t sec_timer;
@ -81,12 +82,13 @@ static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg); static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg);
static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg); static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg);
static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg); static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg);
static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg);
static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg); static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg);
static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg); static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg);
static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg); static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg);
static int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg); static int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg);
static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg); static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg);
static int8_t ws_cfg_rpl_default_set(ws_rpl_cfg_t *cfg); static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg);
static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg); static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg);
static int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg); static int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg);
static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg); static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg);
@ -107,7 +109,7 @@ static const ws_cfg_cb_t cfg_cb[] = {
CFG_CB(ws_cfg_gen_default_set, ws_cfg_gen_validate, ws_cfg_gen_set, offsetof(ws_cfg_t, gen)), CFG_CB(ws_cfg_gen_default_set, ws_cfg_gen_validate, ws_cfg_gen_set, offsetof(ws_cfg_t, gen)),
CFG_CB(ws_cfg_phy_default_set, ws_cfg_phy_validate, ws_cfg_phy_set, offsetof(ws_cfg_t, phy)), CFG_CB(ws_cfg_phy_default_set, ws_cfg_phy_validate, ws_cfg_phy_set, offsetof(ws_cfg_t, phy)),
CFG_CB(ws_cfg_timing_default_set, ws_cfg_timing_validate, ws_cfg_timing_set, offsetof(ws_cfg_t, timing)), CFG_CB(ws_cfg_timing_default_set, ws_cfg_timing_validate, ws_cfg_timing_set, offsetof(ws_cfg_t, timing)),
CFG_CB(ws_cfg_rpl_default_set, ws_cfg_rpl_validate, ws_cfg_rpl_set, offsetof(ws_cfg_t, rpl)), CFG_CB(ws_cfg_bbr_default_set, ws_cfg_bbr_validate, ws_cfg_bbr_set, offsetof(ws_cfg_t, bbr)),
CFG_CB(ws_cfg_mpl_default_set, ws_cfg_mpl_validate, ws_cfg_mpl_set, offsetof(ws_cfg_t, mpl)), CFG_CB(ws_cfg_mpl_default_set, ws_cfg_mpl_validate, ws_cfg_mpl_set, offsetof(ws_cfg_t, mpl)),
CFG_CB(ws_cfg_fhss_default_set, ws_cfg_fhss_validate, ws_cfg_fhss_set, offsetof(ws_cfg_t, fhss)), CFG_CB(ws_cfg_fhss_default_set, ws_cfg_fhss_validate, ws_cfg_fhss_set, offsetof(ws_cfg_t, fhss)),
CFG_CB(ws_cfg_sec_timer_default_set, ws_cfg_sec_timer_validate, ws_cfg_sec_timer_set, offsetof(ws_cfg_t, sec_timer)), CFG_CB(ws_cfg_sec_timer_default_set, ws_cfg_sec_timer_validate, ws_cfg_sec_timer_set, offsetof(ws_cfg_t, sec_timer)),
@ -128,10 +130,12 @@ static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate
if (*cfg == NULL) { if (*cfg == NULL) {
// In case external configuration is not same as internal // In case external configuration is not same as internal
if (nw_size_external_cfg && (!flags || !(*flags & CFG_FLAGS_FORCE_INTERNAL_CONFIG))) { if (nw_size_external_cfg && (!flags || !(*flags & CFG_FLAGS_FORCE_INTERNAL_CONFIG))) {
if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.timing) { if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.gen) {
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->gen;
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.timing) {
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->timing; *cfg = (ws_cfgs_t *) &nw_size_external_cfg->timing;
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.rpl) { } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.bbr) {
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->rpl; *cfg = (ws_cfgs_t *) &nw_size_external_cfg->bbr;
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.sec_prot) { } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.sec_prot) {
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->sec_prot; *cfg = (ws_cfgs_t *) &nw_size_external_cfg->sec_prot;
} else { } else {
@ -245,8 +249,9 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
cfg->network_size = new_cfg->network_size; cfg->network_size = new_cfg->network_size;
ws_cfg_nw_size_t nw_size_cfg; ws_cfg_nw_size_t nw_size_cfg;
ws_cfg_gen_get(&nw_size_cfg.gen, NULL);
ws_cfg_timing_get(&nw_size_cfg.timing, NULL); ws_cfg_timing_get(&nw_size_cfg.timing, NULL);
ws_cfg_rpl_get(&nw_size_cfg.rpl, NULL); ws_cfg_bbr_get(&nw_size_cfg.bbr, NULL);
ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot, NULL); ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot, NULL);
ws_cfg_network_size_config_set_size set_function = NULL; ws_cfg_network_size_config_set_size set_function = NULL;
@ -257,8 +262,10 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
set_function = ws_cfg_network_size_config_set_small; set_function = ws_cfg_network_size_config_set_small;
} else if (cfg->network_size <= NETWORK_SIZE_MEDIUM) { } else if (cfg->network_size <= NETWORK_SIZE_MEDIUM) {
set_function = ws_cfg_network_size_config_set_medium; set_function = ws_cfg_network_size_config_set_medium;
} else { } else if (cfg->network_size <= NETWORK_SIZE_LARGE) {
set_function = ws_cfg_network_size_config_set_large; set_function = ws_cfg_network_size_config_set_large;
} else {
set_function = ws_cfg_network_size_config_set_xlarge;
} }
// Overrides the values on the new configuration // Overrides the values on the new configuration
@ -279,13 +286,17 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
} }
/* Sets values if changed or network size has been previously automatic (to make sure /* Sets values if changed or network size has been previously automatic (to make sure
the settings are in sync */ the settings are in sync */
if (ws_cfg_gen_validate(&ws_cfg.gen, &nw_size_cfg.gen) == CFG_SETTINGS_CHANGED ||
old_network_size == NETWORK_SIZE_AUTOMATIC) {
ws_cfg_gen_set(cur, &ws_cfg.gen, &nw_size_cfg.gen, &set_flags);
}
if (ws_cfg_timing_validate(&ws_cfg.timing, &nw_size_cfg.timing) == CFG_SETTINGS_CHANGED || if (ws_cfg_timing_validate(&ws_cfg.timing, &nw_size_cfg.timing) == CFG_SETTINGS_CHANGED ||
old_network_size == NETWORK_SIZE_AUTOMATIC) { old_network_size == NETWORK_SIZE_AUTOMATIC) {
ws_cfg_timing_set(cur, &ws_cfg.timing, &nw_size_cfg.timing, &set_flags); ws_cfg_timing_set(cur, &ws_cfg.timing, &nw_size_cfg.timing, &set_flags);
} }
if (ws_cfg_rpl_validate(&ws_cfg.rpl, &nw_size_cfg.rpl) == CFG_SETTINGS_CHANGED || if (ws_cfg_bbr_validate(&ws_cfg.bbr, &nw_size_cfg.bbr) == CFG_SETTINGS_CHANGED ||
old_network_size == NETWORK_SIZE_AUTOMATIC) { old_network_size == NETWORK_SIZE_AUTOMATIC) {
ws_cfg_rpl_set(cur, &ws_cfg.rpl, &nw_size_cfg.rpl, &set_flags); ws_cfg_bbr_set(cur, &ws_cfg.bbr, &nw_size_cfg.bbr, &set_flags);
} }
if (ws_cfg_sec_prot_validate(&ws_cfg.sec_prot, &nw_size_cfg.sec_prot) == CFG_SETTINGS_CHANGED || if (ws_cfg_sec_prot_validate(&ws_cfg.sec_prot, &nw_size_cfg.sec_prot) == CFG_SETTINGS_CHANGED ||
old_network_size == NETWORK_SIZE_AUTOMATIC) { old_network_size == NETWORK_SIZE_AUTOMATIC) {
@ -305,8 +316,10 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1
// Read settings that are affected by network size // Read settings that are affected by network size
ws_cfg_nw_size_t new_nw_size_cfg; ws_cfg_nw_size_t new_nw_size_cfg;
uint8_t flags = CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET | CFG_FLAGS_FORCE_INTERNAL_CONFIG; uint8_t flags = CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET | CFG_FLAGS_FORCE_INTERNAL_CONFIG;
ws_cfg_gen_get(&new_nw_size_cfg.gen, &flags);
ws_cfg_timing_get(&new_nw_size_cfg.timing, &flags); ws_cfg_timing_get(&new_nw_size_cfg.timing, &flags);
ws_cfg_rpl_get(&new_nw_size_cfg.rpl, &flags); ws_cfg_bbr_get(&new_nw_size_cfg.bbr, &flags);
ws_cfg_sec_prot_get(&new_nw_size_cfg.sec_prot, &flags); ws_cfg_sec_prot_get(&new_nw_size_cfg.sec_prot, &flags);
if (!nw_size_external_cfg) { if (!nw_size_external_cfg) {
@ -321,16 +334,20 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1
if (network_size < 100) { if (network_size < 100) {
// Automatic // Automatic
ws_cfg_network_size_config_set_small(&new_nw_size_cfg); ws_cfg_network_size_config_set_small(&new_nw_size_cfg);
} else if (network_size < 300) { } else if (network_size < 800) {
// Medium // Medium
ws_cfg_network_size_config_set_medium(&new_nw_size_cfg); ws_cfg_network_size_config_set_medium(&new_nw_size_cfg);
} else if (network_size < 1500) {
// Medium
ws_cfg_network_size_config_set_large(&new_nw_size_cfg);
} else { } else {
// Large // Large
ws_cfg_network_size_config_set_large(&new_nw_size_cfg); ws_cfg_network_size_config_set_xlarge(&new_nw_size_cfg);
} }
ws_cfg_gen_set(cur, NULL, &new_nw_size_cfg.gen, &flags);
ws_cfg_timing_set(cur, NULL, &new_nw_size_cfg.timing, &flags); ws_cfg_timing_set(cur, NULL, &new_nw_size_cfg.timing, &flags);
ws_cfg_rpl_set(cur, NULL, &new_nw_size_cfg.rpl, &flags); ws_cfg_bbr_set(cur, NULL, &new_nw_size_cfg.bbr, &flags);
ws_cfg_sec_prot_set(cur, NULL, &new_nw_size_cfg.sec_prot, &flags); ws_cfg_sec_prot_set(cur, NULL, &new_nw_size_cfg.sec_prot, &flags);
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
@ -338,112 +355,190 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg)
{ {
// Configure the Wi-SUN parent configuration
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// Configure the Wi-SUN timing trickle parameter // Configure the Wi-SUN timing trickle parameter
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds
cfg->timing.disc_trickle_k = 1; cfg->timing.disc_trickle_k = 1;
cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT; cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT;
// RPL configuration // RPL configuration
cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds
cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128 cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128
cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// EAPOL configuration // EAPOL configuration
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
} }
static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg)
{ {
// Configure the Wi-SUN parent configuration
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// Configure the Wi-SUN timing trickle parameters // Configure the Wi-SUN timing trickle parameters
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_30_SECS; // 30 seconds cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_30_SECS << 5; // 960 seconds; 16 minutes cfg->timing.disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes
cfg->timing.disc_trickle_k = 1; cfg->timing.disc_trickle_k = 1;
cfg->timing.pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT; cfg->timing.pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_MEDIUM_TIMEOUT;
// RPL configuration // RPL configuration
cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 15; 32s cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 17; 128s
cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 2; 1024s cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 3; 1024s
cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10 cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10
cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// EAPOL configuration // EAPOL configuration
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
cfg->sec_prot.initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->sec_prot.initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
} }
static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
{ {
// Configure the Wi-SUN parent configuration
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// Configure the Wi-SUN timing trickle parameters // Configure the Wi-SUN timing trickle parameters
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 2; // 240 seconds
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes cfg->timing.disc_trickle_imax = 1536; // 1536 seconds; 25 minutes
cfg->timing.disc_trickle_k = 1; cfg->timing.disc_trickle_k = 1;
cfg->timing.pan_timeout = PAN_VERSION_LARGE_NETWORK_TIMEOUT; cfg->timing.pan_timeout = PAN_VERSION_LARGE_NETWORK_TIMEOUT;
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE; cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE;
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT;
// RPL configuration // RPL configuration
cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 19; 524s, 9min cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 18; 262s, 4.5min
cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_LARGE; // 1; 1024s, 17min cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_LARGE; // 3; 2048s, 34min
cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10 cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10
cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// EAPOL configuration // EAPOL configuration
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN; cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN;
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX; cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX;
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_LARGE;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
cfg->sec_prot.initial_key_imin = LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->sec_prot.initial_key_imax = LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->sec_prot.initial_key_retry_cnt = LARGE_NW_INITIAL_KEY_RETRY_COUNT;
}
static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg)
{
// Configure the Wi-SUN parent configuration
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
// Configure the Wi-SUN timing trickle parameters
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 2; // 240 seconds
cfg->timing.disc_trickle_imax = 1920; // 1920 seconds; 32 minutes
cfg->timing.disc_trickle_k = 1;
cfg->timing.pan_timeout = PAN_VERSION_XLARGE_NETWORK_TIMEOUT;
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE;
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT;
// RPL configuration
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_XLARGE; // 18; 262s, 4.5min
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_XLARGE; // 4; 2048s, 34min
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_XLARGE; // 10
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
// EAPOL configuration
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN;
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX;
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
cfg->sec_prot.initial_key_imin = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->sec_prot.initial_key_imax = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->sec_prot.initial_key_retry_cnt = EXTRA_LARGE_NW_INITIAL_KEY_RETRY_COUNT;
} }
static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg)
{ {
// Configure the Wi-SUN parent configuration
cfg->gen.rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX;
cfg->gen.rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX;
// Configure the Wi-SUN timing trickle parameters // Configure the Wi-SUN timing trickle parameters
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds
cfg->timing.disc_trickle_k = 1; cfg->timing.disc_trickle_k = 1;
cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT; cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT;
// RPL configuration (small) // RPL configuration (small)
cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds
cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128 cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128
cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
cfg->rpl.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE;
cfg->rpl.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE;
cfg->rpl.rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
cfg->rpl.rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX;
// EAPOL configuration // EAPOL configuration
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL;
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
} }
static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg) static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg)
{ {
memset(cfg->network_name, 0, sizeof(cfg->network_name)); memset(cfg->network_name, 0, sizeof(cfg->network_name));
cfg->network_pan_id = 0xffff; cfg->network_pan_id = 0xffff;
cfg->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
cfg->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
@ -467,7 +562,9 @@ int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
// Regulator domain, operating mode or class has changed // Regulator domain, operating mode or class has changed
if (strcmp(cfg->network_name, new_cfg->network_name) != 0 || if (strcmp(cfg->network_name, new_cfg->network_name) != 0 ||
cfg->network_pan_id != new_cfg->network_pan_id) { cfg->network_pan_id != new_cfg->network_pan_id ||
cfg->rpl_parent_candidate_max != new_cfg->rpl_parent_candidate_max ||
cfg->rpl_selected_parent_max != new_cfg->rpl_selected_parent_max) {
return CFG_SETTINGS_CHANGED; return CFG_SETTINGS_CHANGED;
} }
@ -493,6 +590,8 @@ int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, w
strncpy(cfg->network_name, new_cfg->network_name, 32); strncpy(cfg->network_name, new_cfg->network_name, 32);
} }
cfg->network_pan_id = new_cfg->network_pan_id; cfg->network_pan_id = new_cfg->network_pan_id;
cfg->rpl_parent_candidate_max = new_cfg->rpl_parent_candidate_max;
cfg->rpl_selected_parent_max = new_cfg->rpl_selected_parent_max;
if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) { if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
ws_bootstrap_restart_delayed(cur->id); ws_bootstrap_restart_delayed(cur->id);
@ -584,11 +683,12 @@ int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, w
static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg) static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg)
{ {
// Configure the Wi-SUN timing trickle parameters // Configure the Wi-SUN timing trickle parameters
cfg->disc_trickle_imin = TRICKLE_IMIN_30_SECS; // 30 seconds cfg->disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds
cfg->disc_trickle_imax = TRICKLE_IMIN_30_SECS << 5; // 960 seconds; 16 minutes cfg->disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes
cfg->disc_trickle_k = 1; cfg->disc_trickle_k = 1;
cfg->pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT; cfg->pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
cfg->temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; cfg->temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
cfg->temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_MEDIUM_TIMEOUT;
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
@ -658,58 +758,56 @@ int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
static int8_t ws_cfg_rpl_default_set(ws_rpl_cfg_t *cfg) static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg)
{ {
// Something in between // Something in between
// imin: 15 (32s) // imin: 17 (128s)
// doublings:5 (960s) // doublings:3 (1024s)
// redundancy; 10 // redundancy; 10
//ws_bbr_rpl_config(cur, 15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); //ws_bbr_rpl_config(cur, 17, 3, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
cfg->dio_interval_min = 15; // 32s cfg->dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 128s
cfg->dio_interval_doublings = 5; // 1024s cfg->dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 1024s
cfg->dio_redundancy_constant = 10; cfg->dio_redundancy_constant = 10;
cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
cfg->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; cfg->dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
cfg->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
int8_t ws_cfg_rpl_get(ws_rpl_cfg_t *cfg, uint8_t *flags) int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg, uint8_t *flags)
{ {
ws_rpl_cfg_t *get_cfg = NULL; ws_bbr_cfg_t *get_cfg = NULL;
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.rpl, 0, flags); ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.bbr, 0, flags);
*cfg = *get_cfg; *cfg = *get_cfg;
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
int8_t ws_cfg_rpl_validate(ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg) int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg)
{ {
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.rpl, 0, 0); ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.bbr, 0, 0);
if (cfg->dio_interval_min != new_cfg->dio_interval_min || if (cfg->dio_interval_min != new_cfg->dio_interval_min ||
cfg->dio_interval_doublings != new_cfg->dio_interval_doublings || cfg->dio_interval_doublings != new_cfg->dio_interval_doublings ||
cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant || cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant ||
cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase || cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase ||
cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase || cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase ||
cfg->rpl_parent_candidate_max != new_cfg->rpl_parent_candidate_max || cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime) {
cfg->rpl_selected_parent_max != new_cfg->rpl_selected_parent_max) {
return CFG_SETTINGS_CHANGED; return CFG_SETTINGS_CHANGED;
} }
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
int8_t ws_cfg_rpl_set(protocol_interface_info_entry_t *cur, ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg, uint8_t *flags) int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg, uint8_t *flags)
{ {
(void) cur; (void) cur;
(void) flags; (void) flags;
uint8_t cfg_flags; uint8_t cfg_flags;
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_rpl_validate, (ws_cfgs_t *) &ws_cfg.rpl, &cfg_flags, flags); int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_bbr_validate, (ws_cfgs_t *) &ws_cfg.bbr, &cfg_flags, flags);
if (ret != CFG_SETTINGS_CHANGED) { if (ret != CFG_SETTINGS_CHANGED) {
return ret; return ret;
} }
@ -719,13 +817,14 @@ int8_t ws_cfg_rpl_set(protocol_interface_info_entry_t *cur, ws_rpl_cfg_t *cfg, w
ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings, ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings,
new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase, new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase,
new_cfg->min_hop_rank_increase); new_cfg->min_hop_rank_increase);
ws_bbr_dhcp_address_lifetime_set(cur, new_cfg->dhcp_address_lifetime);
} }
if (cfg == new_cfg) { if (cfg == new_cfg) {
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_rpl_cfg_t), "rpl"); ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_bbr_cfg_t), "rpl");
*cfg = *new_cfg; *cfg = *new_cfg;
@ -978,7 +1077,12 @@ static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg)
cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
cfg->sec_prot_trickle_timer_exp = 2; cfg->sec_prot_trickle_timer_exp = 2;
cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM; cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
cfg->initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
cfg->initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
cfg->initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
cfg->initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;
} }
@ -999,7 +1103,11 @@ int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_c
cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax || cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax ||
cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp || cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp ||
cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout || cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout ||
cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication) { cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication ||
cfg->initial_key_retry_delay != new_cfg->initial_key_retry_delay ||
cfg->initial_key_imin != new_cfg->initial_key_retry_delay ||
cfg->initial_key_imax != new_cfg->initial_key_retry_delay ||
cfg->initial_key_retry_cnt != new_cfg->initial_key_retry_delay) {
return CFG_SETTINGS_CHANGED; return CFG_SETTINGS_CHANGED;
} }
@ -1095,8 +1203,9 @@ int8_t ws_cfg_settings_get(protocol_interface_info_entry_t *cur, ws_cfg_t *cfg)
*cfg = ws_cfg; *cfg = ws_cfg;
ws_cfg_gen_get(&cfg->gen, NULL);
ws_cfg_timing_get(&cfg->timing, NULL); ws_cfg_timing_get(&cfg->timing, NULL);
ws_cfg_rpl_get(&cfg->rpl, NULL); ws_cfg_bbr_get(&cfg->bbr, NULL);
ws_cfg_sec_prot_get(&cfg->sec_prot, NULL); ws_cfg_sec_prot_get(&cfg->sec_prot, NULL);
return CFG_SETTINGS_OK; return CFG_SETTINGS_OK;

View File

@ -27,6 +27,8 @@ typedef struct ws_gen_cfg_s {
uint8_t network_size; /**< Network size selection; default medium (= 8) */ uint8_t network_size; /**< Network size selection; default medium (= 8) */
char network_name[33]; /**< Network name; max 32 octets + terminating 0 */ char network_name[33]; /**< Network name; max 32 octets + terminating 0 */
uint16_t network_pan_id; /**< PAN identifier; PAN_ID; default 0xffff */ uint16_t network_pan_id; /**< PAN identifier; PAN_ID; default 0xffff */
uint16_t rpl_parent_candidate_max; /**< RPL parent candidate maximum value; default 5 */
uint16_t rpl_selected_parent_max; /**< RPL selected parent maximum value; default 2 */
} ws_gen_cfg_t; } ws_gen_cfg_t;
/** /**
@ -47,20 +49,20 @@ typedef struct ws_timing_cfg_s {
uint8_t disc_trickle_k; /**< Discovery trickle k; DISC_K; default 1 */ uint8_t disc_trickle_k; /**< Discovery trickle k; DISC_K; default 1 */
uint16_t pan_timeout; /**< PAN timeout; PAN_TIMEOUT; seconds; range 60-15300; default 3840 */ uint16_t pan_timeout; /**< PAN timeout; PAN_TIMEOUT; seconds; range 60-15300; default 3840 */
uint16_t temp_link_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 260 */ uint16_t temp_link_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 260 */
uint16_t temp_eapol_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 330 */
} ws_timing_cfg_t; } ws_timing_cfg_t;
/** /**
* \brief Struct ws_rpl_cfg_t RPL configuration * \brief Struct ws_rpl_cfg_t RPL configuration
*/ */
typedef struct ws_rpl_cfg_s { typedef struct ws_bbr_cfg_s {
uint8_t dio_interval_min; /**> DIO interval min; DEFAULT_DIO_INTERVAL_MIN; 2^value in milliseconds; range 1-255; default */ uint8_t dio_interval_min; /**> DIO interval min; DEFAULT_DIO_INTERVAL_MIN; 2^value in milliseconds; range 1-255; default */
uint8_t dio_interval_doublings; /**> DIO interval doublings; DEFAULT_DIO_INTERVAL_DOUBLINGS; range 1-8; default */ uint8_t dio_interval_doublings; /**> DIO interval doublings; DEFAULT_DIO_INTERVAL_DOUBLINGS; range 1-8; default */
uint8_t dio_redundancy_constant; /**> DIO redundancy constant; DEFAULT_DIO_REDUNDANCY_CONSTANT; range 0-10; default */ uint8_t dio_redundancy_constant; /**> DIO redundancy constant; DEFAULT_DIO_REDUNDANCY_CONSTANT; range 0-10; default */
uint16_t dag_max_rank_increase; uint16_t dag_max_rank_increase;
uint16_t min_hop_rank_increase; uint16_t min_hop_rank_increase;
uint16_t rpl_parent_candidate_max; /**< RPL parent candidate maximum value; default 5 */ uint32_t dhcp_address_lifetime; /**> DHCP address lifetime in seconds minimum 2 hours and maximum as days hours*/
uint16_t rpl_selected_parent_max; /**< RPL selected parent maximum value; default 2 */ } ws_bbr_cfg_t;
} ws_rpl_cfg_t;
/** /**
* \brief Struct ws_fhss_cfg_t Frequency hopping configuration * \brief Struct ws_fhss_cfg_t Frequency hopping configuration
@ -111,6 +113,10 @@ typedef struct ws_sec_prot_cfg_s {
uint16_t sec_prot_trickle_imax; /**< Security protocol trickle parameters Imax; seconds; default 90 */ uint16_t sec_prot_trickle_imax; /**< Security protocol trickle parameters Imax; seconds; default 90 */
uint8_t sec_prot_trickle_timer_exp; /**< Security protocol trickle timer expirations; default 2 */ uint8_t sec_prot_trickle_timer_exp; /**< Security protocol trickle timer expirations; default 2 */
uint16_t sec_max_ongoing_authentication; /**< Pae authenticator max Accept ongoing authentication count */ uint16_t sec_max_ongoing_authentication; /**< Pae authenticator max Accept ongoing authentication count */
uint16_t initial_key_retry_delay; /**< Delay before starting initial key trickle; seconds; default 120 */
uint16_t initial_key_imin; /**< Initial key trickle Imin; seconds; default 360 */
uint16_t initial_key_imax; /**< Initial key trickle Imax; seconds; default 720 */
uint8_t initial_key_retry_cnt; /**< Number of initial key retries; default 2 */
} ws_sec_prot_cfg_t; } ws_sec_prot_cfg_t;
/** /**
@ -120,7 +126,7 @@ typedef struct ws_cfg_s {
ws_gen_cfg_t gen; /**< General configuration */ ws_gen_cfg_t gen; /**< General configuration */
ws_phy_cfg_t phy; /**< Physical layer configuration */ ws_phy_cfg_t phy; /**< Physical layer configuration */
ws_timing_cfg_t timing; /**< Timing configuration */ ws_timing_cfg_t timing; /**< Timing configuration */
ws_rpl_cfg_t rpl; /**< RPL configuration */ ws_bbr_cfg_t bbr; /**< RPL configuration */
ws_fhss_cfg_t fhss; /**< Frequency hopping configuration */ ws_fhss_cfg_t fhss; /**< Frequency hopping configuration */
ws_mpl_cfg_t mpl; /**< Multicast configuration */ ws_mpl_cfg_t mpl; /**< Multicast configuration */
ws_sec_timer_cfg_t sec_timer; /**< Security timers configuration */ ws_sec_timer_cfg_t sec_timer; /**< Security timers configuration */
@ -161,9 +167,9 @@ int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg); int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg);
int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg, uint8_t *flags); int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg, uint8_t *flags);
int8_t ws_cfg_rpl_get(ws_rpl_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_rpl_validate(ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg); int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg);
int8_t ws_cfg_rpl_set(protocol_interface_info_entry_t *cur, ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg, uint8_t *flags); int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg, uint8_t *flags);
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg); int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg);

View File

@ -49,13 +49,35 @@ uint8_t DEVICE_MIN_SENS = 174 - 93;
uint16_t test_max_child_count_override = 0xffff; uint16_t test_max_child_count_override = 0xffff;
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class)
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain)
{ {
(void)regulatory_domain; uint32_t excluded_start_channel = 0xFFFFFFFF;
for (uint8_t i = 0; i < number_of_channels; i++) { uint32_t excluded_end_channel = 0xFFFFFFFF;
if (regulatory_domain == REG_DOMAIN_BZ) {
if (operating_class == 1) {
excluded_start_channel = 26;
excluded_end_channel = 64;
} else if (operating_class == 2) {
excluded_start_channel = 12;
excluded_end_channel = 32;
} else if (operating_class == 3) {
excluded_start_channel = 7;
excluded_end_channel = 21;
}
}
// Clear channel mask
for (uint8_t i = 0; i < 8; i++) {
channel_mask[i] = 0;
}
// Set channel maks outside excluded channels
for (uint16_t i = 0; i < number_of_channels; i++) {
if (i < excluded_start_channel || i > excluded_end_channel) {
channel_mask[0 + (i / 32)] |= (1 << (i % 32)); channel_mask[0 + (i / 32)] |= (1 << (i % 32));
} }
}
return 0; return 0;
} }
@ -159,6 +181,19 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
} else { } else {
return -1; return -1;
} }
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_BZ) {
if (hopping_schdule->operating_class == 1) {
hopping_schdule->ch0_freq = 9022;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else if (hopping_schdule->operating_class == 2) {
hopping_schdule->ch0_freq = 9024;
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
} else if (hopping_schdule->operating_class == 3) {
hopping_schdule->ch0_freq = 9026;
hopping_schdule->channel_spacing = CHANNEL_SPACING_600;
} else {
return -1;
}
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) { } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) {
if (hopping_schdule->operating_class == 1) { if (hopping_schdule->operating_class == 1) {
hopping_schdule->ch0_freq = 9206; hopping_schdule->ch0_freq = 9206;
@ -189,6 +224,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
if (!hopping_schdule->number_of_channels) { if (!hopping_schdule->number_of_channels) {
return -1; return -1;
} }
return 0; return 0;
} }
@ -232,6 +268,14 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
} else if (operating_class == 3) { } else if (operating_class == 3) {
return 12; return 12;
} }
} else if (regulatory_domain == REG_DOMAIN_BZ) {
if (operating_class == 1) {
return 129;
} else if (operating_class == 2) {
return 64;
} else if (operating_class == 3) {
return 42;
}
} else if (regulatory_domain == REG_DOMAIN_WW) { } else if (regulatory_domain == REG_DOMAIN_WW) {
if (operating_class == 1) { if (operating_class == 1) {
// TODO we dont support this yet, but it is used as test value // TODO we dont support this yet, but it is used as test value
@ -388,11 +432,13 @@ uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur)
if (network_size <= NETWORK_SIZE_SMALL) { if (network_size <= NETWORK_SIZE_SMALL) {
// handles also NETWORK_SIZE_CERTIFICATE // handles also NETWORK_SIZE_CERTIFICATE
latency = 8000; latency = 4000;
} else if (network_size <= NETWORK_SIZE_MEDIUM) { } else if (network_size <= NETWORK_SIZE_MEDIUM) {
latency = 8000;
} else if (network_size <= NETWORK_SIZE_LARGE) {
latency = 16000; latency = 16000;
} else { } else {
latency = 32000; latency = 24000;
} }
return latency; return latency;
@ -405,22 +451,11 @@ uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur)
uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur) uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur)
{ {
uint32_t network_size_estimate = 0; uint32_t network_size_estimate = 100;
uint8_t network_size = cur->ws_info->cfg->gen.network_size;
if (network_size == NETWORK_SIZE_AUTOMATIC) { if ((cur->ws_info->cfg->gen.network_size != NETWORK_SIZE_AUTOMATIC) &&
network_size = cur->ws_info->pan_information.pan_size / 100; (cur->ws_info->cfg->gen.network_size != NETWORK_SIZE_CERTIFICATE)) {
} network_size_estimate = cur->ws_info->cfg->gen.network_size * 100;
if (network_size <= NETWORK_SIZE_SMALL) {
// tens of devices (now 30), handles also NETWORK_SIZE_CERTIFICATE
network_size_estimate = 30;
} else if (network_size <= NETWORK_SIZE_MEDIUM) {
// hundreds of devices (now 300)
network_size_estimate = 300;
} else {
// huge amount of devices (now 1000)
network_size_estimate = 1000;
} }
return network_size_estimate; return network_size_estimate;

View File

@ -82,6 +82,7 @@ typedef struct ws_info_s {
trickle_params_t trickle_params_pan_discovery; trickle_params_t trickle_params_pan_discovery;
uint8_t rpl_state; // state from rpl_event_t uint8_t rpl_state; // state from rpl_event_t
uint8_t pas_requests; // Amount of PAN solicits sent uint8_t pas_requests; // Amount of PAN solicits sent
uint8_t eapol_tx_index;
parent_info_t parent_info[WS_PARENT_LIST_SIZE]; parent_info_t parent_info[WS_PARENT_LIST_SIZE];
parent_info_list_t parent_list_free; parent_info_list_t parent_list_free;
parent_info_list_t parent_list_reserved; parent_info_list_t parent_list_reserved;
@ -112,7 +113,7 @@ typedef struct ws_info_s {
#ifdef HAVE_WS #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_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class);
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing); uint32_t ws_decode_channel_spacing(uint8_t channel_spacing);

View File

@ -236,9 +236,12 @@ typedef struct ws_bs_ie {
#define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL 260 #define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL 260
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
#define WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT 330
#define WS_EAPOL_TEMPORARY_ENTRY_MEDIUM_TIMEOUT WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT
#define WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT 750
#define WS_NEIGHBOR_ETX_SAMPLE_MAX 3 #define WS_NEIGHBOR_ETX_SAMPLE_MAX 3
#define WS_NEIGHBOR_FIRST_ETX_SAMPLE_MIN_COUNT 3 //This can't be bigger than WS_NEIGHBOR_ETX_SAMPLE_MAX #define WS_NEIGHBOR_FIRST_ETX_SAMPLE_MIN_COUNT 3 //This can't be bigger than WS_NEIGHBOR_ETX_SAMPLE_MAX
#define WS_NEIGHBOUR_MAX_CANDIDATE_PROBE 5
#define WS_PROBE_INIT_BASE_SECONDS 8 #define WS_PROBE_INIT_BASE_SECONDS 8
@ -295,6 +298,34 @@ typedef struct ws_bs_ie {
*/ */
#define WS_TACK_MAX_MS 5 #define WS_TACK_MAX_MS 5
/* WS requires at least 19 MAC retransmissions (total 1+19=20 attempts). Default 802.15.4 macMaxFrameRetries is 3 (total 1+3=4 attempts).
* At least 4 channel retries must be used: (Initial channel + WS_NUMBER_OF_CHANNEL_RETRIES) * MAC attempts = (1+4)*4=20 attempts
*
* Valid settings could be for example:
* WS_MAX_FRAME_RETRIES WS_NUMBER_OF_CHANNEL_RETRIES Total attempts
* 0 19 1+0*1+19=20
* 1 9 1+1*1+9=20
* 2 6 1+2*1+6=21
* 3 4 1+3*1+4=20
*
*/
#define WS_MAX_FRAME_RETRIES 3
#define WS_NUMBER_OF_CHANNEL_RETRIES 4
#if (1 + WS_MAX_FRAME_RETRIES) * (1 + WS_NUMBER_OF_CHANNEL_RETRIES) < 20
#warning "MAX frame retries set too low"
#endif
/*
* Automatic CCA threshold: default threshold and range in dBm.
*/
#define CCA_DEFAULT_DBM -60
#define CCA_HIGH_LIMIT -60
#define CCA_LOW_LIMIT -100
/* /*
* Config new version consistent filter period in 100ms periods * Config new version consistent filter period in 100ms periods
*/ */

View File

@ -31,14 +31,18 @@
#define WS_RPL_DIO_DOUBLING_SMALL 2 #define WS_RPL_DIO_DOUBLING_SMALL 2
#define WS_RPL_DIO_REDUNDANCY_SMALL 0 #define WS_RPL_DIO_REDUNDANCY_SMALL 0
#define WS_RPL_DIO_IMIN_MEDIUM 15 #define WS_RPL_DIO_IMIN_MEDIUM 17
#define WS_RPL_DIO_DOUBLING_MEDIUM 5 #define WS_RPL_DIO_DOUBLING_MEDIUM 3
#define WS_RPL_DIO_REDUNDANCY_MEDIUM 10 #define WS_RPL_DIO_REDUNDANCY_MEDIUM 10
#define WS_RPL_DIO_IMIN_LARGE 19 #define WS_RPL_DIO_IMIN_LARGE 18
#define WS_RPL_DIO_DOUBLING_LARGE 1 #define WS_RPL_DIO_DOUBLING_LARGE 3
#define WS_RPL_DIO_REDUNDANCY_LARGE 10 // May need some tuning still #define WS_RPL_DIO_REDUNDANCY_LARGE 10 // May need some tuning still
#define WS_RPL_DIO_IMIN_XLARGE 18
#define WS_RPL_DIO_DOUBLING_XLARGE 4
#define WS_RPL_DIO_REDUNDANCY_XLARGE 10 // May need some tuning still
#define WS_RPL_DIO_IMIN_AUTOMATIC 14 #define WS_RPL_DIO_IMIN_AUTOMATIC 14
#define WS_RPL_DIO_DOUBLING_AUTOMATIC 3 #define WS_RPL_DIO_DOUBLING_AUTOMATIC 3
#define WS_RPL_DIO_REDUNDANCY_AUTOMATIC 0 #define WS_RPL_DIO_REDUNDANCY_AUTOMATIC 0
@ -46,6 +50,10 @@
#define WS_RPL_MIN_HOP_RANK_INCREASE 196 #define WS_RPL_MIN_HOP_RANK_INCREASE 196
#define WS_RPL_MAX_HOP_RANK_INCREASE 2048 #define WS_RPL_MAX_HOP_RANK_INCREASE 2048
#define WS_DHCP_ADDRESS_LIFETIME_SMALL 2*3600 // small networks less than devices 100
#define WS_DHCP_ADDRESS_LIFETIME_MEDIUM 12*3600 // Medium size networks from 100 - 1000 device networks
#define WS_DHCP_ADDRESS_LIFETIME_LARGE 24*3600 // Large size networks 1000 + device networks
#define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128 #define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128
#define WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE 0 #define WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE 0
@ -64,7 +72,10 @@
// RPL version number update intervall // RPL version number update intervall
// after restart version numbers are increased faster and then slowed down when network is stable // after restart version numbers are increased faster and then slowed down when network is stable
#define RPL_VERSION_LIFETIME 12*3600 #define RPL_VERSION_LIFETIME 12*3600
#define RPL_VERSION_LIFETIME_RESTART 3600 #define RPL_VERSION_LIFETIME_RESTART_SMALL 3600
#define RPL_VERSION_LIFETIME_RESTART_MEDIUM 2*3600
#define RPL_VERSION_LIFETIME_RESTART_LARGE 4*3600
#define RPL_VERSION_LIFETIME_RESTART_EXTRA_LARGE 8*3600
/* Border router connection lost timeout /* Border router connection lost timeout
* *
@ -81,6 +92,8 @@
#define PAN_VERSION_LARGE_NETWORK_TIMEOUT 90*60 #define PAN_VERSION_LARGE_NETWORK_TIMEOUT 90*60
#define PAN_VERSION_XLARGE_NETWORK_TIMEOUT 120*60
/* Routing Cost Weighting factor /* Routing Cost Weighting factor
*/ */
#define PRC_WEIGHT_FACTOR 256 #define PRC_WEIGHT_FACTOR 256
@ -153,7 +166,8 @@ extern uint8_t DEVICE_MIN_SENS;
/* /*
* MAC frame counter NVM storing configuration * MAC frame counter NVM storing configuration
*/ */
#define FRAME_COUNTER_STORE_INTERVAL 60 // Time interval (on seconds) between frame counter store operations #define FRAME_COUNTER_STORE_INTERVAL 60 // Time interval (on seconds) between checking if frame counter storing is needed
#define FRAME_COUNTER_STORE_FORCE_INTERVAL (3600 * 20) // Time interval (on seconds) before frame counter storing is forced (if no other storing operations triggered)
#define FRAME_COUNTER_STORE_TRIGGER 5 // Delay (on seconds) before storing, when storing of frame counters is triggered #define FRAME_COUNTER_STORE_TRIGGER 5 // Delay (on seconds) before storing, when storing of frame counters is triggered
#define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up #define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up
#define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored #define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored
@ -199,10 +213,10 @@ extern uint8_t DEVICE_MIN_SENS;
#define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries #define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries
// Maximum number of simultaneous EAP-TLS negotiations // Maximum number of simultaneous security negotiations
#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL 3 #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 3
#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM 20 #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM 20
#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_LARGE 50 #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 50
/* /*
* Security protocol timer configuration parameters * Security protocol timer configuration parameters
@ -218,4 +232,33 @@ extern uint8_t DEVICE_MIN_SENS;
#define DEFAULT_GTK_MAX_MISMATCH 64 // 64 minutes #define DEFAULT_GTK_MAX_MISMATCH 64 // 64 minutes
#define DEFAULT_GTK_NEW_INSTALL_REQUIRED 80 // 80 percent of GTK lifetime --> 24 days #define DEFAULT_GTK_NEW_INSTALL_REQUIRED 80 // 80 percent of GTK lifetime --> 24 days
/*
* Security protocol initial EAPOL-key parameters
*/
// How long the wait is before the first initial EAPOL-key retry
#define DEFAULT_INITIAL_KEY_RETRY_TIMER 120
#define NONE_INITIAL_KEY_RETRY_TIMER 0
// Small network Default trickle values for sending of initial EAPOL-key
#define SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 360 /* 6 to 8.3 minutes */
#define SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS 500
// Small network Default trickle values for sending of initial EAPOL-key
#define MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 360 /* 6 to 12 minutes */
#define MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS 720
// Large network trickle values for sending of initial EAPOL-key
#define LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 600 /* 10 to 20 minutes */
#define LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS 1200
#define LARGE_NW_INITIAL_KEY_RETRY_COUNT 4
// Very slow network values for sending of initial EAPOL-key
#define EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 600 /* 10 to 20 minutes */
#define EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS 1200
#define EXTRA_LARGE_NW_INITIAL_KEY_RETRY_COUNT 4
// How many times sending of initial EAPOL-key is retried
#define DEFAULT_INITIAL_KEY_RETRY_COUNT 2
#endif /* WS_CONFIG_H_ */ #endif /* WS_CONFIG_H_ */

View File

@ -31,6 +31,7 @@
#include "6LoWPAN/MAC/mpx_api.h" #include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_eapol_pdu.h" #include "6LoWPAN/ws/ws_eapol_pdu.h"
#include "6LoWPAN/ws/ws_llc.h"
#ifdef HAVE_WS #ifdef HAVE_WS
@ -49,6 +50,7 @@ typedef NS_LIST_HEAD(eapol_pdu_msdu_t, link) eapol_pdu_msdu_list_t;
typedef struct { typedef struct {
uint8_t priority; uint8_t priority;
bool filter_requsted: 1;
ws_eapol_pdu_address_check *addr_check; ws_eapol_pdu_address_check *addr_check;
ws_eapol_pdu_receive *receive; ws_eapol_pdu_receive *receive;
ns_list_link_t link; ns_list_link_t link;
@ -147,6 +149,7 @@ int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr,
new_cb->priority = cb_data->priority; new_cb->priority = cb_data->priority;
new_cb->addr_check = cb_data->addr_check; new_cb->addr_check = cb_data->addr_check;
new_cb->receive = cb_data->receive; new_cb->receive = cb_data->receive;
new_cb->filter_requsted = cb_data->filter_requsted;
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) { ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
if (new_cb->priority <= entry->priority) { if (new_cb->priority <= entry->priority) {
@ -307,6 +310,11 @@ static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) { ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
if (entry->addr_check(eapol_pdu_data->interface_ptr, data->SrcAddr) >= 0) { if (entry->addr_check(eapol_pdu_data->interface_ptr, data->SrcAddr) >= 0) {
if (entry->filter_requsted && !ws_llc_eapol_relay_forward_filter(eapol_pdu_data->interface_ptr, data->SrcAddr, data->DSN, data->timestamp)) {
tr_info("EAPOL relay filter drop");
return;
}
entry->receive(eapol_pdu_data->interface_ptr, data->SrcAddr, data->msdu_ptr, data->msduLength); entry->receive(eapol_pdu_data->interface_ptr, data->SrcAddr, data->msdu_ptr, data->msduLength);
break; break;
} }

View File

@ -99,6 +99,7 @@ typedef enum {
typedef struct { typedef struct {
eapol_pdu_recv_prior_t priority; /**< Priority: high, medium or low */ eapol_pdu_recv_prior_t priority; /**< Priority: high, medium or low */
bool filter_requsted: 1; /**< True when EAPOL temporary filter requsted, false for normal functionality */
ws_eapol_pdu_address_check *addr_check; /**< Address check callback */ ws_eapol_pdu_address_check *addr_check; /**< Address check callback */
ws_eapol_pdu_receive *receive; /**< PDU receive callback */ ws_eapol_pdu_receive *receive; /**< PDU receive callback */
} eapol_pdu_recv_cb_data_t; } eapol_pdu_recv_cb_data_t;

View File

@ -53,6 +53,7 @@ static void ws_eapol_relay_socket_cb(void *cb);
static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = { static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
.priority = EAPOL_PDU_RECV_LOW_PRIORITY, .priority = EAPOL_PDU_RECV_LOW_PRIORITY,
.filter_requsted = true,
.addr_check = ws_eapol_relay_eapol_pdu_address_check, .addr_check = ws_eapol_relay_eapol_pdu_address_check,
.receive = ws_eapol_relay_eapol_pdu_receive .receive = ws_eapol_relay_eapol_pdu_receive
}; };

View File

@ -25,6 +25,7 @@
#include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_common.h"
#include "ws_management_api.h" #include "ws_management_api.h"
#include "ns_time_api.h"
#ifndef HAVE_WS #ifndef HAVE_WS
int ws_management_node_init( int ws_management_node_init(
@ -392,4 +393,9 @@ int ws_statistics_stop(int8_t interface_id)
return -1; return -1;
} }
void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callback)
{
(void) callback;
}
#endif // no HAVE_WS #endif // no HAVE_WS

View File

@ -78,11 +78,18 @@ typedef struct llc_neighbour_req {
struct ws_neighbor_class_entry *ws_neighbor; /**< Wi-sun Neighbor information entry. */ struct ws_neighbor_class_entry *ws_neighbor; /**< Wi-sun Neighbor information entry. */
} llc_neighbour_req_t; } llc_neighbour_req_t;
typedef struct eapol_temporary_info_s {
uint8_t eapol_rx_relay_filter; /*!< seconds for dropping duplicate id */
uint8_t last_rx_mac_sequency; /*!< Only compared when Timer is active */
uint16_t eapol_timeout; /*!< EAPOL relay Temporary entry lifetime */
} eapol_temporary_info_t;
/** /**
* Neighbor temporary structure for storage FHSS data before create a real Neighbour info * Neighbor temporary structure for storage FHSS data before create a real Neighbour info
*/ */
typedef struct ws_neighbor_temp_class_s { typedef struct ws_neighbor_temp_class_s {
struct ws_neighbor_class_entry neigh_info_list; /*!< Allocated hopping info array*/ struct ws_neighbor_class_entry neigh_info_list; /*!< Allocated hopping info array*/
eapol_temporary_info_t eapol_temp_info;
uint8_t mac64[8]; uint8_t mac64[8];
uint8_t mpduLinkQuality; uint8_t mpduLinkQuality;
int8_t signal_dbm; int8_t signal_dbm;
@ -217,6 +224,10 @@ void ws_llc_set_pan_information_pointer(struct protocol_interface_info_entry *in
*/ */
void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interface, struct ws_hopping_schedule_s *hopping_schedule); void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interface, struct ws_hopping_schedule_s *hopping_schedule);
void ws_llc_timer_seconds(struct protocol_interface_info_entry *interface, uint16_t seconds_update);
bool ws_llc_eapol_relay_forward_filter(struct protocol_interface_info_entry *interface, const uint8_t *joiner_eui64, uint8_t mac_sequency, uint32_t rx_timestamp);
ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(struct protocol_interface_info_entry *interface, const uint8_t *mac64); ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(struct protocol_interface_info_entry *interface, const uint8_t *mac64);
void ws_llc_free_multicast_temp_entry(struct protocol_interface_info_entry *interface, ws_neighbor_temp_class_t *neighbor); void ws_llc_free_multicast_temp_entry(struct protocol_interface_info_entry *interface, ws_neighbor_temp_class_t *neighbor);

View File

@ -41,9 +41,11 @@ int ws_management_node_init(
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
cur = protocol_stack_interface_info_get_by_id(interface_id); cur = protocol_stack_interface_info_get_by_id(interface_id);
if (interface_id >= 0 && (!cur || !ws_info(cur))) { if (interface_id >= 0 && (!cur || !ws_info(cur))) {
return -1; return -1;
} }
if (!network_name_ptr || !fhss_timer_ptr) { if (!network_name_ptr || !fhss_timer_ptr) {
return -2; return -2;
} }
@ -70,7 +72,9 @@ int ws_management_node_init(
return -4; return -4;
} }
if (cur && ws_info(cur)) {
cur->ws_info->fhss_timer_ptr = fhss_timer_ptr; cur->ws_info->fhss_timer_ptr = fhss_timer_ptr;
}
return 0; return 0;
} }
@ -398,7 +402,7 @@ int ws_management_channel_plan_set(
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
cur = protocol_stack_interface_info_get_by_id(interface_id); cur = protocol_stack_interface_info_get_by_id(interface_id);
if (interface_id >= 0 && (!cur || !ws_info(cur))) { if (!cur || !ws_info(cur)) {
return -1; return -1;
} }
cur->ws_info->hopping_schdule.channel_plan = channel_plan; cur->ws_info->hopping_schdule.channel_plan = channel_plan;

View File

@ -322,5 +322,32 @@ void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor,
return; return;
} }
bool ws_neighbor_class_neighbor_duplicate_packet_check(ws_neighbor_class_entry_t *ws_neighbor, uint8_t mac_dsn, uint32_t rx_timestamp)
{
if (ws_neighbor->last_DSN != mac_dsn) {
// New packet allways accepted
ws_neighbor->last_DSN = mac_dsn;
return true;
}
if (!ws_neighbor->unicast_data_rx) {
// No unicast info stored always accepted
return true;
}
rx_timestamp -= ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp;
rx_timestamp /= 1000000; //Convert to s
//Compare only when last rx timestamp is less than 5 seconds
if (rx_timestamp < 5) {
//Packet is sent too fast filter it out
return false;
}
return true;
}
#endif /* HAVE_WS */ #endif /* HAVE_WS */

View File

@ -28,6 +28,7 @@ typedef struct ws_neighbor_class_entry {
uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/ uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/
uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/ uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/
uint16_t routing_cost; /*!< ETX to border Router. */ uint16_t routing_cost; /*!< ETX to border Router. */
uint8_t last_DSN;
bool candidate_parent: 1; bool candidate_parent: 1;
bool broadcast_timing_info_stored: 1; bool broadcast_timing_info_stored: 1;
bool broadcast_shedule_info_stored: 1; bool broadcast_shedule_info_stored: 1;
@ -181,4 +182,6 @@ void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor,
*/ */
void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported); void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported);
bool ws_neighbor_class_neighbor_duplicate_packet_check(ws_neighbor_class_entry_t *ws_neighbor, uint8_t mac_dsn, uint32_t rx_timestamp);
#endif /* WS_NEIGHBOR_CLASS_H_ */ #endif /* WS_NEIGHBOR_CLASS_H_ */

View File

@ -28,6 +28,7 @@
#include "eventOS_scheduler.h" #include "eventOS_scheduler.h"
#include "eventOS_event_timer.h" #include "eventOS_event_timer.h"
#include "ns_address.h" #include "ns_address.h"
#include "Service_Libs/utils/ns_file.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "Security/protocols/sec_prot_cfg.h" #include "Security/protocols/sec_prot_cfg.h"
@ -46,6 +47,8 @@
#include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_timers.h"
#include "6LoWPAN/ws/ws_pae_auth.h" #include "6LoWPAN/ws/ws_pae_auth.h"
#include "6LoWPAN/ws/ws_pae_lib.h" #include "6LoWPAN/ws/ws_pae_lib.h"
#include "6LoWPAN/ws/ws_pae_time.h"
#include "6LoWPAN/ws/ws_pae_key_storage.h"
#ifdef HAVE_WS #ifdef HAVE_WS
#ifdef HAVE_PAE_AUTH #ifdef HAVE_PAE_AUTH
@ -56,16 +59,18 @@
#define PAE_TASKLET_EVENT 2 #define PAE_TASKLET_EVENT 2
#define PAE_TASKLET_TIMER 3 #define PAE_TASKLET_TIMER 3
// Wait for for supplicant to indicate activity (e.g. to send a message) /* Wait for supplicant to indicate activity (e.g. to send a message) when
#define WAIT_FOR_AUTHENTICATION_TICKS 5 * 60 * 10 // 5 minutes authentication is ongoing */
#define WAIT_FOR_AUTHENTICATION_TICKS 2 * 60 * 10 // 2 minutes
// Wait after authentication has completed before supplicant entry goes inactive
#define WAIT_AFTER_AUTHENTICATION_TICKS 15 * 10 // 15 seconds
/* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how /* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how
long to wait for previous negotiation to complete */ long to wait for previous negotiation to complete */
#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds #define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds
// Default for maximum number of supplicants // Default for maximum number of supplicants
#define SUPPLICANT_MAX_NUMBER 1000 #define SUPPLICANT_MAX_NUMBER 5000
/* Default for number of supplicants to purge per garbage collect call from /* Default for number of supplicants to purge per garbage collect call from
nanostack monitor */ nanostack monitor */
@ -76,21 +81,23 @@
typedef struct { typedef struct {
ns_list_link_t link; /**< Link */ ns_list_link_t link; /**< Link */
uint16_t pan_id; /**< PAN ID */
char network_name[33]; /**< Network name */
kmp_service_t *kmp_service; /**< KMP service */ kmp_service_t *kmp_service; /**< KMP service */
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */ protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
ws_pae_auth_gtk_hash_set *hash_set; /**< GTK hash set callback */ ws_pae_auth_gtk_hash_set *hash_set; /**< GTK hash set callback */
ws_pae_auth_nw_key_insert *nw_key_insert; /**< Key insert callback */ ws_pae_auth_nw_key_insert *nw_key_insert; /**< Key insert callback */
ws_pae_auth_nw_keys_remove *nw_keys_remove; /**< Network keys remove callback */
ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */ ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
supp_list_t active_supp_list; /**< List of active supplicants */ supp_list_t active_supp_list; /**< List of active supplicants */
supp_list_t inactive_supp_list; /**< List of inactive supplicants */
arm_event_storage_t *timer; /**< Timer */ arm_event_storage_t *timer; /**< Timer */
sec_prot_gtk_keys_t *gtks; /**< GTKs */
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
const sec_prot_certs_t *certs; /**< Certificates */ const sec_prot_certs_t *certs; /**< Certificates */
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */ sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */
sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */ sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */
uint16_t supp_max_number; /**< Max number of stored supplicants */ uint16_t supp_max_number; /**< Max number of stored supplicants */
uint16_t slow_timer_seconds; /**< Slow timer seconds */
bool timer_running : 1; /**< Timer is running */ bool timer_running : 1; /**< Timer is running */
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */ bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */ bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */
@ -119,15 +126,15 @@ static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys); static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry); static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry); static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *cfg); static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg);
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp); static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
static int8_t tasklet_id = -1; static int8_t tasklet_id = -1;
static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link); static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link);
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg) int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
{ {
if (!interface_ptr || !gtks || !certs) { if (!interface_ptr || !next_gtks || !certs || !sec_timer_cfg || !sec_prot_cfg || !sec_keys_nw_info) {
return -1; return -1;
} }
@ -140,23 +147,25 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
return -1; return -1;
} }
memset(&pae_auth->network_name, 0, 33);
pae_auth->pan_id = 0xffff;
pae_auth->interface_ptr = interface_ptr; pae_auth->interface_ptr = interface_ptr;
ws_pae_lib_supp_list_init(&pae_auth->active_supp_list); ws_pae_lib_supp_list_init(&pae_auth->active_supp_list);
ws_pae_lib_supp_list_init(&pae_auth->inactive_supp_list);
pae_auth->timer = NULL; pae_auth->timer = NULL;
pae_auth->hash_set = NULL; pae_auth->hash_set = NULL;
pae_auth->nw_key_insert = NULL; pae_auth->nw_key_insert = NULL;
pae_auth->nw_keys_remove = NULL;
pae_auth->nw_key_index_set = NULL; pae_auth->nw_key_index_set = NULL;
pae_auth->gtks = gtks;
pae_auth->next_gtks = next_gtks; pae_auth->next_gtks = next_gtks;
pae_auth->certs = certs; pae_auth->certs = certs;
pae_auth->sec_keys_nw_info = sec_keys_nw_info;
pae_auth->sec_timer_cfg = sec_timer_cfg; pae_auth->sec_timer_cfg = sec_timer_cfg;
pae_auth->sec_prot_cfg = sec_prot_cfg; pae_auth->sec_prot_cfg = sec_prot_cfg;
pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER;
pae_auth->slow_timer_seconds = 0;
pae_auth->gtk_new_inst_req_exp = false; pae_auth->gtk_new_inst_req_exp = false;
pae_auth->gtk_new_act_time_exp = false; pae_auth->gtk_new_act_time_exp = false;
@ -254,7 +263,7 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr)
return 0; return 0;
} }
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set) void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated)
{ {
if (!interface_ptr) { if (!interface_ptr) {
return; return;
@ -268,6 +277,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
pae_auth->hash_set = hash_set; pae_auth->hash_set = hash_set;
pae_auth->nw_key_insert = nw_key_insert; pae_auth->nw_key_insert = nw_key_insert;
pae_auth->nw_key_index_set = nw_key_index_set; pae_auth->nw_key_index_set = nw_key_index_set;
pae_auth->nw_info_updated = nw_info_updated;
} }
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr) void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
@ -282,15 +292,17 @@ void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
} }
// Checks if there is predefined active key // Checks if there is predefined active key
int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->sec_keys_nw_info->gtks);
if (index < 0) { if (index < 0) {
// If there is no key, inserts a new one // If there is no key, inserts a new one
ws_pae_auth_gtk_key_insert(pae_auth); ws_pae_auth_gtk_key_insert(pae_auth);
index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->gtks); index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->sec_keys_nw_info->gtks);
ws_pae_auth_active_gtk_set(pae_auth, index); ws_pae_auth_active_gtk_set(pae_auth, index);
} else { } else {
ws_pae_auth_active_gtk_set(pae_auth, index); ws_pae_auth_active_gtk_set(pae_auth, index);
} }
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
// Inserts keys and updates GTK hash on stack // Inserts keys and updates GTK hash on stack
ws_pae_auth_network_keys_from_gtks_set(pae_auth); ws_pae_auth_network_keys_from_gtks_set(pae_auth);
@ -331,13 +343,15 @@ int8_t ws_pae_auth_nw_key_index_update(protocol_interface_info_entry_t *interfac
int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64) int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
{ {
int8_t ret_value = -1;
if (!interface_ptr) { if (!interface_ptr) {
return -1; return ret_value;
} }
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
if (!pae_auth) { if (!pae_auth) {
return -1; return ret_value;
} }
// Checks if supplicant is active // Checks if supplicant is active
@ -348,20 +362,16 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p
sec_prot_keys_pmk_delete(&supp->sec_keys); sec_prot_keys_pmk_delete(&supp->sec_keys);
sec_prot_keys_ptk_delete(&supp->sec_keys); sec_prot_keys_ptk_delete(&supp->sec_keys);
supp->access_revoked = true; supp->access_revoked = true;
tr_info("Access revoked; keys removed, eui-64: %s", trace_array(supp->addr.eui_64, 8)); tr_info("Access revoked; keys removed, eui-64: %s", trace_array(eui_64, 8));
return 0; ret_value = 0;
} }
// Checks if supplicant is inactive if (ws_pae_key_storage_supp_delete(pae_auth, eui_64)) {
supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, eui_64); tr_info("Access revoked; key store deleted, eui-64: %s", trace_array(eui_64, 8));
if (supp) { ret_value = 0;
// Deletes supplicant
tr_info("Access revoked; deleted, eui-64: %s", trace_array(supp->addr.eui_64, 8));
ws_pae_lib_supp_list_remove(&pae_auth->inactive_supp_list, supp);
return 0;
} }
return -1; return ret_value;
} }
int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr) int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr)
@ -376,7 +386,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
} }
// Gets active GTK // Gets active GTK
int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->sec_keys_nw_info->gtks);
if (active_index >= 0) { if (active_index >= 0) {
// As default removes other keys than active // As default removes other keys than active
@ -384,22 +394,24 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->sec_timer_cfg); uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->sec_timer_cfg);
uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, active_index); uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, active_index);
uint64_t current_time = ws_pae_current_time_get();
// If active GTK lifetime is larger than revocation lifetime decrements active GTK lifetime // If active GTK lifetime is larger than revocation lifetime decrements active GTK lifetime
if (active_lifetime > revocation_lifetime) { if (active_lifetime > revocation_lifetime) {
sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, active_index, active_lifetime - revocation_lifetime); sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, active_index, current_time, active_lifetime - revocation_lifetime);
tr_info("Access revocation start, GTK active index: %i, revoked lifetime: %"PRIu32"", active_index, revocation_lifetime); tr_info("Access revocation start, GTK active index: %i, revoked lifetime: %"PRIu32"", active_index, revocation_lifetime);
} else { } else {
// Otherwise decrements lifetime of the GTK to be installed after the active one // Otherwise decrements lifetime of the GTK to be installed after the active one
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->sec_keys_nw_info->gtks);
if (second_index >= 0) { if (second_index >= 0) {
// Second GTK revocation lifetime is the active GTK lifetime added with revocation time // Second GTK revocation lifetime is the active GTK lifetime added with revocation time
uint32_t second_revocation_lifetime = active_lifetime + revocation_lifetime; uint32_t second_revocation_lifetime = active_lifetime + revocation_lifetime;
uint32_t second_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, second_index); uint32_t second_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, second_index);
if (second_lifetime > second_revocation_lifetime) { if (second_lifetime > second_revocation_lifetime) {
sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, second_index, second_lifetime - second_revocation_lifetime); sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, second_index, current_time, second_lifetime - second_revocation_lifetime);
tr_info("Access revocation start, GTK second active index: %i, revoked lifetime: %"PRIu32"", second_index, second_revocation_lifetime); tr_info("Access revocation start, GTK second active index: %i, revoked lifetime: %"PRIu32"", second_index, second_revocation_lifetime);
} }
// Removes other keys than active and GTK to be installed next // Removes other keys than active and GTK to be installed next
@ -408,11 +420,11 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
} }
// Deletes other GTKs // Deletes other GTKs
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->sec_keys_nw_info->gtks);
while (last_index >= 0 && last_index != not_removed_index) { while (last_index >= 0 && last_index != not_removed_index) {
tr_info("Access revocation GTK clear index: %i", last_index); tr_info("Access revocation GTK clear index: %i", last_index);
sec_prot_keys_gtk_clear(pae_auth->gtks, last_index); sec_prot_keys_gtk_clear(pae_auth->sec_keys_nw_info->gtks, last_index);
last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->sec_keys_nw_info->gtks);
} }
} }
@ -420,6 +432,9 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
ws_pae_auth_gtk_key_insert(pae_auth); ws_pae_auth_gtk_key_insert(pae_auth);
ws_pae_auth_network_keys_from_gtks_set(pae_auth); ws_pae_auth_network_keys_from_gtks_set(pae_auth);
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
return 0; return 0;
} }
@ -452,22 +467,69 @@ void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr)
/* Purge in maximum five entries from supplicant list (starting from oldest one) /* Purge in maximum five entries from supplicant list (starting from oldest one)
per call to the function (called by nanostack monitor) */ per call to the function (called by nanostack monitor) */
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE); ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE);
}
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
{
if (!interface_ptr || !network_name) {
return -1;
}
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
if (!pae_auth) {
return -1;
}
// On authenticator pan_id is always selected locally and is always valid for keys
if (pae_auth->sec_keys_nw_info->key_pan_id != pan_id) {
pae_auth->sec_keys_nw_info->key_pan_id = pan_id;
pae_auth->sec_keys_nw_info->updated = true;
}
bool update_keys = false;
if (pae_auth->pan_id != 0xffff && pae_auth->pan_id != pan_id) {
update_keys = true;
}
pae_auth->pan_id = pan_id;
if (strlen((char *) &pae_auth->network_name) > 0 && strcmp((char *) &pae_auth->network_name, network_name) != 0) {
update_keys = true;
}
strcpy((char *) &pae_auth->network_name, network_name);
if (!update_keys) {
return 0;
}
if (pae_auth->nw_keys_remove) {
pae_auth->nw_keys_remove(pae_auth->interface_ptr);
}
ws_pae_auth_network_keys_from_gtks_set(pae_auth);
int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->sec_keys_nw_info->gtks);
if (index >= 0) {
// Sets active key index
ws_pae_auth_network_key_index_set(pae_auth, index);
}
return 0;
} }
static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth) static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth)
{ {
// Authenticator keys are always fresh // Authenticator keys are always fresh
sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks); sec_prot_keys_gtk_status_all_fresh_set(pae_auth->sec_keys_nw_info->gtks);
if (pae_auth->hash_set) { if (pae_auth->hash_set) {
uint8_t gtk_hash[32]; uint8_t gtk_hash[32];
sec_prot_keys_gtks_hash_generate(pae_auth->gtks, gtk_hash); sec_prot_keys_gtks_hash_generate(pae_auth->sec_keys_nw_info->gtks, gtk_hash);
pae_auth->hash_set(pae_auth->interface_ptr, gtk_hash); pae_auth->hash_set(pae_auth->interface_ptr, gtk_hash);
} }
if (pae_auth->nw_key_insert) { if (pae_auth->nw_key_insert) {
pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->gtks); pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->sec_keys_nw_info->gtks);
} }
return 0; return 0;
@ -475,12 +537,12 @@ static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth)
static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index) static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index)
{ {
return sec_prot_keys_gtk_status_active_set(pae_auth->gtks, index); return sec_prot_keys_gtk_status_active_set(pae_auth->sec_keys_nw_info->gtks, index);
} }
static int8_t ws_pae_auth_gtk_clear(pae_auth_t *pae_auth, uint8_t index) static int8_t ws_pae_auth_gtk_clear(pae_auth_t *pae_auth, uint8_t index)
{ {
return sec_prot_keys_gtk_clear(pae_auth->gtks, index); return sec_prot_keys_gtk_clear(pae_auth->sec_keys_nw_info->gtks, index);
} }
static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index) static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index)
@ -499,7 +561,6 @@ static void ws_pae_auth_free(pae_auth_t *pae_auth)
} }
ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list); ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list);
ws_pae_lib_supp_list_delete(&pae_auth->inactive_supp_list);
kmp_socket_if_unregister(pae_auth->kmp_service); kmp_socket_if_unregister(pae_auth->kmp_service);
@ -582,7 +643,7 @@ void ws_pae_auth_fast_timer(uint16_t ticks)
} }
// Updates KMP timers // Updates KMP timers
bool running = ws_pae_lib_supp_list_timer_update(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, ticks, kmp_service_timer_if_timeout); bool running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->active_supp_list, ticks, kmp_service_timer_if_timeout);
if (!running) { if (!running) {
ws_pae_auth_timer_stop(pae_auth); ws_pae_auth_timer_stop(pae_auth);
} }
@ -594,22 +655,26 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) { ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) {
// Gets index of currently active GTK // Gets index of currently active GTK
int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->sec_keys_nw_info->gtks);
uint64_t current_time = ws_pae_current_time_get();
for (uint8_t i = 0; i < GTK_NUM; i++) { for (uint8_t i = 0; i < GTK_NUM; i++) {
if (!sec_prot_keys_gtk_is_set(pae_auth->gtks, i)) { if (!sec_prot_keys_gtk_is_set(pae_auth->sec_keys_nw_info->gtks, i)) {
continue; continue;
} }
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, i, seconds); uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds);
if (active_index == i) { if (active_index == i) {
if (!pae_auth->gtk_new_inst_req_exp) { if (!pae_auth->gtk_new_inst_req_exp) {
pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_timer_cfg, timer_seconds); pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_timer_cfg, timer_seconds);
if (pae_auth->gtk_new_inst_req_exp) { if (pae_auth->gtk_new_inst_req_exp) {
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->sec_keys_nw_info->gtks);
if (second_index < 0) { if (second_index < 0) {
tr_info("GTK new install required active index: %i, time: %"PRIu32", system time: %"PRIu32"", active_index, timer_seconds, protocol_core_monotonic_time / 10); tr_info("GTK new install required active index: %i, time: %"PRIu32", system time: %"PRIu32"", active_index, timer_seconds, protocol_core_monotonic_time / 10);
ws_pae_auth_gtk_key_insert(pae_auth); ws_pae_auth_gtk_key_insert(pae_auth);
ws_pae_auth_network_keys_from_gtks_set(pae_auth); ws_pae_auth_network_keys_from_gtks_set(pae_auth);
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
} else { } else {
tr_info("GTK new install already done; second index: %i, time: %"PRIu32", system time: %"PRIu32"", second_index, timer_seconds, protocol_core_monotonic_time / 10); tr_info("GTK new install already done; second index: %i, time: %"PRIu32", system time: %"PRIu32"", second_index, timer_seconds, protocol_core_monotonic_time / 10);
} }
@ -626,6 +691,8 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
} }
pae_auth->gtk_new_inst_req_exp = false; pae_auth->gtk_new_inst_req_exp = false;
pae_auth->gtk_new_act_time_exp = false; pae_auth->gtk_new_act_time_exp = false;
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
} }
} }
} }
@ -634,22 +701,22 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
tr_info("GTK expired index: %i, system time: %"PRIu32"", i, protocol_core_monotonic_time / 10); tr_info("GTK expired index: %i, system time: %"PRIu32"", i, protocol_core_monotonic_time / 10);
ws_pae_auth_gtk_clear(pae_auth, i); ws_pae_auth_gtk_clear(pae_auth, i);
ws_pae_auth_network_keys_from_gtks_set(pae_auth); ws_pae_auth_network_keys_from_gtks_set(pae_auth);
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
} }
} }
pae_auth->slow_timer_seconds += seconds; ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, seconds);
if (pae_auth->slow_timer_seconds > 60) {
ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, pae_auth->sec_timer_cfg, pae_auth->slow_timer_seconds);
ws_pae_lib_supp_list_slow_timer_update(&pae_auth->inactive_supp_list, pae_auth->sec_timer_cfg, pae_auth->slow_timer_seconds);
pae_auth->slow_timer_seconds = 0;
}
} }
// Update key storage timer
ws_pae_key_storage_timer(seconds);
} }
static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth) static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth)
{ {
// Gets index to install the key // Gets index to install the key
uint8_t install_index = sec_prot_keys_gtk_install_index_get(pae_auth->gtks); uint8_t install_index = sec_prot_keys_gtk_install_index_get(pae_auth->sec_keys_nw_info->gtks);
// Key to install // Key to install
uint8_t gtk_value[GTK_LEN]; uint8_t gtk_value[GTK_LEN];
@ -671,24 +738,24 @@ static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth)
// Gets latest installed key lifetime and adds GTK expire offset to it // Gets latest installed key lifetime and adds GTK expire offset to it
uint32_t lifetime = pae_auth->sec_timer_cfg->gtk_expire_offset; uint32_t lifetime = pae_auth->sec_timer_cfg->gtk_expire_offset;
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->sec_keys_nw_info->gtks);
if (last_index >= 0) { if (last_index >= 0) {
lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, last_index); lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, last_index);
} }
// Installs the new key // Installs the new key
sec_prot_keys_gtk_clear(pae_auth->gtks, install_index); sec_prot_keys_gtk_clear(pae_auth->sec_keys_nw_info->gtks, install_index);
sec_prot_keys_gtk_set(pae_auth->gtks, install_index, gtk_value, lifetime); sec_prot_keys_gtk_set(pae_auth->sec_keys_nw_info->gtks, install_index, gtk_value, lifetime);
// Authenticator keys are always fresh // Authenticator keys are always fresh
sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks); sec_prot_keys_gtk_status_all_fresh_set(pae_auth->sec_keys_nw_info->gtks);
tr_info("GTK install new index: %i, lifetime: %"PRIu32" system time: %"PRIu32"", install_index, lifetime, protocol_core_monotonic_time / 10); tr_info("GTK install new index: %i, lifetime: %"PRIu32" system time: %"PRIu32"", install_index, lifetime, protocol_core_monotonic_time / 10);
} }
static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth) static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth)
{ {
int8_t new_active_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); int8_t new_active_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->sec_keys_nw_info->gtks);
if (new_active_index >= 0) { if (new_active_index >= 0) {
ws_pae_auth_active_gtk_set(pae_auth, new_active_index); ws_pae_auth_active_gtk_set(pae_auth, new_active_index);
} }
@ -717,8 +784,6 @@ static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
return -1; return -1;
} }
ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry);
ws_pae_lib_kmp_timer_start(&supp_entry->kmp_list, entry); ws_pae_lib_kmp_timer_start(&supp_entry->kmp_list, entry);
return 0; return 0;
} }
@ -798,26 +863,27 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr)); supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr));
if (!supp_entry) { if (!supp_entry) {
// Find supplicant from list of inactive supplicants // Checks if active supplicant list has space for new supplicants
supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, kmp_address_eui_64_get(addr)); if (ws_pae_lib_supp_list_active_limit_reached(&pae_auth->active_supp_list, pae_auth->sec_prot_cfg->sec_max_ongoing_authentication)) {
tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8));
return NULL;
}
// Find supplicant from key storage
supp_entry = ws_pae_key_storage_supp_read(pae_auth, kmp_address_eui_64_get(addr), pae_auth->sec_keys_nw_info->gtks, pae_auth->certs);
if (supp_entry) { if (supp_entry) {
// Move supplicant to active list // Move supplicant to active list
ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry); tr_debug("PAE: to active, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
ns_list_add_to_start(&pae_auth->active_supp_list, supp_entry);
} }
} }
// If does not exists add it to list // If does not exists add it to list
if (!supp_entry) { if (!supp_entry) {
// Checks if maximum number of supplicants is reached and purge supplicant list (starting from oldest one)
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, pae_auth->supp_max_number, 0);
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr); supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr);
if (!supp_entry) { if (!supp_entry) {
return 0; return 0;
} }
sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->gtks, pae_auth->certs); sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->sec_keys_nw_info->gtks, pae_auth->certs);
// Fixes the address of the supplicant to keys
sec_prot_keys_ptk_eui_64_write(&supp_entry->sec_keys, kmp_address_eui_64_get(addr));
} else { } else {
// Updates relay address // Updates relay address
kmp_address_copy(&supp_entry->addr, addr); kmp_address_copy(&supp_entry->addr, addr);
@ -833,7 +899,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
} }
// Create a new KMP for initial eapol-key // Create a new KMP for initial eapol-key
kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY, pae_auth->sec_prot_cfg); kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg);
if (!kmp) { if (!kmp) {
return 0; return 0;
@ -913,10 +979,11 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
kmp_type_e next_type = ws_pae_auth_next_protocol_get(pae_auth, supp_entry); kmp_type_e next_type = ws_pae_auth_next_protocol_get(pae_auth, supp_entry);
if (next_type == KMP_TYPE_NONE) { if (next_type == KMP_TYPE_NONE) {
// Supplicant goes inactive after 15 seconds
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_AFTER_AUTHENTICATION_TICKS);
// All done // All done
return; return;
} else { } else {
kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type); kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type);
if (api != NULL) { if (api != NULL) {
/* For other types than GTK, only one ongoing negotiation at the same time, /* For other types than GTK, only one ongoing negotiation at the same time,
@ -947,7 +1014,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
} }
// Create new instance // Create new instance
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry, pae_auth->sec_prot_cfg); kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg);
if (!new_kmp) { if (!new_kmp) {
return; return;
} }
@ -960,7 +1027,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
return; return;
} }
// Create TLS instance */ // Create TLS instance */
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry, pae_auth->sec_prot_cfg) == NULL) { if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg) == NULL) {
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp); ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
return; return;
} }
@ -1027,11 +1094,10 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
return next_type; return next_type;
} }
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg)
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *cfg)
{ {
// Create KMP instance for new authentication // Create KMP instance for new authentication
kmp_api_t *kmp = kmp_api_create(service, type, cfg); kmp_api_t *kmp = kmp_api_create(service, type, prot_cfg, timer_cfg);
if (!kmp) { if (!kmp) {
return NULL; return NULL;
@ -1084,7 +1150,6 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8)); tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8));
ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp); ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp);
} }
} }
#endif /* HAVE_PAE_AUTH */ #endif /* HAVE_PAE_AUTH */

View File

@ -43,18 +43,18 @@
* \param local_port local port * \param local_port local port
* \param remote_addr remote address * \param remote_addr remote address
* \param remote_port remote port * \param remote_port remote port
* \param gtks group keys
* \param next_gtks next group keys to be used * \param next_gtks next group keys to be used
* \param cert_chain certificate chain * \param cert_chain certificate chain
* \param timer_settings timer settings * \param timer_settings timer settings
* \param sec_timer_cfg timer configuration * \param sec_timer_cfg timer configuration
* \param sec_prot_cfg protocol configuration * \param sec_prot_cfg protocol configuration
* \param sec_keys_nw_info security keys network information
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg); int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
/** /**
* ws_pae_auth_addresses_set set relay addresses * ws_pae_auth_addresses_set set relay addresses
@ -168,6 +168,19 @@ int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr
*/ */
void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr); void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr);
/**
* ws_pae_auth_nw_info_set set network information
*
* \param interface_ptr interface
* \param pan_id PAD ID
* \param network_name network name
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
/** /**
* ws_pae_auth_gtk_hash_set GTK hash set callback * ws_pae_auth_gtk_hash_set GTK hash set callback
* *
@ -189,6 +202,14 @@ typedef void ws_pae_auth_gtk_hash_set(protocol_interface_info_entry_t *interface
*/ */
typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
/**
* ws_pae_auth_nw_keys_remove remove network keys callback
*
* \param interface_ptr interface
*
*/
typedef void ws_pae_auth_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr);
/** /**
* ws_pae_auth_nw_key_index_set network send key index set callback * ws_pae_auth_nw_key_index_set network send key index set callback
* *
@ -198,6 +219,14 @@ typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interf
*/ */
typedef void ws_pae_auth_nw_key_index_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index); typedef void ws_pae_auth_nw_key_index_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
/**
* ws_pae_auth_nw_info_updated security keys network information updated
*
* \param interface_ptr interface
*
*/
typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interface_ptr);
/** /**
* ws_pae_auth_cb_register register PAE authenticator callbacks * ws_pae_auth_cb_register register PAE authenticator callbacks
* *
@ -205,9 +234,10 @@ typedef void ws_pae_auth_nw_key_index_set(protocol_interface_info_entry_t *inter
* \param hash_set GTK hash set callback * \param hash_set GTK hash set callback
* \param nw_key_insert network key index callback * \param nw_key_insert network key index callback
* \param nw_key_index_set network send key index callback * \param nw_key_index_set network send key index callback
* \param nw_info_updated network keys updated callback
* *
*/ */
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set); void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated);
#else #else
@ -215,10 +245,11 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
#define ws_pae_auth_timing_adjust(timing) #define ws_pae_auth_timing_adjust(timing)
#define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1 #define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1
#define ws_pae_auth_delete NULL #define ws_pae_auth_delete NULL
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set) {(void) hash_set;} #define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated) {(void) hash_set;}
#define ws_pae_auth_start(interface_ptr) #define ws_pae_auth_start(interface_ptr)
#define ws_pae_auth_gtks_updated NULL #define ws_pae_auth_gtks_updated NULL
#define ws_pae_auth_nw_key_index_update NULL #define ws_pae_auth_nw_key_index_update NULL
#define ws_pae_auth_nw_info_set NULL
#define ws_pae_auth_node_keys_remove(interface_ptr, eui64) -1 #define ws_pae_auth_node_keys_remove(interface_ptr, eui64) -1
#define ws_pae_auth_node_access_revoke_start(interface_ptr) #define ws_pae_auth_node_access_revoke_start(interface_ptr)
#define ws_pae_auth_node_limit_set(interface_ptr, limit) #define ws_pae_auth_node_limit_set(interface_ptr, limit)

View File

@ -24,6 +24,7 @@
#include "fhss_config.h" #include "fhss_config.h"
#include "ns_address.h" #include "ns_address.h"
#include "ws_management_api.h" #include "ws_management_api.h"
#include "Service_Libs/utils/ns_file.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_cfg_settings.h"
@ -36,6 +37,8 @@
#include "6LoWPAN/ws/ws_pae_auth.h" #include "6LoWPAN/ws/ws_pae_auth.h"
#include "6LoWPAN/ws/ws_pae_nvm_store.h" #include "6LoWPAN/ws/ws_pae_nvm_store.h"
#include "6LoWPAN/ws/ws_pae_nvm_data.h" #include "6LoWPAN/ws/ws_pae_nvm_data.h"
#include "6LoWPAN/ws/ws_pae_time.h"
#include "6LoWPAN/ws/ws_pae_key_storage.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#ifdef HAVE_WS #ifdef HAVE_WS
@ -49,6 +52,7 @@ typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_pt
typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr); typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index); typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
typedef int8_t ws_pae_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
typedef struct { typedef struct {
uint8_t gtk[GTK_LEN]; /**< GTK key */ uint8_t gtk[GTK_LEN]; /**< GTK key */
@ -63,15 +67,17 @@ typedef struct {
uint8_t br_eui_64[8]; /**< Border router EUI-64 */ uint8_t br_eui_64[8]; /**< Border router EUI-64 */
sec_prot_gtk_keys_t gtks; /**< GTKs */ sec_prot_gtk_keys_t gtks; /**< GTKs */
sec_prot_gtk_keys_t next_gtks; /**< Next GTKs */ sec_prot_gtk_keys_t next_gtks; /**< Next GTKs */
sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */
int8_t gtk_index; /**< GTK index */ int8_t gtk_index; /**< GTK index */
uint8_t gtkhash[32]; /**< GTK hashes */ uint8_t gtkhash[32]; /**< GTK hashes */
sec_prot_certs_t certs; /**< Certificates */ sec_prot_certs_t certs; /**< Certificates */
nw_key_t nw_key[GTK_NUM]; /**< Currently active network keys (on MAC) */ nw_key_t nw_key[GTK_NUM]; /**< Currently active network keys (on MAC) */
char *network_name; /**< Network name for GAK generation */ uint16_t frame_cnt_store_timer; /**< Timer to check if storing of frame counter value is needed */
uint16_t frame_cnt_store_timer; /**< Timer for storing frame counter value */ uint32_t frame_cnt_store_force_timer; /**< Timer to force storing of frame counter, if no other updates */
frame_counters_t frame_counters; /**< Frame counters */ frame_counters_t frame_counters; /**< Frame counters */
sec_timer_cfg_t sec_timer_cfg; /**< Timer configuration (configuration set values) */ sec_timer_cfg_t sec_timer_cfg; /**< Timer configuration (configuration set values) */
sec_prot_cfg_t sec_prot_cfg; /**< Configuration */ sec_prot_cfg_t sec_prot_cfg; /**< Configuration */
uint32_t restart_cnt; /**< Re-start counter */
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */ protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */ ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
ws_pae_controller_nw_key_set *nw_key_set; /**< Key set callback */ ws_pae_controller_nw_key_set *nw_key_set; /**< Key set callback */
@ -80,6 +86,8 @@ typedef struct {
ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set; /**< Frame counter set callback */ ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set; /**< Frame counter set callback */
ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read; /**< Frame counter read callback */ ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read; /**< Frame counter read callback */
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */ ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */
ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */
ws_pae_delete *pae_delete; /**< PAE delete callback */ ws_pae_delete *pae_delete; /**< PAE delete callback */
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */ ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */ ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */
@ -88,7 +96,8 @@ typedef struct {
ws_pae_gtks_updated *pae_gtks_updated; /**< PAE GTKs updated */ ws_pae_gtks_updated *pae_gtks_updated; /**< PAE GTKs updated */
ws_pae_gtk_hash_update *pae_gtk_hash_update; /**< PAE GTK HASH update */ ws_pae_gtk_hash_update *pae_gtk_hash_update; /**< PAE GTK HASH update */
ws_pae_nw_key_index_update *pae_nw_key_index_update; /**< PAE NW key index update */ ws_pae_nw_key_index_update *pae_nw_key_index_update; /**< PAE NW key index update */
nvm_tlv_entry_t *pae_nvm_buffer; /**< Buffer For PAE NVM write operation*/ ws_pae_nw_info_set *pae_nw_info_set; /**< PAE security key network info set */
uint8_t pae_nvm_buffer[PAE_NVM_DEFAULT_BUFFER_SIZE]; /**< Buffer for PAE NVM read and write operations */
bool gtks_set : 1; /**< GTKs are set */ bool gtks_set : 1; /**< GTKs are set */
bool gtkhash_set : 1; /**< GTK hashes are set */ bool gtkhash_set : 1; /**< GTK hashes are set */
bool key_index_set : 1; /**< NW key index is set */ bool key_index_set : 1; /**< NW key index is set */
@ -101,12 +110,14 @@ typedef struct {
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */ bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
} pae_controller_config_t; } pae_controller_config_t;
static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks);
static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr);
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr); static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry); static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry); static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry);
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold); static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold);
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry); static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry);
static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters); static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters);
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id); static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
@ -114,12 +125,19 @@ static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key);
static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index); static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index);
static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name); static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name);
static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr, pae_controller_t *controller, bool use_threshold); static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr, pae_controller_t *controller, bool use_threshold);
#ifdef HAVE_PAE_AUTH
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index); static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
#endif
static void ws_pae_controller_data_init(pae_controller_t *controller); static void ws_pae_controller_data_init(pae_controller_t *controller);
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller); static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller);
static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters); static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters);
static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks);
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, sec_prot_gtk_keys_t *gtks);
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, sec_prot_gtk_keys_t *gtks);
static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME; static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
static const char *NW_INFO_FILE = NW_INFO_FILE_NAME;
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link); static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
@ -129,26 +147,6 @@ pae_controller_config_t pae_controller_config = {
.ext_cert_valid_enabled = false .ext_cert_valid_enabled = false
}; };
#if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks)
{
uint8_t gtk[GTK_LEN];
// Test data
for (int i = 0; i < GTK_LEN; i++) {
gtk[i] = 0xcf - i;
}
sec_prot_keys_gtk_set(gtks, 0, gtk, GTK_DEFAULT_LIFETIME);
}
#else
#define ws_pae_controller_test_keys_set(gtks);
#endif
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr) int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
{ {
pae_controller_t *controller = ws_pae_controller_get(interface_ptr); pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -168,16 +166,9 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface
return 0; return 0;
} }
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) < 0) { if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64, controller->sec_keys_nw_info.network_name) < 0) {
controller->auth_completed(interface_ptr, AUTH_RESULT_ERR_UNSPEC, controller->target_eui_64); controller->auth_completed(interface_ptr, AUTH_RESULT_ERR_UNSPEC, controller->target_eui_64);
} }
#else
ws_pae_controller_test_keys_set(&controller->gtks);
ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
controller->auth_completed(interface_ptr, AUTH_RESULT_OK);
#endif #endif
return 0; return 0;
@ -216,20 +207,6 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
return -1; return -1;
} }
#ifdef HAVE_PAE_AUTH
if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
ws_pae_auth_gtks_updated(interface_ptr);
if (controller->gtk_index >= 0) {
controller->pae_nw_key_index_update(interface_ptr, controller->gtk_index);
}
sec_prot_keys_gtks_updated_reset(&controller->gtks);
}
#else
ws_pae_controller_test_keys_set(&controller->gtks);
ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
#endif
if (ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) < 0) { if (ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) < 0) {
return -1; return -1;
} }
@ -238,14 +215,14 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit); ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
} }
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set); ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check);
ws_pae_auth_start(interface_ptr); ws_pae_auth_start(interface_ptr);
return 0; return 0;
} }
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment) int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated)
{ {
if (!interface_ptr) { if (!interface_ptr) {
return -1; return -1;
@ -263,7 +240,8 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
controller->nw_frame_counter_set = nw_frame_counter_set; controller->nw_frame_counter_set = nw_frame_counter_set;
controller->nw_frame_counter_read = nw_frame_counter_read; controller->nw_frame_counter_read = nw_frame_counter_read;
controller->pan_ver_increment = pan_ver_increment; controller->pan_ver_increment = pan_ver_increment;
controller->nw_info_updated = nw_info_updated;
controller->auth_next_target = auth_next_target;
return 0; return 0;
} }
@ -284,6 +262,20 @@ int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_p
return 0; return 0;
} }
static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks)
{
if (!sec_keys_nw_info) {
return;
}
memset(sec_keys_nw_info, 0, sizeof(sec_prot_keys_nw_info_t));
sec_keys_nw_info->gtks = gtks;
sec_keys_nw_info->new_pan_id = 0xFFFF;
sec_keys_nw_info->key_pan_id = 0xFFFF;
sec_keys_nw_info->updated = false;
}
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name) int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
{ {
(void) pan_id; (void) pan_id;
@ -298,12 +290,44 @@ int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_
return -1; return -1;
} }
controller->network_name = network_name; // Network name has been modified
if (network_name && strncmp(controller->sec_keys_nw_info.network_name, network_name, 33) != 0) {
strncpy(controller->sec_keys_nw_info.network_name, network_name, 32);
controller->sec_keys_nw_info.updated = true;
}
return ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name); // PAN ID has been modified
if (pan_id != 0xffff && pan_id != controller->sec_keys_nw_info.new_pan_id) {
controller->sec_keys_nw_info.new_pan_id = pan_id;
controller->sec_keys_nw_info.updated = true;
}
if (controller->pae_nw_info_set) {
controller->pae_nw_info_set(interface_ptr, pan_id, network_name);
}
return 0;
} }
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr) static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr)
{
if (!interface_ptr) {
return;
}
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
if (!controller) {
return;
}
if (controller->sec_keys_nw_info.updated || sec_prot_keys_gtks_are_updated(controller->sec_keys_nw_info.gtks)) {
ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, controller->sec_keys_nw_info.gtks);
controller->sec_keys_nw_info.updated = false;
sec_prot_keys_gtks_updated_reset(controller->sec_keys_nw_info.gtks);
}
}
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
{ {
if (!interface_ptr) { if (!interface_ptr) {
return -1; return -1;
@ -314,7 +338,7 @@ int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface
return -1; return -1;
} }
return ws_pae_supp_nw_key_valid(interface_ptr); return ws_pae_supp_nw_key_valid(interface_ptr, br_iid);
} }
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks) static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
@ -366,21 +390,21 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_
sec_prot_keys_gtk_hash_generate(gtk, gtkhash); sec_prot_keys_gtk_hash_generate(gtk, gtkhash);
tr_info("NW key set: %i, hash: %s", i, trace_array(gtkhash, 8)); tr_info("NW key set: %i, hash: %s", i, trace_array(gtkhash, 8));
uint8_t gak[GTK_LEN]; uint8_t gak[GTK_LEN];
if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) { if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->sec_keys_nw_info.network_name) >= 0) {
// Install the new network key derived from GTK and network name (GAK) to MAC // Install the new network key derived from GTK and network name (GAK) to MAC
controller->nw_key_set(interface_ptr, i, i, gak); controller->nw_key_set(interface_ptr, i, i, gak);
nw_key[i].installed = true; nw_key[i].installed = true;
ret = 0; ret = 0;
#ifdef EXTRA_DEBUG_INFO #ifdef EXTRA_DEBUG_INFO
tr_info("NW name: %s", controller->network_name); tr_info("NW name: %s", controller->sec_keys_nw_info.network_name);
size_t nw_name_len = strlen(controller->network_name); size_t nw_name_len = strlen(controller->sec_keys_nw_info.network_name);
tr_info("NW name: %s", trace_array((uint8_t *)controller->network_name, nw_name_len)); tr_info("NW name: %s", trace_array((uint8_t *)controller->sec_keys_nw_info.network_name, nw_name_len));
tr_info("GTK: %s", trace_array(gtk, 16)); tr_info("GTK: %s", trace_array(gtk, 16));
tr_info("GAK: %s", trace_array(gak, 16)); tr_info("GAK: %s", trace_array(gak, 16));
#endif #endif
} else { } else {
tr_error("GAK generation failed network name: %s", controller->network_name); tr_error("GAK generation failed network name: %s", controller->sec_keys_nw_info.network_name);
continue; continue;
} }
@ -512,6 +536,7 @@ static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_in
} }
} }
#ifdef HAVE_PAE_AUTH
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index) static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
{ {
pae_controller_t *controller = ws_pae_controller_get(interface_ptr); pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -534,6 +559,7 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info
controller->key_index_set = true; controller->key_index_set = true;
} }
} }
#endif
static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index) static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index)
{ {
@ -564,11 +590,9 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
} }
pae_controller_t *controller = ns_dyn_mem_alloc(sizeof(pae_controller_t)); pae_controller_t *controller = ns_dyn_mem_alloc(sizeof(pae_controller_t));
void *pae_nvm_buffer = ws_pae_buffer_allocate();
if (!controller || !pae_nvm_buffer) { if (!controller) {
ns_dyn_mem_free(controller); ns_dyn_mem_free(controller);
ns_dyn_mem_free(pae_nvm_buffer);
return -1; return -1;
} }
@ -579,7 +603,9 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
controller->nw_send_key_index_set = NULL; controller->nw_send_key_index_set = NULL;
controller->nw_frame_counter_set = NULL; controller->nw_frame_counter_set = NULL;
controller->pan_ver_increment = NULL; controller->pan_ver_increment = NULL;
controller->pae_nvm_buffer = pae_nvm_buffer; controller->nw_info_updated = NULL;
controller->auth_next_target = NULL;
memset(&controller->sec_timer_cfg, 0, sizeof(ws_sec_timer_cfg_t)); memset(&controller->sec_timer_cfg, 0, sizeof(ws_sec_timer_cfg_t));
memset(&controller->sec_prot_cfg, 0, sizeof(sec_prot_cfg_t)); memset(&controller->sec_prot_cfg, 0, sizeof(sec_prot_cfg_t));
@ -603,7 +629,15 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
controller->sec_prot_cfg.sec_prot_trickle_params.k = 0; controller->sec_prot_cfg.sec_prot_trickle_params.k = 0;
controller->sec_prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp; controller->sec_prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp;
controller->sec_prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10; controller->sec_prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10;
controller->sec_prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication; controller->sec_prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication;
controller->sec_prot_cfg.initial_key_retry_delay = sec_prot_cfg->initial_key_retry_delay;
controller->sec_prot_cfg.initial_key_trickle_params.Imin = sec_prot_cfg->initial_key_imin;
controller->sec_prot_cfg.initial_key_trickle_params.Imax = sec_prot_cfg->initial_key_imax;
controller->sec_prot_cfg.initial_key_trickle_params.k = 0;
controller->sec_prot_cfg.initial_key_trickle_params.TimerExpirations = 2;
controller->sec_prot_cfg.initial_key_retry_cnt = sec_prot_cfg->initial_key_retry_cnt;
} }
if (sec_timer_cfg) { if (sec_timer_cfg) {
@ -613,7 +647,6 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
return 0; return 0;
} }
static void ws_pae_controller_data_init(pae_controller_t *controller) static void ws_pae_controller_data_init(pae_controller_t *controller)
{ {
memset(controller->target_eui_64, 0, 8); memset(controller->target_eui_64, 0, 8);
@ -634,29 +667,43 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
controller->pae_gtks_updated = NULL; controller->pae_gtks_updated = NULL;
controller->pae_gtk_hash_update = NULL; controller->pae_gtk_hash_update = NULL;
controller->pae_nw_key_index_update = NULL; controller->pae_nw_key_index_update = NULL;
controller->pae_nw_info_set = NULL;
controller->gtks_set = false; controller->gtks_set = false;
controller->gtkhash_set = false; controller->gtkhash_set = false;
controller->key_index_set = false; controller->key_index_set = false;
controller->frame_counter_read = false; controller->frame_counter_read = false;
controller->gtk_index = -1; controller->gtk_index = -1;
controller->network_name = NULL;
controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL; controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
controller->frame_cnt_store_force_timer = FRAME_COUNTER_STORE_FORCE_INTERVAL;
controller->restart_cnt = 0;
ws_pae_controller_frame_counter_reset(&controller->frame_counters); ws_pae_controller_frame_counter_reset(&controller->frame_counters);
sec_prot_keys_gtks_init(&controller->gtks); sec_prot_keys_gtks_init(&controller->gtks);
sec_prot_keys_gtks_init(&controller->next_gtks); sec_prot_keys_gtks_init(&controller->next_gtks);
sec_prot_certs_init(&controller->certs); sec_prot_certs_init(&controller->certs);
sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled); sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled);
ws_pae_controller_keys_nw_info_init(&controller->sec_keys_nw_info, &controller->gtks);
} }
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller) static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
{ {
int8_t ret_value = 0;
if (controller->frame_counter_read) { if (controller->frame_counter_read) {
return; return ret_value;
} }
controller->frame_counter_read = true; controller->frame_counter_read = true;
uint64_t stored_time = 0;
// Read frame counters // Read frame counters
if (ws_pae_controller_nvm_frame_counter_read(&controller->frame_counters) >= 0) { if (ws_pae_controller_nvm_frame_counter_read(&controller->restart_cnt, &stored_time, &controller->frame_counters) >= 0) {
// Current time is not valid
if (ws_pae_current_time_set(stored_time) < 0) {
ret_value = -1;
}
// This is used to ensure that PMK replay counters are fresh after each re-start.
controller->restart_cnt++;
bool updated = false; bool updated = false;
// Checks frame counters // Checks frame counters
for (uint8_t index = 0; index < GTK_NUM; index++) { for (uint8_t index = 0; index < GTK_NUM; index++) {
@ -673,10 +720,12 @@ static void ws_pae_controller_frame_counter_read(pae_controller_t *controller)
} }
if (updated) { if (updated) {
// Writes incremented frame counters // Writes incremented frame counters
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, &controller->frame_counters); ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &controller->pae_nvm_buffer, controller->restart_cnt, &controller->frame_counters);
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer); ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &controller->pae_nvm_buffer);
} }
} }
return ret_value;
} }
static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters) static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters)
@ -689,6 +738,53 @@ static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counte
} }
} }
static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks)
{
if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtks) < 0) {
// If no stored GTKs and network info (pan_id and network name) exits
return -1;
}
// Sets also new pan_id used for pan_id set by bootstrap
controller->sec_keys_nw_info.new_pan_id = controller->sec_keys_nw_info.key_pan_id;
return 0;
}
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, sec_prot_gtk_keys_t *gtks)
{
nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(interface_ptr);
if (!tlv) {
return -1;
}
ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtks);
ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, tlv);
return 0;
}
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, sec_prot_gtk_keys_t *gtks)
{
nvm_tlv_t *tlv_entry = ws_pae_controller_nvm_tlv_get(interface_ptr);
if (!tlv_entry) {
return -1;
}
ws_pae_nvm_store_generic_tlv_create(tlv_entry, PAE_NVM_NW_INFO_TAG, PAE_NVM_NW_INFO_LEN);
if (ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, tlv_entry) < 0) {
return -1;
}
if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtks) < 0) {
return -1;
}
return 0;
}
int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr) int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr)
{ {
pae_controller_t *controller = ws_pae_controller_get(interface_ptr); pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -696,7 +792,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
return -1; return -1;
} }
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg) < 0) { if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg, &controller->sec_keys_nw_info) < 0) {
return -1; return -1;
} }
@ -707,10 +803,14 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read; controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update; controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update;
controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update; controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
controller->pae_nw_info_set = NULL;
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get); ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->auth_next_target, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get, ws_pae_controller_nw_info_updated_check);
ws_pae_controller_frame_counter_read(controller); ws_pae_controller_frame_counter_read(controller);
ws_pae_controller_nw_info_read(controller, controller->sec_keys_nw_info.gtks);
// Set active key back to fresh so that it can be used again after re-start
sec_prot_keys_gtk_status_active_to_fresh_set(&controller->gtks);
return 0; return 0;
} }
@ -722,7 +822,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
return -1; return -1;
} }
if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->next_gtks, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg) < 0) { if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg, &controller->sec_keys_nw_info) < 0) {
return -1; return -1;
} }
@ -731,8 +831,45 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
controller->pae_slow_timer = ws_pae_auth_slow_timer; controller->pae_slow_timer = ws_pae_auth_slow_timer;
controller->pae_gtks_updated = ws_pae_auth_gtks_updated; controller->pae_gtks_updated = ws_pae_auth_gtks_updated;
controller->pae_nw_key_index_update = ws_pae_auth_nw_key_index_update; controller->pae_nw_key_index_update = ws_pae_auth_nw_key_index_update;
controller->pae_nw_info_set = ws_pae_auth_nw_info_set;
ws_pae_controller_frame_counter_read(controller); sec_prot_gtk_keys_t *read_gtks_to = controller->sec_keys_nw_info.gtks;
if (ws_pae_controller_frame_counter_read(controller) < 0) {
tr_error("Stored key material invalid");
// Key material invalid, do not read GTKs or any other security data
read_gtks_to = NULL;
}
#ifdef HAVE_PAE_AUTH
if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
// If application has set GTK keys prepare those for use
ws_pae_auth_gtks_updated(interface_ptr);
if (controller->gtk_index >= 0) {
controller->pae_nw_key_index_update(interface_ptr, controller->gtk_index);
}
sec_prot_keys_gtks_updated_reset(&controller->gtks);
}
#endif
if (ws_pae_controller_nw_info_read(controller, read_gtks_to) >= 0) {
/* If network information i.e pan_id and network name exists updates bootstrap with it,
(in case already configured by application then no changes are made) */
if (controller->nw_info_updated) {
controller->nw_info_updated(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name);
}
if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) {
// Key material invalid or GTKs are expired, delete GTKs from NVM
ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, NULL);
}
}
ws_pae_key_storage_init();
if (read_gtks_to) {
ws_pae_key_storage_read(controller->restart_cnt);
} else {
// Key material invalid, delete key storage
ws_pae_key_storage_remove();
}
return 0; return 0;
} }
@ -747,6 +884,15 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
// Stores frame counters and removes network keys from PAE controller and MAC // Stores frame counters and removes network keys from PAE controller and MAC
ws_pae_controller_frame_counter_store_and_nw_keys_remove(interface_ptr, controller, false); ws_pae_controller_frame_counter_store_and_nw_keys_remove(interface_ptr, controller, false);
// Store security key network info if it has been modified
ws_pae_controller_nw_info_updated_check(interface_ptr);
// Store key storage if it has been modified
ws_pae_key_storage_store();
// Delete key storage
ws_pae_key_storage_delete();
// If PAE has been initialized, deletes it // If PAE has been initialized, deletes it
if (controller->pae_delete) { if (controller->pae_delete) {
controller->pae_delete(interface_ptr); controller->pae_delete(interface_ptr);
@ -775,7 +921,6 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
} }
ns_list_remove(&pae_controller_list, controller); ns_list_remove(&pae_controller_list, controller);
ns_dyn_mem_free(controller->pae_nvm_buffer);
ns_dyn_mem_free(controller); ns_dyn_mem_free(controller);
return 0; return 0;
@ -1028,6 +1173,10 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
} }
} }
// Sets active key
int8_t index = sec_prot_keys_gtk_install_order_first_index_get(&controller->gtks);
sec_prot_keys_gtk_status_active_set(&controller->gtks, index);
// Notifies PAE authenticator that GTKs have been updated */ // Notifies PAE authenticator that GTKs have been updated */
if (controller->pae_gtks_updated) { if (controller->pae_gtks_updated) {
controller->pae_gtks_updated(controller->interface_ptr); controller->pae_gtks_updated(controller->interface_ptr);
@ -1234,6 +1383,13 @@ static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controll
entry->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL; entry->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
ws_pae_controller_frame_counter_store(entry, true); ws_pae_controller_frame_counter_store(entry, true);
} }
if (entry->frame_cnt_store_force_timer > seconds) {
entry->frame_cnt_store_force_timer -= seconds;
} else {
entry->frame_cnt_store_force_timer = 0;
ws_pae_controller_frame_counter_store(entry, true);
}
} }
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry) static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry)
@ -1287,33 +1443,38 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool
} }
} }
if (update_needed) { if (update_needed || entry->frame_cnt_store_force_timer == 0) {
tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10); tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
// Writes modified frame counters // Writes modified frame counters
ws_pae_nvm_store_frame_counter_tlv_create(entry->pae_nvm_buffer, &entry->frame_counters); ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, &entry->frame_counters);
ws_pae_controller_nvm_frame_counter_write(entry->pae_nvm_buffer); ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &entry->pae_nvm_buffer);
// Reset force interval when ever values are stored
entry->frame_cnt_store_force_timer = FRAME_COUNTER_STORE_FORCE_INTERVAL;
} }
} }
static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters) static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters)
{ {
nvm_tlv_list_t tlv_list; nvm_tlv_t *tlv = ws_pae_nvm_store_generic_tlv_allocate_and_create(
ns_list_init(&tlv_list); PAE_NVM_FRAME_COUNTER_TAG, PAE_NVM_FRAME_COUNTER_LEN);
if (!tlv) {
if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, &tlv_list) < 0) {
return -1; return -1;
} }
int8_t result = -1; if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, tlv) < 0) {
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) { ws_pae_nvm_store_generic_tlv_free(tlv);
if (ws_pae_nvm_store_frame_counter_tlv_read(entry, counters) >= 0) { return -1;
result = 0;
}
ns_list_remove(&tlv_list, entry);
ns_dyn_mem_free(entry);
} }
return result; if (ws_pae_nvm_store_frame_counter_tlv_read(tlv, restart_cnt, stored_time, counters) < 0) {
ws_pae_nvm_store_generic_tlv_free(tlv);
return -1;
}
ws_pae_nvm_store_generic_tlv_free(tlv);
return 0;
} }
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr) static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr)
@ -1346,22 +1507,19 @@ static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id)
return controller; return controller;
} }
nvm_tlv_entry_t *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr) nvm_tlv_t *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr)
{ {
pae_controller_t *controller = ws_pae_controller_get(interface_ptr); pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
if (!controller) { if (!controller) {
return NULL; return NULL;
} }
return controller->pae_nvm_buffer; return (nvm_tlv_t *) &controller->pae_nvm_buffer;
} }
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry) static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry)
{ {
nvm_tlv_list_t tlv_list; ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, tlv_entry);
ns_list_init(&tlv_list);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, &tlv_list);
} }

View File

@ -249,12 +249,13 @@ int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_
* ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap * ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap
* *
* \param interface_ptr interface * \param interface_ptr interface
* \param br_iid border router IID for which the keys are valid
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr); int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid);
/** /**
* ws_pae_controller_border_router_addr_write write border router address * ws_pae_controller_border_router_addr_write write border router address
@ -278,7 +279,7 @@ int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64); int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *iid);
/** /**
* ws_pae_controller_gtk_update update GTKs (test interface) * ws_pae_controller_gtk_update update GTKs (test interface)
@ -492,6 +493,18 @@ typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_ent
*/ */
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64); typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64);
/**
* ws_pae_controller_auth_next_target get next target to attempt authentication
*
* \param interface_ptr interface
* \param previous_eui_64 EUI-64 of previous target
* \param pan_id pan id
*
* \return EUI-64 of the next target or previous target if new one not available
*
*/
typedef const uint8_t *ws_pae_controller_auth_next_target(protocol_interface_info_entry_t *interface_ptr, const uint8_t *previous_eui_64, uint16_t *pan_id);
/** /**
* ws_pae_controller_pan_ver_increment PAN version increment callback * ws_pae_controller_pan_ver_increment PAN version increment callback
* *
@ -500,23 +513,35 @@ typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *i
*/ */
typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t *interface_ptr); typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t *interface_ptr);
/**
* ws_pae_controller_nw_info_updated network information is updated (read from memory)
*
* \param interface_ptr interface
* \param pan_id PAN ID
* \param network_name network name
*
*/
typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
/** /**
* ws_pae_controller_cb_register register PEA controller callbacks * ws_pae_controller_cb_register register PEA controller callbacks
* *
* \param interface_ptr interface * \param interface_ptr interface
* \param completed authentication completed callback * \param completed authentication completed callback
* \param next_target authentication next target callback
* \param nw_key_set network key set callback * \param nw_key_set network key set callback
* \param nw_key_clear network key clear callback * \param nw_key_clear network key clear callback
* \param nw_send_key_index_set network send key index set callback * \param nw_send_key_index_set network send key index set callback
* \param nw_frame_counter_set network frame counter set callback * \param nw_frame_counter_set network frame counter set callback
* \param nw_frame_counter_read network frame counter read callback * \param nw_frame_counter_read network frame counter read callback
* \param pan_ver_increment PAN version increment callback * \param pan_ver_increment PAN version increment callback
* \param nw_info_updated network information updated callback
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment); int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
/** /**
* ws_pae_controller_fast_timer PAE controller fast timer call * ws_pae_controller_fast_timer PAE controller fast timer call
@ -534,7 +559,7 @@ void ws_pae_controller_fast_timer(uint16_t ticks);
*/ */
void ws_pae_controller_slow_timer(uint16_t seconds); void ws_pae_controller_slow_timer(uint16_t seconds);
struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr); struct nvm_tlv *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr);
/** /**
* ws_pae_controller_forced_gc PAE controller garbage cleanup callback * ws_pae_controller_forced_gc PAE controller garbage cleanup callback

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2020, 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 WS_PAE_KEY_STORAGE_H_
#define WS_PAE_KEY_STORAGE_H_
/*
* Port access entity key storage functions.
*
*/
// Number of storages i.e. records in NVM
#define DEFAULT_NUMBER_OF_STORAGES 50
// Number of entries stored in a storage i.e. one record in NVM
#define DEFAULT_NUMBER_OF_ENTRIES_IN_ONE_STORAGE 100
// Interval to check if storage has been modified and needs to be updated to NVM
#define DEFAULT_STORING_INTERVAL 3600
struct supp_entry_s;
struct sec_prot_gtk_keys_s;
struct sec_prot_certs_s;
/**
* ws_pae_key_storage_memory_set sets memory used for key storages
*
* This functions can be used to set memory used by key storage. When memory areas
* are set, module does not allocate memory internally from heap.
*
* \param key_storages_number number of memory areas
* \param key_storage_size array of memory area sizes
* \param key_storages array of memory area start pointers
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_key_storage_memory_set(uint8_t key_storages_number, const uint16_t *key_storage_size, void **key_storages);
/**
* ws_pae_key_storage_memory_set sets key storage settings
*
* Allocation max number and allocation size sets the settings that are used when key storage
* memory is allocated dynamically from heap. These settings must be set before (first) interface
* up and shall not be set if key storage memory is set by ws_pae_key_storage_memory_set() call.
*
* \param alloc_max_number maximum number of allocation made to dynamic memory
* \param alloc_size size of each allocation
* \param storing_interval interval in which the check to store to NVM is made
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_key_storage_settings_set(uint8_t alloc_max_number, uint16_t alloc_size, uint16_t storing_interval);
/**
* ws_pae_key_storage_init init key storage
*
*/
void ws_pae_key_storage_init(void);
/**
* ws_pae_key_storage_init delete key storage
*
*/
void ws_pae_key_storage_delete(void);
/**
* ws_pae_key_storage_store store to NVM
*
* Checks whether key storage data has been updated and stores to NVM.
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_key_storage_store(void);
/**
* ws_pae_key_storage_read read from NVM
*
* Reads key storage data from NVM.
*
*/
void ws_pae_key_storage_read(uint32_t restart_cnt);
/**
* ws_pae_key_storage_remove remove storage from NVM
*
* Removes key storage data from NVM.
*
*/
void ws_pae_key_storage_remove(void);
/**
* ws_pae_key_storage_supp_write writes supplicant entry to key storage
*
* \param instance instance
* \param pae_supp supplicant entry
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_key_storage_supp_write(const void *instance, struct supp_entry_s *pae_supp);
/**
* ws_pae_key_storage_supp_read reads supplicant entry from key storage
*
* \param instance instance
* \param eui_64 EUI-64 of the supplicant
* \param gtks GTK keys
* \param cert_chain certificates
*
* \return supplicant entry or NULL if supplicant entry does not exits
*
*/
struct supp_entry_s *ws_pae_key_storage_supp_read(const void *instance, const uint8_t *eui_64, struct sec_prot_gtk_keys_s *gtks, const struct sec_prot_certs_s *certs);
/**
* ws_pae_key_storage_supp_delete delete supplicant entry from key storage
*
* \param instance instance
* \param eui_64 EUI-64 of the supplicant
*
* \return true entry was deleted
* \return false entry was not deleted
*
*/
bool ws_pae_key_storage_supp_delete(const void *instance, const uint8_t *eui64);
/**
* ws_pae_key_storage_timer key storage timers
*
* \param seconds Seconds passed
*
*/
void ws_pae_key_storage_timer(uint16_t seconds);
/**
* ws_pae_key_storage_storing_interval_get gets key storage storing interval
*
* \return storing interval in seconds
*
*/
uint16_t ws_pae_key_storage_storing_interval_get(void);
#endif /* WS_PAE_KEY_STORAGE_H_ */

View File

@ -26,13 +26,14 @@
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_pae_timers.h"
#include "Security/protocols/sec_prot_cfg.h" #include "Security/protocols/sec_prot_cfg.h"
#include "6LoWPAN/ws/ws_pae_timers.h"
#include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_addr.h"
#include "Security/kmp/kmp_api.h" #include "Security/kmp/kmp_api.h"
#include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/sec_prot_certs.h"
#include "Security/protocols/sec_prot_keys.h" #include "Security/protocols/sec_prot_keys.h"
#include "6LoWPAN/ws/ws_pae_lib.h" #include "6LoWPAN/ws/ws_pae_lib.h"
#include "6LoWPAN/ws/ws_pae_key_storage.h"
#ifdef HAVE_WS #ifdef HAVE_WS
@ -126,6 +127,16 @@ kmp_entry_t *ws_pae_lib_kmp_list_entry_get(kmp_list_t *kmp_list, kmp_api_t *kmp)
return 0; return 0;
} }
bool ws_pae_lib_kmp_list_empty(kmp_list_t *kmp_list)
{
return ns_list_is_empty(kmp_list);
}
uint8_t ws_pae_lib_kmp_list_count(kmp_list_t *kmp_list)
{
return ns_list_count(kmp_list);
}
void ws_pae_lib_kmp_timer_start(kmp_list_t *kmp_list, kmp_entry_t *entry) void ws_pae_lib_kmp_timer_start(kmp_list_t *kmp_list, kmp_entry_t *entry)
{ {
if (ns_list_get_first(kmp_list) != entry) { if (ns_list_get_first(kmp_list) != entry) {
@ -171,7 +182,7 @@ void ws_pae_lib_supp_list_init(supp_list_t *supp_list)
supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr) supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr)
{ {
supp_entry_t *entry = ns_dyn_mem_alloc(sizeof(supp_entry_t)); supp_entry_t *entry = ns_dyn_mem_temporary_alloc(sizeof(supp_entry_t));
if (!entry) { if (!entry) {
return NULL; return NULL;
@ -215,33 +226,32 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list)
} }
} }
bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout) bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
{ {
bool timer_running = false; bool timer_running = false;
ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) { ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) {
bool running = ws_pae_lib_supp_timer_update(entry, ticks, timeout); bool running = ws_pae_lib_supp_timer_update(instance, entry, ticks, timeout);
if (running) { if (running) {
timer_running = true; timer_running = true;
} else { } else {
ws_pae_lib_supp_list_to_inactive(active_supp_list, inactive_supp_list, entry); ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry);
} }
} }
return timer_running; return timer_running;
} }
void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, sec_timer_cfg_t *timer_settings, uint16_t seconds) void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, uint16_t seconds)
{ {
ns_list_foreach(supp_entry_t, entry, supp_list) { ns_list_foreach(supp_entry_t, entry, supp_list) {
if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, timer_settings->pmk_lifetime, seconds)) { if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, seconds)) {
tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10); tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
} }
if (sec_prot_keys_ptk_lifetime_decrement(&entry->sec_keys, timer_settings->ptk_lifetime, seconds)) { if (sec_prot_keys_ptk_lifetime_decrement(&entry->sec_keys, seconds)) {
tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10); tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
} }
} }
} }
void ws_pae_lib_supp_init(supp_entry_t *entry) void ws_pae_lib_supp_init(supp_entry_t *entry)
@ -251,6 +261,7 @@ void ws_pae_lib_supp_init(supp_entry_t *entry)
memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t)); memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
entry->ticks = 0; entry->ticks = 0;
entry->retry_ticks = 0; entry->retry_ticks = 0;
entry->store_ticks = ws_pae_key_storage_storing_interval_get() * 1000;
entry->active = true; entry->active = true;
entry->access_revoked = false; entry->access_revoked = false;
} }
@ -260,7 +271,7 @@ void ws_pae_lib_supp_delete(supp_entry_t *entry)
ws_pae_lib_kmp_list_free(&entry->kmp_list); ws_pae_lib_kmp_list_free(&entry->kmp_list);
} }
bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout) bool ws_pae_lib_supp_timer_update(void *instance, supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
{ {
// Updates KMP timers and calls timeout callback // Updates KMP timers and calls timeout callback
bool keep_timer_running = ws_pae_lib_kmp_timer_update(&entry->kmp_list, ticks, timeout); bool keep_timer_running = ws_pae_lib_kmp_timer_update(&entry->kmp_list, ticks, timeout);
@ -286,6 +297,19 @@ bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_li
entry->retry_ticks = 0; entry->retry_ticks = 0;
} }
if (!instance) {
return keep_timer_running;
}
// Updates retry timer
if (entry->store_ticks > ticks) {
entry->store_ticks -= ticks;
} else {
tr_info("PAE active entry key storage update timeout");
ws_pae_key_storage_supp_write(instance, entry);
entry->store_ticks = ws_pae_key_storage_storing_interval_get() * 1000;
}
return keep_timer_running; return keep_timer_running;
} }
@ -326,7 +350,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
entry->addr.type = KMP_ADDR_EUI_64_AND_IP; entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
} }
void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry) void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry)
{ {
if (!entry->active) { if (!entry->active) {
return; return;
@ -340,34 +364,28 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
return; return;
} }
ns_list_remove(active_supp_list, entry); // Store to key storage
ns_list_add_to_start(inactive_supp_list, entry); ws_pae_key_storage_supp_write(instance, entry);
entry->active = false; // Remove supplicant entry
entry->ticks = 0; ws_pae_lib_supp_list_remove(active_supp_list, entry);
// Removes relay address data
entry->addr.type = KMP_ADDR_EUI_64;
entry->addr.port = 0;
memset(entry->addr.relay_address, 0, 16);
} }
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge) void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge)
{ {
uint16_t active_supp = ns_list_count(active_supp_list); uint16_t active_supp = ns_list_count(active_supp_list);
uint16_t inactive_supp = ns_list_count(inactive_supp_list);
if (active_supp + inactive_supp > max_number) { if (active_supp > max_number) {
uint16_t remove_count = active_supp + inactive_supp - max_number; uint16_t remove_count = active_supp - max_number;
if (max_purge > 0 && remove_count > max_purge) { if (max_purge > 0 && remove_count > max_purge) {
remove_count = max_purge; remove_count = max_purge;
} }
// Remove entries from inactive list // Remove entries from active list if there are no active KMPs ongoing for the entry
ns_list_foreach_safe(supp_entry_t, entry, inactive_supp_list) { ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) {
if (remove_count > 0) { if (remove_count > 0 && ws_pae_lib_kmp_list_empty(&entry->kmp_list)) {
tr_info("Inactive supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8)); tr_info("Active supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8));
ws_pae_lib_supp_list_remove(inactive_supp_list, entry); ws_pae_lib_supp_list_remove(active_supp_list, entry);
remove_count--; remove_count--;
} else { } else {
break; break;
@ -376,6 +394,16 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inac
} }
} }
bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number)
{
uint16_t active_supp = ns_list_count(active_supp_list);
if (active_supp > max_number) {
return true;
}
return false;
}
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type) uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
{ {
uint16_t kmp_count = 0; uint16_t kmp_count = 0;

View File

@ -31,12 +31,13 @@ typedef struct {
typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t; typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t;
typedef struct { typedef struct supp_entry_s {
kmp_list_t kmp_list; /**< Ongoing KMP negotiations */ kmp_list_t kmp_list; /**< Ongoing KMP negotiations */
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */ kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
sec_prot_keys_t sec_keys; /**< Security keys */ sec_prot_keys_t sec_keys; /**< Security keys */
uint32_t ticks; /**< Ticks */ uint32_t ticks; /**< Ticks */
uint16_t retry_ticks; /**< Retry ticks */ uint16_t retry_ticks; /**< Retry ticks */
uint16_t store_ticks; /**< NVM store ticks */
bool active : 1; /**< Is active */ bool active : 1; /**< Is active */
bool access_revoked : 1; /**< Nodes access is revoked */ bool access_revoked : 1; /**< Nodes access is revoked */
ns_list_link_t link; /**< Link */ ns_list_link_t link; /**< Link */
@ -123,6 +124,27 @@ kmp_api_t *ws_pae_lib_kmp_list_instance_id_get(kmp_list_t *kmp_list, uint8_t ins
*/ */
kmp_entry_t *ws_pae_lib_kmp_list_entry_get(kmp_list_t *kmp_list, kmp_api_t *kmp); kmp_entry_t *ws_pae_lib_kmp_list_entry_get(kmp_list_t *kmp_list, kmp_api_t *kmp);
/**
* ws_pae_lib_kmp_list_empty checks whether KMP list is empty
*
* \param kmp_list KMP list
*
* \return true list is empty
* \return false list is not empty
*
*/
bool ws_pae_lib_kmp_list_empty(kmp_list_t *kmp_list);
/**
* ws_pae_lib_kmp_list_count counts entries on KMP list
*
* \param kmp_list KMP list
*
* \return count of entries on the list
*
*/
uint8_t ws_pae_lib_kmp_list_count(kmp_list_t *kmp_list);
/** /**
* ws_pae_lib_kmp_timer_start starts KMP timer * ws_pae_lib_kmp_timer_start starts KMP timer
* *
@ -215,6 +237,7 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list);
/** /**
* ws_pae_lib_supp_list_timer_update updates timers on supplicant list * ws_pae_lib_supp_list_timer_update updates timers on supplicant list
* *
* \param instance Instance
* \param active_supp_list list of active supplicants * \param active_supp_list list of active supplicants
* \param inactive_supp_list list of inactive supplicants * \param inactive_supp_list list of inactive supplicants
* \param ticks timer ticks * \param ticks timer ticks
@ -223,17 +246,16 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list);
* \return true timer needs still to be running * \return true timer needs still to be running
* \return false timer can be stopped * \return false timer can be stopped
*/ */
bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout); bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
/** /**
* ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list * ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list
* *
* \param supp_list list of supplicants * \param supp_list list of supplicants
* \param timer_settings timer settings
* \param seconds seconds * \param seconds seconds
* *
*/ */
void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, sec_timer_cfg_t *timer_settings, uint16_t seconds); void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, uint16_t seconds);
/** /**
* ws_pae_lib_supp_list_timer_update updates supplicant timers * ws_pae_lib_supp_list_timer_update updates supplicant timers
@ -245,7 +267,7 @@ void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, sec_timer_cf
* \return true timer needs still to be running * \return true timer needs still to be running
* \return false timer can be stopped * \return false timer can be stopped
*/ */
bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout); bool ws_pae_lib_supp_timer_update(void *instance, supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
/** /**
* ws_pae_lib_supp_init initiates supplicant entry * ws_pae_lib_supp_init initiates supplicant entry
@ -304,24 +326,34 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
/** /**
* ws_pae_lib_supp_list_to_inactive move supplicant to inactive supplicants list * ws_pae_lib_supp_list_to_inactive move supplicant to inactive supplicants list
* *
* \param instance Instance
* \param active_supp_list list of active supplicants * \param active_supp_list list of active supplicants
* \param inactive_supp_list list of inactive supplicants
* \param entry supplicant entry * \param entry supplicant entry
* *
*/ */
void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry); void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry);
/** /**
* ws_pae_lib_supp_list_purge purge inactive supplicants list * ws_pae_lib_supp_list_purge purge inactive supplicants list
* *
* \param active_supp_list list of active supplicants * \param active_supp_list list of active supplicants
* \param inactive_supp_list list of inactive supplicants
* \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge * \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge
* to free list entries even when maximum number supplicant entries has not been reached * to free list entries even when maximum number supplicant entries has not been reached
* \param max_purge maximum number of supplicants to purge in one call, 0 means not limited * \param max_purge maximum number of supplicants to purge in one call, 0 means not limited
* *
*/ */
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge); void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge);
/**
* ws_pae_lib_supp_list_limit_reached_check check if active supplicant list limit has been reached
*
* \param active_supp_list list of active supplicants
* \param max_number maximum number of supplicant entries
*
* \return true limit has been reached
* \return false limit has not been reached
*/
bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number);
/** /**
* ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants * ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants

View File

@ -24,38 +24,50 @@
#include "common_functions.h" #include "common_functions.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "ns_file_system.h" #include "ns_file_system.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Service_Libs/utils/ns_file.h"
#include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/sec_prot_certs.h"
#include "Security/protocols/sec_prot_keys.h" #include "Security/protocols/sec_prot_keys.h"
#include "6LoWPAN/ws/ws_pae_nvm_store.h" #include "6LoWPAN/ws/ws_pae_nvm_store.h"
#include "6LoWPAN/ws/ws_pae_nvm_data.h" #include "6LoWPAN/ws/ws_pae_nvm_data.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_pae_time.h"
#ifdef HAVE_WS #ifdef HAVE_WS
#define TRACE_GROUP "wsnv" #define TRACE_GROUP "wsnv"
#define PAE_NVM_NW_INFO_TAG 1
#define PAE_NVM_KEYS_TAG 2
#define PAE_NVM_FRAME_COUNTER_TAG 3
// pan_id (2) + network name (33) + (GTK set (1) + GTK lifetime (4) + GTK (16)) * 4
#define PAE_NVM_NW_INFO_LEN 2 + 33 + (1 + 4 + GTK_LEN) * GTK_NUM
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK (48)
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + PMK_LEN + 8 + 1 + PTK_LEN
// (frame counter set (1) + GTK (16) + frame counter (4)) * 4
#define PAE_NVM_FRAME_COUNTER_LEN (1 + GTK_LEN + 4) * GTK_NUM
#define PAE_NVM_FIELD_NOT_SET 0 // Field is not present #define PAE_NVM_FIELD_NOT_SET 0 // Field is not present
#define PAE_NVM_FIELD_SET 1 // Field is present #define PAE_NVM_FIELD_SET 1 // Field is present
nvm_tlv_entry_t *ws_pae_buffer_allocate(void) void ws_pae_nvm_store_generic_tlv_create(nvm_tlv_t *tlv_entry, uint16_t tag, uint16_t length)
{ {
//Allocate worts case buffer tlv_entry->tag = tag;
return ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + PAE_NVM_NW_INFO_LEN); tlv_entry->len = length;
} }
void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) nvm_tlv_t *ws_pae_nvm_store_generic_tlv_allocate_and_create(uint16_t tag, uint16_t length)
{
nvm_tlv_t *tlv_entry = ns_dyn_mem_alloc(length + sizeof(nvm_tlv_t));
if (!tlv_entry) {
return NULL;
}
tlv_entry->tag = tag;
tlv_entry->len = length;
return tlv_entry;
}
void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry)
{
if (!tlv_entry) {
return;
}
ns_dyn_mem_free(tlv_entry);
}
void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
{ {
int len; int len;
tlv_entry->tag = PAE_NVM_NW_INFO_TAG; tlv_entry->tag = PAE_NVM_NW_INFO_TAG;
@ -75,19 +87,31 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa
memcpy((char *)tlv, nw_name, len); memcpy((char *)tlv, nw_name, len);
tlv += 33; tlv += 33;
uint64_t current_time = ws_pae_current_time_get();
for (uint8_t i = 0; i < GTK_NUM; i++) { for (uint8_t i = 0; i < GTK_NUM; i++) {
if (sec_prot_keys_gtk_is_set(gtks, i)) { if (gtks && sec_prot_keys_gtk_is_set(gtks, i)) {
*tlv++ = PAE_NVM_FIELD_SET; // GTK is set *tlv++ = PAE_NVM_FIELD_SET; // GTK is set
uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
tlv = common_write_32_bit(lifetime, tlv); uint64_t expirytime = sec_prot_keys_gtk_exptime_from_lifetime_get(gtks, i, current_time);
// Sets stored expiration time to GTKs; no need to update anymore to NVM if not changed
sec_prot_keys_gtk_expirytime_set(gtks, i, expirytime);
tlv = common_write_64_bit(expirytime, tlv);
uint8_t status = sec_prot_keys_gtk_status_get(gtks, i);
*tlv++ = status;
uint8_t install_order = sec_prot_keys_gtk_install_order_get(gtks, i);
*tlv++ = install_order;
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i); uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
memcpy(tlv, gtk, GTK_LEN); memcpy(tlv, gtk, GTK_LEN);
tlv += GTK_LEN; tlv += GTK_LEN;
} else { } else {
*tlv++ = PAE_NVM_FIELD_NOT_SET; // GTK is not set *tlv++ = PAE_NVM_FIELD_NOT_SET; // GTK is not set
memset(tlv, 0, 4 + GTK_LEN); memset(tlv, 0, 8 + 1 + 1 + GTK_LEN);
tlv += 4 + GTK_LEN; tlv += 8 + 1 + 1 + GTK_LEN;
} }
} }
@ -95,9 +119,9 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa
} }
int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
{ {
if (!tlv_entry || !pan_id || !nw_name || !gtks) { if (!tlv_entry || !pan_id || !nw_name) {
return -1; return -1;
} }
@ -107,31 +131,60 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *p
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
if (*pan_id == 0xffff) {
// If application has not set pan_id read it from NVM
*pan_id = common_read_16_bit(tlv); *pan_id = common_read_16_bit(tlv);
}
tlv += 2; tlv += 2;
if (strlen(nw_name) == 0) {
// If application has not set network name read it from NVM
memset(nw_name, 0, 33); memset(nw_name, 0, 33);
strncpy(nw_name, (char *) tlv, 32); strncpy(nw_name, (char *) tlv, 32);
}
tlv += 33; tlv += 33;
uint64_t current_time = ws_pae_current_time_get();
tr_debug("NVM NW_INFO current time: %"PRIi64, current_time);
if (gtks && sec_prot_keys_gtk_count(gtks) == 0) {
// If application has not set GTKs read them from NVM
for (uint8_t i = 0; i < GTK_NUM; i++) { for (uint8_t i = 0; i < GTK_NUM; i++) {
if (*tlv++ == PAE_NVM_FIELD_SET) { /* GTK is set */ if (*tlv++ == PAE_NVM_FIELD_SET) { /* GTK is set */
uint32_t lifetime = common_read_32_bit(tlv); uint64_t expirytime = common_read_64_bit(tlv);
tlv += 4; uint32_t lifetime = 0;
if (ws_pae_time_diff_calc(current_time, expirytime, &lifetime, true) < 0) {
tlv += 8 + 1 + 1 + GTK_LEN;
tr_debug("GTK index %i, expired expiry time: %"PRIi64", lifetime: %"PRIi32, i, expirytime, lifetime);
continue;
}
tlv += 8;
uint8_t status = *tlv++;
uint8_t install_order = *tlv++;
tr_debug("GTK index: %i, status: %i, install order %i, expiry time: %"PRIi64", lifetime: %"PRIi32, i, status, install_order, expirytime, lifetime);
sec_prot_keys_gtk_set(gtks, i, tlv, lifetime); sec_prot_keys_gtk_set(gtks, i, tlv, lifetime);
sec_prot_keys_gtk_expirytime_set(gtks, i, expirytime);
tlv += GTK_LEN; tlv += GTK_LEN;
sec_prot_keys_gtk_status_set(gtks, i, status);
sec_prot_keys_gtk_install_order_set(gtks, i, install_order);
} else { } else {
tlv += 4 + GTK_LEN; tlv += 8 + 1 + 1 + GTK_LEN;
} }
} }
sec_prot_keys_gtks_updated_reset(gtks); sec_prot_keys_gtks_updated_reset(gtks);
}
tr_debug("NVM NW_INFO read PAN ID %i name: %s", *pan_id, nw_name); tr_debug("NVM NW_INFO read PAN ID %i name: %s", *pan_id, nw_name);
return 0; return 0;
} }
void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys) void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys)
{ {
tlv_entry->tag = PAE_NVM_KEYS_TAG; tlv_entry->tag = PAE_NVM_KEYS_TAG;
tlv_entry->len = PAE_NVM_KEYS_LEN; tlv_entry->len = PAE_NVM_KEYS_LEN;
@ -151,10 +204,12 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys); uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
if (pmk) { if (pmk) {
*tlv++ = PAE_NVM_FIELD_SET; *tlv++ = PAE_NVM_FIELD_SET;
uint32_t lifetime = sec_prot_keys_pmk_lifetime_get(sec_keys);
tlv = common_write_32_bit(lifetime, tlv);
memcpy(tlv, pmk, PMK_LEN); memcpy(tlv, pmk, PMK_LEN);
} else { } else {
*tlv++ = PAE_NVM_FIELD_NOT_SET; *tlv++ = PAE_NVM_FIELD_NOT_SET;
memset(tlv, 0, PMK_LEN); memset(tlv, 0, 4 + PMK_LEN);
} }
tlv += PMK_LEN; tlv += PMK_LEN;
@ -164,18 +219,19 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys); uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys);
if (ptk) { if (ptk) {
*tlv++ = PAE_NVM_FIELD_SET; *tlv++ = PAE_NVM_FIELD_SET;
uint32_t lifetime = sec_prot_keys_ptk_lifetime_get(sec_keys);
tlv = common_write_32_bit(lifetime, tlv);
memcpy(tlv, ptk, PTK_LEN); memcpy(tlv, ptk, PTK_LEN);
} else { } else {
*tlv++ = PAE_NVM_FIELD_NOT_SET; *tlv++ = PAE_NVM_FIELD_NOT_SET;
memset(tlv, 0, PTK_LEN); memset(tlv, 0, 4 + PTK_LEN);
} }
tlv += PTK_LEN; tlv += PTK_LEN;
tr_debug("NVM KEYS write"); tr_debug("NVM KEYS write");
} }
int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys) int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys)
{ {
if (!tlv_entry || !sec_keys) { if (!tlv_entry || !sec_keys) {
return -1; return -1;
@ -195,7 +251,11 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
// PMK set // PMK set
if (*tlv++ == PAE_NVM_FIELD_SET) { if (*tlv++ == PAE_NVM_FIELD_SET) {
sec_prot_keys_pmk_write(sec_keys, tlv); uint32_t lifetime = common_read_32_bit(tlv);
tlv += 4;
sec_prot_keys_pmk_write(sec_keys, tlv, lifetime);
} else {
tlv += 4;
} }
tlv += PMK_LEN; tlv += PMK_LEN;
@ -205,7 +265,11 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
// PTK set // PTK set
if (*tlv++ == PAE_NVM_FIELD_SET) { if (*tlv++ == PAE_NVM_FIELD_SET) {
sec_prot_keys_ptk_write(sec_keys, tlv); uint32_t lifetime = common_read_32_bit(tlv);
tlv += 4;
sec_prot_keys_ptk_write(sec_keys, tlv, lifetime);
} else {
tlv += 4;
} }
tlv += PTK_LEN; tlv += PTK_LEN;
@ -217,13 +281,18 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
return 0; return 0;
} }
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters) void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, frame_counters_t *counters)
{ {
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG; tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN; tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
tlv = common_write_32_bit(restart_cnt, tlv);
uint64_t stored_time = ws_pae_current_time_get();
tlv = common_write_64_bit(stored_time, tlv);
for (uint8_t index = 0; index < GTK_NUM; index++) { for (uint8_t index = 0; index < GTK_NUM; index++) {
if (!counters->counter[index].set) { if (!counters->counter[index].set) {
*tlv++ = PAE_NVM_FIELD_NOT_SET; *tlv++ = PAE_NVM_FIELD_NOT_SET;
@ -240,7 +309,7 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame
tr_debug("NVM FRAME COUNTER write"); tr_debug("NVM FRAME COUNTER write");
} }
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters) int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters)
{ {
if (!tlv_entry || !counters) { if (!tlv_entry || !counters) {
return -1; return -1;
@ -252,6 +321,12 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
*restart_cnt = common_read_32_bit(tlv);
tlv += 4;
*stored_time = common_read_64_bit(tlv);
tlv += 8;
for (uint8_t index = 0; index < GTK_NUM; index++) { for (uint8_t index = 0; index < GTK_NUM; index++) {
// Frame counter not set // Frame counter not set
if (*tlv++ == PAE_NVM_FIELD_NOT_SET) { if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
@ -272,5 +347,61 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame
return 0; return 0;
} }
void ws_pae_nvm_store_key_storage_index_tlv_create(nvm_tlv_t *tlv_entry, uint64_t bitfield)
{
tlv_entry->tag = PAE_NVM_KEY_STORAGE_INDEX_TAG;
tlv_entry->len = PAE_NVM_KEY_STORAGE_INDEX_LEN;
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
tlv = common_write_64_bit(bitfield, tlv);
tr_debug("NVM KEY STORAGE INDEX write");
}
int8_t ws_pae_nvm_store_key_storage_index_tlv_read(nvm_tlv_t *tlv_entry, uint64_t *bitfield)
{
if (!tlv_entry || !bitfield) {
return -1;
}
if (tlv_entry->tag != PAE_NVM_KEY_STORAGE_INDEX_TAG || tlv_entry->len != PAE_NVM_KEY_STORAGE_INDEX_LEN) {
return -1;
}
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
*bitfield = common_read_64_bit(tlv);
tlv += 8;
tr_debug("NVM KEY STORAGE INDEX read");
return 0;
}
void ws_pae_nvm_store_key_storage_tlv_create(nvm_tlv_t *tlv_entry, uint16_t length)
{
memset(tlv_entry, 0, sizeof(key_storage_nvm_tlv_entry_t));
tlv_entry->tag = PAE_NVM_KEY_STORAGE_TAG;
tlv_entry->len = length - sizeof(nvm_tlv_t);
tr_debug("NVM KEY STORAGE create");
}
int8_t ws_pae_nvm_store_key_storage_tlv_read(nvm_tlv_t *tlv_entry, uint16_t length)
{
if (!tlv_entry || !length) {
return -1;
}
if (tlv_entry->tag != PAE_NVM_KEY_STORAGE_TAG || tlv_entry->len != length - sizeof(nvm_tlv_t)) {
return -1;
}
tr_debug("NVM KEY STORAGE read");
return 0;
}
#endif /* HAVE_WS */ #endif /* HAVE_WS */

View File

@ -24,10 +24,52 @@
* *
*/ */
// file names
#define NW_INFO_FILE_NAME "pae_nw_info"
#define KEYS_FILE_NAME "pae_keys"
#define FRAME_COUNTER_FILE_NAME "pae_frame_counter"
#define PAE_NVM_NW_INFO_TAG 1
#define PAE_NVM_KEYS_TAG 2
#define PAE_NVM_FRAME_COUNTER_TAG 3
#define PAE_NVM_KEY_STORAGE_INDEX_TAG 4
#define PAE_NVM_KEY_STORAGE_TAG 5
// pan_id (2) + network name (33) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4
#define PAE_NVM_NW_INFO_LEN 2 + 33 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK lifetime (4) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK lifetime (4) + PTK (48)
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + 4 + PMK_LEN + 8 + 1 + 4 + PTK_LEN
// restart counter + stored time + (frame counter set (1) + GTK (16) + frame counter (4)) * 4
#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + (1 + GTK_LEN + 4) * GTK_NUM
#define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_NW_INFO_LEN
// key storage index bitfield (8)
#define PAE_NVM_KEY_STORAGE_INDEX_LEN 8
/**
* ws_pae_nvm_store_generic_tlv_create create NVM generic storage TLV
*
* \param tlv_entry TLV entry
* \param tag tag
* \param length length of the (whole) entry
*
* \return < 0 failure
* \return >= 0 success
*
*/
void ws_pae_nvm_store_generic_tlv_create(nvm_tlv_t *tlv_entry, uint16_t tag, uint16_t length);
nvm_tlv_t *ws_pae_nvm_store_generic_tlv_allocate_and_create(uint16_t tag, uint16_t length);
void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry);
/** /**
* ws_pae_nvm_store_nw_info_tlv_create create NVM network info TLV * ws_pae_nvm_store_nw_info_tlv_create create NVM network info TLV
* *
* \param tlv_entry TLV entry pointer * \param tlv_entry TLV
* \param pan_id PAN ID * \param pan_id PAN ID
* \param nw_name network name * \param nw_name network name
* \param gtks GTK keys * \param gtks GTK keys
@ -35,12 +77,12 @@
* \return TLV entry or NULL * \return TLV entry or NULL
* *
*/ */
void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks);
/** /**
* ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV * ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV
* *
* \param tlv_entry TLV entry * \param tlv_entry TLV
* \param pan_id PAN ID * \param pan_id PAN ID
* \param nw_name network name * \param nw_name network name
* \param gtks GTK keys * \param gtks GTK keys
@ -49,50 +91,101 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks);
/** /**
* ws_pae_nvm_store_keys_tlv_create create NVM keys TLV * ws_pae_nvm_store_keys_tlv_create create NVM keys TLV
* *
* \param tlv_entry TLV entry buffer pointer * \param tlv_entry TLV
* \param sec_keys security keys * \param sec_keys security keys
* *
*/ */
void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys); void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys);
/** /**
* ws_pae_nvm_store_nw_info_tlv_read read from NVM keys TLV * ws_pae_nvm_store_nw_info_tlv_read read from NVM keys TLV
* *
* \param tlv_entry TLV entry * \param tlv_entry TLV
* \param sec_keys security keys * \param sec_keys security keys
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys); int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys);
/** /**
* ws_pae_nvm_store_frame_counter_tlv_create create NVM frame counter TLV * ws_pae_nvm_store_frame_counter_tlv_create create NVM frame counter TLV
* *
* \param tlv_entry TLV entry buffer pointer * \param tlv_entry TLV buffer pointer
* \param restart_cnt re-start counter
* \param counters frame counters * \param counters frame counters
* *
*/ */
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters); void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, frame_counters_t *counters);
/** /**
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV * ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV
* *
* \param tlv_entry TLV entry * \param tlv_entry TLV
* \param restart_cnt re-start counter
* \param stored_time stored timestampt
* \param counters frame counters * \param counters frame counters
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters); int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters);
nvm_tlv_entry_t *ws_pae_buffer_allocate(void); /**
* ws_pae_nvm_store_key_storage_index_tlv_create create NVM key storage index TLV
*
* \param tlv_entry TLV entry
* \param bitfield index of filenames
*
* \return < 0 failure
* \return >= 0 success
*
*/
void ws_pae_nvm_store_key_storage_index_tlv_create(nvm_tlv_t *tlv_entry, uint64_t bitfield);
/**
* ws_pae_nvm_store_key_storage_index_tlv_read read NVM key storage index TLV
*
* \param tlv_entry TLV entry
* \param bitfield index of filenames
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_nvm_store_key_storage_index_tlv_read(nvm_tlv_t *tlv_entry, uint64_t *bitfield);
/**
* ws_pae_nvm_store_key_storage_tlv_create create NVM key storage TLV
*
* \param tlv_entry TLV entry
* \param length length of the (whole) entry
*
* \return < 0 failure
* \return >= 0 success
*
*/
void ws_pae_nvm_store_key_storage_tlv_create(nvm_tlv_t *tlv_entry, uint16_t length);
/**
* ws_pae_nvm_store_key_storage_tlv_read read NVM key storage TLV
*
* \param tlv_entry TLV entry
* \param length length of the (whole) entry
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_nvm_store_key_storage_tlv_read(nvm_tlv_t *tlv_entry, uint16_t length);
nvm_tlv_t *ws_pae_buffer_allocate(void);
#endif /* WS_PAE_NVM_DATA_H_ */ #endif /* WS_PAE_NVM_DATA_H_ */

View File

@ -17,7 +17,6 @@
#include "nsconfig.h" #include "nsconfig.h"
#include <string.h> #include <string.h>
#include <stdio.h>
#include "ns_types.h" #include "ns_types.h"
#include "ns_list.h" #include "ns_list.h"
#include "ns_trace.h" #include "ns_trace.h"
@ -25,9 +24,11 @@
#include "common_functions.h" #include "common_functions.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "ns_file_system.h" #include "ns_file_system.h"
#include "Service_Libs/utils/ns_file.h"
#include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/sec_prot_certs.h"
#include "Security/protocols/sec_prot_keys.h" #include "Security/protocols/sec_prot_keys.h"
#include "6LoWPAN/ws/ws_pae_nvm_store.h" #include "6LoWPAN/ws/ws_pae_nvm_store.h"
#include "ns_file_system.h"
#ifdef HAVE_WS #ifdef HAVE_WS
@ -39,10 +40,10 @@ static uint16_t ws_pae_nvm_store_path_len_get(const char *file_name);
static const char *ws_pae_nvm_store_get_root_path(void); static const char *ws_pae_nvm_store_get_root_path(void);
static int8_t ws_pae_nvm_store_root_path_valid(void); static int8_t ws_pae_nvm_store_root_path_valid(void);
static int8_t ws_pae_nvm_store_create_path(char *fast_data_path, const char *file_name); static int8_t ws_pae_nvm_store_create_path(char *fast_data_path, const char *file_name);
static int8_t ws_pae_nvm_store_write(const char *file_name, nvm_tlv_list_t *tlv_list); static int8_t ws_pae_nvm_store_write(const char *file_name, nvm_tlv_t *tlv);
static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_list_t *tlv_list); static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_t *tlv);
int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_list_t *tlv_list) int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_t *tlv)
{ {
if (!ws_pae_nvm_store_root_path_valid()) { if (!ws_pae_nvm_store_root_path_valid()) {
return PAE_NVM_FILE_ROOT_PATH_INVALID; return PAE_NVM_FILE_ROOT_PATH_INVALID;
@ -54,10 +55,10 @@ int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_list_t *tlv_lis
ws_pae_nvm_store_create_path(nw_info_path, file); ws_pae_nvm_store_create_path(nw_info_path, file);
return ws_pae_nvm_store_write(nw_info_path, tlv_list); return ws_pae_nvm_store_write(nw_info_path, tlv);
} }
int8_t ws_pae_nvm_store_tlv_file_read(const char *file, nvm_tlv_list_t *tlv_list) int8_t ws_pae_nvm_store_tlv_file_read(const char *file, nvm_tlv_t *tlv)
{ {
if (!ws_pae_nvm_store_root_path_valid()) { if (!ws_pae_nvm_store_root_path_valid()) {
return PAE_NVM_FILE_ROOT_PATH_INVALID; return PAE_NVM_FILE_ROOT_PATH_INVALID;
@ -69,7 +70,27 @@ int8_t ws_pae_nvm_store_tlv_file_read(const char *file, nvm_tlv_list_t *tlv_list
ws_pae_nvm_store_create_path(nw_info_path, file); ws_pae_nvm_store_create_path(nw_info_path, file);
return ws_pae_nvm_store_read(nw_info_path, tlv_list); return ws_pae_nvm_store_read(nw_info_path, tlv);
}
int8_t ws_pae_nvm_store_tlv_file_remove(const char *file)
{
if (!ws_pae_nvm_store_root_path_valid()) {
return PAE_NVM_FILE_ROOT_PATH_INVALID;
}
uint16_t path_len = ws_pae_nvm_store_path_len_get(file);
char nw_info_path[path_len];
ws_pae_nvm_store_create_path(nw_info_path, file);
int ret = ns_fremove(nw_info_path);
if (ret < 0) {
return -1;
}
return 0;
} }
static const char *ws_pae_nvm_store_get_root_path(void) static const char *ws_pae_nvm_store_get_root_path(void)
@ -106,104 +127,49 @@ static int8_t ws_pae_nvm_store_create_path(char *data_path, const char *file_nam
return 0; return 0;
} }
static int8_t ws_pae_nvm_store_write(const char *file_name, nvm_tlv_list_t *tlv_list) static int8_t ws_pae_nvm_store_write(const char *file_name, nvm_tlv_t *tlv)
{ {
FILE *fp = fopen(file_name, "w"); if (!file_name || !tlv) {
return -1;
}
NS_FILE *fp = ns_fopen(file_name, "w");
if (fp == NULL) { if (fp == NULL) {
tr_error("NVM open error: %s", file_name); tr_error("NVM open error: %s", file_name);
return PAE_NVM_FILE_CANNOT_OPEN; return PAE_NVM_FILE_CANNOT_OPEN;
} }
uint16_t list_count = ns_list_count(tlv_list); size_t n_bytes = ns_fwrite(fp, tlv, tlv->len + sizeof(nvm_tlv_t));
size_t n_bytes = fwrite(&list_count, 1, sizeof(uint16_t), fp); ns_fclose(fp);
if (n_bytes != sizeof(uint16_t)) { if (n_bytes != tlv->len + sizeof(nvm_tlv_t)) {
tr_warning("NVM TLV list count write error");
fclose(fp);
return PAE_NVM_FILE_WRITE_ERROR;
}
bool failure = false;
ns_list_foreach(nvm_tlv_entry_t, entry, tlv_list) {
n_bytes = fwrite(&entry->tag, 1, entry->len + NVM_TLV_FIXED_LEN, fp);
if (n_bytes != (size_t) entry->len + NVM_TLV_FIXED_LEN) {
failure = true;
break;
}
}
fclose(fp);
if (failure) {
tr_error("NVM write error %s", file_name); tr_error("NVM write error %s", file_name);
return PAE_NVM_FILE_WRITE_ERROR; return PAE_NVM_FILE_WRITE_ERROR;
} else {
return PAE_NVM_FILE_SUCCESS;
} }
return PAE_NVM_FILE_SUCCESS;
} }
static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_list_t *tlv_list) static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_t *tlv)
{ {
FILE *fp = fopen(file_name, "r"); if (!file_name || !tlv) {
return -1;
}
NS_FILE *fp = ns_fopen(file_name, "r");
if (fp == NULL) { if (fp == NULL) {
tr_warning("File not found: %s", file_name); tr_warning("File not found: %s", file_name);
return PAE_NVM_FILE_CANNOT_OPEN; return PAE_NVM_FILE_CANNOT_OPEN;
} }
uint16_t list_count; size_t n_bytes = ns_fread(fp, tlv, tlv->len + sizeof(nvm_tlv_t));
size_t n_bytes = fread(&list_count, 1, sizeof(uint16_t), fp); ns_fclose(fp);
if (n_bytes != sizeof(uint16_t)) { if (n_bytes != tlv->len + sizeof(nvm_tlv_t)) {
tr_warning("NVM TLV list count read error %s", file_name); tr_warning("File not found or cannot be read: %s", file_name);
fclose(fp);
return PAE_NVM_FILE_READ_ERROR; return PAE_NVM_FILE_READ_ERROR;
} }
bool failure = false; return PAE_NVM_FILE_SUCCESS;
while (list_count-- > 0) {
nvm_tlv_entry_t entry_header;
memset(&entry_header, 0, sizeof(nvm_tlv_entry_t));
n_bytes = fread(&entry_header.tag, 1, NVM_TLV_FIXED_LEN, fp);
if (n_bytes != NVM_TLV_FIXED_LEN) {
failure = true;
break;
}
uint16_t len = entry_header.len;
nvm_tlv_entry_t *entry = ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + len);
if (!entry) {
failure = true;
break;
}
memcpy(&entry->tag, &entry_header.tag, NVM_TLV_FIXED_LEN);
if (len > 0) {
uint8_t *data_ptr = ((uint8_t *)&entry->tag) + NVM_TLV_FIXED_LEN;
n_bytes = fread(data_ptr, 1, len, fp);
if (n_bytes != len) {
ns_dyn_mem_free(entry);
failure = true;
break;
}
}
ns_list_add_to_end(tlv_list, entry);
}
fclose(fp);
if (failure) {
ns_list_foreach_safe(nvm_tlv_entry_t, entry, tlv_list) {
ns_list_remove(tlv_list, entry);
ns_dyn_mem_free(entry);
}
tr_error("NVM read error %s", file_name);
return PAE_NVM_FILE_READ_ERROR;
} else {
return PAE_NVM_FILE_SUCCESS; // return how many bytes was written.
}
} }
#endif /* HAVE_WS */ #endif /* HAVE_WS */

View File

@ -24,22 +24,6 @@
* *
*/ */
// tag + length
#define NVM_TLV_FIXED_LEN 4
// file names
#define NW_INFO_FILE_NAME "pae_nw_info"
#define KEYS_FILE_NAME "pae_keys"
#define FRAME_COUNTER_FILE_NAME "pae_frame_counter"
typedef struct nvm_tlv_entry {
ns_list_link_t link; /**< Link */
uint16_t tag; /**< Unique tag */
uint16_t len; /**< Number of the bytes after the length field */
} nvm_tlv_entry_t;
typedef NS_LIST_HEAD(nvm_tlv_entry_t, link) nvm_tlv_list_t;
#define PAE_NVM_FILE_SUCCESS 0 #define PAE_NVM_FILE_SUCCESS 0
#define PAE_NVM_FILE_READ_ERROR -1 #define PAE_NVM_FILE_READ_ERROR -1
#define PAE_NVM_FILE_WRITE_ERROR -2 #define PAE_NVM_FILE_WRITE_ERROR -2
@ -49,28 +33,53 @@ typedef NS_LIST_HEAD(nvm_tlv_entry_t, link) nvm_tlv_list_t;
#define PAE_NVM_FILE_PARAMETER_INVALID -6 #define PAE_NVM_FILE_PARAMETER_INVALID -6
#define PAE_NVM_FILE_REMOVE_ERROR -7 #define PAE_NVM_FILE_REMOVE_ERROR -7
typedef struct nvm_tlv {
uint16_t tag; /**< Unique tag */
uint16_t len; /**< Number of the bytes after the length field */
} nvm_tlv_t;
typedef struct {
nvm_tlv_t nvm_tlv; /**< NVM TLV */
uint64_t reference_time; /**< Reference time used for timers (set when file is created) */
uint32_t reference_restart_cnt; /**< Reference re-start counter set when file is created) */
} key_storage_nvm_tlv_entry_t;
// tag + length
#define NVM_TLV_FIXED_LEN sizeof(nvm_tlv_t)
/** /**
* ws_pae_nvm_store_tlv_file_write write a list of TLVs to file * ws_pae_nvm_store_tlv_file_write write a list of TLVs to file
* *
* \param file file name * \param file file name
* \param tlv_list TLV list * \param tlv TLV
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_list_t *tlv_list); int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_t *tlv);
/** /**
* ws_pae_nvm_store_tlv_file_read read a list of TLVs from file * ws_pae_nvm_store_tlv_file_read read a list of TLVs from file
* *
* \param file file name * \param file file name
* \param tlv_list TLV list * \param tlv TLV
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_nvm_store_tlv_file_read(const char *file, nvm_tlv_list_t *tlv_list); int8_t ws_pae_nvm_store_tlv_file_read(const char *file, nvm_tlv_t *tlv);
/**
* ws_pae_nvm_store_tlv_file_remove delete a file
*
* \param file file name
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_nvm_store_tlv_file_remove(const char *file);
#endif /* WS_PAE_NVM_STORE_H_ */ #endif /* WS_PAE_NVM_STORE_H_ */

View File

@ -28,6 +28,7 @@
#include "eventOS_scheduler.h" #include "eventOS_scheduler.h"
#include "eventOS_event_timer.h" #include "eventOS_event_timer.h"
#include "ns_address.h" #include "ns_address.h"
#include "Service_Libs/utils/ns_file.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "RPL/rpl_protocol.h" #include "RPL/rpl_protocol.h"
#include "RPL/rpl_control.h" #include "RPL/rpl_control.h"
@ -48,6 +49,7 @@
#include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_timers.h"
#include "6LoWPAN/ws/ws_pae_supp.h" #include "6LoWPAN/ws/ws_pae_supp.h"
#include "6LoWPAN/ws/ws_pae_lib.h" #include "6LoWPAN/ws/ws_pae_lib.h"
#include "6LoWPAN/ws/ws_pae_time.h"
#include "6LoWPAN/ws/ws_pae_nvm_store.h" #include "6LoWPAN/ws/ws_pae_nvm_store.h"
#include "6LoWPAN/ws/ws_pae_nvm_data.h" #include "6LoWPAN/ws/ws_pae_nvm_data.h"
#include "6LoWPAN/MAC/mpx_api.h" #include "6LoWPAN/MAC/mpx_api.h"
@ -79,31 +81,25 @@
#define INITIAL_KEY_TIMER_MIN 3 #define INITIAL_KEY_TIMER_MIN 3
#define INITIAL_KEY_TIMER_MAX 30 #define INITIAL_KEY_TIMER_MAX 30
typedef struct {
char network_name[33]; /**< Network name for keys */
sec_prot_gtk_keys_t *gtks; /**< Link to GTKs */
uint16_t new_pan_id; /**< new PAN ID indicated by bootstrap */
uint16_t key_pan_id; /**< PAN ID for keys */
bool updated : 1; /**< Network info has been updated */
} sec_prot_keys_nw_info_t;
typedef struct { typedef struct {
ns_list_link_t link; /**< Link */ ns_list_link_t link; /**< Link */
kmp_service_t *kmp_service; /**< KMP service */ kmp_service_t *kmp_service; /**< KMP service */
protocol_interface_info_entry_t *interface_ptr; /**< Interface */ protocol_interface_info_entry_t *interface_ptr; /**< Interface */
ws_pae_supp_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */ ws_pae_supp_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
ws_pae_supp_auth_next_target *auth_next_target; /**< Authentication next target callback */
ws_pae_supp_nw_key_insert *nw_key_insert; /**< Key insert callback */ ws_pae_supp_nw_key_insert *nw_key_insert; /**< Key insert callback */
ws_pae_supp_nw_key_index_set *nw_key_index_set; /**< Key index set callback */ ws_pae_supp_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get; /**< Get pointer to GTK hash storage callback */ ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get; /**< Get pointer to GTK hash storage callback */
ws_pae_supp_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
supp_entry_t entry; /**< Supplicant data */ supp_entry_t entry; /**< Supplicant data */
kmp_addr_t target_addr; /**< EAPOL target (parent) address */ kmp_addr_t target_addr; /**< EAPOL target (parent) address */
uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */ uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */
uint16_t initial_key_retry_timer; /**< Timer to trigger initial EAPOL-Key 1st retry */ uint16_t initial_key_retry_timer; /**< Timer to trigger initial EAPOL-Key 1st retry */
trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */ trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */
trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */ trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */
sec_prot_gtk_keys_t gtks; /**< GTKs */ uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap start */
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap */ uint8_t comp_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap completed */
sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */ sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */ sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */
sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */ sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */ uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
@ -111,47 +107,26 @@ typedef struct {
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */ bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */ bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */
bool timer_running : 1; /**< Timer is running */ bool timer_running : 1; /**< Timer is running */
bool new_br_eui_64_set : 1; /**< Border router address has been set */ bool new_br_eui_64_set : 1; /**< Border router address has been set after bootstrap start */
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */ bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
bool entry_address_active: 1; bool comp_br_eui_64_set : 1; /**< Border router address has been set after bootstrap completed */
bool entry_address_active: 1; /**< EAPOL target address is set */
bool tx_failure_on_initial_key: 1; /**< TX failure has happened on initial EAPOL-key sequence */
} pae_supp_t; } pae_supp_t;
// How many times sending of initial EAPOL-key is retried
#define INITIAL_KEY_RETRY_COUNT 2
// How many times sending of initial EAPOL-key is initiated on key update // How many times sending of initial EAPOL-key is initiated on key update
#define KEY_UPDATE_RETRY_COUNT 3 #define KEY_UPDATE_RETRY_COUNT 3
#define LIFETIME_MISMATCH_RETRY_COUNT 1 /* No retries */ #define LIFETIME_MISMATCH_RETRY_COUNT 1 /* No retries */
// How long the wait is before the first initial EAPOL-key retry
#define DEFAULT_INITIAL_KEY_RETRY_TIMER 120
#define NONE_INITIAL_KEY_RETRY_TIMER 0
// Default trickle values for sending of initial EAPOL-key
#define DEFAULT_TRICKLE_IMIN_SECS 360 /* 6 to 12 minutes */
#define DEFAULT_TRICKLE_IMAX_SECS 720
// Very slow network values for sending of initial EAPOL-key
#define VERY_SLOW_NW_TRICKLE_IMIN_SECS 600 /* 10 to 60 minutes */
#define VERY_SLOW_NW_TRICKLE_IMAX_SECS 3600
// Trickle timer on how long to wait response after last retry before failing authentication // Trickle timer on how long to wait response after last retry before failing authentication
#define LAST_INTERVAL_TRICKLE_IMIN_SECS 240 /* 4 minutes */ #define LAST_INTERVAL_TRICKLE_IMIN_SECS 240 /* 4 minutes */
#define LAST_INTERVAL_TRICKLE_IMAX_SECS 240 #define LAST_INTERVAL_TRICKLE_IMAX_SECS 240
static trickle_params_t initial_eapol_key_trickle_params = {
.Imin = DEFAULT_TRICKLE_IMIN_SECS, /* 360 second; ticks are 1 second */
.Imax = DEFAULT_TRICKLE_IMAX_SECS, /* 720 second */
.k = 0, /* infinity - no consistency checking */
.TimerExpirations = 2
};
static void ws_pae_supp_free(pae_supp_t *pae_supp); static void ws_pae_supp_free(pae_supp_t *pae_supp);
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result); static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp); static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp); static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id); static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name);
static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp);
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp); static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr); static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data); static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data);
@ -182,16 +157,15 @@ static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp);
static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = { static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
.priority = EAPOL_PDU_RECV_HIGH_PRIORITY, .priority = EAPOL_PDU_RECV_HIGH_PRIORITY,
.filter_requsted = false,
.addr_check = ws_pae_supp_eapol_pdu_address_check, .addr_check = ws_pae_supp_eapol_pdu_address_check,
.receive = kmp_eapol_pdu_if_receive .receive = kmp_eapol_pdu_if_receive
}; };
static const char *NW_INFO_FILE = NW_INFO_FILE_NAME;
static const char *KEYS_FILE = KEYS_FILE_NAME; static const char *KEYS_FILE = KEYS_FILE_NAME;
static int8_t tasklet_id = -1; static int8_t tasklet_id = -1;
static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link); static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link);
static uint8_t timing_value = 0; // Timing value set based e.g. on network size
static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address) static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address)
{ {
@ -209,33 +183,35 @@ static bool ws_pae_supp_address_is_set(pae_supp_t *pae_supp)
return pae_supp->entry_address_active; return pae_supp->entry_address_active;
} }
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64) int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64, char *dest_network_name)
{ {
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) { if (!pae_supp) {
return -1; return -1;
} }
if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id) >= 0) { if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id, dest_network_name) >= 0) {
pae_supp->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL); pae_supp->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
return 0; return 0;
} }
// Delete GTKs // Delete GTKs
sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info.gtks); sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks);
/* PAN ID has changed, delete key data associated with border router /* Network name or PAN ID has changed, delete key data associated with border router
i.e PMK, PTK, EA-IE data (border router EUI-64) */ i.e PMK, PTK, EA-IE data (border router EUI-64) */
if (pae_supp->sec_keys_nw_info.key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info.key_pan_id != dest_pan_id) { if (strcmp(pae_supp->sec_keys_nw_info->network_name, dest_network_name) != 0 ||
(pae_supp->sec_keys_nw_info->key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info->key_pan_id != dest_pan_id)) {
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys); sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys); sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys); sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
} }
pae_supp->sec_keys_nw_info.key_pan_id = dest_pan_id; pae_supp->sec_keys_nw_info->key_pan_id = dest_pan_id;
// Prepare to receive new border router address // Prepare to receive new border router address
pae_supp->new_br_eui_64_fresh = false; pae_supp->new_br_eui_64_fresh = false;
pae_supp->comp_br_eui_64_set = false;
// Stores target/parent address // Stores target/parent address
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64); kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64);
@ -255,29 +231,6 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,
return 1; return 1;
} }
int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
{
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) {
return -1;
}
// PAN ID has been modified
if (pan_id != 0xffff && pan_id != pae_supp->sec_keys_nw_info.new_pan_id) {
pae_supp->sec_keys_nw_info.new_pan_id = pan_id;
pae_supp->sec_keys_nw_info.updated = true;
}
// Network name has been modified
if (network_name && strncmp(pae_supp->sec_keys_nw_info.network_name, network_name, 33) != 0) {
strncpy(pae_supp->sec_keys_nw_info.network_name, network_name, 32);
pae_supp->sec_keys_nw_info.updated = true;
}
return 0;
}
int8_t ws_pae_supp_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64) int8_t ws_pae_supp_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
{ {
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
@ -299,24 +252,46 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
return -1; return -1;
} }
// Check if there is border router EUI-64 on used on 4WH PTK generation
uint8_t *br_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys); uint8_t *br_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
if (!br_eui_64) { if (!br_eui_64) {
// Check if there is border router EUI-64 indicated by the bootstrap when bootstrap completed
if (!pae_supp->comp_br_eui_64_set) {
return -1; return -1;
} }
br_eui_64 = pae_supp->comp_br_eui_64;
}
memcpy(eui_64, br_eui_64, 8); memcpy(eui_64, br_eui_64, 8);
return 0; return 0;
} }
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr) int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
{ {
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) { if (!pae_supp) {
return -1; return -1;
} }
tr_info("NW key valid"); tr_info("NW key valid indication");
// Store border router EUI-64 received on bootstrap complete
memcpy(pae_supp->comp_br_eui_64, br_iid, 8);
pae_supp->comp_br_eui_64[0] ^= 0x02;
pae_supp->comp_br_eui_64_set = true;
// Get the EUI-64 used on 4WH handshake PTK generation
uint8_t *ptk_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
/* If border router EUI-64 received on bootstrap complete does not match to
EUI-64 stored with keys, delete keys */
if (memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) {
tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s", tr_array(ptk_eui_64, 8), tr_array(pae_supp->comp_br_eui_64, 8));
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
}
// Stored keys are valid // Stored keys are valid
pae_supp->nw_keys_used_cnt = 0; pae_supp->nw_keys_used_cnt = 0;
@ -335,7 +310,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp)
} }
// Check GTK hashes and initiate EAPOL procedure if mismatch is detected */ // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(&pae_supp->gtks, gtkhash); gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash);
if (mismatch != GTK_NO_MISMATCH) { if (mismatch != GTK_NO_MISMATCH) {
return -1; return -1;
} }
@ -352,7 +327,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
} }
// Check GTK hashes and initiate EAPOL procedure if mismatch is detected */ // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(&pae_supp->gtks, gtkhash); gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash);
if (mismatch > GTK_NO_MISMATCH) { if (mismatch > GTK_NO_MISMATCH) {
tr_info("GTK hash update %s %s %s %s", tr_info("GTK hash update %s %s %s %s",
trace_array(&gtkhash[0], 8), trace_array(&gtkhash[0], 8),
@ -379,7 +354,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
} }
// Modify keys // Modify keys
pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks); pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks);
return 0; return 0;
} }
@ -391,7 +366,7 @@ int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interfac
return -1; return -1;
} }
if (sec_prot_keys_gtk_status_active_set(&pae_supp->gtks, index) >= 0) { if (sec_prot_keys_gtk_status_active_set(pae_supp->sec_keys_nw_info->gtks, index) >= 0) {
pae_supp->nw_key_index_set(interface_ptr, index); pae_supp->nw_key_index_set(interface_ptr, index);
} else { } else {
tr_info("NW send key index: %i, no changes", index + 1); tr_info("NW send key index: %i, no changes", index + 1);
@ -407,7 +382,7 @@ int8_t ws_pae_supp_gtks_set(protocol_interface_info_entry_t *interface_ptr, sec_
return -1; return -1;
} }
pae_supp->gtks = *gtks; *pae_supp->sec_keys_nw_info->gtks = *gtks;
return 0; return 0;
} }
@ -427,12 +402,8 @@ int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interfac
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp) static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
{ {
// Check if NW info or GTKs have been changed // Indicate to PAE controller that NW info or GTKs may have been changed
if (pae_supp->sec_keys_nw_info.updated || sec_prot_keys_gtks_are_updated(pae_supp->sec_keys_nw_info.gtks)) { pae_supp->nw_info_updated(pae_supp->interface_ptr);
ws_pae_supp_nvm_nw_info_write(pae_supp);
pae_supp->sec_keys_nw_info.updated = false;
sec_prot_keys_gtks_updated_reset(pae_supp->sec_keys_nw_info.gtks);
}
// Check if pairwise security keys have been changed // Check if pairwise security keys have been changed
if (sec_prot_keys_are_updated(&pae_supp->entry.sec_keys)) { if (sec_prot_keys_are_updated(&pae_supp->entry.sec_keys)) {
@ -441,75 +412,30 @@ static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
} }
} }
static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp)
{
nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
if (!tlv_entry) {
return -1;
}
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
ws_pae_nvm_store_nw_info_tlv_create(tlv_entry, pae_supp->sec_keys_nw_info.key_pan_id,
pae_supp->sec_keys_nw_info.network_name,
&pae_supp->gtks);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, &tlv_list);
return 0;
}
static int8_t ws_pae_supp_nvm_nw_info_read(pae_supp_t *pae_supp)
{
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, &tlv_list);
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
ws_pae_nvm_store_nw_info_tlv_read(entry, &pae_supp->sec_keys_nw_info.key_pan_id,
pae_supp->sec_keys_nw_info.network_name,
&pae_supp->gtks);
ns_list_remove(&tlv_list, entry);
ns_dyn_mem_free(entry);
}
return 0;
}
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp) static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp)
{ {
nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr); nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
if (!tlv_entry) { if (!tlv) {
return -1; return -1;
} }
nvm_tlv_list_t tlv_list; ws_pae_nvm_store_keys_tlv_create(tlv, &pae_supp->entry.sec_keys);
ns_list_init(&tlv_list); ws_pae_nvm_store_tlv_file_write(KEYS_FILE, tlv);
ws_pae_nvm_store_keys_tlv_create(tlv_entry, &pae_supp->entry.sec_keys);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(KEYS_FILE, &tlv_list);
return 0; return 0;
} }
static int8_t ws_pae_supp_nvm_keys_read(pae_supp_t *pae_supp) static int8_t ws_pae_supp_nvm_keys_read(pae_supp_t *pae_supp)
{ {
nvm_tlv_list_t tlv_list; nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
ns_list_init(&tlv_list); if (!tlv) {
return -1;
ws_pae_nvm_store_tlv_file_read(KEYS_FILE, &tlv_list);
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
ws_pae_nvm_store_keys_tlv_read(entry, &pae_supp->entry.sec_keys);
ns_list_remove(&tlv_list, entry);
ns_dyn_mem_free(entry);
} }
ws_pae_nvm_store_generic_tlv_create(tlv, PAE_NVM_KEYS_TAG, PAE_NVM_KEYS_LEN);
if (ws_pae_nvm_store_tlv_file_read(KEYS_FILE_NAME, tlv) < 0) {
return -1;
}
ws_pae_nvm_store_keys_tlv_read(tlv, &pae_supp->entry.sec_keys);
return 0; return 0;
} }
@ -562,29 +488,31 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
return 0; return 0;
} }
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id) static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name)
{ {
// Checks how many times authentication has been tried with current network keys // Checks how many times authentication has been tried with current network keys
if (pae_supp->nw_keys_used_cnt >= STORED_KEYS_MAXIMUM_USE_COUNT) { if (pae_supp->nw_keys_used_cnt >= STORED_KEYS_MAXIMUM_USE_COUNT) {
tr_debug("Keys not valid, delete GTKs"); tr_debug("Keys not valid, delete GTKs");
// Delete GTKs // Delete GTKs
sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info.gtks); sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks);
sec_prot_keys_gtks_updated_set(pae_supp->sec_keys_nw_info.gtks); sec_prot_keys_gtks_updated_set(pae_supp->sec_keys_nw_info->gtks);
ws_pae_supp_nvm_update(pae_supp); ws_pae_supp_nvm_update(pae_supp);
pae_supp->nw_keys_used_cnt = 0; pae_supp->nw_keys_used_cnt = 0;
return -1; return -1;
} }
/* Checks if keys match to PAN ID and that needed keys exists (PMK, PTK and a GTK), /* Checks if keys match to network name and PAN ID and that needed keys exists (PMK,
and calls inserts function that will update the network keys as needed */ PTK and a GTK), and calls inserts function that will update the network keys as
if ((pan_id == pae_supp->sec_keys_nw_info.key_pan_id) && needed */
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info.gtks) > 0) && if ((strcmp(dest_network_name, pae_supp->sec_keys_nw_info->network_name) == 0 &&
pan_id == pae_supp->sec_keys_nw_info->key_pan_id) &&
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info->gtks) > 0) &&
(sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) && (sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
(sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) { (sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) {
tr_debug("Existing keys used, counter %i", pae_supp->nw_keys_used_cnt); tr_debug("Existing keys used, counter %i", pae_supp->nw_keys_used_cnt);
if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks) >= 0) { if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks) >= 0) {
tr_debug("Keys inserted"); tr_debug("Keys inserted");
} }
pae_supp->nw_keys_used_cnt++; pae_supp->nw_keys_used_cnt++;
@ -595,21 +523,7 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
} }
} }
static void ws_pae_supp_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks) void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_auth_next_target *auth_next_target, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated)
{
if (!sec_keys_nw_info) {
return;
}
memset(sec_keys_nw_info, 0, sizeof(sec_prot_keys_nw_info_t));
sec_keys_nw_info->gtks = gtks;
sec_keys_nw_info->new_pan_id = 0xFFFF;
sec_keys_nw_info->key_pan_id = 0xFFFF;
sec_keys_nw_info->updated = false;
}
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get)
{ {
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) { if (!pae_supp) {
@ -617,12 +531,14 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
} }
pae_supp->auth_completed = completed; pae_supp->auth_completed = completed;
pae_supp->auth_next_target = auth_next_target;
pae_supp->nw_key_insert = nw_key_insert; pae_supp->nw_key_insert = nw_key_insert;
pae_supp->nw_key_index_set = nw_key_index_set; pae_supp->nw_key_index_set = nw_key_index_set;
pae_supp->gtk_hash_ptr_get = gtk_hash_ptr_get; pae_supp->gtk_hash_ptr_get = gtk_hash_ptr_get;
pae_supp->nw_info_updated = nw_info_updated;
} }
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg) int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
{ {
if (!interface_ptr) { if (!interface_ptr) {
return -1; return -1;
@ -639,13 +555,15 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
pae_supp->interface_ptr = interface_ptr; pae_supp->interface_ptr = interface_ptr;
pae_supp->auth_completed = NULL; pae_supp->auth_completed = NULL;
pae_supp->auth_next_target = NULL;
pae_supp->nw_key_insert = NULL; pae_supp->nw_key_insert = NULL;
pae_supp->nw_key_index_set = NULL; pae_supp->nw_key_index_set = NULL;
pae_supp->gtk_hash_ptr_get = NULL; pae_supp->gtk_hash_ptr_get = NULL;
pae_supp->initial_key_timer = 0; pae_supp->initial_key_timer = 0;
pae_supp->initial_key_retry_timer = 0; pae_supp->initial_key_retry_timer = 0;
pae_supp->nw_keys_used_cnt = 0; pae_supp->nw_keys_used_cnt = 0;
pae_supp->initial_key_retry_cnt = INITIAL_KEY_RETRY_COUNT; pae_supp->initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
pae_supp->sec_keys_nw_info = sec_keys_nw_info;
pae_supp->sec_timer_cfg = sec_timer_cfg; pae_supp->sec_timer_cfg = sec_timer_cfg;
pae_supp->sec_prot_cfg = sec_prot_cfg; pae_supp->sec_prot_cfg = sec_prot_cfg;
pae_supp->auth_trickle_running = false; pae_supp->auth_trickle_running = false;
@ -653,16 +571,15 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
pae_supp->timer_running = false; pae_supp->timer_running = false;
pae_supp->new_br_eui_64_set = false; pae_supp->new_br_eui_64_set = false;
pae_supp->new_br_eui_64_fresh = false; pae_supp->new_br_eui_64_fresh = false;
pae_supp->comp_br_eui_64_set = false;
pae_supp->entry_address_active = false; pae_supp->entry_address_active = false;
ws_pae_lib_supp_init(&pae_supp->entry); ws_pae_lib_supp_init(&pae_supp->entry);
ws_pae_supp_keys_nw_info_init(&pae_supp->sec_keys_nw_info, &pae_supp->gtks);
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, 0); kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, 0);
sec_prot_keys_gtks_init(&pae_supp->gtks); sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks);
sec_prot_keys_init(&pae_supp->entry.sec_keys, &pae_supp->gtks, certs); sec_prot_keys_init(&pae_supp->entry.sec_keys, pae_supp->sec_keys_nw_info->gtks, certs);
memset(pae_supp->new_br_eui_64, 0, 8); memset(pae_supp->new_br_eui_64, 0, 8);
pae_supp->kmp_service = kmp_service_create(); pae_supp->kmp_service = kmp_service_create();
@ -721,7 +638,6 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
goto error; goto error;
} }
ws_pae_supp_nvm_nw_info_read(pae_supp);
ws_pae_supp_nvm_keys_read(pae_supp); ws_pae_supp_nvm_keys_read(pae_supp);
ns_list_add_to_end(&pae_supp_list, pae_supp); ns_list_add_to_end(&pae_supp_list, pae_supp);
@ -840,7 +756,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
} }
// Updates KMP timers and supplicant authentication ongoing timer // Updates KMP timers and supplicant authentication ongoing timer
bool running = ws_pae_lib_supp_timer_update(&pae_supp->entry, ticks, kmp_service_timer_if_timeout); bool running = ws_pae_lib_supp_timer_update(NULL, &pae_supp->entry, ticks, kmp_service_timer_if_timeout);
// Checks whether timer needs to be active // Checks whether timer needs to be active
if (!ws_pae_supp_authentication_ongoing(pae_supp) && !running) { if (!ws_pae_supp_authentication_ongoing(pae_supp) && !running) {
@ -881,6 +797,15 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
// Checks if trickle timer expires // Checks if trickle timer expires
if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) { if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
if (pae_supp->initial_key_retry_cnt > 0) { if (pae_supp->initial_key_retry_cnt > 0) {
// On initial EAPOL-key TX failure, check for other parents
if (pae_supp->auth_requested && pae_supp->tx_failure_on_initial_key) {
// Returns same target if no other valid targets found
const uint8_t *next_target = pae_supp->auth_next_target(pae_supp->interface_ptr, kmp_address_eui_64_get(&pae_supp->target_addr), &pae_supp->sec_keys_nw_info->key_pan_id);
kmp_address_eui_64_set(&pae_supp->target_addr, next_target);
ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr);
}
pae_supp->tx_failure_on_initial_key = false;
// Sends initial EAPOL-key
if (ws_pae_supp_initial_key_send(pae_supp) < 0) { if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
tr_info("EAPOL-Key send failed"); tr_info("EAPOL-Key send failed");
} }
@ -895,7 +820,12 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
tr_info("GTKs do not match to GTK hash"); tr_info("GTKs do not match to GTK hash");
retry = true; retry = true;
} }
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); auth_result_e result = AUTH_RESULT_ERR_UNSPEC;
if (pae_supp->tx_failure_on_initial_key) {
result = AUTH_RESULT_ERR_TX_NO_ACK;
pae_supp->tx_failure_on_initial_key = false;
}
ws_pae_supp_authenticate_response(pae_supp, result);
if (retry) { if (retry) {
// Start trickle timer to try re-authentication // Start trickle timer to try re-authentication
ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, KEY_UPDATE_RETRY_COUNT); ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, KEY_UPDATE_RETRY_COUNT);
@ -921,10 +851,11 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
// Decrements GTK lifetimes // Decrements GTK lifetimes
for (uint8_t i = 0; i < GTK_NUM; i++) { for (uint8_t i = 0; i < GTK_NUM; i++) {
if (!sec_prot_keys_gtk_is_set(&pae_supp->gtks, i)) { if (!sec_prot_keys_gtk_is_set(pae_supp->sec_keys_nw_info->gtks, i)) {
continue; continue;
} }
sec_prot_keys_gtk_lifetime_decrement(&pae_supp->gtks, i, seconds); uint64_t current_time = ws_pae_current_time_get();
sec_prot_keys_gtk_lifetime_decrement(pae_supp->sec_keys_nw_info->gtks, i, current_time, seconds);
} }
if (pae_supp->initial_key_timer > 0) { if (pae_supp->initial_key_timer > 0) {
@ -932,7 +863,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
pae_supp->initial_key_timer -= seconds; pae_supp->initial_key_timer -= seconds;
} else { } else {
pae_supp->initial_key_timer = 0; pae_supp->initial_key_timer = 0;
pae_supp->tx_failure_on_initial_key = false;
// Sends initial EAPOL-Key message // Sends initial EAPOL-Key message
if (ws_pae_supp_initial_key_send(pae_supp) < 0) { if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
tr_info("EAPOL-Key send failed"); tr_info("EAPOL-Key send failed");
@ -946,11 +877,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp) static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp)
{ {
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params; /* Starts trickle for initial EAPOL-key. Default sequence has fixed delay of 2 minutes,
// Very fast, medium and slow network
if (timing_value < 25) {
/* Starts trickle for initial EAPOL-key. Sequence has fixed delay of 2 minutes,
* one re-transmit interval, last re-transmit interval transmit time and a wait time * one re-transmit interval, last re-transmit interval transmit time and a wait time
* for the authenticator to answer the last re-transmit. * for the authenticator to answer the last re-transmit.
* *
@ -960,32 +887,30 @@ static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp)
* *
* There are two retries. Minimum time that sequence takes before authentication failure * There are two retries. Minimum time that sequence takes before authentication failure
* is 16 minutes and maximum is 30 minutes. * is 16 minutes and maximum is 30 minutes.
*/ *
pae_supp->initial_key_retry_timer = DEFAULT_INITIAL_KEY_RETRY_TIMER; // 2 minutes *
} else { * Extremely slow network
/* Extremely slow network
* *
* Starts trickle for initial EAPOL-key, Interval I [10,60] minutes. Sequence: * Starts trickle for initial EAPOL-key, Interval I [10,60] minutes. Sequence:
* I + last I transmit time t + wait for answer [2,4] minutes * I + last I transmit time t + wait for answer [2,4] minutes
* There are two retries. Minimum time that sequence takes before authentication failure * There are two retries. Minimum time that sequence takes before authentication failure
* is 22 minutes and maximum is 124 minutes. * is 22 minutes and maximum is 124 minutes.
*/ */
pae_supp->auth_trickle_params.Imin = VERY_SLOW_NW_TRICKLE_IMIN_SECS; pae_supp->auth_trickle_params = pae_supp->sec_prot_cfg->initial_key_trickle_params;
pae_supp->auth_trickle_params.Imax = VERY_SLOW_NW_TRICKLE_IMAX_SECS; pae_supp->initial_key_retry_timer = pae_supp->sec_prot_cfg->initial_key_retry_delay;
pae_supp->initial_key_retry_timer = NONE_INITIAL_KEY_RETRY_TIMER; // 0 seconds
}
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t);
pae_supp->auth_trickle_running = true; pae_supp->auth_trickle_running = true;
pae_supp->initial_key_retry_cnt = INITIAL_KEY_RETRY_COUNT; pae_supp->initial_key_retry_cnt = pae_supp->sec_prot_cfg->initial_key_retry_cnt;
} }
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp) static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp)
{ {
// Starts trickle last to wait response after last retry before failing authentication // Starts trickle last to wait response after last retry before failing authentication
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
pae_supp->auth_trickle_params.Imin = LAST_INTERVAL_TRICKLE_IMIN_SECS; pae_supp->auth_trickle_params.Imin = LAST_INTERVAL_TRICKLE_IMIN_SECS;
pae_supp->auth_trickle_params.Imax = LAST_INTERVAL_TRICKLE_IMAX_SECS; pae_supp->auth_trickle_params.Imax = LAST_INTERVAL_TRICKLE_IMAX_SECS;
pae_supp->auth_trickle_params.k = 0;
pae_supp->auth_trickle_params.TimerExpirations = 1; pae_supp->auth_trickle_params.TimerExpirations = 1;
// Set I to [iMin,iMax] (4 to 4 minutes) -> t is [I/2 - I] (2 minutes to 4 minutes) // Set I to [iMin,iMax] (4 to 4 minutes) -> t is [I/2 - I] (2 minutes to 4 minutes)
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
@ -1213,7 +1138,7 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp) static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp)
{ {
// Create new instance // Create new instance
kmp_api_t *kmp = kmp_api_create(service, type, pae_supp->sec_prot_cfg); kmp_api_t *kmp = kmp_api_create(service, type, pae_supp->sec_prot_cfg, pae_supp->sec_timer_cfg);
if (!kmp) { if (!kmp) {
return NULL; return NULL;
} }
@ -1308,7 +1233,12 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
that bootstrap can decide if EAPOL target should be changed */ that bootstrap can decide if EAPOL target should be changed */
else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) { else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) {
tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8)); tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK); /* Fails authentication only if other authentication protocols are not yet
started by authenticator */
if (ws_pae_lib_kmp_list_count(&pae_supp->entry.kmp_list) <= 1) {
// Continues with trickle but selects different parent
pae_supp->tx_failure_on_initial_key = true;
}
} }
} }

View File

@ -40,12 +40,13 @@
* \param cert_chain certificate chain * \param cert_chain certificate chain
* \param sec_timer_cfg timer configuration * \param sec_timer_cfg timer configuration
* \param sec_prot_cfg protocol configuration * \param sec_prot_cfg protocol configuration
* \param sec_keys_nw_info security keys network information
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg); int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
/** /**
* ws_pae_supp_delete deletes PAE supplicant * ws_pae_supp_delete deletes PAE supplicant
@ -80,26 +81,14 @@ void ws_pae_supp_slow_timer(uint16_t seconds);
* \param interface_ptr interface * \param interface_ptr interface
* \param dest_pan_id EAPOL target PAN ID * \param dest_pan_id EAPOL target PAN ID
* \param dest_eui_64 EAPOL target * \param dest_eui_64 EAPOL target
* \param dest_network_name EAPOL target network name
* *
* \return < 0 failure * \return < 0 failure
* \return 0 authentication done, continue * \return 0 authentication done, continue
* \return > 0 authentication started * \return > 0 authentication started
* *
*/ */
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64); int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64, char *dest_network_name);
/**
* ws_pae_supp_nw_info_set set network information
*
* \param interface_ptr interface
* \param pan_id PAD ID
* \param network_name network name
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
/** /**
* ws_pae_supp_border_router_addr_write write border router address * ws_pae_supp_border_router_addr_write write border router address
@ -129,12 +118,13 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
* ws_pae_supp_nw_key_valid network key is valid i.e. used successfully on bootstrap * ws_pae_supp_nw_key_valid network key is valid i.e. used successfully on bootstrap
* *
* \param interface_ptr interface * \param interface_ptr interface
* \param br_iid border router IID for which the keys are valid
* *
* \return < 0 failure * \return < 0 failure
* \return >= 0 success * \return >= 0 success
* *
*/ */
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr); int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid);
/** /**
* ws_pae_supp_gtk_hash_update GTK hash has been updated (on PAN configuration) * ws_pae_supp_gtk_hash_update GTK hash has been updated (on PAN configuration)
@ -202,6 +192,17 @@ typedef void ws_pae_supp_nw_key_index_set(protocol_interface_info_entry_t *inter
*/ */
typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64); typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64);
/**
* ws_pae_supp_auth_next_target get next target to attempt authentication
*
* \param interface_ptr interface
* \param previous_eui_64 EUI-64 of previous target
*
* \return EUI-64 of the next target or previous target if new one not available
*
*/
typedef const uint8_t *ws_pae_supp_auth_next_target(protocol_interface_info_entry_t *interface_ptr, const uint8_t *previous_eui_64, uint16_t *pan_id);
/** /**
* ws_pae_supp_nw_key_insert network key insert callback * ws_pae_supp_nw_key_insert network key insert callback
* *
@ -224,6 +225,14 @@ typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interf
*/ */
typedef uint8_t *ws_pae_supp_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr); typedef uint8_t *ws_pae_supp_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr);
/**
* ws_pae_supp_nw_info_updated security keys network information updated
*
* \param interface_ptr interface
*
*/
typedef void ws_pae_supp_nw_info_updated(protocol_interface_info_entry_t *interface_ptr);
/** /**
* ws_pae_supp_cb_register register PEA supplicant callbacks * ws_pae_supp_cb_register register PEA supplicant callbacks
* *
@ -231,9 +240,10 @@ typedef uint8_t *ws_pae_supp_gtk_hash_ptr_get(protocol_interface_info_entry_t *i
* \param completed authentication completed callback * \param completed authentication completed callback
* \param nw_key_insert network key index callback * \param nw_key_insert network key index callback
* \param nw_key_index_set network send key index callback * \param nw_key_index_set network send key index callback
* \param nw_info_updated security keys network information updated callback
* *
*/ */
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get); void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_auth_next_target *auth_next_target, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated);
#else #else
@ -241,7 +251,6 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
#define ws_pae_supp_delete NULL #define ws_pae_supp_delete NULL
#define ws_pae_supp_timing_adjust(timing) 1 #define ws_pae_supp_timing_adjust(timing) 1
#define ws_pae_supp_cb_register(interface_ptr, completed, nw_key_insert, nw_key_index_set) #define ws_pae_supp_cb_register(interface_ptr, completed, nw_key_insert, nw_key_index_set)
#define ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name) -1
#define ws_pae_supp_nw_key_valid(interface_ptr) -1 #define ws_pae_supp_nw_key_valid(interface_ptr) -1
#define ws_pae_supp_fast_timer NULL #define ws_pae_supp_fast_timer NULL
#define ws_pae_supp_slow_timer NULL #define ws_pae_supp_slow_timer NULL

View File

@ -0,0 +1,190 @@
/*
* Copyright (c) 2020, 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.
*/
#include "nsconfig.h"
#include <string.h>
#include "ns_types.h"
#include "ns_list.h"
#include "ns_trace.h"
#include "ns_time_api.h"
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_pae_time.h"
#include "Security/protocols/sec_prot_certs.h"
#include "Security/protocols/sec_prot_keys.h"
#ifdef HAVE_WS
#define TRACE_GROUP "wst"
// Wednesday, January 1, 2020 0:00:00 GMT
#define CURRENT_TIME_INIT_VALUE 1577836800
// Increment two hours in addition to maximum storing interval
#define CURRENT_TIME_INCREMENT_VALUE (2 * 3600)
static uint64_t current_time = CURRENT_TIME_INIT_VALUE;
static ns_time_api_system_time_callback *system_time_callback = NULL;
uint16_t ws_pae_time_to_short_convert(uint32_t time)
{
uint16_t short_time;
time_format_t format;
if (time < STIME_TIME_MAX) {
short_time = time;
format = TIME_FORMAT_SECONDS;
} else if (time < (STIME_TIME_MAX * 60)) {
short_time = time / 60;
format = TIME_FORMAT_MINUTES;
} else if (time < (STIME_TIME_MAX * 3600)) {
short_time = time / 3600;
format = TIME_FORMAT_HOURS;
} else {
short_time = time / 86400;
format = TIME_FORMAT_DAYS;
}
short_time |= ((uint16_t) format) << STIME_TIME_BITS;
return short_time;
}
uint32_t ws_pae_time_from_short_convert(uint16_t short_time)
{
uint32_t time;
time_format_t format = short_time >> STIME_TIME_BITS;
short_time &= STIME_TIME_MASK;
if (format == TIME_FORMAT_SECONDS) {
time = short_time;
} else if (format == TIME_FORMAT_MINUTES) {
time = short_time * 60;
} else if (format == TIME_FORMAT_HOURS) {
time = short_time * 3600;
} else {
time = short_time * 86400;
}
return time;
}
bool ws_pae_time_from_short_time_compare(uint16_t short_time1, uint16_t short_time2)
{
uint32_t time1 = ws_pae_time_from_short_convert(short_time1);
uint32_t time2 = ws_pae_time_from_short_convert(short_time2);
// Calculate difference
uint32_t difference;
if (time1 > time2) {
difference = time1 - time2;
} else {
difference = time2 - time1;
}
// Allow variable difference to be regarded as same based on format
if (STIME_FORMAT_GET(short_time1) == TIME_FORMAT_DAYS || STIME_FORMAT_GET(short_time2) == TIME_FORMAT_DAYS) {
if (difference > 2 * 24 * 3600) { // Two days
return false;
}
} else if (STIME_FORMAT_GET(short_time1) == TIME_FORMAT_HOURS || STIME_FORMAT_GET(short_time2) == TIME_FORMAT_HOURS) {
if (difference > 2 * 3600) { // Two hours
return false;
}
} else if (STIME_FORMAT_GET(short_time1) == TIME_FORMAT_MINUTES || STIME_FORMAT_GET(short_time2) == TIME_FORMAT_MINUTES) {
if (difference > 5 * 60) { // 5 minutes
return false;
}
} else {
if (difference > 10) { // 10 seconds
return false;
}
}
return true;
}
int8_t ws_pae_time_diff_calc(uint64_t curr_time, uint64_t comp_time, uint32_t *time_diff, bool future)
{
int32_t difference;
*time_diff = 0;
// Comparison time is in future
if (curr_time < comp_time) {
if (!future) {
// Do not allow times in future
return -1;
}
difference = comp_time - curr_time;
} else {
// Comparison time is in past
if (future) {
// Do not allow times in past
return -1;
}
difference = curr_time - comp_time;
}
// If difference is more two years time is invalid
if (difference > SEC_MAXIMUM_LIFETIME) {
return -1;
}
*time_diff = difference;
return 0;
}
uint64_t ws_pae_current_time_get(void)
{
if (system_time_callback) {
return system_time_callback();
}
return current_time;
}
void ws_pae_current_time_update(uint16_t seconds)
{
current_time += seconds;
}
int8_t ws_pae_current_time_set(uint64_t time)
{
current_time = time;
if (system_time_callback) {
uint64_t system_time = system_time_callback();
// System time has gone backwards
if (system_time < current_time || system_time > current_time + SYSTEM_TIME_MAXIMUM_DIFF) {
tr_error("FATAL: system time less than reference time or more than 12 months in future: %"PRIi64" reference time: %"PRIi64, system_time, current_time);
return -1;
}
} else {
current_time += FRAME_COUNTER_STORE_FORCE_INTERVAL + CURRENT_TIME_INCREMENT_VALUE;
}
return 0;
}
void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callback)
{
system_time_callback = callback;
}
#endif /* HAVE_WS */

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2020, 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 WS_PAE_TIME_H_
#define WS_PAE_TIME_H_
/*
* Port access entity time functions.
*
*/
typedef enum {
TIME_FORMAT_SECONDS = 0,
TIME_FORMAT_MINUTES,
TIME_FORMAT_HOURS,
TIME_FORMAT_DAYS,
} time_format_t;
#define STIME_TIME_BITS 14
#define STIME_TIME_MAX 0x3FFF
#define STIME_TIME_MASK STIME_TIME_MAX
#define STIME_FORMAT_GET(stime) (stime >> STIME_TIME_BITS)
#define STIME_TIME_GET(stime) (stime & STIME_TIME_MASK)
// Maximum difference in stored and indicated system time
#define SYSTEM_TIME_MAXIMUM_DIFF (60 * 60 * 24 * 30 * 12)
/**
* ws_pae_time_to_short_convert convert time to short format
*
* \param time time in seconds to convert
*
* \return < 0 failure
* \return >= 0 success
*
*/
uint16_t ws_pae_time_to_short_convert(uint32_t time);
/**
* ws_pae_time_from_short_convert convert short time to time format
*
* \param short_time short_time to convert
*
* \return time in seconds
*
*/
uint32_t ws_pae_time_from_short_convert(uint16_t short_time);
/**
* ws_pae_time_from_short_time_compare compare two times in short format
*
* \param short_time1 time 1 to compare
* \param short_time1 time 2 to compare
*
* \return true times are equal
* \return false times are not equal
*
*/
bool ws_pae_time_from_short_time_compare(uint16_t short_time1, uint16_t short_time2);
/**
* ws_pae_time_diff_calc calculates difference between two times
*
* \param curr_time current time
* \param comp_time time which is compared
* \param time_diff returns time difference
* \param future compared time should in future
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_time_diff_calc(uint64_t curr_time, uint64_t comp_time, uint32_t *time_diff, bool future);
/**
* ws_pae_current_time_get gets current time
*
* \return current time in seconds after 1970
*
*/
uint64_t ws_pae_current_time_get(void);
/**
* ws_pae_current_time_get updates current time
*
* \param seconds seconds to be added to current time
*
*/
void ws_pae_current_time_update(uint16_t seconds);
/**
* ws_pae_current_time_set sets current time
*
* \param time new time
*
* \return < 0 failure
* \return >= 0 success
*/
int8_t ws_pae_current_time_set(uint64_t time);
#endif /* WS_PAE_KEY_STORAGE_H_ */

View File

@ -26,6 +26,7 @@
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_cfg_settings.h"
#include "Security/protocols/sec_prot_cfg.h"
#include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_timers.h"
#ifdef HAVE_WS #ifdef HAVE_WS

View File

@ -18,18 +18,6 @@
#ifndef WS_PAE_TIMERS_H_ #ifndef WS_PAE_TIMERS_H_
#define WS_PAE_TIMERS_H_ #define WS_PAE_TIMERS_H_
typedef struct sec_timer_cfg_s {
uint32_t gtk_expire_offset; /* GTK lifetime; GTK_EXPIRE_OFFSET (seconds) */
uint32_t pmk_lifetime; /* PMK lifetime (seconds) */
uint32_t ptk_lifetime; /* PTK lifetime (seconds) */
uint16_t gtk_new_act_time; /* GTK_NEW_ACTIVATION_TIME (1/X of expire offset) */
uint16_t revocat_lifetime_reduct; /* REVOCATION_LIFETIME_REDUCTION (reduction of lifetime) */
uint16_t gtk_request_imin; /* GTK_REQUEST_IMIN (seconds) */
uint16_t gtk_request_imax; /* GTK_REQUEST_IMAX (seconds) */
uint16_t gtk_max_mismatch; /* GTK_MAX_MISMATCH (seconds) */
uint8_t gtk_new_install_req; /* GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime) */
} sec_timer_cfg_t;
/** /**
* ws_pae_timers_settings_init initializes timer settings structure * ws_pae_timers_settings_init initializes timer settings structure
* *

View File

@ -23,7 +23,9 @@
#include <net_ws_test.h> #include <net_ws_test.h>
#include "fhss_config.h" #include "fhss_config.h"
#include "ws_management_api.h" #include "ws_management_api.h"
#include "mac_api.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bbr_api_internal.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h"

View File

@ -1714,7 +1714,11 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP); buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP);
buf->interface = cur; buf->interface = cur;
if (aro) {
tr_info("Build NA ARO");
} else {
tr_info("Build NA"); tr_info("Build NA");
}
return (buf); return (buf);
} }

View File

@ -35,5 +35,10 @@ void ns_monitor_timer(uint16_t seconds);
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical); int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical);
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
bool ns_monitor_packet_allocation_allowed(void);
#endif // _NS_MONITOR_H #endif // _NS_MONITOR_H

View File

@ -62,6 +62,8 @@ typedef struct ns_monitor__s {
static ns_monitor_t *ns_monitor_ptr = NULL; static ns_monitor_t *ns_monitor_ptr = NULL;
static uint8_t ns_dyn_mem_rate_limiting_threshold_percentage = 0; // Percentage of free memory required to allow routing
typedef void (ns_maintenance_gc_cb)(bool full_gc); typedef void (ns_maintenance_gc_cb)(bool full_gc);
/* /*
@ -189,3 +191,31 @@ int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage
return -1; return -1;
} }
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
{
if (free_heap_percentage < 100) {
ns_dyn_mem_rate_limiting_threshold_percentage = free_heap_percentage;
return 0;
}
return -1;
}
bool ns_monitor_packet_allocation_allowed(void)
{
// If there is no packets to forward this should not be blocked.
// There should be cleanup routine enabled that will remove unneeded memory to prevent locks
// this could trigger a function to clean packets from routing and allow newest packets
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold_percentage) {
if (ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_stat->heap_sector_size / 100 * (100 - ns_dyn_mem_rate_limiting_threshold_percentage)) {
// Packet allocation not allowed as memory is running low.
return false;
}
}
return true;
}

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2020, 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.
*/
#include "string.h"
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "MAC/IEEE802_15_4/mac_defines.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#define TRACE_GROUP "mcth"
int8_t mac_cca_thr_init(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit)
{
// No changes
if (rf_ptr->cca_threshold &&
(number_of_channels == rf_ptr->cca_threshold->number_of_channels) &&
(default_dbm == rf_ptr->cca_threshold->default_dbm) &&
(high_limit == rf_ptr->cca_threshold->high_limit) &&
(low_limit == rf_ptr->cca_threshold->low_limit)) {
return -1;
}
// Validate given dBm range. Default must be in between high and low limit.
if ((default_dbm > high_limit) || (default_dbm < low_limit)) {
return -1;
}
mac_cca_thr_deinit(rf_ptr);
rf_ptr->cca_threshold = ns_dyn_mem_alloc(sizeof(mac_cca_threshold_s));
if (!rf_ptr->cca_threshold) {
return -1;
}
rf_ptr->cca_threshold->ch_thresholds = ns_dyn_mem_alloc(number_of_channels);
if (!rf_ptr->cca_threshold->ch_thresholds) {
ns_dyn_mem_free(rf_ptr->cca_threshold);
rf_ptr->cca_threshold = 0;
return -1;
}
memset(rf_ptr->cca_threshold->ch_thresholds, default_dbm, number_of_channels);
rf_ptr->cca_threshold->high_limit = high_limit;
rf_ptr->cca_threshold->low_limit = low_limit;
rf_ptr->cca_threshold->default_dbm = default_dbm;
rf_ptr->cca_threshold->number_of_channels = number_of_channels;
tr_info("Initialized CCA threshold: %u, %i, %i, %i", number_of_channels, default_dbm, high_limit, low_limit);
return 0;
}
int8_t mac_cca_thr_deinit(protocol_interface_rf_mac_setup_s *rf_ptr)
{
if (!rf_ptr->cca_threshold) {
return -1;
}
ns_dyn_mem_free(rf_ptr->cca_threshold->ch_thresholds);
ns_dyn_mem_free(rf_ptr->cca_threshold);
rf_ptr->cca_threshold = 0;
return 0;
}
int8_t mac_cca_thr_get_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel)
{
if (!rf_ptr->cca_threshold) {
return CCA_FAILED_DBM;
}
// If channel is unknown, use default threshold
if (channel > (rf_ptr->cca_threshold->number_of_channels - 1)) {
return rf_ptr->cca_threshold->default_dbm;
}
return rf_ptr->cca_threshold->ch_thresholds[channel];
}
static int8_t mac_cca_thr_set_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
{
if (rf_ptr->cca_threshold->ch_thresholds[channel] != dbm) {
rf_ptr->cca_threshold->ch_thresholds[channel] = dbm;
return 0;
}
return -1;
}
static int8_t mac_cca_thr_update_channel_threshold(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
{
// Already on low limit
if (rf_ptr->cca_threshold->ch_thresholds[channel] == rf_ptr->cca_threshold->low_limit) {
return -1;
}
// Already using lower threshold
if (rf_ptr->cca_threshold->ch_thresholds[channel] <= (dbm - CCA_THRESHOLD_STEP)) {
return -1;
}
// Do not set below configured low limit
if ((dbm - CCA_THRESHOLD_STEP) < rf_ptr->cca_threshold->low_limit) {
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->low_limit);
}
return mac_cca_thr_set_dbm(rf_ptr, channel, dbm - CCA_THRESHOLD_STEP);
}
static int8_t mac_cca_thr_channel_failed(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel)
{
// Already on high limit
if (rf_ptr->cca_threshold->ch_thresholds[channel] == rf_ptr->cca_threshold->high_limit) {
return -1;
}
// Do not set above configured high limit
if ((rf_ptr->cca_threshold->ch_thresholds[channel] + CCA_THRESHOLD_STEP) > rf_ptr->cca_threshold->high_limit) {
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->high_limit);
}
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->ch_thresholds[channel] + CCA_THRESHOLD_STEP);
}
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
{
if (!rf_ptr->cca_threshold) {
return -1;
}
if (channel > (rf_ptr->cca_threshold->number_of_channels - 1)) {
return -1;
}
if (dbm == CCA_FAILED_DBM) {
if (mac_cca_thr_channel_failed(rf_ptr, channel)) {
return -1;
}
} else {
if (mac_cca_thr_update_channel_threshold(rf_ptr, channel, dbm)) {
return -1;
}
}
tr_debug("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
return 0;
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2020, 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 MAC_CCA_THRESHOLD_H_
#define MAC_CCA_THRESHOLD_H_
#define CCA_THRESHOLD_STEP 1
#define CCA_FAILED_DBM 0x7F
typedef struct mac_cca_threshold {
int8_t *ch_thresholds;
int8_t high_limit;
int8_t low_limit;
int8_t default_dbm;
uint8_t number_of_channels;
} mac_cca_threshold_s;
/**
* @brief Initialize automatic CCA threshold.
* @param rf_ptr Pointer to MAC instance.
* @param number_of_channels Number of MAC channels.
* @param default_dbm Default threshold.
* @param high_limit Highest allowed CCA threshold.
* @param low_limit Lowest allowed CCA threshold.
* @return 0 Success, negative Failed.
*/
int8_t mac_cca_thr_init(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit);
/**
* @brief Deinitialize automatic CCA threshold.
* @param rf_ptr Pointer to MAC instance.
* @return 0 Success, negative Not found.
*/
int8_t mac_cca_thr_deinit(protocol_interface_rf_mac_setup_s *rf_ptr);
/**
* @brief Read CCA threshold of specific channel.
* @param channel Channel.
* @return CCA threshold (dBm), CCA_FAILED_DBM Feature not enabled.
*/
int8_t mac_cca_thr_get_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel);
/**
* @brief Update CCA threshold of specific channel.
* @param channel Channel.
* @param dbm CCA threshold (dBm).
* @return 0 Updated, negative Already using this value.
*/
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm);
#endif /* MAC_CCA_THRESHOLD_H_ */

View File

@ -91,11 +91,13 @@ typedef struct mac_pre_build_frame {
uint8_t csma_periods_left; uint8_t csma_periods_left;
uint8_t fhss_retry_count; uint8_t fhss_retry_count;
uint8_t fhss_cca_retry_count; uint8_t fhss_cca_retry_count;
uint16_t initial_tx_channel;
uint32_t tx_time; uint32_t tx_time;
bool upper_layer_request: 1; bool upper_layer_request: 1;
bool mac_allocated_payload_ptr: 1; bool mac_allocated_payload_ptr: 1;
bool asynch_request: 1; bool asynch_request: 1;
bool message_builded: 1; bool message_builded: 1;
bool DSN_allocated: 1;
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
unsigned priority: 2; unsigned priority: 2;
struct mac_pre_build_frame *next; //Pointer for queue purpose struct mac_pre_build_frame *next; //Pointer for queue purpose

View File

@ -276,6 +276,7 @@ typedef struct protocol_interface_rf_mac_setup {
struct arm_device_driver_list *tun_extension_rf_driver; struct arm_device_driver_list *tun_extension_rf_driver;
/* End of API Control */ /* End of API Control */
struct mlme_scan_conf_s *mac_mlme_scan_resp; struct mlme_scan_conf_s *mac_mlme_scan_resp;
struct mac_cca_threshold *cca_threshold;
//beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr; //beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr;
struct mac_statistics_s *mac_statistics; struct mac_statistics_s *mac_statistics;
/* FHSS API*/ /* FHSS API*/

View File

@ -34,6 +34,7 @@
#include "fhss_api.h" #include "fhss_api.h"
#include "platform/arm_hal_interrupt.h" #include "platform/arm_hal_interrupt.h"
#include "common_functions.h" #include "common_functions.h"
#include "Core/include/ns_monitor.h"
#include "MAC/IEEE802_15_4/sw_mac_internal.h" #include "MAC/IEEE802_15_4/sw_mac_internal.h"
#include "MAC/IEEE802_15_4/mac_defines.h" #include "MAC/IEEE802_15_4/mac_defines.h"
@ -45,6 +46,7 @@
#include "MAC/IEEE802_15_4/mac_mcps_sap.h" #include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h" #include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
#include "MAC/IEEE802_15_4/mac_indirect_data.h" #include "MAC/IEEE802_15_4/mac_indirect_data.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#include "MAC/rf_driver_storage.h" #include "MAC/rf_driver_storage.h"
#include "sw_mac.h" #include "sw_mac.h"
@ -74,8 +76,6 @@ static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s
static int8_t mac_tasklet_event_handler = -1; static int8_t mac_tasklet_event_handler = -1;
static ns_mem_heap_size_t ns_dyn_mem_rate_limiting_threshold = 0xFFFFFFFF;
/** /**
* Get PHY time stamp. * Get PHY time stamp.
* *
@ -1196,6 +1196,9 @@ static void mac_mcps_sap_data_tasklet(arm_event_s *event)
case MAC_MLME_SCAN_CONFIRM_HANDLER: case MAC_MLME_SCAN_CONFIRM_HANDLER:
mac_mlme_scan_confirmation_handle((protocol_interface_rf_mac_setup_s *) event->data_ptr); mac_mlme_scan_confirmation_handle((protocol_interface_rf_mac_setup_s *) event->data_ptr);
break; break;
case MAC_CCA_THR_UPDATE:
mac_cca_threshold_update((protocol_interface_rf_mac_setup_s *) event->data_ptr, event->event_data >> 8, (int8_t) event->event_data);
break;
case MAC_SAP_TRIG_TX: case MAC_SAP_TRIG_TX:
mac_clear_active_event((protocol_interface_rf_mac_setup_s *) event->data_ptr, MAC_SAP_TRIG_TX); mac_clear_active_event((protocol_interface_rf_mac_setup_s *) event->data_ptr, MAC_SAP_TRIG_TX);
mac_mcps_trig_buffer_from_queue((protocol_interface_rf_mac_setup_s *) event->data_ptr); mac_mcps_trig_buffer_from_queue((protocol_interface_rf_mac_setup_s *) event->data_ptr);
@ -1221,7 +1224,9 @@ mac_pre_build_frame_t *mcps_sap_prebuild_frame_buffer_get(uint16_t payload_size)
return NULL; return NULL;
} }
memset(buffer, 0, sizeof(mac_pre_build_frame_t)); memset(buffer, 0, sizeof(mac_pre_build_frame_t));
buffer->initial_tx_channel = 0xffff;
buffer->aux_header.frameCounter = 0xffffffff; buffer->aux_header.frameCounter = 0xffffffff;
buffer->DSN_allocated = false;
if (payload_size) { if (payload_size) {
//Mac interlnal payload allocate //Mac interlnal payload allocate
buffer->mac_payload = ns_dyn_mem_temporary_alloc(payload_size); buffer->mac_payload = ns_dyn_mem_temporary_alloc(payload_size);
@ -1498,7 +1503,10 @@ static void mcps_generic_sequence_number_allocate(protocol_interface_rf_mac_setu
switch (buffer->fcf_dsn.frametype) { switch (buffer->fcf_dsn.frametype) {
case MAC_FRAME_CMD: case MAC_FRAME_CMD:
case MAC_FRAME_DATA: case MAC_FRAME_DATA:
if (!buffer->DSN_allocated) {
buffer->fcf_dsn.DSN = mac_mlme_set_new_sqn(rf_ptr); buffer->fcf_dsn.DSN = mac_mlme_set_new_sqn(rf_ptr);
buffer->DSN_allocated = true;
}
break; break;
case MAC_FRAME_BEACON: case MAC_FRAME_BEACON:
buffer->fcf_dsn.DSN = mac_mlme_set_new_beacon_sqn(rf_ptr); buffer->fcf_dsn.DSN = mac_mlme_set_new_beacon_sqn(rf_ptr);
@ -2126,8 +2134,8 @@ void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf)
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length) mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length)
{ {
// check that system has enough space to handle the new packet // check that system has enough space to handle the new packet
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat(); if (!ns_monitor_packet_allocation_allowed()) {
if (ns_dyn_mem_stat && ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_rate_limiting_threshold) { // stack can not handle new packets for routing
return NULL; return NULL;
} }
@ -2251,6 +2259,25 @@ void mcps_sap_trig_tx(void *mac_ptr)
} }
} }
void mac_cca_threshold_event_send(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int16_t dbm)
{
// Return if feature is not initialized
if (!rf_ptr->cca_threshold) {
return;
}
uint16_t data = channel << 8 | (uint8_t) dbm;
arm_event_s event = {
.receiver = mac_tasklet_event_handler,
.sender = 0,
.event_id = 0,
.event_data = data,
.data_ptr = rf_ptr,
.event_type = MAC_CCA_THR_UPDATE,
.priority = ARM_LIB_LOW_PRIORITY_EVENT,
};
eventOS_event_send(&event);
}
void mac_generic_event_trig(uint8_t event_type, void *mac_ptr, bool low_latency) void mac_generic_event_trig(uint8_t event_type, void *mac_ptr, bool low_latency)
{ {
@ -2363,18 +2390,6 @@ uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_set
return confirmation.status; return confirmation.status;
} }
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
{
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
if (ns_dyn_mem_stat && free_heap_percentage < 100) {
ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * (100 - free_heap_percentage);
return 0;
}
return -1;
}
void mcps_pending_packet_counter_update_check(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) void mcps_pending_packet_counter_update_check(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{ {
if (buffer->fcf_dsn.securityEnabled) { if (buffer->fcf_dsn.securityEnabled) {

View File

@ -56,6 +56,7 @@ typedef enum {
#define MAC_MLME_SCAN_CONFIRM_HANDLER 6 #define MAC_MLME_SCAN_CONFIRM_HANDLER 6
#define MAC_SAP_TRIG_TX 7 #define MAC_SAP_TRIG_TX 7
#define MCPS_SAP_DATA_ACK_CNF_EVENT 8 #define MCPS_SAP_DATA_ACK_CNF_EVENT 8
#define MAC_CCA_THR_UPDATE 9
// Default number of CSMA-CA periods // Default number of CSMA-CA periods
#define MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS 1 #define MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS 1
@ -142,4 +143,6 @@ uint32_t mac_mcps_sap_get_phy_timestamp(struct protocol_interface_rf_mac_setup *
void mcps_pending_packet_counter_update_check(struct protocol_interface_rf_mac_setup *rf_mac_setup, mac_pre_build_frame_t *buffer); void mcps_pending_packet_counter_update_check(struct protocol_interface_rf_mac_setup *rf_mac_setup, mac_pre_build_frame_t *buffer);
void mac_cca_threshold_event_send(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint8_t channel, int16_t dbm);
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */ #endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */

View File

@ -48,6 +48,7 @@
#include "MAC/IEEE802_15_4/mac_timer.h" #include "MAC/IEEE802_15_4/mac_timer.h"
#include "MAC/IEEE802_15_4/mac_pd_sap.h" #include "MAC/IEEE802_15_4/mac_pd_sap.h"
#include "MAC/IEEE802_15_4/mac_mcps_sap.h" #include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#include "MAC/virtual_rf/virtual_rf_defines.h" #include "MAC/virtual_rf/virtual_rf_defines.h"
#include "MAC/rf_driver_storage.h" #include "MAC/rf_driver_storage.h"
@ -668,14 +669,50 @@ static int8_t mac_mlme_set_ack_wait_duration(protocol_interface_rf_mac_setup_s *
return 0; return 0;
} }
static void mac_mlme_trig_pending_ack(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_device_descriptor_t *device_ptr)
{
platform_enter_critical();
if (rf_mac_setup->mac_ack_tx_active && !rf_mac_setup->ack_tx_possible &&
device_ptr->PANId == rf_mac_setup->enhanced_ack_buffer.DstPANId) {
//Compare address for pending neigbour add
if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) {
uint16_t short_id = common_read_16_bit(rf_mac_setup->enhanced_ack_buffer.DstAddr);
if (short_id == device_ptr->ShortAddress) {
rf_mac_setup->ack_tx_possible = true;
}
} else if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_64_BIT) {
if (memcmp(device_ptr->ExtAddress, rf_mac_setup->enhanced_ack_buffer.DstAddr, 8) == 0) {
rf_mac_setup->ack_tx_possible = true;
}
}
}
platform_exit_critical();
}
static int8_t mac_mlme_device_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req) static int8_t mac_mlme_device_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
{ {
if (set_req->value_size != sizeof(mlme_device_descriptor_t)) { if (set_req->value_size != sizeof(mlme_device_descriptor_t)) {
return -1; return -1;
} }
if (mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup) != 0) {
return -1;
}
return mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup); mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer);
return 0;
}
static int8_t mac_mlme_device_pending_ack_trig(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
{
if (set_req->value_size != sizeof(mlme_device_descriptor_t)) {
return -1;
}
mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer);
return 0;
} }
static int8_t mac_mlme_key_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req) static int8_t mac_mlme_key_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
@ -754,6 +791,8 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
return mac_mlme_set_ack_wait_duration(rf_mac_setup, set_req); return mac_mlme_set_ack_wait_duration(rf_mac_setup, set_req);
case macDeviceTable: case macDeviceTable:
return mac_mlme_device_description_set(rf_mac_setup, set_req); return mac_mlme_device_description_set(rf_mac_setup, set_req);
case macDevicePendingAckTrig:
return mac_mlme_device_pending_ack_trig(rf_mac_setup, set_req);
case macKeyTable: case macKeyTable:
return mac_mlme_key_description_set(rf_mac_setup, set_req); return mac_mlme_key_description_set(rf_mac_setup, set_req);
case macDefaultKeySource: case macDefaultKeySource:
@ -768,6 +807,10 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8); memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
} }
return 0; return 0;
case macCCAThresholdStart:
pu8 = (uint8_t *) set_req->value_pointer;
mac_cca_thr_init(rf_mac_setup, *pu8, *((int8_t *)pu8 + 1), *((int8_t *)pu8 + 2), *((int8_t *)pu8 + 3));
return 0;
case mac802_15_4Mode: case mac802_15_4Mode:
pu8 = (uint8_t *) set_req->value_pointer; pu8 = (uint8_t *) set_req->value_pointer;
if (rf_mac_setup->current_mac_mode == *pu8) { if (rf_mac_setup->current_mac_mode == *pu8) {
@ -1059,6 +1102,7 @@ void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_ma
ns_dyn_mem_free(rf_mac->mac_beacon_payload); ns_dyn_mem_free(rf_mac->mac_beacon_payload);
mac_sec_mib_deinit(rf_mac); mac_sec_mib_deinit(rf_mac);
mac_cca_thr_deinit(rf_mac);
ns_dyn_mem_free(rf_mac); ns_dyn_mem_free(rf_mac);
} }
} }

View File

@ -34,6 +34,7 @@
#include "MAC/IEEE802_15_4/mac_mlme.h" #include "MAC/IEEE802_15_4/mac_mlme.h"
#include "MAC/IEEE802_15_4/mac_filter.h" #include "MAC/IEEE802_15_4/mac_filter.h"
#include "MAC/IEEE802_15_4/mac_mcps_sap.h" #include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#include "MAC/rf_driver_storage.h" #include "MAC/rf_driver_storage.h"
/* Define TX Timeot Period */ /* Define TX Timeot Period */
@ -45,7 +46,7 @@
#define MIN_FHSS_CSMA_PERIOD_US 5000 #define MIN_FHSS_CSMA_PERIOD_US 5000
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 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); static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr, uint16_t failed_channel);
void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup) void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
@ -273,7 +274,7 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) { if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) {
if (rf_mac_setup->rf_csma_extension_supported) { if (rf_mac_setup->rf_csma_extension_supported) {
mac_sap_cca_fail_cb(rf_mac_setup); mac_sap_cca_fail_cb(rf_mac_setup, 0xffff);
return; return;
} }
@ -328,7 +329,7 @@ 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) static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr, uint16_t failed_channel)
{ {
if (rf_ptr->mac_ack_tx_active) { if (rf_ptr->mac_ack_tx_active) {
if (rf_ptr->active_pd_data_request) { if (rf_ptr->active_pd_data_request) {
@ -340,6 +341,11 @@ static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { 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 //Send MAC_CCA_FAIL
mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
if (failed_channel != 0xffff && rf_ptr->active_pd_data_request) {
if (failed_channel == rf_ptr->active_pd_data_request->initial_tx_channel) {
mac_cca_threshold_event_send(rf_ptr, failed_channel, CCA_FAILED_DBM);
}
}
} else { } else {
timer_mac_stop(rf_ptr); timer_mac_stop(rf_ptr);
mac_csma_BE_update(rf_ptr); mac_csma_BE_update(rf_ptr);
@ -414,7 +420,7 @@ static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
mcps_pending_packet_counter_update_check(rf_ptr, rf_ptr->active_pd_data_request); mcps_pending_packet_counter_update_check(rf_ptr, rf_ptr->active_pd_data_request);
//GEN TX failure //GEN TX failure
mac_sap_cca_fail_cb(rf_ptr); mac_sap_cca_fail_cb(rf_ptr, 0xffff);
} }
} }
@ -442,6 +448,11 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
} }
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) { if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel;
int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel);
if (CCA_FAILED_DBM != channel_cca_threshold) {
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, (uint8_t *)&channel_cca_threshold);
}
return PHY_TX_ALLOWED; return PHY_TX_ALLOWED;
} }
@ -458,7 +469,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); 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 // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer
if (tx_handle_retval == -1) { if (tx_handle_retval == -1) {
mac_sap_cca_fail_cb(rf_ptr); mac_sap_cca_fail_cb(rf_ptr, 0xffff);
return PHY_TX_NOT_ALLOWED; return PHY_TX_NOT_ALLOWED;
} }
// When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back
@ -470,6 +481,13 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION); mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION);
return PHY_TX_NOT_ALLOWED; return PHY_TX_NOT_ALLOWED;
} }
if (rf_ptr->mac_cca_retry == 0 && rf_ptr->active_pd_data_request) {
rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel;
}
int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel);
if (CCA_FAILED_DBM != channel_cca_threshold) {
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, (uint8_t *)&channel_cca_threshold);
}
if (active_buf->csma_periods_left > 0) { if (active_buf->csma_periods_left > 0) {
active_buf->csma_periods_left--; active_buf->csma_periods_left--;
active_buf->tx_time += rf_ptr->multi_cca_interval; active_buf->tx_time += rf_ptr->multi_cca_interval;
@ -501,7 +519,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
rf_ptr->mac_tx_retry += tx_retry; rf_ptr->mac_tx_retry += tx_retry;
timer_mac_stop(rf_ptr); timer_mac_stop(rf_ptr);
} }
uint16_t failed_channel = rf_ptr->mac_channel;
if (rf_ptr->fhss_api && rf_ptr->active_pd_data_request->asynch_request == false) { if (rf_ptr->fhss_api && rf_ptr->active_pd_data_request->asynch_request == false) {
/* waiting_ack == false allows FHSS to change back to RX channel after transmission /* waiting_ack == false allows FHSS to change back to RX channel after transmission
* tx_completed == true allows FHSS to delete stored failure handles * tx_completed == true allows FHSS to delete stored failure handles
@ -543,7 +561,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
break; break;
case PHY_LINK_CCA_FAIL: case PHY_LINK_CCA_FAIL:
mac_sap_cca_fail_cb(rf_ptr); mac_sap_cca_fail_cb(rf_ptr, failed_channel);
break; break;
case PHY_LINK_CCA_OK: case PHY_LINK_CCA_OK:
@ -788,11 +806,17 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
return -1; return -1;
} }
if (rf_ptr->enhanced_ack_buffer.fcf_dsn.securityEnabled == 0 || rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0) {
//Unsecured data will be acked immediately
rf_ptr->ack_tx_possible = true;
} else {
if (mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) { if (mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) {
rf_ptr->ack_tx_possible = true; rf_ptr->ack_tx_possible = true;
} else { } else {
rf_ptr->ack_tx_possible = false; rf_ptr->ack_tx_possible = false;
} }
}
return mcps_generic_ack_build(rf_ptr, true); return mcps_generic_ack_build(rf_ptr, true);
} }
@ -898,7 +922,7 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
if (pd_data_ind->data_len < 3) { if (pd_data_ind->data_len < 3) {
return -1; return -1;
} }
mac_cca_threshold_event_send(rf_ptr, rf_ptr->mac_channel, pd_data_ind->dbm);
mac_fcf_sequence_t fcf_read; mac_fcf_sequence_t fcf_read;
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr); const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);

View File

@ -295,21 +295,6 @@ int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_de
*device_ptr = *device_descriptor; *device_ptr = *device_descriptor;
if (rf_mac_setup->mac_ack_tx_active && !rf_mac_setup->ack_tx_possible &&
device_ptr->PANId == rf_mac_setup->enhanced_ack_buffer.DstPANId) {
//Compare address for pending neigbour add
if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) {
uint16_t short_id = common_read_16_bit(rf_mac_setup->enhanced_ack_buffer.DstAddr);
if (short_id == device_ptr->ShortAddress) {
rf_mac_setup->ack_tx_possible = true;
}
} else if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_64_BIT) {
if (memcmp(device_ptr->ExtAddress, rf_mac_setup->enhanced_ack_buffer.DstAddr, 8) == 0) {
rf_mac_setup->ack_tx_possible = true;
}
}
}
platform_exit_critical(); platform_exit_critical();
return 0; return 0;

View File

@ -22,6 +22,7 @@
#include "nsdynmemLIB.h" #include "nsdynmemLIB.h"
#include "common_functions.h" #include "common_functions.h"
#include "MAC/rf_driver_storage.h" #include "MAC/rf_driver_storage.h"
#include "Core/include/ns_monitor.h"
typedef struct eth_mac_internal_s { typedef struct eth_mac_internal_s {
eth_mac_api_t *mac_api; eth_mac_api_t *mac_api;
@ -269,6 +270,11 @@ static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uin
return -1; return -1;
} }
if (!ns_monitor_packet_allocation_allowed()) {
// stack can not handle new packets for routing
return -1;
}
eth_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(eth_data_ind_t)); eth_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(eth_data_ind_t));
if (!data_ind) { if (!data_ind) {
return -1; return -1;

View File

@ -23,6 +23,7 @@
#include "common_functions.h" #include "common_functions.h"
#include "ns_trace.h" #include "ns_trace.h"
#include "MAC/rf_driver_storage.h" #include "MAC/rf_driver_storage.h"
#include "Core/include/ns_monitor.h"
#define TRACE_GROUP "seMa" #define TRACE_GROUP "seMa"
@ -317,10 +318,16 @@ static int8_t serial_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len,
(void)link_quality; (void)link_quality;
(void) dbm; (void) dbm;
if (!ns_monitor_packet_allocation_allowed()) {
// stack can not handle new packets for routing
return -1;
}
serial_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(serial_data_ind_t)); serial_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(serial_data_ind_t));
if (!data_ind) { if (!data_ind) {
return -1; return -1;
} }
data_ind->msdu = ns_dyn_mem_temporary_alloc(data_len); data_ind->msdu = ns_dyn_mem_temporary_alloc(data_len);
if (!data_ind->msdu) { if (!data_ind->msdu) {
ns_dyn_mem_free(data_ind); ns_dyn_mem_free(data_ind);

View File

@ -391,7 +391,7 @@ static void rpl_control_addr_notifier(struct protocol_interface_info_entry *inte
} }
} }
static void rpl_control_etx_change_callback(int8_t nwk_id, uint16_t previous_etx, uint16_t current_etx, uint8_t attribute_index) static void rpl_control_etx_change_callback(int8_t nwk_id, uint16_t previous_etx, uint16_t current_etx, uint8_t attribute_index, const uint8_t *mac64)
{ {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(nwk_id); protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(nwk_id);
@ -405,14 +405,29 @@ static void rpl_control_etx_change_callback(int8_t nwk_id, uint16_t previous_et
uint16_t delay = rpl_policy_etx_change_parent_selection_delay(domain); uint16_t delay = rpl_policy_etx_change_parent_selection_delay(domain);
tr_debug("Triggering parent selection due to ETX %s on neigh index %u, etx %u", better ? "better" : "worse", attribute_index, current_etx); tr_debug("Triggering parent selection due to ETX %s on neigh index %u, etx %u", better ? "better" : "worse", attribute_index, current_etx);
rpl_dodag_t *dodag = NULL; rpl_dodag_t *dodag = NULL;
//Define Link Local Address
uint8_t ll_parent_address[16];
memcpy(ll_parent_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_parent_address + 8, mac64, 8);
ll_parent_address[8] ^= 2;
ns_list_foreach(rpl_instance_t, instance, &domain->instances) { ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
if (better) {
dodag = rpl_instance_current_dodag(instance);
}
rpl_instance_trigger_parent_selection(instance, delay, dodag);
if (rpl_instance_am_root(instance)) { if (rpl_instance_am_root(instance)) {
rpl_downward_paths_invalidate(instance); rpl_downward_paths_invalidate(instance);
} else {
if (better) {
//Only react here for candidate updates and when DODAG version is configured
if (rpl_instance_address_is_candidate(instance, ll_parent_address, 0)) {
dodag = rpl_instance_current_dodag(instance);
if (dodag) {
rpl_instance_trigger_parent_selection(instance, delay, dodag);
}
}
} else if (rpl_instance_address_is_parent(instance, ll_parent_address)) {
//Quick reaction for selected parent only
rpl_instance_trigger_parent_selection(instance, delay, NULL);
}
} }
} }
} }
@ -1886,6 +1901,11 @@ static void rpl_domain_print(const rpl_domain_t *domain, route_print_fn_t *print
} }
} }
uint16_t rpl_control_route_table_get(struct rpl_instance *instance, uint8_t *prefix, rpl_route_info_t *output_table, uint16_t output_table_len)
{
return rpl_downward_route_table_get(instance, prefix, output_table, output_table_len);
}
void rpl_control_print(route_print_fn_t *print_fn) void rpl_control_print(route_print_fn_t *print_fn)
{ {
unsigned t = protocol_core_monotonic_time % 10; unsigned t = protocol_core_monotonic_time % 10;

View File

@ -44,6 +44,10 @@ typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle,
typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank); typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank);
typedef struct rpl_route_info {
uint8_t node[8]; /* IID of parent in parent child relation table */
uint8_t parent[8]; /* IID of child in parent child relation table */
} rpl_route_info_t;
typedef struct rpl_domain { typedef struct rpl_domain {
NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances;
@ -186,6 +190,7 @@ ipv6_route_predicate_fn_t *rpl_control_get_route_predicate(rpl_domain_t *domain,
/* Diagnostic APIs */ /* Diagnostic APIs */
void rpl_control_print(route_print_fn_t *print_fn); void rpl_control_print(route_print_fn_t *print_fn);
uint16_t rpl_control_route_table_get(struct rpl_instance *instance, uint8_t *prefix, rpl_route_info_t *output_table, uint16_t output_table_len);
struct rpl_instance *rpl_control_enumerate_instances(rpl_domain_t *domain, struct rpl_instance *instance); struct rpl_instance *rpl_control_enumerate_instances(rpl_domain_t *domain, struct rpl_instance *instance);
struct rpl_instance *rpl_control_lookup_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid); struct rpl_instance *rpl_control_lookup_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid);

View File

@ -1754,6 +1754,52 @@ void rpl_downward_print_instance(rpl_instance_t *instance, route_print_fn_t *pri
} }
} }
uint16_t rpl_downward_route_table_get(rpl_instance_t *instance, uint8_t *prefix, rpl_route_info_t *output_table, uint16_t output_table_len)
{
uint16_t index = 0;
if (!prefix || !output_table || !output_table_len) {
return 0;
}
if (ns_list_is_empty(&instance->dao_targets)) {
return 0;
}
if (!rpl_instance_am_root(instance)) {
// Question should this be available also for non roots in storing mode
return 0;
}
#ifdef HAVE_RPL_ROOT
rpl_downward_compute_paths(instance);
ns_list_foreach(rpl_dao_target_t, target, &instance->dao_targets) {
if (memcmp(target->prefix, prefix, 8) != 0) {
continue;
}
if (target->root) {
/* Target has root structure
* We take the first transit only from table as simple topology is needed
*/
rpl_dao_root_transit_t *transit = ns_list_get_first(&target->info.root.transits);
if (transit) {
memcpy(output_table->node, &target->prefix[8], 8);
memcpy(output_table->parent, &transit->transit[8], 8);
index++;
if (index == output_table_len) {
//table is full
return index;
}
output_table++;
}
}
/* We dont put non roots to list so border router is not visible as a node in list*/
}
#endif
return index;
}
rpl_dao_target_t *rpl_instance_get_active_target_confirmation(rpl_instance_t *instance) rpl_dao_target_t *rpl_instance_get_active_target_confirmation(rpl_instance_t *instance)
{ {
ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) { ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) {

View File

@ -27,6 +27,7 @@ struct rpl_dao_root_transit;
void rpl_downward_dao_slow_timer(struct rpl_instance *instance, uint16_t seconds); void rpl_downward_dao_slow_timer(struct rpl_instance *instance, uint16_t seconds);
void rpl_downward_dao_timer(struct rpl_instance *instance, uint16_t ticks); void rpl_downward_dao_timer(struct rpl_instance *instance, uint16_t ticks);
void rpl_downward_print_instance(struct rpl_instance *instance, route_print_fn_t *print_fn); void rpl_downward_print_instance(struct rpl_instance *instance, route_print_fn_t *print_fn);
uint16_t rpl_downward_route_table_get(rpl_instance_t *instance, uint8_t *prefix, rpl_route_info_t *output_table, uint16_t output_table_len);
void rpl_downward_convert_dodag_preferences_to_dao_path_control(struct rpl_dodag *dodag); void rpl_downward_convert_dodag_preferences_to_dao_path_control(struct rpl_dodag *dodag);
void rpl_downward_process_dao_parent_changes(struct rpl_instance *instance); void rpl_downward_process_dao_parent_changes(struct rpl_instance *instance);

View File

@ -99,7 +99,7 @@ static void kmp_sec_prot_receive_disable(sec_prot_t *prot);
#define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot)); #define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot));
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *cfg) kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg)
{ {
if (!service) { if (!service) {
return 0; return 0;
@ -151,7 +151,8 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get; kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
kmp->sec_prot.type_get = kmp_sec_prot_by_type_get; kmp->sec_prot.type_get = kmp_sec_prot_by_type_get;
kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable; kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable;
kmp->sec_prot.cfg = cfg; kmp->sec_prot.prot_cfg = prot_cfg;
kmp->sec_prot.timer_cfg = timer_cfg;
if (sec_prot->init(&kmp->sec_prot) < 0) { if (sec_prot->init(&kmp->sec_prot) < 0) {
ns_dyn_mem_free(kmp); ns_dyn_mem_free(kmp);

View File

@ -125,12 +125,13 @@ typedef void kmp_api_finished(kmp_api_t *kmp);
* *
* \param service KMP service * \param service KMP service
* \param type KMP type * \param type KMP type
* \param cfg configuration * \param prot_cfg protocol configuration
* \param timer_cfg timer configuration
* *
* \return KMP instance or NULL * \return KMP instance or NULL
* *
*/ */
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *cfg); kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg);
/** /**
* kmp_api_start start KMP api * kmp_api_start start KMP api

View File

@ -189,7 +189,7 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_
// Call state machine // Call state machine
prot->state_machine(prot); prot->state_machine(prot);
// Resets trickle timer to give time for supplicant to answer // Resets trickle timer to give time for supplicant to answer
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
data->init_key_cnt++; data->init_key_cnt++;
} }
// Filters repeated initial EAPOL-key messages // Filters repeated initial EAPOL-key messages
@ -297,7 +297,7 @@ static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks
} }
sec_prot_timer_timeout_handle(prot, &data->common, sec_prot_timer_timeout_handle(prot, &data->common,
&prot->cfg->sec_prot_trickle_params, ticks); &prot->prot_cfg->sec_prot_trickle_params, ticks);
} }
static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot) static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot)
@ -421,7 +421,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE); auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID);
break; break;
@ -445,7 +445,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START); auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_START); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_START);
break; break;
@ -527,7 +527,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING); auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
} else { } else {
// TLS done, indicate success to peer // TLS done, indicate success to peer
if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) { if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) {

View File

@ -404,7 +404,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
} }
// Set retry timeout based on network size // Set retry timeout based on network size
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
// Store sequence ID // Store sequence ID
supp_eap_tls_sec_prot_seq_id_update(prot); supp_eap_tls_sec_prot_seq_id_update(prot);
@ -449,7 +449,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
supp_eap_tls_sec_prot_seq_id_update(prot); supp_eap_tls_sec_prot_seq_id_update(prot);
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST);
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
// Initialize TLS protocol // Initialize TLS protocol
if (supp_eap_tls_sec_prot_init_tls(prot) < 0) { if (supp_eap_tls_sec_prot_init_tls(prot) < 0) {
@ -483,7 +483,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// Store sequence ID // Store sequence ID
if (supp_eap_tls_sec_prot_seq_id_update(prot)) { if (supp_eap_tls_sec_prot_seq_id_update(prot)) {
// When receiving a new sequence number, adds more time for re-send if no response // When receiving a new sequence number, adds more time for re-send if no response
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
} }
// All fragments received for a message // All fragments received for a message

View File

@ -66,6 +66,7 @@ typedef struct {
fwh_sec_prot_msg_e recv_msg; /**< Received message */ fwh_sec_prot_msg_e recv_msg; /**< Received message */
uint8_t nonce[EAPOL_KEY_NONCE_LEN]; /**< Authenticator nonce */ uint8_t nonce[EAPOL_KEY_NONCE_LEN]; /**< Authenticator nonce */
uint8_t new_ptk[PTK_LEN]; /**< PTK (384 bits) */ uint8_t new_ptk[PTK_LEN]; /**< PTK (384 bits) */
uint8_t remote_eui64[8]; /**< Remote EUI-64 used to calculate PTK */
void *recv_pdu; /**< received pdu */ void *recv_pdu; /**< received pdu */
uint16_t recv_size; /**< received pdu size */ uint16_t recv_size; /**< received pdu size */
} fwh_sec_prot_int_t; } fwh_sec_prot_int_t;
@ -265,14 +266,20 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
switch (msg) { switch (msg) {
case FWH_MESSAGE_1: case FWH_MESSAGE_1:
sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys); if (!sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys)) {
ns_dyn_mem_free(kde_start);
return 1;
}
eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys); eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys);
eapol_pdu.msg.key.key_information.key_ack = true; eapol_pdu.msg.key.key_information.key_ack = true;
eapol_pdu.msg.key.key_length = EAPOL_KEY_LEN; eapol_pdu.msg.key.key_length = EAPOL_KEY_LEN;
eapol_pdu.msg.key.key_nonce = data->nonce; eapol_pdu.msg.key.key_nonce = data->nonce;
break; break;
case FWH_MESSAGE_3: case FWH_MESSAGE_3:
sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys); if (!sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys)) {
ns_dyn_mem_free(kde_start);
return -1;
}
eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys); eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys);
eapol_pdu.msg.key.key_information.install = true; eapol_pdu.msg.key.key_information.install = true;
eapol_pdu.msg.key.key_information.key_ack = true; eapol_pdu.msg.key.key_information.key_ack = true;
@ -306,7 +313,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
{ {
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot); fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
sec_prot_timer_timeout_handle(prot, &data->common, &prot->cfg->sec_prot_trickle_params, ticks); sec_prot_timer_timeout_handle(prot, &data->common, &prot->prot_cfg->sec_prot_trickle_params, ticks);
} }
static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
@ -343,7 +350,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1); auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_2); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_2);
break; break;
@ -371,7 +378,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3); auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_4); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_4);
} }
@ -391,12 +398,16 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
} }
// PTK is fresh for installing any GTKs // PTK is fresh for installing any GTKs
sec_prot_keys_ptk_installed_gtk_hash_clear_all(prot->sec_keys); sec_prot_keys_ptk_installed_gtk_hash_clear_all(prot->sec_keys);
/* Store the hash for to-be installed GTK as used for the PTK, on 4WH
this stores only the hash in NVM and does not affect otherwise */
sec_prot_keys_ptk_installed_gtk_hash_set(prot->sec_keys, true);
// If GTK was inserted set it valid // If GTK was inserted set it valid
sec_prot_keys_gtkl_from_gtk_insert_index_set(prot->sec_keys); sec_prot_keys_gtkl_from_gtk_insert_index_set(prot->sec_keys);
// Reset PTK mismatch // Reset PTK mismatch
sec_prot_keys_ptk_mismatch_reset(prot->sec_keys); sec_prot_keys_ptk_mismatch_reset(prot->sec_keys);
// Update PTK // Update PTK
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk); sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->timer_cfg->ptk_lifetime);
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH); sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
} }
break; break;
@ -427,9 +438,7 @@ static int8_t auth_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot); fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
uint8_t local_eui64[8]; uint8_t local_eui64[8];
uint8_t remote_eui64[8]; prot->addr_get(prot, local_eui64, data->remote_eui64);
prot->addr_get(prot, local_eui64, remote_eui64);
uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce; uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
if (!remote_nonce) { if (!remote_nonce) {
@ -438,7 +447,7 @@ static int8_t auth_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
} }
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys); uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
sec_prot_lib_ptk_calc(pmk, local_eui64, remote_eui64, data->nonce, remote_nonce, data->new_ptk); sec_prot_lib_ptk_calc(pmk, local_eui64, data->remote_eui64, data->nonce, remote_nonce, data->new_ptk);
return 0; return 0;
} }

View File

@ -139,7 +139,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot)
sec_prot_init(&data->common); sec_prot_init(&data->common);
sec_prot_state_set(prot, &data->common, FWH_STATE_INIT); sec_prot_state_set(prot, &data->common, FWH_STATE_INIT);
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
data->msg3_received = false; data->msg3_received = false;
data->msg3_retry_wait = false; data->msg3_retry_wait = false;
data->recv_replay_cnt = 0; data->recv_replay_cnt = 0;
@ -337,7 +337,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
if (sec_prot_result_ok_check(&data->common)) { if (sec_prot_result_ok_check(&data->common)) {
// Send 4WH message 2 // Send 4WH message 2
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3);
} else { } else {
// Ready to be deleted // Ready to be deleted
@ -365,7 +365,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
// Send 4WH message 2 // Send 4WH message 2
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
return; return;
} else if (data->recv_msg != FWH_MESSAGE_3) { } else if (data->recv_msg != FWH_MESSAGE_3) {
return; return;
@ -392,7 +392,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
// Sends 4WH Message 4 // Sends 4WH Message 4
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4); supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH); sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
break; break;
@ -409,7 +409,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
tr_info("4WH: finish, wait Message 3 retry"); tr_info("4WH: finish, wait Message 3 retry");
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk); sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->timer_cfg->ptk_lifetime);
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64); sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
data->common.ticks = 60 * 10; // 60 seconds data->common.ticks = 60 * 10; // 60 seconds

View File

@ -226,7 +226,10 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
switch (msg) { switch (msg) {
case GKH_MESSAGE_1: case GKH_MESSAGE_1:
sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys); if (!sec_prot_keys_pmk_replay_cnt_increment(prot->sec_keys)) {
ns_dyn_mem_free(kde_start);
return -1;
}
eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys); eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys);
eapol_pdu.msg.key.key_information.key_ack = true; eapol_pdu.msg.key.key_information.key_ack = true;
eapol_pdu.msg.key.key_information.key_mic = true; eapol_pdu.msg.key.key_information.key_mic = true;
@ -258,7 +261,7 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
{ {
gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot);
sec_prot_timer_timeout_handle(prot, &data->common, &prot->cfg->sec_prot_trickle_params, ticks); sec_prot_timer_timeout_handle(prot, &data->common, &prot->prot_cfg->sec_prot_trickle_params, ticks);
} }
static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot) static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
@ -283,16 +286,16 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
// KMP-CREATE.confirm // KMP-CREATE.confirm
prot->create_conf(prot, SEC_RESULT_OK); prot->create_conf(prot, SEC_RESULT_OK);
// Sends 4WH Message 1 // Sends GKH Message 1
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1); auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1);
// Start trickle timer to re-send if no response // Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2); sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2);
// Store the hash for to-be installed GTK as used for the PTK // Store the hash for to-be installed GTK as used for the PTK
sec_prot_keys_ptk_installed_gtk_hash_set(prot->sec_keys); sec_prot_keys_ptk_installed_gtk_hash_set(prot->sec_keys, false);
break; break;
// Wait GKH message 2 // Wait GKH message 2

View File

@ -268,6 +268,7 @@ static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
// Checks if supplicant indicates that it has valid PMK // Checks if supplicant indicates that it has valid PMK
uint8_t remote_keyid[KEYID_LEN]; uint8_t remote_keyid[KEYID_LEN];
if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) { if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) {
tr_debug("recv PMKID: %s", trace_array(remote_keyid, 16));
uint8_t pmkid[PMKID_LEN]; uint8_t pmkid[PMKID_LEN];
if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) { if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) {
if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) { if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) {
@ -278,6 +279,7 @@ static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
// Checks if supplicant indicates that it has valid PTK // Checks if supplicant indicates that it has valid PTK
if (kde_ptkid_read(kde, kde_len, remote_keyid) >= 0) { if (kde_ptkid_read(kde, kde_len, remote_keyid) >= 0) {
tr_debug("recv PTKID: %s", trace_array(remote_keyid, 16));
uint8_t ptkid[PTKID_LEN]; uint8_t ptkid[PTKID_LEN];
if (sec_prot_lib_ptkid_generate(prot, ptkid, true) >= 0) { if (sec_prot_lib_ptkid_generate(prot, ptkid, true) >= 0) {
if (memcmp(remote_keyid, ptkid, PTKID_LEN) == 0) { if (memcmp(remote_keyid, ptkid, PTKID_LEN) == 0) {

Some files were not shown because too many files have changed in this diff Show More