Skip to content

Commit 560619d

Browse files
Mika TervonenMika Tervonen
Mika Tervonen
authored and
Mika Tervonen
committed
Add network time vendor data element to DHCPv6 reply message
New ARM vendor data specified where Network time can be distributed Added support for Dynamic vendor data for individual request changed vendor data length to uint16 Removed static variables from border router
1 parent 6d290dc commit 560619d

File tree

9 files changed

+218
-14
lines changed

9 files changed

+218
-14
lines changed

source/6LoWPAN/ws/ws_bbr_api.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "ws_management_api.h"
4343
#include "net_rpl.h"
4444
#include "Service_Libs/nd_proxy/nd_proxy.h"
45+
#include "Service_Libs/utils/ns_time.h"
4546
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
4647
#include "6LoWPAN/ws/ws_pae_controller.h"
4748
#include "6LoWPAN/lowpan_adaptation_interface.h"
@@ -96,9 +97,6 @@ static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix
9697
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
9798
static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
9899

99-
static uint8_t *dhcp_vendor_data_ptr = NULL;
100-
static uint8_t dhcp_vendor_data_len = 0;
101-
102100
static rpl_dodag_conf_t rpl_conf = {
103101
// Lifetime values
104102
.default_lifetime = 120,
@@ -485,9 +483,38 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
485483
return true;
486484
}
487485

486+
static uint8_t *ws_bbr_dhcp_server_dynamic_vendor_data_write(int8_t interfaceId, uint8_t *ptr, uint16_t *data_len)
487+
{
488+
// If local time is not available vendor data is not written and data_len is not modified
489+
(void)interfaceId;
490+
491+
uint64_t time_read;
492+
493+
if (0 != ns_time_system_time_read(&time_read)) {
494+
return ptr;
495+
}
496+
497+
if (data_len) {
498+
*data_len += net_vendor_option_current_time_length();
499+
}
500+
if (!ptr) {
501+
return ptr;
502+
}
503+
time_read += 2208988800; // Time starts now from the 0 era instead of First day of Unix (1 Jan 1970)
504+
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);
508+
509+
return ptr;
510+
}
511+
512+
488513
static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur, uint8_t *global_id)
489514
{
490515
//add DNS server information to DHCP server that is learned from the backbone interface.
516+
uint8_t *dhcp_vendor_data_ptr = NULL;
517+
uint8_t dhcp_vendor_data_len = 0;
491518
uint8_t dns_server_address[16];
492519
uint8_t *dns_search_list_ptr = NULL;
493520
uint8_t dns_search_list_len = 0;
@@ -497,33 +524,40 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
497524
DHCPv6_server_service_set_dns_server(cur->id, global_id, dns_server_address, dns_search_list_ptr, dns_search_list_len);
498525
}
499526

500-
//TODO Generate vendor data in Wi-SUN network include the cached DNS query results in some sort of TLV format
527+
//Generate ARM specific vendor data in Wi-SUN network
528+
// Cached DNS query results
529+
// Network Time
530+
501531
int vendor_data_len = 0;
502532
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
503533
if (pre_resolved_dns_queries[n].domain_name != NULL) {
504534
vendor_data_len += net_dns_option_vendor_option_data_dns_query_length(pre_resolved_dns_queries[n].domain_name);
505535
}
506536
}
537+
507538
if (vendor_data_len) {
508-
ns_dyn_mem_free(dhcp_vendor_data_ptr);
509-
dhcp_vendor_data_ptr = ns_dyn_mem_alloc(vendor_data_len);
539+
dhcp_vendor_data_ptr = ns_dyn_mem_temporary_alloc(vendor_data_len);
510540
if (!dhcp_vendor_data_ptr) {
511541
tr_warn("Vendor info set fail");
512542
return;
513543
}
514544
dhcp_vendor_data_len = vendor_data_len;
515545
}
546+
// Write ARM vendor data
547+
uint8_t *ptr = dhcp_vendor_data_ptr;
548+
516549
if (dhcp_vendor_data_ptr) {
517550
// Write vendor data
518-
uint8_t *ptr = dhcp_vendor_data_ptr;
519551
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
520552
if (pre_resolved_dns_queries[n].domain_name != NULL) {
521553
ptr = net_dns_option_vendor_option_data_dns_query_write(ptr, pre_resolved_dns_queries[n].address, pre_resolved_dns_queries[n].domain_name);
522554
}
523555
}
524556
}
557+
DHCPv6_server_service_set_vendor_data_callback(cur->id, global_id, ARM_ENTERPRISE_NUMBER, ws_bbr_dhcp_server_dynamic_vendor_data_write);
525558

