Skip to content

Commit 37f7ae9

Browse files
Mika TervonenMika Tervonen
authored andcommitted
Time configuration distribution using DHCPv6 vendor data
Border router can distribute timezone and day light saving time configuration to devices joining Wi-SUN network. New ARM defined vendor extension added to DHCP server New Time API extension added to all devices to learn new configuration from network
1 parent 7415bc7 commit 37f7ae9

File tree

9 files changed

+236
-12
lines changed

9 files changed

+236
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Added support for triggering test procedures (e.g. for manually sending DIS, DIO, DAO, PAS, PS, PCS and PC).
77
* Added automatic test procedure triggering during bootstrap (PAS, EAPOL target selection, PCS, DIS, RPL parent selection).
88
* Added checks for Border Router frame counter space exhaustion.
9+
* Added Daylight saving time and time zone configuration distribution using DHCPv6 vendor data during address renewal.
910

1011
### Changes
1112
* PAN_TIMEOUT for medium sized network changed to 30 minutes.

nanostack/ns_time_api.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@
2828

2929
#include "ns_types.h"
3030

31+
/**
32+
* Time zone information structure.
33+
*
34+
* Daylight saving time and time zone information learned by network stack
35+
*
36+
*/
37+
typedef struct timezone_info {
38+
/** Timestamp of the Daylight saving time change*/
39+
uint64_t timestamp;
40+
/** Time zone information in minutes*/
41+
int16_t timezone;
42+
/** Change that is applied when timestamp is reached*/
43+
int16_t deviation;
44+
/** Time configuration status bit field
45+
* "bit xxxxxxxxxxxxxxxS" 0 = false 1 = true Daylight saving time status*/
46+
uint16_t status;
47+
} timezone_info_t;
48+
3149
/**
3250
* System time read callback.
3351
*
@@ -48,6 +66,22 @@ typedef uint64_t ns_time_api_system_time_callback(void);
4866
*/
4967
typedef void ns_time_api_system_time_write_callback(uint64_t write_time);
5068

69+
/**
70+
* New time zone and daylight saving time information learned from stack.
71+
*
72+
* Called when network stack learns the time zone and daylights saving time information.
73+
*
74+
* In Wi-SUN Border router can distribute this information to synchronize all nodes in network.
75+
* This information is updated roughly once a day using DHCPv6 protocol
76+
*
77+
* If network stack does not have the information this is not called and can be called when information becomes available.
78+
* This can be called multiple times with same information.
79+
*
80+
* \param info_ptr time zone and daylight saving time configuration.
81+
*
82+
*/
83+
typedef void ns_time_api_time_configuration_notify_callback(timezone_info_t *info_ptr);
84+
5185
/**
5286
* System time read callback set.
5387
*
@@ -68,4 +102,15 @@ void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callb
68102
*/
69103
void ns_time_api_system_time_write_callback_set(ns_time_api_system_time_write_callback callback_wr);
70104

105+
/**
106+
* Set system time configuration notify callback.
107+
*
108+
* Sets system time configuration notify callback that is called if network stack
109+
* learns time information from other devices in the network.
110+
*
111+
* \param callback_wr system time write callback.
112+
*
113+
*/
114+
void ns_time_api_time_configuration_notify_callback_set(ns_time_api_time_configuration_notify_callback callback_wr);
115+
71116
#endif /* NS_TIME_API_H_ */

nanostack/ws_bbr_api.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ typedef struct bbr_radius_timing {
7474
uint8_t radius_retry_count;
7575
} bbr_radius_timing_t;
7676

77+
/**
78+
* \brief Daylights saving time parameters.
79+
*/
80+
typedef struct bbr_timezone_configuration {
81+
/** Timestamp of the Daylight saving time change*/
82+
uint64_t timestamp;
83+
/** Time zone information in minutes*/
84+
int16_t timezone;
85+
/** Change that is applied when timestamp is reached*/
86+
int16_t deviation;
87+
/** Time configuration status bit field
88+
* "bit xxxxxxxxxxxxxxxS" 0 = false 1 = true Daylight saving time status*/
89+
uint16_t status;
90+
} bbr_timezone_configuration_t;
7791
/**
7892
* Start backbone border router service.
7993
*
@@ -521,4 +535,22 @@ int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timi
521535
*/
522536
int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr);
523537

