Skip to content

Commit 0bec980

Browse files
committed
tests: net: socket: udp: Add IP_MULTICAST_IF set/get testing
Add tests that verify that IP_MULTICAST_IF socket option set/get works as expected. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent d94b35a commit 0bec980

File tree

1 file changed

+254
-0
lines changed
  • tests/net/socket/udp/src

1 file changed

+254
-0
lines changed

tests/net/socket/udp/src/main.c

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
949949
0, 0, 0, 0, 0, 0, 0, 0x3 } } };
950950
static struct in6_addr my_mcast_addr1 = { { { 0xff, 0x01, 0, 0, 0, 0, 0, 0,
951951
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
952+
static struct in_addr my_mcast_addr2 = { { { 224, 0, 0, 2 } } };
952953
static uint8_t server_lladdr[] = { 0x01, 0x02, 0x03, 0xff, 0xfe,
953954
0x04, 0x05, 0x06 };
954955
static struct net_linkaddr server_link_addr = {
@@ -2671,6 +2672,259 @@ ZTEST(net_socket_udp, test_38_ipv6_multicast_ifindex)
26712672
loopback_enable_address_swap(true);
26722673
}
26732674

2675+
ZTEST(net_socket_udp, test_39_ipv4_multicast_ifindex)
2676+
{
2677+
struct sockaddr_in saddr4 = {
2678+
.sin_family = AF_INET,
2679+
.sin_port = htons(SERVER_PORT),
2680+
.sin_addr = my_mcast_addr2,
2681+
};
2682+
struct sockaddr_in dst_addr = {
2683+
.sin_family = AF_INET,
2684+
.sin_port = htons(SERVER_PORT),
2685+
.sin_addr = my_mcast_addr2,
2686+
};
2687+
struct net_if_mcast_addr *ifmaddr;
2688+
struct net_if_addr *ifaddr;
2689+
struct in_addr addr = { 0 };
2690+
struct ip_mreqn mreqn;
2691+
struct ip_mreq mreq;
2692+
struct net_if *iface;
2693+
int server_sock;
2694+
size_t addrlen;
2695+
size_t optlen;
2696+
int ifindex;
2697+
int sock;
2698+
int ret;
2699+
int err;
2700+
2701+
net_if_foreach(iface_cb, &eth_iface);
2702+
zassert_not_null(eth_iface, "No ethernet interface found");
2703+
2704+
ifmaddr = net_if_ipv4_maddr_add(eth_iface, &my_mcast_addr2);
2705+
if (!ifmaddr) {
2706+
DBG("Cannot add IPv4 multicast address %s\n",
2707+
net_sprint_ipv4_addr(&my_mcast_addr2));
2708+
zassert_not_null(ifmaddr, "mcast_addr2");
2709+
}
2710+
2711+
ifaddr = net_if_ipv4_addr_add(eth_iface, &my_addr2,
2712+
NET_ADDR_MANUAL, 0);
2713+
if (!ifaddr) {
2714+
DBG("Cannot add IPv4 address %s\n",
2715+
net_sprint_ipv4_addr(&my_addr2));
2716+
zassert_not_null(ifaddr, "addr2");
2717+
}
2718+
2719+
net_if_up(eth_iface);
2720+
2721+
/* Check that we get the default interface */
2722+
sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2723+
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
2724+
2725+
optlen = sizeof(addr);
2726+
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2727+
&addr, &optlen);
2728+
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
2729+
zexpect_equal(optlen, sizeof(addr), "invalid optlen %d vs %d",
2730+
optlen, sizeof(addr));
2731+
ifindex = net_if_get_by_iface(net_if_get_default());
2732+
ret = net_if_ipv4_addr_lookup_by_index(&addr);
2733+
zexpect_equal(ret, ifindex,
2734+
"getsockopt multicast ifindex (expected %d got %d)",
2735+
ifindex, ret);
2736+
2737+
ret = zsock_close(sock);
2738+
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
2739+
2740+
/* Check failure for IPv6 socket */
2741+
sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
2742+
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
2743+
2744+
optlen = 0U;
2745+
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2746+
&addr, &optlen);
2747+
err = -errno;
2748+
zexpect_equal(ret, -1, "setsockopt failed (%d)", errno);
2749+
zexpect_equal(err, -EAFNOSUPPORT, "setsockopt failed (%d)", errno);
2750+
zexpect_equal(optlen, 0U, "setsockopt optlen (%d)", optlen);
2751+
2752+
ret = zsock_close(sock);
2753+
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
2754+
2755+
/* Check that we can set the interface */
2756+
sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2757+
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
2758+
2759+
/* Clear any existing interface value by setting it to 0 */
2760+
optlen = sizeof(mreqn);
2761+
mreqn.imr_ifindex = 0;
2762+
mreqn.imr_address.s_addr = 0;
2763+
2764+
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2765+
&mreqn, optlen);
2766+
err = -errno;
2767+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2768+
2769+
/* Verify that we get the empty value */
2770+
optlen = sizeof(addr);
2771+
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2772+
&addr, &optlen);
2773+
err = -errno;
2774+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2775+
zexpect_equal(optlen, sizeof(addr), "setsockopt optlen (%d)", optlen);
2776+
2777+
/* Set the output multicast packet interface to the default interface */
2778+
optlen = sizeof(mreqn);
2779+
mreqn.imr_ifindex = net_if_get_by_iface(net_if_get_default());
2780+
mreqn.imr_address.s_addr = 0;
2781+
2782+
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2783+
&mreqn, optlen);
2784+
err = -errno;
2785+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2786+
2787+
/* Verify that we get the default interface */
2788+
optlen = sizeof(addr);
2789+
memset(&addr, 0, sizeof(addr));
2790+
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2791+
&addr, &optlen);
2792+
err = -errno;
2793+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2794+
zexpect_equal(optlen, sizeof(addr), "setsockopt optlen (%d)", optlen);
2795+
2796+
ifaddr = net_if_ipv4_addr_lookup(&addr, &iface);
2797+
zexpect_not_null(ifaddr, "Address %s not found",
2798+
net_sprint_ipv4_addr(&addr));
2799+
zexpect_equal(net_if_get_by_iface(iface),
2800+
net_if_get_by_iface(net_if_get_default()),
2801+
"Invalid interface %d vs %d",
2802+
net_if_get_by_iface(iface),
2803+
net_if_get_by_iface(net_if_get_default()));
2804+
2805+
/* Now send a packet and verify that it is sent via the default
2806+
* interface instead of the Ethernet interface.
2807+
*/
2808+
server_sock = prepare_listen_sock_udp_v4(&saddr4);
2809+
zassert_not_equal(server_sock, -1, "Cannot create server socket (%d)", -errno);
2810+
2811+
test_started = true;
2812+
loopback_enable_address_swap(false);
2813+
2814+
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
2815+
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
2816+
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
2817+
"invalid send len (was %d expected %d) (%d)",
2818+
ret, STRLEN(TEST_STR_SMALL), -errno);
2819+
2820+
/* Test that the sent data is received from Ethernet interface. */
2821+
addrlen = sizeof(saddr4);
2822+
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
2823+
0, (struct sockaddr *)&saddr4, &addrlen);
2824+
zexpect_true(ret >= 0, "recvfrom fail");
2825+
zexpect_equal(ret, strlen(TEST_STR_SMALL),
2826+
"unexpected received bytes");
2827+
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
2828+
"wrong data");
2829+
2830+
/* Clear the old interface value by setting it to 0 */
2831+
optlen = sizeof(mreqn);
2832+
mreqn.imr_ifindex = 0;
2833+
mreqn.imr_address.s_addr = 0;
2834+
2835+
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2836+
&mreqn, optlen);
2837+
err = -errno;
2838+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2839+
2840+
/* Then do it the other way around, set the address but leave the
2841+
* interface number unassigned.
2842+
*/
2843+
optlen = sizeof(mreqn);
2844+
mreqn.imr_ifindex = 0;
2845+
2846+
/* Get the address of default interface and set it as a target
2847+
* interface.
2848+
*/
2849+
ifaddr = net_if_ipv4_addr_get_first_by_index(net_if_get_by_iface(net_if_get_default()));
2850+
zexpect_not_null(ifaddr, "No address found for interface %d",
2851+
net_if_get_by_iface(net_if_get_default()));
2852+
mreqn.imr_address.s_addr = ifaddr->address.in_addr.s_addr;
2853+
2854+
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2855+
&mreqn, optlen);
2856+
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
2857+
2858+
/* Verify that we get the default interface address */
2859+
optlen = sizeof(struct in_addr);
2860+
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2861+
&addr, &optlen);
2862+
err = -errno;
2863+
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
2864+
zexpect_equal(optlen, sizeof(struct in_addr), "setsockopt optlen (%d)", optlen);
2865+
ret = net_if_ipv4_addr_lookup_by_index(&addr);
2866+
zexpect_equal(ret, net_if_get_by_iface(net_if_get_default()),
2867+
"getsockopt multicast ifindex (expected %d got %d)",
2868+
net_if_get_by_iface(net_if_get_default()), ret);
2869+
zexpect_equal(ifaddr->address.in_addr.s_addr,
2870+
addr.s_addr,
2871+
"getsockopt iface address mismatch (expected %s got %s)",
2872+
net_sprint_ipv4_addr(&ifaddr->address.in_addr),
2873+
net_sprint_ipv4_addr(&addr));
2874+
2875+
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
2876+
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
2877+
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
2878+
"invalid send len (was %d expected %d) (%d)",
2879+
ret, STRLEN(TEST_STR_SMALL), -errno);
2880+
2881+
/* Test that the sent data is received from default interface. */
2882+
addrlen = sizeof(saddr4);
2883+
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
2884+
0, (struct sockaddr *)&saddr4, &addrlen);
2885+
zexpect_true(ret >= 0, "recvfrom fail");
2886+
zexpect_equal(ret, strlen(TEST_STR_SMALL),
2887+
"unexpected received bytes");
2888+
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
2889+
"wrong data");
2890+
2891+
/* Then use mreq structure to set the interface */
2892+
optlen = sizeof(mreq);
2893+
ifaddr = net_if_ipv4_addr_get_first_by_index(net_if_get_by_iface(net_if_get_default()));
2894+
zexpect_not_null(ifaddr, "No address found for interface %d",
2895+
net_if_get_by_iface(net_if_get_default()));
2896+
mreq.imr_interface.s_addr = ifaddr->address.in_addr.s_addr;
2897+
2898+
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
2899+
&mreq, optlen);
2900+
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
2901+
2902+
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
2903+
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
2904+
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
2905+
"invalid send len (was %d expected %d) (%d)",
2906+
ret, STRLEN(TEST_STR_SMALL), -errno);
2907+
2908+
/* Test that the sent data is received from default interface. */
2909+
addrlen = sizeof(saddr4);
2910+
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
2911+
0, (struct sockaddr *)&saddr4, &addrlen);
2912+
zexpect_true(ret >= 0, "recvfrom fail");
2913+
zexpect_equal(ret, strlen(TEST_STR_SMALL),
2914+
"unexpected received bytes");
2915+
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
2916+
"wrong data");
2917+
2918+
ret = zsock_close(sock);
2919+
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
2920+
2921+
ret = zsock_close(server_sock);
2922+
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
2923+
2924+
test_started = false;
2925+
loopback_enable_address_swap(true);
2926+
}
2927+
26742928
static void after(void *arg)
26752929
{
26762930
ARG_UNUSED(arg);

0 commit comments

Comments
 (0)