526559
DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
560+
ns_dyn_mem_free(dhcp_vendor_data_ptr);
527561
}
528562

529563
static void wisun_dhcp_address_remove_cb(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info)

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "Common_Protocols/ip.h"
5050
#include "Service_Libs/Trickle/trickle.h"
5151
#include "Service_Libs/fhss/channel_list.h"
52+
#include "Service_Libs/utils/ns_time.h"
5253
#include "6LoWPAN/ws/ws_common_defines.h"
5354
#include "6LoWPAN/ws/ws_common_defines.h"
5455
#include "6LoWPAN/ws/ws_config.h"
@@ -999,6 +1000,34 @@ static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notif
9991000
net_dns_query_result_set(interface, address, domain, server_info->life_time);
10001001
}
10011002
}
1003+
if (option_type == ARM_DHCP_VENDOR_DATA_NETWORK_TIME) {
1004+
// Process ARM Network Time
1005+
// Get Current time
1006+
// Get Round trip time of the DHCP request
1007+
// Estimated error is elapsed time of request
1008+
// If current time difference is larger than estimated error update current time
1009+
// set the time for server time + *.5 RTT
1010+
int32_t era;
1011+
uint32_t offset;
1012+
if (net_vendor_option_current_time_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &era, &offset, NULL)) {
1013+
uint32_t estimated_error = 10;
1014+
uint64_t current_time;
1015+
uint64_t network_time = (era * (uint64_t)(4294967296)) + offset - 2208988800; //Convert to First day of Unix (1 Jan 1970)
1016+
if (0 == ns_time_system_time_read(&current_time)) {
1017+
uint64_t difference;
1018+
if (current_time > network_time) {
1019+
difference = current_time - network_time;
1020+
} else {
1021+
difference = network_time - current_time;
1022+
}
1023+
if (difference > estimated_error) {
1024+
// Larger than 10 second difference update the time
1025+
int ret = ns_time_system_time_write(network_time);
1026+
tr_info("Network Time %s: Era:%"PRId32" Offset:%"PRIu32" old time: %"PRIu64" time: %"PRIu64, ret == 0 ? "updated" : "update FAILED", era, offset, current_time, network_time);
1027+
}
1028+
}
1029+
}
1030+
}
10021031

10031032
options->option.vendor_spesific.data_length -= option_len;
10041033
options->option.vendor_spesific.data += option_len;

source/DHCPv6_Server/DHCPv6_Server_service.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[sta
464464
return 0;
465465
}
466466

467-
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len)
467+
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint16_t dhcp_vendor_data_len)
468468
{
469469
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
470470
if (!serverInfo) {
@@ -496,6 +496,21 @@ int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[st
496496
return 0;
497497
}
498498

499+
int DHCPv6_server_service_set_vendor_data_callback(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, dhcp_vendor_data_cb *vendor_data_cb)
500+
{
501+
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
502+
if (!serverInfo) {
503+
return -1;
504+
}
505+
506+
dhcpv6_vendor_data_t *vendor_data_entry = libdhcpv6_vendor_data_allocate(serverInfo, enterprise_number);
507+
508+
if (!vendor_data_entry) {
509+
return -1;
510+
}
511+
vendor_data_entry->vendor_data_cb = vendor_data_cb;
512+
return 0;
513+
}
499514
#else
500515

501516
int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType)

source/DHCPv6_Server/DHCPv6_server_service.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
9898

9999
int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len);
100100

101-
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len);
101+
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint16_t dhcp_vendor_data_len);
102+
103+
int DHCPv6_server_service_set_vendor_data_callback(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, dhcp_vendor_data_cb *vendor_data_cb);
102104

103105
#else
104106
#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses)

source/libDHCPv6/libDHCPv6_server.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,12 +461,12 @@ dhcpv6_vendor_data_t *libdhcpv6_vendor_data_allocate(dhcpv6_gua_server_entry_s *
461461
}
462462
ns_list_add_to_end(&serverInfo->vendorDataList, entry);
463463
entry->enterprise_number = enterprise_number;
464+
entry->vendor_data_cb = NULL;
464465
entry->vendor_data = NULL;
465466
entry->vendor_data_length = 0;
466467
return entry;
467468
}
468469