538+
/**
539+
* \brief A function to set time zone and daylights saving time configuration
540+
*
541+
* Border router distributes this information in DHCP Reply messages to
542+
* all the devices joining to the Wi-SUN mesh network.
543+
*
544+
* Border router keeps this information until reboot and continues to distribute the information.
545+
* If the information is changed the updates are sent to devices in network when they
546+
* renew their address. This can take time from 1 to 24 hours
547+
*
548+
* \param interface_id Network interface ID.
549+
* \param daylight_saving_time_ptr daylights saving time configuration. NULL if you want to remove the configuration.
550+
*
551+
* \return < 0 failure
552+
* \return >= 0 success
553+
*/
554+
int ws_bbr_timezone_configuration_set(int8_t interface_id, bbr_timezone_configuration_t *daylight_saving_time_ptr);
555+
524556
#endif /* WS_BBR_API_H_ */

source/6LoWPAN/ws/ws_bbr_api.c

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix
9797
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
9898
static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
9999

100+
static bbr_timezone_configuration_t *bbr_time_config = NULL;
101+
102+
100103
static rpl_dodag_conf_t rpl_conf = {
101104
// Lifetime values
102105
.default_lifetime = 120,
@@ -488,24 +491,32 @@ static uint8_t *ws_bbr_dhcp_server_dynamic_vendor_data_write(int8_t interfaceId,
488491
// If local time is not available vendor data is not written and data_len is not modified
489492
(void)interfaceId;
490493

491-
uint64_t time_read;
494+
uint64_t time_read = 0;
492495

493-
if (0 != ns_time_system_time_read(&time_read)) {
494-
return ptr;
495-
}
496+
ns_time_system_time_read(&time_read);
496497

497498
if (data_len) {
498-
*data_len += net_vendor_option_current_time_length();
499+
if (time_read) {
500+
*data_len += net_vendor_option_current_time_length();
501+
}
502+
if (bbr_time_config) {
503+
*data_len += net_vendor_option_time_configuration_length();
504+
}
499505
}
500506
if (!ptr) {
501507
return ptr;
502508
}
503-
time_read += 2208988800; // Time starts now from the 0 era instead of First day of Unix (1 Jan 1970)
509+
if (time_read) {
510+
time_read += 2208988800; // Time starts now from the 0 era instead of First day of Unix (1 Jan 1970)
504511

505-
uint32_t era = time_read / (uint64_t)(4294967296);
506-
uint32_t timestamp = time_read - (era * (uint64_t)(4294967296));
507-
ptr = net_vendor_option_current_time_write(ptr, era, timestamp, 0);
512+
uint32_t era = time_read / (uint64_t)(4294967296);
513+
uint32_t timestamp = time_read - (era * (uint64_t)(4294967296));
514+
ptr = net_vendor_option_current_time_write(ptr, era, timestamp, 0);
515+
}
516+
if (bbr_time_config) {
517+
ptr = net_vendor_option_time_configuration_write(ptr, bbr_time_config->timestamp, bbr_time_config->timezone, bbr_time_config->deviation, bbr_time_config->status);
508518

519+
}
509520
return ptr;
510521
}
511522

@@ -1553,3 +1564,32 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
15531564
return -1;
15541565
#endif
15551566
}
1567+
1568+
int ws_bbr_timezone_configuration_set(int8_t interface_id, bbr_timezone_configuration_t *daylight_saving_time_ptr)
1569+
{
1570+
#ifdef HAVE_WS_BORDER_ROUTER
1571+
(void) interface_id;
1572+
1573+
if (!daylight_saving_time_ptr) {
1574+
// Delete configuration
1575+
ns_dyn_mem_free(bbr_time_config);
1576+
bbr_time_config = NULL;
1577+
return 0;
1578+
}
1579+
1580+
if (!bbr_time_config) {
1581+
bbr_time_config = ns_dyn_mem_alloc(sizeof(bbr_timezone_configuration_t));
1582+
}
1583+
1584+
if (!bbr_time_config) {
1585+
return -2;
1586+
}
1587+
*bbr_time_config = *daylight_saving_time_ptr;
1588+
1589+
return 0;
1590+
#else
1591+
(void) interface_id;
1592+
(void) daylight_saving_time_ptr;
1593+
return -1;
1594+
#endif
1595+
}

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,13 @@ static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notif
10031003
net_dns_query_result_set(interface, address, domain, server_info->life_time);
10041004
}
10051005
}
1006+
if (option_type == ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION) {
1007+
timezone_info_t time_configuration;
1008+
if (net_vendor_option_time_configuration_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &time_configuration.timestamp, &time_configuration.timezone, &time_configuration.deviation, &time_configuration.status)) {
1009+
int ret = ns_time_system_timezone_info_notify(&time_configuration);
1010+
tr_info("Network Time configuration %s status:%"PRIu16" time stamp: %"PRIu64" deviation: %"PRId16" Time Zone: %"PRId16, ret == 0 ? "notified" : "notify FAILED", time_configuration.status, time_configuration.timestamp, time_configuration.deviation, time_configuration.timezone);
1011+
}
1012+
}
10061013
if (option_type == ARM_DHCP_VENDOR_DATA_NETWORK_TIME) {
10071014
// Process ARM Network Time
10081015
// Get Current time

source/Service_Libs/utils/ns_time.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
static ns_time_api_system_time_callback *system_time_read_callback = NULL;
2424
static ns_time_api_system_time_write_callback *system_time_write_callback = NULL;
25+
static ns_time_api_time_configuration_notify_callback *system_time_configuration_notify_callback = NULL;
2526

2627
void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callback_rd)
2728
{
@@ -33,6 +34,11 @@ void ns_time_api_system_time_write_callback_set(ns_time_api_system_time_write_ca
3334
system_time_write_callback = callback_wr;
3435
}
3536

37+
void ns_time_api_time_configuration_notify_callback_set(ns_time_api_time_configuration_notify_callback callback_wr)
38+
{
39+
system_time_configuration_notify_callback = callback_wr;
40+
}
41+
3642
int ns_time_system_time_write(uint64_t time_write)
3743
{
3844
if (system_time_write_callback) {
@@ -53,3 +59,13 @@ int ns_time_system_time_read(uint64_t *time_read)
5359

5460
return -1;
5561
}
62+
63+
int ns_time_system_timezone_info_notify(timezone_info_t *info_ptr)
64+
{
65+
if (system_time_configuration_notify_callback && info_ptr) {
66+
system_time_configuration_notify_callback(info_ptr);
67+
return 0;
68+
}
69+
70+
return -1;
71+
}

source/Service_Libs/utils/ns_time.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* \file ns_time.h
2323
* \brief Nanostack internal time handling API.
2424
*/
25+
#include "ns_time_api.h"
2526

2627
/**
2728
* Write new time as a platform time
@@ -51,6 +52,15 @@ int ns_time_system_time_write(uint64_t time_write);
5152
*/
5253
int ns_time_system_time_read(uint64_t *time_read);
5354

54-
55+
/**
56+
* Notify Time zone and daylight saving time information
57+
*
58+
* \param info_ptr time zone information pointer.
59+
*
60+
* \return 0 in success.
61+
* \return <0 in case of errors.
62+
*
63+
*/
64+
int ns_time_system_timezone_info_notify(timezone_info_t *info_ptr);
5565

5666
#endif /* _NS_TIME_H_ */

source/libDHCPv6/libDHCPv6_vendordata.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int3
137137
}
138138

139139
option_len = common_read_16_bit(ptr + 2);
140-
ptr += 4;
140+
ptr += 2 * sizeof(uint16_t);
141141

142142
if (option_len < 3 * sizeof(uint32_t)) {
143143
// Corrupted as not enough room for fields
@@ -147,11 +147,70 @@ uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int3
147147
if (era) {
148148
*era = (int32_t)common_read_32_bit(ptr);
149149
}
150+
150151
if (offset) {
151152
*offset = common_read_32_bit(ptr + sizeof(uint32_t));
152153
}
154+
153155
if (fraction) {
154-
*fraction = common_read_32_bit(ptr + 2 * sizeof(uint32_t));
156+
*fraction = common_read_32_bit(ptr + sizeof(uint32_t) + sizeof(uint32_t));
157+
}
158+
159+
return ptr;
160+
}
161+
162+
uint16_t net_vendor_option_time_configuration_length(void)
163+
{
164+
return 4 + 1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t);
165+
}
166+
167+
uint8_t *net_vendor_option_time_configuration_write(uint8_t *ptr, uint64_t timestamp, int16_t timezone, int16_t deviation, uint16_t status)
168+
{
169+
170+
ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION, ptr);
171+
ptr = common_write_16_bit(1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t), ptr);
172+
ptr = common_write_16_bit(status, ptr);
173+
ptr = common_write_64_bit(timestamp, ptr);
174+
ptr = common_write_16_bit((uint16_t)deviation, ptr);
175+
ptr = common_write_16_bit((uint16_t)timezone, ptr);
176+
return ptr;
177+
}
178+
179+
uint8_t *net_vendor_option_time_configuration_read(uint8_t *ptr, uint16_t length, uint64_t *timestamp, int16_t *timezone, int16_t *deviation, uint16_t *status)
180+
{
181+
uint16_t option_len;
182+
183+
if (length < net_vendor_option_time_configuration_length()) {
184+
// Corrupted as there is no room for all fields
185+
return 0;
186+
}
187+
188+
if (common_read_16_bit(ptr) != ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION) {
189+
return 0;
190+
}
191+
192+
option_len = common_read_16_bit(ptr + sizeof(uint16_t));
193+
ptr += 2 * sizeof(uint16_t);
194+
195+
if (option_len < 1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t)) {
196+
// Corrupted as not enough room for fields
197+
return 0;
198+
}
199+
200+
if (status) {
201+
*status = (uint16_t)common_read_16_bit(ptr);
202+
}
203+
204+
if (timestamp) {
205+
*timestamp = common_read_64_bit(ptr + sizeof(uint16_t));
206+
}
207+
208+
if (deviation) {
209+
*deviation = (int16_t)common_read_16_bit(ptr + sizeof(uint16_t) + sizeof(uint64_t));
210+
}
211+
212+
if (timezone) {
213+
*timezone = (int16_t)common_read_16_bit(ptr + sizeof(uint16_t) + sizeof(uint64_t) + sizeof(uint16_t));
155214
}
156215

