commit 56fbe9e4228416b290bd5243607c97f5cc988d6a
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu May 3 11:23:54 2012 +0200
multicast: New test case source_membership.xml
Adding new testcase for source specific multicast inferface:
IP_ADD_SOURCE_MEMBERSHIP
IP_DROP_SOURCE_MEMBERSIP
There is one new offline conformance test and one new server
setup.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Tests/TestMulticast.py | 2 +-
.../cmd_sequences/multicast/source_membership.xml | 83 +++++++++++++++++++
test_tools/multicast/Makefile | 4 +-
.../multicast/offline/sockopt_source_membership.c | 85 ++++++++++++++++++++
.../multicast/server/recv_source_membership.c | 63 +++++++++++++++
5 files changed, 234 insertions(+), 3 deletions(-)
---
diff --git a/Tests/TestMulticast.py b/Tests/TestMulticast.py
index c757bca..4710f89 100644
--- a/Tests/TestMulticast.py
+++ b/Tests/TestMulticast.py
@@ -53,7 +53,7 @@ class TestMulticast(TestGeneric):
opts["delay"] = self.get_opt("delay")
# receiver-specific
- opts["source"] = self._remove_mask(self.get_opt("source"))
+ opts["source_address"] =
self._remove_mask(self.get_opt("source"))
cmd = "./{0} ".format(setup)
diff --git a/example_recipes/cmd_sequences/multicast/source_membership.xml
b/example_recipes/cmd_sequences/multicast/source_membership.xml
new file mode 100644
index 0000000..aeb525b
--- /dev/null
+++ b/example_recipes/cmd_sequences/multicast/source_membership.xml
@@ -0,0 +1,83 @@
+<!-- IP_ADD/DROP_SOURCE_MEMBERSHIP test -->
+<!-- Requires: 2 hosts
+ - [1] with one interface
+ - [2] with one interface
+ - -->
+<!-- NOTICE: IGMP packets must be forwarded through the network!
+ In kvm/libvirt environment, iptables on host must be off or
+ configured to forward igmp traffic through the bridge -->
+
+<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_source_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_source_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 type="recipe_eval" name="source"
value="['machines'][1]['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" />
+
+ <!-- Nonexistent source -->
+ <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_source_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="source" value="127.0.0.200" />
+
+ <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 68a5406..9eb8fe9 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 recv_membership
-OFFLINE=sockopt_loop sockopt_ttl sockopt_if sockopt_membership
+RECEIVERS=recv_simple recv_membership recv_source_membership
+OFFLINE=sockopt_loop sockopt_ttl sockopt_if sockopt_membership sockopt_source_membership
all: $(SENDERS) $(RECEIVERS) $(OFFLINE)
diff --git a/test_tools/multicast/offline/sockopt_source_membership.c
b/test_tools/multicast/offline/sockopt_source_membership.c
new file mode 100644
index 0000000..a43b43c
--- /dev/null
+++ b/test_tools/multicast/offline/sockopt_source_membership.c
@@ -0,0 +1,85 @@
+/*
+ * sockopt_source_membership.c - IP_ADD/DROP_SOURCE_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_source_membership()
+{
+ struct ip_mreq_source mreq;
+
+ mreq.imr_multiaddr.s_addr = 0x0100007f;
+ mreq.imr_interface.s_addr = 0x0100007f;
+ mreq.imr_sourceaddr.s_addr = 0x12345678;
+ test_setsockopt_error("IP_ADD_SOURCE_MEMBERSHIP Bad multicast address",
+ IP_ADD_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), EINVAL);
+
+
+ mreq.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreq.imr_interface.s_addr = 0xffffffff;
+ mreq.imr_sourceaddr.s_addr = 0x12345678;
+ test_setsockopt_error("IP_ADD_SOURCE_MEMBERSHIP Bad interface",
+ IP_ADD_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), ENODEV);
+
+
+ test_setsockopt_error("IP_ADD_SOURCE_MEMBERSHIP Bad optlen",
+ IP_ADD_SOURCE_MEMBERSHIP, &mreq, 2, EINVAL);
+}
+
+void test_drop_source_membership()
+{
+ struct ip_mreq_source mreq;
+
+ mreq.imr_multiaddr.s_addr = 0x0100007f;
+ mreq.imr_interface.s_addr = 0x0100007f;
+ mreq.imr_sourceaddr.s_addr = 0x12345678;
+ test_setsockopt_error("IP_DROP_SOURCE_MEMBERSHIP Bad multicast address",
+ IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), EINVAL);
+
+ mreq.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreq.imr_interface.s_addr = 0x0100007f;
+ mreq.imr_sourceaddr.s_addr = 0x12345678;
+ test_setsockopt_error("IP_DROP_SOURCE_MEMBERSHIP Not a member",
+ IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), EINVAL);
+
+ mreq.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreq.imr_interface.s_addr = 0xffffffff;
+ mreq.imr_sourceaddr.s_addr = 0x12345678;
+ test_setsockopt_error("IP_DROP_SOURCE_MEMBERSHIP No device found",
+ IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), ENODEV);
+
+ test_setsockopt_error("IP_DROP_SOURCE_MEMBERSHIP Bad optlen",
+ IP_DROP_SOURCE_MEMBERSHIP, &mreq, 5, EINVAL);
+}
+
+int main()
+{
+ initialize();
+
+ test_add_source_membership();
+ test_drop_source_membership();
+
+ report_and_exit();
+ return 0;
+}
diff --git a/test_tools/multicast/server/recv_source_membership.c
b/test_tools/multicast/server/recv_source_membership.c
new file mode 100644
index 0000000..88d546d
--- /dev/null
+++ b/test_tools/multicast/server/recv_source_membership.c
@@ -0,0 +1,63 @@
+/*
+ * recv_drop_membership.c - Join multicast group only for a specific
+ * source and then leave it in the middle of
+ * ongoing 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);
+
+ int num_recv = 0;
+ struct ip_mreq_source mreq;
+ mreq.imr_multiaddr = params.multiaddr;
+ mreq.imr_interface = params.interface;
+ mreq.imr_sourceaddr = params.sourceaddr;
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
+ &(mreq), sizeof(mreq)) < 0)
+ {
+ perror("setsockopt");
+ return -1;
+ }
+
+ num_recv = wait_for_data(sockfd, params.duration/2, 0);
+ printf("packets_received=%d\n", num_recv);
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP,
+ &(mreq), sizeof(mreq)) < 0)
+ {
+ perror("setsockopt");
+ return -1;
+ }
+
+ num_recv = wait_for_data(sockfd, params.duration/2, 0);
+ printf("packets_received_after_drop=%d\n", num_recv);
+
+ return EXIT_SUCCESS;
+}