test: net: igmp: Add IGMP query test

Add functionality to test the IGMP query handling. This test should
prevent the IGMP logic from sending IGMPv3 messages to IGMPv2 queriers.
The test does now also check backwards compatability when IGMPv3 queries
are received but only IGMPv2 is enabled.

Signed-off-by: Ibe Van de Veire <ibe.vandeveire@basalte.be>
This commit is contained in:
Ibe Van de Veire 2024-10-17 17:09:57 +02:00 committed by Maureen Helm
commit fa07b9fcf1

View file

@ -45,6 +45,24 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV4_LOG_LEVEL);
#define DBG(fmt, ...)
#endif
static const unsigned char igmp_v2_query[] = {
/* IPv4 header */
0x46, 0xc0, 0x00, 0x20, 0x1b, 0x58, 0x00, 0x00, 0x01, 0x02, 0x66, 0x79,
0xc0, 0x00, 0x02, 0x45, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00,
/* IGMP header */
0x11, 0xff, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char igmp_v3_query[] = {
/* IPv4 header */
0x46, 0xc0, 0x00, 0x24, 0xac, 0x72, 0x00, 0x00, 0x01, 0x02, 0xd5, 0x5a,
0xc0, 0x00, 0x02, 0x45, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00,
/* IGMP header */
0x11, 0x64, 0xec, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00,
};
static struct in_addr my_addr = { { { 192, 0, 2, 1 } } };
static struct in_addr mcast_addr = { { { 224, 0, 2, 63 } } };
static struct in_addr any_addr = INADDR_ANY_INIT;
@ -56,6 +74,8 @@ static bool is_join_msg_ok;
static bool is_leave_msg_ok;
static bool is_query_received;
static bool is_report_sent;
static bool is_igmpv2_query_sent;
static bool is_igmpv3_query_sent;
static bool ignore_already;
K_SEM_DEFINE(wait_data, 0, UINT_MAX);
@ -151,8 +171,8 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
k_sem_give(&wait_data);
} else if (igmp_header->type == NET_IPV4_IGMP_REPORT_V2) {
NET_DBG("Received v2 report....");
zassert_false(IS_ENABLED(CONFIG_NET_IPV4_IGMPV3),
"Wrong IGMP report received (IGMPv2)");
zassert_true(!IS_ENABLED(CONFIG_NET_IPV4_IGMPV3) || is_igmpv2_query_sent,
"Wrong IGMP report received (IGMPv2)");
is_join_msg_ok = true;
is_report_sent = true;
k_sem_give(&wait_data);
@ -160,6 +180,7 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
NET_DBG("Received v3 report....");
zassert_true(IS_ENABLED(CONFIG_NET_IPV4_IGMPV3),
"Wrong IGMP report received (IGMPv3)");
zassert_false(is_igmpv2_query_sent, "IGMPv3 response to IGMPv2 request");
#if defined(CONFIG_NET_IPV4_IGMPV3)
zassert_true(ntohs(igmp_header->groups_len) == 1,
@ -285,6 +306,24 @@ static void igmp_teardown(void *dummy)
net_if_ipv4_addr_rm(net_iface, &my_addr);
}
static struct net_pkt *prepare_igmp_query(struct net_if *iface, bool is_igmpv3)
{
struct net_pkt *pkt;
const unsigned char *igmp_query = is_igmpv3 ? igmp_v3_query : igmp_v2_query;
size_t igmp_query_size = is_igmpv3 ? sizeof(igmp_v3_query) : sizeof(igmp_v2_query);
pkt = net_pkt_alloc_with_buffer(iface, igmp_query_size, AF_INET, IPPROTO_IGMP, K_FOREVER);
zassert_not_null(pkt, "Failed to allocate buffer");
zassert_ok(net_pkt_write(pkt, igmp_query, igmp_query_size));
net_pkt_set_overwrite(pkt, true);
net_pkt_cursor_init(pkt);
return pkt;
}
static void join_group(void)
{
int ret;
@ -559,4 +598,47 @@ ZTEST_USER(net_igmp, test_socket_catch_join_with_index)
socket_leave_group_with_index(&my_addr);
}
static void igmp_send_query(bool is_imgpv3)
{
struct net_pkt *pkt;
is_report_sent = false;
is_join_msg_ok = false;
is_igmpv2_query_sent = false;
is_igmpv3_query_sent = false;
/* Joining group first to get reply on query*/
join_group();
is_igmpv2_query_sent = !is_imgpv3;
is_igmpv3_query_sent = is_imgpv3;
pkt = prepare_igmp_query(net_iface, is_imgpv3);
zassert_not_null(pkt, "IGMPv2 query packet prep failed");
zassert_equal(net_ipv4_input(pkt, false), NET_OK, "Failed to send");
zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting query event");
zassert_true(is_report_sent, "Did not catch query event");
zassert_true(is_join_msg_ok, "Join msg invalid");
is_igmpv2_query_sent = false;
is_igmpv3_query_sent = false;
leave_group();
}
ZTEST_USER(net_igmp, test_igmpv3_query)
{
igmp_send_query(true);
}
ZTEST_USER(net_igmp, test_igmpv2_query)
{
igmp_send_query(false);
}
ZTEST_SUITE(net_igmp, NULL, igmp_setup, NULL, NULL, igmp_teardown);