Skip to content

Commit 8d61f3b

Browse files
author
Arto Kinnunen
authored
Merge pull request #12883 from artokin/feature_wisun_backport_12522
[feature-wisun] Add getsockopt option to read network property
2 parents 35d28d4 + 09f9560 commit 8d61f3b

File tree

5 files changed

+150
-2
lines changed

5 files changed

+150
-2
lines changed

UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ TEST_F(TestInternetSocket, modify_multicast_group)
185185
EXPECT_EQ(socket->leave_multicast_group(a), NSAPI_ERROR_UNSUPPORTED);
186186
}
187187

188+
TEST_F(TestInternetSocket, network_property)
189+
{
190+
SocketAddress a("fd00:db8::ff", 1024);
191+
uint32_t rtt_estimate;
192+
uint16_t stagger_min, stagger_max, stagger_rand;
193+
stack.return_value = NSAPI_ERROR_OK;
194+
socket->open((NetworkStack *)&stack);
195+
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, &rtt_estimate), NSAPI_ERROR_UNSUPPORTED);
196+
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, NULL), NSAPI_ERROR_PARAMETER);
197+
EXPECT_EQ(socket->get_stagger_estimate_to_address(a, 1, &stagger_min, &stagger_max, &stagger_rand), NSAPI_ERROR_UNSUPPORTED);
198+
}
199+
188200
// set_blocking and set_timeout are tested within TCPSocket.
189201

190202
TEST_F(TestInternetSocket, bind_no_socket)

features/nanostack/nanostack-interface/Nanostack.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,18 +840,58 @@ nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const
840840
nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
841841
{
842842
NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
843+
843844
if (handle == NULL) {
844845
MBED_ASSERT(false);
845846
return NSAPI_ERROR_NO_SOCKET;
846847
}
847848

848849
NanostackLockGuard lock;
850+
// pointers to Mbed OS structures
851+
nsapi_latency_req_t *ns_latency_r = static_cast<nsapi_latency_req_t *>(optval);
852+
nsapi_stagger_req_t *ns_stagger_r = static_cast<nsapi_stagger_req_t *>(optval);
853+
// Nanostack internal structures
854+
ns_ipv6_latency_t nanostack_latency;
855+
ns_ipv6_stagger_t nanostack_stagger;
856+
int nanostack_optname = optname;
857+
858+
void *ns_option_value = optval;
859+
860+
if (level == NSAPI_SOCKET) {
861+
if (optname == NSAPI_LATENCY) {
862+
if (*optlen < sizeof(nsapi_latency_req_t)) {
863+
return NSAPI_ERROR_PARAMETER;
864+
}
865+
// Adjust to Nanostack namespace
866+
level = SOCKET_IPPROTO_IPV6;
867+
nanostack_optname = SOCKET_LATENCY;
868+
memcpy(nanostack_latency.dest_addr, ns_latency_r->addr, 16);
869+
ns_option_value = &nanostack_latency;
870+
} else if (optname == NSAPI_STAGGER) {
871+
if (*optlen < sizeof(nsapi_stagger_req_t)) {
872+
return NSAPI_ERROR_PARAMETER;
873+
}
874+
// Adjust to Nanostack namespace
875+
level = SOCKET_IPPROTO_IPV6;
876+
nanostack_optname = SOCKET_STAGGER;
877+
memcpy(nanostack_stagger.dest_addr, ns_stagger_r->addr, 16);
878+
nanostack_stagger.data_amount = ns_stagger_r->data_amount;
879+
ns_option_value = &nanostack_stagger;
880+
}
881+
}
849882

850883
uint16_t optlen16 = *optlen;
851884

852-
int retcode = ::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16);
885+
int retcode = ::socket_getsockopt(socket->socket_id, level, nanostack_optname, ns_option_value, &optlen16);
853886
if (retcode == 0) {
854887
*optlen = optlen16;
888+
if (optname == NSAPI_LATENCY) {
889+
ns_latency_r->latency = nanostack_latency.latency;
890+
} else if (optname == NSAPI_STAGGER) {
891+
ns_stagger_r->stagger_min = nanostack_stagger.stagger_min;
892+
ns_stagger_r->stagger_max = nanostack_stagger.stagger_max;
893+
ns_stagger_r->stagger_rand = nanostack_stagger.stagger_rand;
894+
}
855895
return NSAPI_ERROR_OK;
856896
} else if (retcode == -2) {
857897
return NSAPI_ERROR_UNSUPPORTED;

features/netsocket/InternetSocket.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,54 @@ int InternetSocket::leave_multicast_group(const SocketAddress &address)
119119
return modify_multicast_group(address, NSAPI_DROP_MEMBERSHIP);
120120
}
121121