469-
470470
uint16_t libdhcpv6_dns_server_message_sizes(dhcpv6_gua_server_entry_s *serverInfo)
471471
{
472472
uint16_t message_size = 0;
@@ -482,7 +482,13 @@ uint16_t libdhcpv6_vendor_data_message_sizes(dhcpv6_gua_server_entry_s *serverIn
482482
{
483483
uint16_t message_size = 0;
484484
ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
485-
message_size += 4 + 4 + cur->vendor_data_length; //Type + Length + enterprise + vendor_data_length
485+
uint16_t size = cur->vendor_data_length; //Type + Length + enterprise + vendor_data_length
486+
if (cur->vendor_data_cb) {
487+
cur->vendor_data_cb(serverInfo->interfaceId, NULL, &size);
488+
}
489+
if (size != 0) {
490+
message_size += 2 + 2 + 4 + size;
491+
}
486492
}
487493
return message_size;
488494
}
@@ -510,14 +516,27 @@ uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverI
510516
{
511517
ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
512518

513-
uint16_t length = cur->vendor_data_length + 4;
519+
uint16_t length = cur->vendor_data_length;
520+
521+
if (cur->vendor_data_cb) {
522+
cur->vendor_data_cb(serverInfo->interfaceId, NULL, &length);
523+
}
524+
if (length == 0) {
525+
// No vendor data
526+
continue;
527+
}
528+
length += 4;
529+
514530
ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr);
515531
ptr = common_write_16_bit(length, ptr); //Length
516532
ptr = common_write_32_bit(cur->enterprise_number, ptr);
517533
if (cur->vendor_data_length) {
518534
memcpy(ptr, cur->vendor_data, cur->vendor_data_length);
519535
ptr += cur->vendor_data_length;
520536
}
537+
if (cur->vendor_data_cb) {
538+
ptr = cur->vendor_data_cb(serverInfo->interfaceId, ptr, NULL);
539+
}
521540
}
522541
return ptr;
523542
}

source/libDHCPv6/libDHCPv6_server.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#define DHCP_ADDRESS_ID_START 2
3333

3434
typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info);
35+
typedef uint8_t *(dhcp_vendor_data_cb)(int8_t interfaceId, uint8_t *ptr, uint16_t *dhcp_vendor_data_len);
36+
3537

3638
typedef struct dhcpv6_allocated_address_entry_s {
3739
uint8_t linkId[8]; /*!< Services UL64 */
@@ -54,8 +56,9 @@ typedef struct dhcpv6_dns_server_data_s {
5456

5557
typedef struct dhcpv6_vendor_data_s {
5658
uint32_t enterprise_number;
59+
dhcp_vendor_data_cb *vendor_data_cb; // Additional vendor data that can be set for individual reply
5760
uint8_t *vendor_data;
58-
uint8_t vendor_data_length;
61+
uint16_t vendor_data_length;
5962
ns_list_link_t link; /*!< List link entry */
6063
} dhcpv6_vendor_data_t;
6164

source/libDHCPv6/libDHCPv6_vendordata.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,61 @@ uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t
9898
}
9999
return option_len;
100100
}
101+
102+
uint16_t net_vendor_option_current_time_length(void)
103+
{
104+
return 4 + 3 * sizeof(uint32_t);
105+
}
106+
107+
uint8_t *net_vendor_option_current_time_write(uint8_t *ptr, int32_t era, uint32_t offset, uint32_t fraction)
108+
{
109+
/*
110+
* Time value written using NTP time format
111+
* Following rfc5905
112+
*/
113+
114+
ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_NETWORK_TIME, ptr);
115+
ptr = common_write_16_bit(3 * sizeof(uint32_t), ptr);
116+
ptr = common_write_32_bit((uint32_t)era, ptr);
117+
ptr = common_write_32_bit(offset, ptr);
118+
ptr = common_write_32_bit(fraction, ptr);
119+
return ptr;
120+
}
121+
122+
uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int32_t *era, uint32_t *offset, uint32_t *fraction)
123+
{
124+
/*
125+
* Time value written using NTP time format
126+
* Following rfc5905
127+
*/
128+
uint16_t option_len;
129+
130+
if (length < net_vendor_option_current_time_length()) {
131+
// Corrupted as there is no room for all fields
132+
return 0;
133+
}
134+
135+
if (common_read_16_bit(ptr) != ARM_DHCP_VENDOR_DATA_NETWORK_TIME) {
136+
return 0;
137+
}
138+
139+
option_len = common_read_16_bit(ptr + 2);
140+
ptr += 4;
141+
142+
if (option_len < 3 * sizeof(uint32_t)) {
143+
// Corrupted as not enough room for fields
144+
return 0;
145+
}
146+
147+
if (era) {
148+
*era = (int32_t)common_read_32_bit(ptr);
149+
}
150+
if (offset) {
151+
*offset = common_read_32_bit(ptr + sizeof(uint32_t));
152+
}
153+
if (fraction) {
154+
*fraction = common_read_32_bit(ptr + 2 * sizeof(uint32_t));
155+
}
156+
157+
return ptr;
158+
}