157216
return ptr;

source/libDHCPv6/libDHCPv6_vendordata.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@
6666
* */
6767
#define ARM_DHCP_VENDOR_DATA_NETWORK_TIME 298
6868

69+
/* ARM Defined vendor data option to distribute Time configuration
70+
*
71+
* uint16_t status Bit field for status
72+
* bit 1 Daylight saving time status 0 = false 1 = true
73+
* Additional bits reserved for future and are ignored on receive
74+
* uint64_t timestamp Time stamp of the Daylight saving time change
75+
* int16_t deviation Change that is applied when time stamp is reached
76+
* int16_t timezone Time zone information in minutes compared to UTC time
77+
*/
78+
#define ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION 299
79+
6980
/* DHCPv6 vendor options to distribute ARM vendor data*/
7081

7182
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
@@ -78,5 +89,8 @@ uint16_t net_vendor_option_current_time_length(void);
7889
uint8_t *net_vendor_option_current_time_write(uint8_t *ptr, int32_t era, uint32_t offset, uint32_t fraction);
7990
uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int32_t *era, uint32_t *offset, uint32_t *fraction);
8091

92+
uint16_t net_vendor_option_time_configuration_length(void);
93+
uint8_t *net_vendor_option_time_configuration_write(uint8_t *ptr, uint64_t timestamp, int16_t timezone, int16_t deviation, uint16_t status);
94+
uint8_t *net_vendor_option_time_configuration_read(uint8_t *ptr, uint16_t length, uint64_t *timestamp, int16_t *timezone, int16_t *deviation, uint16_t *status);
8195

8296
#endif /* LIBDHCPV6_VENDOR_DATA_H_ */

0 commit comments

Comments
 (0)