122+
int InternetSocket::get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate)
123+
{
124+
nsapi_error_t ret;
125+
nsapi_latency_req_t ns_api_latency_req;
126+
unsigned opt_len = sizeof(nsapi_latency_req_t);
127+
128+
if (!rtt_estimate) {
129+
return NSAPI_ERROR_PARAMETER;
130+
}
131+
132+
// Set up address
133+
memcpy(ns_api_latency_req.addr, address.get_ip_bytes(), 16);
134+
135+
ret = this->getsockopt(NSAPI_SOCKET, NSAPI_LATENCY, &ns_api_latency_req, &opt_len);
136+
if (ret == NSAPI_ERROR_OK) {
137+
// success, latency found. Convert to RTT.
138+
*rtt_estimate = ns_api_latency_req.latency * 2;
139+
}
140+
141+
return ret;
142+
}
143+
144+
int InternetSocket::get_stagger_estimate_to_address(const SocketAddress &address, uint16_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand)
145+
{
146+
nsapi_error_t ret;
147+
nsapi_stagger_req_t nsapi_stagger;
148+
unsigned opt_len = sizeof(nsapi_stagger_req_t);
149+
150+
// Set up address
151+
memcpy(nsapi_stagger.addr, address.get_ip_bytes(), 16);
152+
nsapi_stagger.data_amount = data_amount;
153+
154+
ret = this->getsockopt(NSAPI_SOCKET, NSAPI_STAGGER, &nsapi_stagger, &opt_len);
155+
if (ret == NSAPI_ERROR_OK) {
156+
// success, stagger found
157+
if (stagger_min) {
158+
*stagger_min = nsapi_stagger.stagger_min;
159+
}
160+
if (stagger_max) {
161+
*stagger_max = nsapi_stagger.stagger_max;
162+
}
163+
if (stagger_rand) {
164+
*stagger_rand = nsapi_stagger.stagger_rand;
165+
}
166+
}
167+
168+
return ret;
169+
}
122170

123171
nsapi_error_t InternetSocket::bind(uint16_t port)
124172
{

features/netsocket/InternetSocket.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,35 @@ class InternetSocket : public Socket {
8686
*/
8787
int leave_multicast_group(const SocketAddress &address);
8888

89+
/** Get estimated round trip time to destination address.
90+
*
91+
* Use estimated round trip time to adjust application retry timers to work in networks
92+
* that have low data rate and high latency.
93+
*
94+
* @param address Destination address to use in rtt estimate.
95+
* @param rtt_estimate Returned round trip time value in milliseconds.
96+
* @return NSAPI_ERROR_OK on success.
97+
* @return NSAPI_ERROR_PARAMETER if the provided pointer is invalid.
98+
* @return negative error code on other failures (@see InternetSocket::getsockopt).
99+
*/
100+
int get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate);
101+
102+
/** Get estimated stagger value.
103+
*
104+
* Stagger value is a time that application should wait before using heavy network operations after connecting to network.
105+
* Purpose of staggering is to avoid network congestion that may happen in low bandwith networks if multiple
106+
* applications simultaneously start heavy network usage after joining to the network.
107+
*
108+
* @param address Destination added used to estimate stagger value.
109+
* @param data_amount Amount of bytes to transfer in kilobytes.
110+
* @param stagger_min Minimum stagger value in seconds.
111+
* @param stagger_max Maximum stagger value in seconds.
112+
* @param stagger_rand Randomized stagger value between stagger_min and stagger_max in seconds.
113+
* @return NSAPI_ERROR_OK on success.
114+
* @return negative error code on other failures (@see InternetSocket::getsockopt).
115+
*/
116+
int get_stagger_estimate_to_address(const SocketAddress &address, uint16_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand);
117+
89118
/** Bind the socket to a port on which to receive data.
90119
*
91120
* @param port Local port to bind.

features/netsocket/nsapi_types.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,9 @@ typedef enum nsapi_socket_option {
267267
NSAPI_RCVBUF, /*!< Sets recv buffer size */
268268
NSAPI_ADD_MEMBERSHIP, /*!< Add membership to multicast address */
269269
NSAPI_DROP_MEMBERSHIP, /*!< Drop membership to multicast address */
270-
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
270+
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
271+
NSAPI_LATENCY, /*!< Read estimated latency to destination */
272+
NSAPI_STAGGER, /*!< Read estimated stagger value to destination */
271273
} nsapi_socket_option_t;
272274

273275
typedef enum nsapi_tlssocket_level {
@@ -338,6 +340,23 @@ typedef struct nsapi_ip_mreq {
338340
nsapi_addr_t imr_interface; /* local IP address of interface */
339341
} nsapi_ip_mreq_t;
340342

343+
/** nsapi_latency_req structure
344+
*/
345+
typedef struct nsapi_latency_req {
346+
uint8_t addr[16]; /* [IN] Destination address to estimate latency */
347+
uint32_t latency; /* [OUT] Latency value */
348+
} nsapi_latency_req_t;
349+
350+
/** nsapi_stagger_req structure
351+
*/
352+
typedef struct nsapi_stagger_req {
353+
uint8_t addr[16]; /* [IN] Destination address to estimate stagger */
354+
uint16_t data_amount; /* [IN] Amount of data to be sent in kilobytes */
355+
uint16_t stagger_min; /* [OUT] Minimum stagger value in seconds */
356+
uint16_t stagger_max; /* [OUT] Maximum stagger value in seconds */
357+
uint16_t stagger_rand; /* [OUT] Randomized stagger value in seconds */
358+
} nsapi_stagger_req_t;
359+
341360
/** nsapi_stack_api structure
342361
*
343362
* Common api structure for network stack operations. A network stack

0 commit comments

Comments
 (0)