source/libDHCPv6/libDHCPv6_vendordata.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,40 @@
3232
* */
3333
#define ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT 297
3434

35+
/* ARM Defined vendor data option to distribute network time through DHCP server
36+
* Format. This can be used to syncronice the times of Wi-SUN devices to match the
37+
* time of border router.
38+
*
39+
* Following rfc5905 date format.
40+
* +-------------+------------+-----+---------------+------------------+
41+
* | Date | MJD | NTP | NTP Timestamp | Epoch |
42+
* | | | Era | Era Offset | |
43+
* +-------------+------------+-----+---------------+------------------+
44+
* | 1 Jan -4712 | -2,400,001 | -49 | 1,795,583,104 | 1st day Julian |
45+
* | 1 Jan -1 | -679,306 | -14 | 139,775,744 | 2 BCE |
46+
* | 1 Jan 0 | -678,491 | -14 | 171,311,744 | 1 BCE |
47+
* | 1 Jan 1 | -678,575 | -14 | 202,939,144 | 1 CE |
48+
* | 4 Oct 1582 | -100,851 | -3 | 2,873,647,488 | Last day Julian |
49+
* | 15 Oct 1582 | -100,840 | -3 | 2,874,597,888 | First day |
50+
* | | | | | Gregorian |
51+
* | 31 Dec 1899 | 15019 | -1 | 4,294,880,896 | Last day NTP Era |
52+
* | | | | | -1 |
53+
* | 1 Jan 1900 | 15020 | 0 | 0 | First day NTP |
54+
* | | | | | Era 0 |
55+
* | 1 Jan 1970 | 40,587 | 0 | 2,208,988,800 | First day UNIX |
56+
* | 1 Jan 1972 | 41,317 | 0 | 2,272,060,800 | First day UTC |
57+
* | 31 Dec 1999 | 51,543 | 0 | 3,155,587,200 | Last day 20th |
58+
* | | | | | Century |
59+
* | 8 Feb 2036 | 64,731 | 1 | 63,104 | First day NTP |
60+
* | | | | | Era 1 |
61+
* +-------------+------------+-----+---------------+------------------+
62+
* int32_t Era
63+
* uint32_t offset
64+
* uint32_t fraction
65+
*
66+
* */
67+
#define ARM_DHCP_VENDOR_DATA_NETWORK_TIME 298
68+
3569
/* DHCPv6 vendor options to distribute ARM vendor data*/
3670

3771
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
@@ -40,5 +74,9 @@ uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t
4074
uint16_t net_dns_option_vendor_option_data_get_next(uint8_t *ptr, uint16_t length, uint16_t *type);
4175
uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t length, uint8_t **address, char **domain);
4276

77+
uint16_t net_vendor_option_current_time_length(void);
78+
uint8_t *net_vendor_option_current_time_write(uint8_t *ptr, int32_t era, uint32_t offset, uint32_t fraction);
79+
uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int32_t *era, uint32_t *offset, uint32_t *fraction);
80+
4381

4482
#endif /* LIBDHCPV6_VENDOR_DATA_H_ */

test/nanostack/unittest/stub/dhcpv6_server_service_stub.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,14 @@ int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[sta
140140
return 0;
141141
}
142142

143-
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len)
143+
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint16_t dhcp_vendor_data_len)
144144
{
145145
return 0;
146146
}
147+
148+
int DHCPv6_server_service_set_vendor_data_callback(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, dhcp_vendor_data_cb *vendor_data_cb)
149+
{
150+
return 0;
151+
}
152+
147153
#endif

0 commit comments

Comments
 (0)