Merge pull request #12522 from artokin/network_interface_property_api

Add property API to InternetSocket
pull/12884/head
Martin Kojtal 2020-04-28 18:10:18 +02:00 committed by GitHub
commit 58c0259dd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 2 deletions

View File

@ -185,6 +185,18 @@ TEST_F(TestInternetSocket, modify_multicast_group)
EXPECT_EQ(socket->leave_multicast_group(a), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestInternetSocket, network_property)
{
SocketAddress a("fd00:db8::ff", 1024);
uint32_t rtt_estimate;
uint16_t stagger_min, stagger_max, stagger_rand;
stack.return_value = NSAPI_ERROR_OK;
socket->open(&stack);
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, &rtt_estimate), NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, NULL), NSAPI_ERROR_PARAMETER);
EXPECT_EQ(socket->get_stagger_estimate_to_address(a, 1, &stagger_min, &stagger_max, &stagger_rand), NSAPI_ERROR_UNSUPPORTED);
}
// set_blocking and set_timeout are tested within TCPSocket.
TEST_F(TestInternetSocket, bind_no_socket)

View File

@ -838,18 +838,58 @@ nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const
nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
{
NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
if (handle == NULL) {
MBED_ASSERT(false);
return NSAPI_ERROR_NO_SOCKET;
}
NanostackLockGuard lock;
// pointers to Mbed OS structures
nsapi_latency_req_t *ns_latency_r = static_cast<nsapi_latency_req_t *>(optval);
nsapi_stagger_req_t *ns_stagger_r = static_cast<nsapi_stagger_req_t *>(optval);
// Nanostack internal structures
ns_ipv6_latency_t nanostack_latency;
ns_ipv6_stagger_t nanostack_stagger;
int nanostack_optname = optname;
void *ns_option_value = optval;
if (level == NSAPI_SOCKET) {
if (optname == NSAPI_LATENCY) {
if (*optlen < sizeof(nsapi_latency_req_t)) {
return NSAPI_ERROR_PARAMETER;
}
// Adjust to Nanostack namespace
level = SOCKET_IPPROTO_IPV6;
nanostack_optname = SOCKET_LATENCY;
memcpy(nanostack_latency.dest_addr, ns_latency_r->addr, 16);
ns_option_value = &nanostack_latency;
} else if (optname == NSAPI_STAGGER) {
if (*optlen < sizeof(nsapi_stagger_req_t)) {
return NSAPI_ERROR_PARAMETER;
}
// Adjust to Nanostack namespace
level = SOCKET_IPPROTO_IPV6;
nanostack_optname = SOCKET_STAGGER;
memcpy(nanostack_stagger.dest_addr, ns_stagger_r->addr, 16);
nanostack_stagger.data_amount = ns_stagger_r->data_amount;
ns_option_value = &nanostack_stagger;
}
}
uint16_t optlen16 = *optlen;
int retcode = ::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16);
int retcode = ::socket_getsockopt(socket->socket_id, level, nanostack_optname, ns_option_value, &optlen16);
if (retcode == 0) {
*optlen = optlen16;
if (optname == NSAPI_LATENCY) {
ns_latency_r->latency = nanostack_latency.latency;
} else if (optname == NSAPI_STAGGER) {
ns_stagger_r->stagger_min = nanostack_stagger.stagger_min;
ns_stagger_r->stagger_max = nanostack_stagger.stagger_max;
ns_stagger_r->stagger_rand = nanostack_stagger.stagger_rand;
}
return NSAPI_ERROR_OK;
} else if (retcode == -2) {
return NSAPI_ERROR_UNSUPPORTED;

View File

@ -114,6 +114,54 @@ int InternetSocket::leave_multicast_group(const SocketAddress &address)
return modify_multicast_group(address, NSAPI_DROP_MEMBERSHIP);
}
int InternetSocket::get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate)
{
nsapi_error_t ret;
nsapi_latency_req_t ns_api_latency_req;
unsigned opt_len = sizeof(nsapi_latency_req_t);
if (!rtt_estimate) {
return NSAPI_ERROR_PARAMETER;
}
// Set up address
memcpy(ns_api_latency_req.addr, address.get_ip_bytes(), 16);
ret = this->getsockopt(NSAPI_SOCKET, NSAPI_LATENCY, &ns_api_latency_req, &opt_len);
if (ret == NSAPI_ERROR_OK) {
// success, latency found. Convert to RTT.
*rtt_estimate = ns_api_latency_req.latency * 2;
}
return ret;
}
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)
{
nsapi_error_t ret;
nsapi_stagger_req_t nsapi_stagger;
unsigned opt_len = sizeof(nsapi_stagger_req_t);
// Set up address
memcpy(nsapi_stagger.addr, address.get_ip_bytes(), 16);
nsapi_stagger.data_amount = data_amount;
ret = this->getsockopt(NSAPI_SOCKET, NSAPI_STAGGER, &nsapi_stagger, &opt_len);
if (ret == NSAPI_ERROR_OK) {
// success, stagger found
if (stagger_min) {
*stagger_min = nsapi_stagger.stagger_min;
}
if (stagger_max) {
*stagger_max = nsapi_stagger.stagger_max;
}
if (stagger_rand) {
*stagger_rand = nsapi_stagger.stagger_rand;
}
}
return ret;
}
nsapi_error_t InternetSocket::bind(uint16_t port)
{

View File

@ -86,6 +86,35 @@ public:
*/
int leave_multicast_group(const SocketAddress &address);
/** Get estimated round trip time to destination address.
*
* Use estimated round trip time to adjust application retry timers to work in networks
* that have low data rate and high latency.
*
* @param address Destination address to use in rtt estimate.
* @param rtt_estimate Returned round trip time value in milliseconds.
* @return NSAPI_ERROR_OK on success.
* @return NSAPI_ERROR_PARAMETER if the provided pointer is invalid.
* @return negative error code on other failures (@see InternetSocket::getsockopt).
*/
int get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate);
/** Get estimated stagger value.
*
* Stagger value is a time that application should wait before using heavy network operations after connecting to network.
* Purpose of staggering is to avoid network congestion that may happen in low bandwith networks if multiple
* applications simultaneously start heavy network usage after joining to the network.
*
* @param address Destination added used to estimate stagger value.
* @param data_amount Amount of bytes to transfer in kilobytes.
* @param stagger_min Minimum stagger value in seconds.
* @param stagger_max Maximum stagger value in seconds.
* @param stagger_rand Randomized stagger value between stagger_min and stagger_max in seconds.
* @return NSAPI_ERROR_OK on success.
* @return negative error code on other failures (@see InternetSocket::getsockopt).
*/
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);
/** Bind the socket to a port on which to receive data.
*
* @param port Local port to bind.

View File

@ -269,7 +269,9 @@ typedef enum nsapi_socket_option {
NSAPI_RCVBUF, /*!< Sets recv buffer size */
NSAPI_ADD_MEMBERSHIP, /*!< Add membership to multicast address */
NSAPI_DROP_MEMBERSHIP, /*!< Drop membership to multicast address */
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
NSAPI_LATENCY, /*!< Read estimated latency to destination */
NSAPI_STAGGER, /*!< Read estimated stagger value to destination */
} nsapi_socket_option_t;
typedef enum nsapi_tlssocket_level {
@ -340,6 +342,23 @@ typedef struct nsapi_ip_mreq {
nsapi_addr_t imr_interface; /* local IP address of interface */
} nsapi_ip_mreq_t;
/** nsapi_latency_req structure
*/
typedef struct nsapi_latency_req {
uint8_t addr[16]; /* [IN] Destination address to estimate latency */
uint32_t latency; /* [OUT] Latency value */
} nsapi_latency_req_t;
/** nsapi_stagger_req structure
*/
typedef struct nsapi_stagger_req {
uint8_t addr[16]; /* [IN] Destination address to estimate stagger */
uint16_t data_amount; /* [IN] Amount of data to be sent in kilobytes */
uint16_t stagger_min; /* [OUT] Minimum stagger value in seconds */
uint16_t stagger_max; /* [OUT] Maximum stagger value in seconds */
uint16_t stagger_rand; /* [OUT] Randomized stagger value in seconds */
} nsapi_stagger_req_t;
/** nsapi_stack_api structure
*
* Common api structure for network stack operations. A network stack