From: Radek Pazdera <rpazdera(a)redhat.com>
Adding new testcase `membership.xml' with the necessary setup and
offline conformance tests for sockopt ADD/DROP_MEMBERSHIP interface.
This simple test case verifies that if one side leaves multicast group
in the middle of ongoing communication, no further packets are delivered
to the process.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
.../cmd_sequences/multicast/membership.xml | 48 ++++++++++++
test_tools/multicast/Makefile | 4 +-
test_tools/multicast/offline/sockopt_membership.c | 78 ++++++++++++++++++++
test_tools/multicast/server/recv_membership.c | 62 ++++++++++++++++
4 files changed, 190 insertions(+), 2 deletions(-)
create mode 100644 example_recipes/cmd_sequences/multicast/membership.xml
create mode 100644 test_tools/multicast/offline/sockopt_membership.c
create mode 100644 test_tools/multicast/server/recv_membership.c
diff --git a/example_recipes/cmd_sequences/multicast/membership.xml
b/example_recipes/cmd_sequences/multicast/membership.xml
new file mode 100644
index 0000000..fd9c166
--- /dev/null
+++ b/example_recipes/cmd_sequences/multicast/membership.xml
@@ -0,0 +1,48 @@
+<!-- IP_ADD/DROP_MEMBERSHIP test -->
+<!-- Requires: 2 hosts
+ - [1] with one interface
+ - [2] with one interface
+ - -->
+
+<command_sequence>
+ <!-- IP_ADD/DROP_MEMBERSHIP sockopt conformance test -->
+ <command type="test" value="Multicast"
machine_id="1" timeout="30">
+ <options>
+ <option name="setup" value="sockopt_membership" />
+ <option name="condition" value="status ==
'pass'" />
+ </options>
+ </command>
+
+ <!-- This simple test case verifies that if one side leaves multicast group
+ - in the middle of ongoing communication, no further packets are delivered
+ - to the process. -->
+ <command type="exec" machine_id="1" value="sleep 1"
/>
+ <command type="exec" machine_id="2" value="sleep 1"
/>
+
+ <command type="test" value="Multicast"
machine_id="1" timeout="30" bg_id="1">
+ <options>
+ <option name="setup" value="send_simple" />
+ <option name="address" value="238.0.0.1" />
+ <option name="port" value="1337" />
+ <option name="duration" value="10" />
+ <option name="delay" value="0.1" />
+ <option name="ttl" value="1" />
+ <option type="recipe_eval" name="interface"
value="['machines'][1]['netconfig'][1]['addresses'][0]"
/>
+ </options>
+ </command>
+
+ <command type="test" value="Multicast"
machine_id="2" timeout="30">
+ <options>
+ <option name="setup" value="recv_membership" />
+ <option name="address" value="238.0.0.1" />
+ <option name="port" value="1337" />
+ <option name="duration" value="10" />
+ <option type="recipe_eval" name="interface"
value="['machines'][2]['netconfig'][1]['addresses'][0]"
/>
+
+ <option name="condition" value="packets_received >
0" />
+ <option name="condition" value="packets_received_after_drop
== 0" />
+ </options>
+ </command>
+
+ <command type="wait" machine_id="1" value="1" />
+</command_sequence>
diff --git a/test_tools/multicast/Makefile b/test_tools/multicast/Makefile
index 47af8f5..68a5406 100644
--- a/test_tools/multicast/Makefile
+++ b/test_tools/multicast/Makefile
@@ -3,8 +3,8 @@ TOOLS_DIR=.
CFLAGS=-Wall -Wextra -I$(TOOLS_DIR)
SENDERS=send_simple
-RECEIVERS=recv_simple
-OFFLINE=sockopt_loop sockopt_ttl sockopt_if
+RECEIVERS=recv_simple recv_membership
+OFFLINE=sockopt_loop sockopt_ttl sockopt_if sockopt_membership
all: $(SENDERS) $(RECEIVERS) $(OFFLINE)
diff --git a/test_tools/multicast/offline/sockopt_membership.c
b/test_tools/multicast/offline/sockopt_membership.c
new file mode 100644
index 0000000..b8612f7
--- /dev/null
+++ b/test_tools/multicast/offline/sockopt_membership.c
@@ -0,0 +1,78 @@
+/*
+ * sockopt_membership.c - IP_ADD/DROP_MEMBERSHIP socket option test
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Author: Radek Pazdera (rpazdera(a)redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "sockopt_utils.h"
+
+
+void test_add_membership()
+{
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr = 0x0100007f;
+ struct ip_mreqn mreqn;
+
+ test_setsockopt_error("IP_ADD_MEMBERSHIP Bad multicast address",
+ IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq), EINVAL);
+
+ test_setsockopt_error("IP_ADD_MEMBERSHIP Bad optlen",
+ IP_ADD_MEMBERSHIP, &mreq, 5, EINVAL);
+
+ mreqn.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreqn.imr_address.s_addr = 0xffffffff;
+ mreqn.imr_ifindex = 500;
+ test_setsockopt_error("IP_ADD_MEMBERSHIP No device found",
+ IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn), ENODEV);
+}
+
+void test_drop_membership()
+{
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr = 0x0100007f;
+ mreq.imr_interface.s_addr = 0x0100007f;
+ struct ip_mreqn mreqn;
+
+ test_setsockopt_error("IP_DROP_MEMBERSHIP Bad optlen",
+ IP_DROP_MEMBERSHIP, &mreq, 5, EINVAL);
+ test_setsockopt_error("IP_DROP_MEMBERSHIP Bad multicast address",
+ IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq), EADDRNOTAVAIL);
+
+ mreq.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreq.imr_interface.s_addr = 0x0100007f;
+ test_setsockopt_error("IP_DROP_MEMBERSHIP Not a member",
+ IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq), EADDRNOTAVAIL);
+
+ mreqn.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreqn.imr_address.s_addr = 0xffffffff;
+ mreqn.imr_ifindex = 500;
+ test_setsockopt_error("IP_DROP_MEMBERSHIP No device found",
+ IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn), ENODEV);
+}
+
+int main()
+{
+ initialize();
+
+ test_add_membership();
+ test_drop_membership();
+
+ report_and_exit();
+ return 0;
+}
diff --git a/test_tools/multicast/server/recv_membership.c
b/test_tools/multicast/server/recv_membership.c
new file mode 100644
index 0000000..018226b
--- /dev/null
+++ b/test_tools/multicast/server/recv_membership.c
@@ -0,0 +1,62 @@
+/*
+ * recv_membership.c - Join multicast group and leave it
+ * in the middle of communication
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Author: Radek Pazdera (rpazdera(a)redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define RECEIVE
+#include "multicast_utils.h"
+
+int main(int argc, char** argv)
+{
+ struct parameters params;
+ parse_args(argc, argv, ¶ms);
+
+ int sockfd = init_in_socket(params.multiaddr, params.port);
+
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr = params.multiaddr;
+ mreq.imr_interface = params.interface;
+
+ int num_recv = 0;
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &(mreq), sizeof(mreq)) < 0) {
+ perror("setsockopt");
+ return EXIT_FAILURE;
+ }
+
+ num_recv = wait_for_data(sockfd, params.duration/2, 0);
+
+ printf("packets_received=%d\n", num_recv);
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ &(mreq), sizeof(mreq)) < 0) {
+ perror("setsockopt");
+ return EXIT_FAILURE;
+ }
+
+ num_recv = wait_for_data(sockfd, params.duration/2, 0);
+
+ printf("packets_received_after_drop=%d\n", num_recv);
+
+ return EXIT_SUCCESS;
+}
--
1.7.7.6