Skip to content

Commit 2ba15a5

Browse files
jerome-pouillerjhedberg
authored andcommitted
drivers: siwx917_wifi: Fix support for IPv6
SiWx917 use byte swapped IPv6 addresses. Once fixed, we are properly able to use UDP and TCP connection over IPv6. Signed-off-by: Jérôme Pouiller <[email protected]>
1 parent 892c436 commit 2ba15a5

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

drivers/wifi/siwx917/siwx917_wifi.c

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,33 @@ struct siwx917_dev {
4141
NET_BUF_POOL_FIXED_DEFINE(siwx917_tx_pool, 1, NET_ETH_MTU, 0, NULL);
4242
NET_BUF_POOL_FIXED_DEFINE(siwx917_rx_pool, 10, NET_ETH_MTU, 0, NULL);
4343

44+
/* SiWx917 does not use the standard struct sockaddr (despite it uses the same
45+
* name):
46+
* - uses Little Endian for port number while Posix uses big endian
47+
* - IPv6 addresses are bytes swapped
48+
* Note: this function allows to have in == out.
49+
*/
50+
static void siwx917_sockaddr_swap_bytes(struct sockaddr *out,
51+
const struct sockaddr *in, socklen_t in_len)
52+
{
53+
const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)in;
54+
struct sockaddr_in6 *out6 = (struct sockaddr_in6 *)out;
55+
int i;
56+
57+
/* In Zephyr, size of sockaddr == size of sockaddr_storage
58+
* (while in Posix sockaddr is smaller than sockaddr_storage).
59+
*/
60+
memcpy(out, in, in_len);
61+
if (in->sa_family == AF_INET6) {
62+
for (i = 0; i < ARRAY_SIZE(in6->sin6_addr.s6_addr32); i++) {
63+
out6->sin6_addr.s6_addr32[i] = ntohl(in6->sin6_addr.s6_addr32[i]);
64+
}
65+
out6->sin6_port = ntohs(in6->sin6_port);
66+
} else if (in->sa_family == AF_INET) {
67+
out6->sin6_port = ntohs(in6->sin6_port);
68+
}
69+
}
70+
4471
static void siwx917_on_join_ipv4(struct siwx917_dev *sidev)
4572
{
4673
#ifdef CONFIG_NET_IPV4
@@ -71,12 +98,18 @@ static void siwx917_on_join_ipv6(struct siwx917_dev *sidev)
7198
.type = SL_IPV6,
7299
};
73100
struct in6_addr addr6 = { };
74-
int ret;
101+
int ret, i;
75102

76103
/* FIXME: support for static IP configuration */
77104
ret = sl_si91x_configure_ip_address(&ip_config6, SL_SI91X_WIFI_CLIENT_VAP_ID);
78105
if (!ret) {
79-
memcpy(addr6.s6_addr, ip_config6.ip.v6.global_address.bytes, sizeof(addr6.s6_addr));
106+
for (i = 0; i < ARRAY_SIZE(addr6.s6_addr32); i++) {
107+
addr6.s6_addr32[i] = ntohl(ip_config6.ip.v6.global_address.value[i]);
108+
}
109+
/* SiWx917 already take care of DAD and sending ND is not
110+
* supported anyway.
111+
*/
112+
net_if_flag_set(sidev->iface, NET_IF_IPV6_NO_ND);
80113
/* FIXME: also report gateway and link local address */
81114
net_if_ipv6_addr_add(sidev->iface, &addr6, NET_ADDR_AUTOCONF, 0);
82115
} else {
@@ -287,17 +320,6 @@ static int siwx917_status(const struct device *dev, struct wifi_iface_status *st
287320
return 0;
288321
}
289322

290-
/* SiWx917 uses Little Endian for port number while Posix uses Big Endian */
291-
static void siwx917_sock_swap_port_endian(struct sockaddr *out,
292-
const struct sockaddr *in, socklen_t in_len)
293-
{
294-
/* In Zephyr, size of sockaddr == size of sockaddr_storage
295-
* (while in Posix sockaddr is smaller than sockaddr_storage).
296-
*/
297-
memcpy(out, in, in_len);
298-
((struct sockaddr_in *)out)->sin_port = ntohs(((struct sockaddr_in *)in)->sin_port);
299-
}
300-
301323
static int siwx917_sock_recv_sync(struct net_context *context,
302324
net_context_recv_cb_t cb, void *user_data)
303325
{
@@ -403,7 +425,7 @@ static int siwx917_sock_bind(struct net_context *context,
403425
!((struct sockaddr_in *)addr)->sin_port) {
404426
return 0;
405427
}
406-
siwx917_sock_swap_port_endian(&addr_le, addr, addrlen);
428+
siwx917_sockaddr_swap_bytes(&addr_le, addr, addrlen);
407429
ret = sl_si91x_bind(sockfd, &addr_le, addrlen);
408430
if (ret) {
409431
return -errno;
@@ -426,8 +448,9 @@ static int siwx917_sock_connect(struct net_context *context,
426448
struct sockaddr addr_le;
427449
int ret;
428450

451+
printk("foo\n");
429452
/* sl_si91x_connect() always return immediately, so we ignore timeout */
430-
siwx917_sock_swap_port_endian(&addr_le, addr, addrlen);
453+
siwx917_sockaddr_swap_bytes(&addr_le, addr, addrlen);
431454
ret = sl_si91x_connect(sockfd, &addr_le, addrlen);
432455
if (ret) {
433456
ret = -errno;
@@ -486,7 +509,7 @@ static int siwx917_sock_accept(struct net_context *context,
486509
}
487510
newcontext->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
488511
newcontext->offload_context = (void *)ret;
489-
siwx917_sock_swap_port_endian(&newcontext->remote, &addr_le, sizeof(addr_le));
512+
siwx917_sockaddr_swap_bytes(&newcontext->remote, &addr_le, sizeof(addr_le));
490513

491514
SL_SI91X_FD_SET(ret, &sidev->fds_watch);
492515
sl_si91x_select(NUMBER_OF_BSD_SOCKETS, &sidev->fds_watch, NULL, NULL, NULL,
@@ -528,7 +551,7 @@ static int siwx917_sock_sendto(struct net_pkt *pkt,
528551
net_buf_add(buf, net_pkt_get_len(pkt));
529552

530553
/* sl_si91x_sendto() always return immediately, so we ignore timeout */
531-
siwx917_sock_swap_port_endian(&addr_le, addr, addrlen);
554+
siwx917_sockaddr_swap_bytes(&addr_le, addr, addrlen);
532555
ret = sl_si91x_sendto(sockfd, buf->data, net_pkt_get_len(pkt), 0, &addr_le, addrlen);
533556
if (ret < 0) {
534557
ret = -errno;

west.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ manifest:
1111
projects:
1212
- name: hal_silabs
1313
remote: silabs
14-
revision: 3febda5e93f51324961a7e374321d10d6b2688f3
14+
revision: c1fcd068ee40be8f13ebe33039cd13560e1af75f
1515
path: modules/hal/silabs
1616
- name: zephyr
1717
remote: zephyrproject-rtos

0 commit comments

Comments
 (0)