Commit 1022b85c authored by Gil Pitney's avatar Gil Pitney Committed by Jukka Rissanen
Browse files

drivers: wifi: simplelink: Implement offloaded getaddrinfo()



This offloads the getaddrinfo() socket operation to the
simplelink WiFi driver, via a socket_offload hook.

This was validated using http_get on cc3220sf_launchxl.

Also implements freeaddrinfo().

Signed-off-by: default avatarGil Pitney <gil.pitney@linaro.org>
parent 5a42292a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ static void simplelink_iface_init(struct net_if *iface)
#ifdef CONFIG_NET_SOCKETS_OFFLOAD
	/* Direct socket offload: */
	socket_offload_register(&simplelink_ops);
	simplelink_sockets_init();
#endif

}
+112 −7
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
#include "simplelink_log.h"
LOG_MODULE_DECLARE(LOG_MODULE_NAME);

#include <stdlib.h>
#include <limits.h>

#include <zephyr.h>
/* Define sockaddr, etc, before simplelink.h */
#include <net/socket_offload.h>
@@ -15,6 +18,9 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
#include <ti/drivers/net/wifi/source/driver.h>
#include "simplelink_support.h"

/* Mutex for getaddrinfo() calls: */
K_MUTEX_DEFINE(ga_mutex);

static int simplelink_socket(int family, int type, int proto)
{
	int retval;
@@ -509,22 +515,121 @@ exit:
	return _SlDrvSetErrno(retval);
}

/*
 * Later SimpleLink SDK versions implement the full getaddrinfo semantics,
 * returning potentially multiple IP addresses.
 * This version implements a simple gethostbyname() API.
 */
static int simplelink_getaddrinfo(const char *node, const char *service,
				  const struct addrinfo *hints,
				  struct addrinfo **res)
{
	ARG_UNUSED(node);
	ARG_UNUSED(service);
	ARG_UNUSED(hints);
	ARG_UNUSED(res);
	_u8 sl_family = SL_AF_INET;
	unsigned long port = 0;
	int socktype = SOCK_STREAM;
	int proto = IPPROTO_TCP;
	struct addrinfo *ai;
	struct sockaddr *ai_addr;
	_i16 retval;
	_u32 ipaddr[4];

	/* Check args: */
	if (!node && !service) {
		retval = EAI_NONAME;
		goto exit;
	}
	if (service) {
		port = strtol(service, NULL, 10);
		if (port < 1 || port > USHRT_MAX) {
			retval = EAI_SERVICE;
			goto exit;
		}
	}
	if (!res) {
		retval = EAI_NONAME;
		goto exit;
	}

	/* See if any hints for family; otherwise, default to AF_INET. */
	if (hints) {
		/* Note: SimpleLink SDK doesn't support AF_UNSPEC: */
		sl_family = (hints->ai_family == AF_INET6 ?
			     SL_AF_INET6 : SL_AF_INET);
	}

	/* Now, try to resolve host name: */
	k_mutex_lock(&ga_mutex, K_FOREVER);
	retval = sl_NetAppDnsGetHostByName((signed char *)node, strlen(node),
					   ipaddr, sl_family);
	k_mutex_unlock(&ga_mutex);

	if (retval < 0) {
		LOG_ERR("Could not resolve name: %s, retval: %d",
			    node, retval);
		retval = EAI_NONAME;
		goto exit;
	}

	/* Allocate out res (addrinfo) struct.	Just one. */
	*res = calloc(1, sizeof(struct addrinfo));
	ai = *res;
	if (!ai) {
		retval = EAI_MEMORY;
		goto exit;
	} else {
		/* Now, alloc the embedded sockaddr struct: */
		ai_addr = calloc(1, sizeof(struct sockaddr));
		if (!ai_addr) {
			retval = EAI_MEMORY;
			free(*res);
			goto exit;
		}
	}

	/* Now, fill in the fields of res (addrinfo struct): */
	ai->ai_family = (sl_family == SL_AF_INET6 ? AF_INET6 : AF_INET);
	if (hints) {
		socktype = hints->ai_socktype;
	}
	ai->ai_socktype = socktype;

	if (socktype == SOCK_DGRAM) {
		proto = IPPROTO_UDP;
	}
	ai->ai_protocol = proto;

	errno = ENOTSUP;
	return EAI_SYSTEM;
	/* Fill sockaddr struct fields based on family: */
	if (ai->ai_family == AF_INET) {
		net_sin(ai_addr)->sin_family = ai->ai_family;
		net_sin(ai_addr)->sin_addr.s_addr = htonl(ipaddr[0]);
		net_sin(ai_addr)->sin_port = htons(port);
		ai->ai_addrlen = sizeof(struct sockaddr_in);
	} else {
		net_sin6(ai_addr)->sin6_family = ai->ai_family;
		net_sin6(ai_addr)->sin6_addr.s6_addr32[0] = htonl(ipaddr[0]);
		net_sin6(ai_addr)->sin6_addr.s6_addr32[1] = htonl(ipaddr[1]);
		net_sin6(ai_addr)->sin6_addr.s6_addr32[2] = htonl(ipaddr[2]);
		net_sin6(ai_addr)->sin6_addr.s6_addr32[3] = htonl(ipaddr[3]);
		net_sin6(ai_addr)->sin6_port = htons(port);
		ai->ai_addrlen = sizeof(struct sockaddr_in6);
	}
	ai->ai_addr = ai_addr;

exit:
	return retval;
}

static void simplelink_freeaddrinfo(struct addrinfo *res)
{
	ARG_UNUSED(res);
	__ASSERT_NO_MSG(res);

	free(res->ai_addr);
	free(res);
}

void simplelink_sockets_init(void)
{
	k_mutex_init(&ga_mutex);
}

const struct socket_offload simplelink_ops = {
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ extern "C" {
#endif

extern const struct socket_offload simplelink_ops;
extern void simplelink_sockets_init(void);

#ifdef __cplusplus
}