[lnst] multicast: Fix endianess bug
by Jiří Pírko
commit 70b140c9619bc22ea9cec6b2f22ac25b2314e134
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 18:01:58 2012 +0200
multicast: Fix endianess bug
There was a bug with IP addresses in socket conformance tests
that occured on big endian machines.
Reported-By: Hangbin Liu <hliu(a)redhat.com>
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
.../multicast/offline/sockopt_block_source.c | 32 +++++++++----------
test_tools/multicast/offline/sockopt_if.c | 8 ++--
test_tools/multicast/offline/sockopt_membership.c | 18 +++++-----
.../multicast/offline/sockopt_source_membership.c | 30 +++++++++---------
4 files changed, 43 insertions(+), 45 deletions(-)
---
diff --git a/test_tools/multicast/offline/sockopt_block_source.c b/test_tools/multicast/offline/sockopt_block_source.c
index f79bb48..c60c151 100644
--- a/test_tools/multicast/offline/sockopt_block_source.c
+++ b/test_tools/multicast/offline/sockopt_block_source.c
@@ -27,20 +27,18 @@ void test_block_source()
{
struct ip_mreq_source mreq;
- mreq.imr_multiaddr.s_addr = 0x0100007f;
- mreq.imr_interface.s_addr = 0x0100007f;
- mreq.imr_sourceaddr.s_addr = 0x12345678;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_BLOCK_SOURCE Bad multicast address",
IP_BLOCK_SOURCE, &mreq, sizeof(mreq), EINVAL);
-
- mreq.imr_multiaddr.s_addr = 0xdeadbeef;
- mreq.imr_interface.s_addr = 0xffffffff;
- mreq.imr_sourceaddr.s_addr = 0x12345678;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("255.255.255.255");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_BLOCK_SOURCE Bad interface",
IP_BLOCK_SOURCE, &mreq, sizeof(mreq), ENODEV);
-
test_setsockopt_error("IP_BLOCK_SOURCE Bad optlen",
IP_BLOCK_SOURCE, &mreq, 2, EINVAL);
}
@@ -49,21 +47,21 @@ void test_unblock_source()
{
struct ip_mreq_source mreq;
- mreq.imr_multiaddr.s_addr = 0x0100007f;
- mreq.imr_interface.s_addr = 0x0100007f;
- mreq.imr_sourceaddr.s_addr = 0x12345678;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_UNBLOCK_SOURCE Bad multicast address",
IP_UNBLOCK_SOURCE, &mreq, sizeof(mreq), EINVAL);
- mreq.imr_multiaddr.s_addr = 0xdeadbeef;
- mreq.imr_interface.s_addr = 0x0100007f;
- mreq.imr_sourceaddr.s_addr = 0x12345678;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_UNBLOCK_SOURCE Not a member",
IP_UNBLOCK_SOURCE, &mreq, sizeof(mreq), EINVAL);
- mreq.imr_multiaddr.s_addr = 0xdeadbeef;
- mreq.imr_interface.s_addr = 0xffffffff;
- mreq.imr_sourceaddr.s_addr = 0x12345678;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("255.255.255.255");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_UNBLOCK_SOURCE No device found",
IP_UNBLOCK_SOURCE, &mreq, sizeof(mreq), ENODEV);
diff --git a/test_tools/multicast/offline/sockopt_if.c b/test_tools/multicast/offline/sockopt_if.c
index ff5bd51..2396629 100644
--- a/test_tools/multicast/offline/sockopt_if.c
+++ b/test_tools/multicast/offline/sockopt_if.c
@@ -32,19 +32,19 @@ void test_if()
test_getsockopt("IP_MULTICAST_IF default value",
IP_MULTICAST_IF, &address, size);
- inet_pton(AF_INET, "127.0.0.1", &address);
+ address.s_addr = inet_addr("127.0.0.1");
test_sockopt_value("IP_MULTICAST_IF set to 127.0.0.1",
IP_MULTICAST_IF, &address, size);
struct ip_mreqn mreqn;
- mreqn.imr_multiaddr.s_addr = 0xdeadbeef;
+ mreqn.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
mreqn.imr_address.s_addr = INADDR_ANY;
mreqn.imr_ifindex = 0;
test_sockopt_value("IP_MULTICAST_IF set to INADDR_ANY",
IP_MULTICAST_IF, &mreqn, sizeof(mreqn));
- mreqn.imr_address.s_addr = 0x0100007f;
+ mreqn.imr_address.s_addr = inet_addr("127.0.0.1");
test_sockopt_value("IP_MULTICAST_IF set to 127.0.0.1",
IP_MULTICAST_IF, &mreqn, sizeof(mreqn));
@@ -53,7 +53,7 @@ void test_if()
test_setsockopt_error("IP_MULTICAST_IF bad optlen",
IP_MULTICAST_IF, &address, 3, EINVAL);
- inet_pton(AF_INET, "238.0.10.0", &address);
+ address.s_addr = inet_addr("238.0.10.0");
test_setsockopt_error("IP_MULTICAST_IF address 238.0.10.0",
IP_MULTICAST_IF, &address,
sizeof(address), EADDRNOTAVAIL);
diff --git a/test_tools/multicast/offline/sockopt_membership.c b/test_tools/multicast/offline/sockopt_membership.c
index b8612f7..4f8adc3 100644
--- a/test_tools/multicast/offline/sockopt_membership.c
+++ b/test_tools/multicast/offline/sockopt_membership.c
@@ -26,7 +26,7 @@
void test_add_membership()
{
struct ip_mreq mreq;
- mreq.imr_multiaddr.s_addr = 0x0100007f;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
struct ip_mreqn mreqn;
test_setsockopt_error("IP_ADD_MEMBERSHIP Bad multicast address",
@@ -35,8 +35,8 @@ void test_add_membership()
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_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreqn.imr_address.s_addr = inet_addr("255.255.255.255");
mreqn.imr_ifindex = 500;
test_setsockopt_error("IP_ADD_MEMBERSHIP No device found",
IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn), ENODEV);
@@ -45,8 +45,8 @@ void test_add_membership()
void test_drop_membership()
{
struct ip_mreq mreq;
- mreq.imr_multiaddr.s_addr = 0x0100007f;
- mreq.imr_interface.s_addr = 0x0100007f;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
struct ip_mreqn mreqn;
test_setsockopt_error("IP_DROP_MEMBERSHIP Bad optlen",
@@ -54,13 +54,13 @@ void test_drop_membership()
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;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
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_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreqn.imr_address.s_addr = inet_addr("255.255.255.255");
mreqn.imr_ifindex = 500;
test_setsockopt_error("IP_DROP_MEMBERSHIP No device found",
IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn), ENODEV);
diff --git a/test_tools/multicast/offline/sockopt_source_membership.c b/test_tools/multicast/offline/sockopt_source_membership.c
index a43b43c..d589dcd 100644
--- a/test_tools/multicast/offline/sockopt_source_membership.c
+++ b/test_tools/multicast/offline/sockopt_source_membership.c
@@ -29,16 +29,16 @@ 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;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
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;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("255.255.255.255");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_ADD_SOURCE_MEMBERSHIP Bad interface",
IP_ADD_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), ENODEV);
@@ -51,21 +51,21 @@ 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;
+ mreq.imr_multiaddr.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
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;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("127.0.0.1");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
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;
+ mreq.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
+ mreq.imr_interface.s_addr = inet_addr("255.255.255.255");
+ mreq.imr_sourceaddr.s_addr = inet_addr("192.168.0.1");
test_setsockopt_error("IP_DROP_SOURCE_MEMBERSHIP No device found",
IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq), ENODEV);
11 years, 4 months
[lnst] multicast: Convert recipe_eval to newer convention
by Jiří Pírko
commit 5eb2a7aa1485c6df1a4851d512c214fd3e5b5321
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 18:01:57 2012 +0200
multicast: Convert recipe_eval to newer convention
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
.../cmd_sequences/multicast/block_source.xml | 10 ++--
example_recipes/cmd_sequences/multicast/if.xml | 38 +++++++-------
example_recipes/cmd_sequences/multicast/loop.xml | 36 +++++++-------
.../cmd_sequences/multicast/max_groups.xml | 9 ++--
.../cmd_sequences/multicast/membership.xml | 18 +++---
example_recipes/cmd_sequences/multicast/simple.xml | 19 +++----
.../cmd_sequences/multicast/source_membership.xml | 38 +++++++-------
example_recipes/cmd_sequences/multicast/ttl.xml | 54 ++++++++++----------
example_recipes/rpazdera-multicast.xml | 22 +++++++-
9 files changed, 129 insertions(+), 115 deletions(-)
---
diff --git a/example_recipes/cmd_sequences/multicast/block_source.xml b/example_recipes/cmd_sequences/multicast/block_source.xml
index a9a3712..72d0fd2 100644
--- a/example_recipes/cmd_sequences/multicast/block_source.xml
+++ b/example_recipes/cmd_sequences/multicast/block_source.xml
@@ -25,7 +25,7 @@
<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]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
@@ -35,8 +35,8 @@
<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="interface" value="{ip(2,1)}" />
+ <option name="source" value="{ip(1,1)}" />
<option name="condition" value="packets_received > 0" />
<option name="condition" value="packets_received_while_blocking == 0" />
@@ -56,7 +56,7 @@
<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]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
@@ -66,7 +66,7 @@
<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="interface" value="{ip(2,1)}" />
<option name="source" value="127.0.0.200" />
<option name="condition" value="packets_received > 0" />
diff --git a/example_recipes/cmd_sequences/multicast/if.xml b/example_recipes/cmd_sequences/multicast/if.xml
index c7fec3f..a81557c 100644
--- a/example_recipes/cmd_sequences/multicast/if.xml
+++ b/example_recipes/cmd_sequences/multicast/if.xml
@@ -1,4 +1,4 @@
-<!-- Offline IP_MULTICAST_IF test -->
+<!-- IP_MULTICAST_IF test -->
<!-- Requires: 2 hosts
- [1] with one interface
- [2] with one interface
@@ -23,22 +23,22 @@
<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="0" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
+ <option name="ttl" value="1" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="2" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
@@ -52,21 +52,21 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="2" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <option name="address" value="238.0.0.1" />
- <option name="port" value="1337" />
- <option name="duration" value="10" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
<option name="interface" value="127.0.0.1" />
<option name="condition" value="packets_received == 0" />
diff --git a/example_recipes/cmd_sequences/multicast/loop.xml b/example_recipes/cmd_sequences/multicast/loop.xml
index 7b155e1..ceac21c 100644
--- a/example_recipes/cmd_sequences/multicast/loop.xml
+++ b/example_recipes/cmd_sequences/multicast/loop.xml
@@ -16,22 +16,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="loop" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="1" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(1,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
@@ -45,22 +45,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="loop" value="0" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="1" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(1,1)}" />
<option name="condition" value="packets_received == 0" />
</options>
diff --git a/example_recipes/cmd_sequences/multicast/max_groups.xml b/example_recipes/cmd_sequences/multicast/max_groups.xml
index 2141678..a2d1a25 100644
--- a/example_recipes/cmd_sequences/multicast/max_groups.xml
+++ b/example_recipes/cmd_sequences/multicast/max_groups.xml
@@ -6,20 +6,19 @@
<command type="test" value="Multicast" machine_id="1" timeout="30">
<options>
<option name="setup" value="max_groups" />
- <option name="interface" value="{$host1if1}" />
+ <option name="interface" value="{ip(1,1)}" />
<option name="condition" value="max_groups > 0" />
</options>
</command>
<!-- Change default max_memberhsips -->
- <command type="exec" value="echo '5' > /proc/sys/net/ipv4/igmp_max_memberships" machine_id="1" />
+
+ <command type="system_config" option="/proc/sys/net/ipv4/igmp_max_memberships" value="5" machine_id="1" />
<command type="test" value="Multicast" machine_id="1" timeout="30">
<options>
<option name="setup" value="max_groups" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
<option name="condition" value="max_groups == 5" />
</options>
</command>
- <command type="exec" value="echo '20' > /proc/sys/net/ipv4/igmp_max_memberships" machine_id="1" />
-
</command_sequence>
diff --git a/example_recipes/cmd_sequences/multicast/membership.xml b/example_recipes/cmd_sequences/multicast/membership.xml
index fd9c166..3136e2f 100644
--- a/example_recipes/cmd_sequences/multicast/membership.xml
+++ b/example_recipes/cmd_sequences/multicast/membership.xml
@@ -22,22 +22,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="condition" value="packets_received > 0" />
<option name="condition" value="packets_received_after_drop == 0" />
diff --git a/example_recipes/cmd_sequences/multicast/simple.xml b/example_recipes/cmd_sequences/multicast/simple.xml
index 236558b..7455201 100644
--- a/example_recipes/cmd_sequences/multicast/simple.xml
+++ b/example_recipes/cmd_sequences/multicast/simple.xml
@@ -8,22 +8,21 @@
<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 type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="2" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <option name="address" value="238.0.0.1" />
- <option name="port" value="1337" />
- <option name="duration" value="10" />
- <!-- <option name="interface" value="192.168.122.179" /> -->
- <option type="recipe_eval" name="interface" value="['machines'][2]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
diff --git a/example_recipes/cmd_sequences/multicast/source_membership.xml b/example_recipes/cmd_sequences/multicast/source_membership.xml
index aeb525b..ffda96f 100644
--- a/example_recipes/cmd_sequences/multicast/source_membership.xml
+++ b/example_recipes/cmd_sequences/multicast/source_membership.xml
@@ -25,23 +25,23 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
+ <option name="source" value="{ip(1,1)}" />
<option name="condition" value="packets_received > 0" />
<option name="condition" value="packets_received_after_drop == 0" />
@@ -56,22 +56,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="source" value="127.0.0.200" />
<option name="condition" value="packets_received == 0" />
diff --git a/example_recipes/cmd_sequences/multicast/ttl.xml b/example_recipes/cmd_sequences/multicast/ttl.xml
index ae55228..d0fe197 100644
--- a/example_recipes/cmd_sequences/multicast/ttl.xml
+++ b/example_recipes/cmd_sequences/multicast/ttl.xml
@@ -19,23 +19,23 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="0" />
<option name="loop" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="1" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(1,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
@@ -58,22 +58,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="0" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="2" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
@@ -87,22 +87,22 @@
<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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="delay" value="{$send_delay}" />
<option name="ttl" value="1" />
- <option type="recipe_eval" name="interface" value="['machines'][1]['netconfig'][1]['addresses'][0]" />
+ <option name="interface" value="{ip(1,1)}" />
</options>
</command>
<command type="test" value="Multicast" machine_id="2" timeout="30">
<options>
<option name="setup" value="recv_simple" />
- <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="address" value="{$multicast_group}" />
+ <option name="port" value="{$port}" />
+ <option name="duration" value="{$test_duration}" />
+ <option name="interface" value="{ip(2,1)}" />
<option name="condition" value="packets_received > 0" />
</options>
diff --git a/example_recipes/rpazdera-multicast.xml b/example_recipes/rpazdera-multicast.xml
index 9a90168..192e462 100644
--- a/example_recipes/rpazdera-multicast.xml
+++ b/example_recipes/rpazdera-multicast.xml
@@ -10,10 +10,14 @@
<netconfig>
<netdevice id="1" type="eth" phys_id="1">
<addresses>
- <address value="192.168.122.237/24" />
+ <address value="192.168.122.225/24" />
+ </addresses>
+ </netdevice>
+ <netdevice id="2" type="eth" phys_id="2">
+ <addresses>
+ <address value="192.168.122.239/24" />
</addresses>
</netdevice>
- <netdevice id="2" type="eth" phys_id="2" />
</netconfig>
</machine>
<machine id="2">
@@ -24,13 +28,25 @@
<netconfig>
<netdevice id="1" type="eth" phys_id="1">
<addresses>
- <address value="192.168.122.179/24" />
+ <address value="192.168.122.200/24" />
</addresses>
</netdevice>
</netconfig>
</machine>
</machines>
+ <define>
+ <alias name="multicast_group" value="239.1.2.3" />
+ <alias name="port" value="1337" />
+ <alias name="test_duration" value="10" />
+ <alias name="send_delay" value="0.1" />
+ <alias name="nonexistent_ip" value="127.0.0.200" />
+ </define>
+
+ <command_sequence source="cmd_sequences/multicast/max_groups.xml" />
+ <command_sequence source="cmd_sequences/multicast/block_source.xml" />
+ <command_sequence source="cmd_sequences/multicast/source_membership.xml" />
+ <command_sequence source="cmd_sequences/multicast/membership.xml" />
<command_sequence source="cmd_sequences/multicast/if.xml" />
<command_sequence source="cmd_sequences/multicast/ttl.xml" />
<command_sequence source="cmd_sequences/multicast/loop.xml" />
11 years, 4 months
[PATCH 0/5] Multicast Tests Update
by Radek Pazdera
From: Radek Pazdera <rpazdera(a)redhat.com>
This patch series contains several small updates of multicast tests.
The older recipe and command sequences were adapted to recent changes
in NetTestParser.
A couple of minor bugs and typing errors was fixed as well.
Radek Pazdera (5):
multicast: Moved IGMP parameters to separate file
multicast: Adding igmp options to TestMulticast.py
multicast: recv_block_source reporting fix
multicast: Convert recipe_eval to newer convention
multicast: Fix endianess bug
Tests/TestMulticast.py | 5 +
.../cmd_sequences/multicast/block_source.xml | 10 +-
example_recipes/cmd_sequences/multicast/if.xml | 38 ++--
example_recipes/cmd_sequences/multicast/loop.xml | 36 ++--
.../cmd_sequences/multicast/max_groups.xml | 9 +-
.../cmd_sequences/multicast/membership.xml | 18 +-
example_recipes/cmd_sequences/multicast/simple.xml | 19 +-
.../cmd_sequences/multicast/source_membership.xml | 38 ++--
example_recipes/cmd_sequences/multicast/ttl.xml | 54 ++--
example_recipes/rpazdera-multicast.xml | 22 ++-
test_tools/multicast/igmp_utils.h | 2 +-
test_tools/multicast/multicast_utils.h | 2 +-
.../multicast/offline/sockopt_block_source.c | 32 +--
test_tools/multicast/offline/sockopt_if.c | 10 +-
test_tools/multicast/offline/sockopt_membership.c | 18 +-
.../multicast/offline/sockopt_source_membership.c | 30 +-
test_tools/multicast/parameters.h | 287 --------------------
test_tools/multicast/parameters_igmp.h | 154 +++++++++++
test_tools/multicast/parameters_multicast.h | 192 +++++++++++++
test_tools/multicast/server/recv_block_source.c | 15 +-
20 files changed, 534 insertions(+), 457 deletions(-)
delete mode 100644 test_tools/multicast/parameters.h
create mode 100644 test_tools/multicast/parameters_igmp.h
create mode 100644 test_tools/multicast/parameters_multicast.h
--
1.7.7.6
11 years, 4 months
[lnst] multicast: recv_block_source reporting fix
by Jiří Pírko
commit ec1e6491779d4db194f4ddb87c730ca9c38e5a0b
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 18:01:56 2012 +0200
multicast: recv_block_source reporting fix
Small fix in recv_block_source setup. The 'packets_sent' report was
printed twice, which lead to correct, but inaccurate stats.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
test_tools/multicast/server/recv_block_source.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
---
diff --git a/test_tools/multicast/server/recv_block_source.c b/test_tools/multicast/server/recv_block_source.c
index 6e2f462..9edcb80 100644
--- a/test_tools/multicast/server/recv_block_source.c
+++ b/test_tools/multicast/server/recv_block_source.c
@@ -32,7 +32,9 @@ int main(int argc, char** argv)
int sockfd = init_in_socket(params.multiaddr, params.port);
- int num_recv = 0;
+ int num_good = 0;
+ int num_bad = 0;
+
struct ip_mreq mreq;
mreq.imr_multiaddr = params.multiaddr;
mreq.imr_interface = params.interface;
@@ -49,8 +51,7 @@ int main(int argc, char** argv)
return -1;
}
- num_recv = wait_for_data(sockfd, params.duration/3, 0);
- printf("packets_received=%d\n", num_recv);
+ num_good += wait_for_data(sockfd, params.duration/3, 0);
if (setsockopt(sockfd, IPPROTO_IP, IP_BLOCK_SOURCE,
&(mreqs), sizeof(mreqs)) < 0)
@@ -59,8 +60,7 @@ int main(int argc, char** argv)
return -1;
}
- num_recv = wait_for_data(sockfd, params.duration/3, 0);
- printf("packets_received_while_blocking=%d\n", num_recv);
+ num_bad += wait_for_data(sockfd, params.duration/3, 0);
if (setsockopt(sockfd, IPPROTO_IP, IP_UNBLOCK_SOURCE,
&(mreqs), sizeof(mreqs)) < 0)
@@ -69,8 +69,9 @@ int main(int argc, char** argv)
return -1;
}
- num_recv = wait_for_data(sockfd, params.duration/3, 0);
- printf("packets_received=%d\n", num_recv);
+ num_good += wait_for_data(sockfd, params.duration/3, 0);
+ printf("packets_received=%d\n", num_good);
+ printf("packets_received_while_blocking=%d\n", num_bad);
return EXIT_SUCCESS;
}
11 years, 4 months
[lnst] multicast: Adding igmp options to TestMulticast.py
by Jiří Pírko
commit 4b0b278f71bd4c2225495eef356043c43e0b1199
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 18:01:55 2012 +0200
multicast: Adding igmp options to TestMulticast.py
There are some new test options after splitting multicast and igmp
parameters, so take them in account.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Tests/TestMulticast.py | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
---
diff --git a/Tests/TestMulticast.py b/Tests/TestMulticast.py
index 4710f89..5e2df5b 100644
--- a/Tests/TestMulticast.py
+++ b/Tests/TestMulticast.py
@@ -55,6 +55,11 @@ class TestMulticast(TestGeneric):
# receiver-specific
opts["source_address"] = self._remove_mask(self.get_opt("source"))
+ # igmp-specific
+ opts["query_type"] = self.get_opt("query_type")
+ opts["dest_address"] = self.get_opt("dest_address")
+ opts["max_resp_time"] = self.get_opt("max_resp_time")
+
cmd = "./{0} ".format(setup)
for optname, optval in opts.iteritems():
11 years, 4 months
[lnst] multicast: Moved IGMP parameters to separate file
by Jiří Pírko
commit 2e390fcec6c9ee3bb43902bbd6566608d4fe3677
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 18:01:54 2012 +0200
multicast: Moved IGMP parameters to separate file
The original parameters.h was getting too heavy, there
was more macros than code. The file was split it into
* parameters_igmp.h
* parameters_multicast.h
Also some code cleanup was done.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
test_tools/multicast/igmp_utils.h | 2 +-
test_tools/multicast/multicast_utils.h | 2 +-
test_tools/multicast/parameters_igmp.h | 154 +++++++++++++++
.../{parameters.h => parameters_multicast.h} | 205 ++++++--------------
4 files changed, 211 insertions(+), 152 deletions(-)
---
diff --git a/test_tools/multicast/igmp_utils.h b/test_tools/multicast/igmp_utils.h
index 901d01f..125232b 100644
--- a/test_tools/multicast/igmp_utils.h
+++ b/test_tools/multicast/igmp_utils.h
@@ -43,7 +43,7 @@
#include <linux/igmp.h>
#define IGMP
-#include "parameters.h"
+#include "parameters_igmp.h"
int __verbosity = 0;
diff --git a/test_tools/multicast/multicast_utils.h b/test_tools/multicast/multicast_utils.h
index 25d0c38..70fcf59 100644
--- a/test_tools/multicast/multicast_utils.h
+++ b/test_tools/multicast/multicast_utils.h
@@ -43,7 +43,7 @@
#error "At least one of SEND/RECEIVE macros must be defined!"
#endif
-#include "parameters.h"
+#include "parameters_multicast.h"
#define MESSAGE "Hello world!"
diff --git a/test_tools/multicast/parameters_igmp.h b/test_tools/multicast/parameters_igmp.h
new file mode 100644
index 0000000..31a9c87
--- /dev/null
+++ b/test_tools/multicast/parameters_igmp.h
@@ -0,0 +1,154 @@
+/*
+ * parameters_igmp.h - common code for parsing sender/receiver parameters
+ * 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.
+ */
+
+#ifndef __PARAMETERS_IGMP_H__
+#define __PARAMETERS_IGMP_H__
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <signal.h>
+#include <time.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern int __verbosity;
+
+enum __igmp_query_types {
+ IGMP_GENERAL_QUERY = 1,
+ IGMP_GROUP_SPECIFIC_QUERY = 2,
+ IGMP_GROUP_AND_SOURCE_SPECIFIC_QUERY = 3
+};
+
+/** Structure that carries test parameters */
+struct parameters
+{
+ struct in_addr multiaddr;
+ struct in_addr interface;
+
+ short query_type;
+ struct in_addr sourceaddr;
+ struct in_addr destaddr;
+ int max_resp_time;
+};
+
+/** Initialize parameters struct with default values. */
+void default_parameters(struct parameters* params)
+{
+ memset(¶ms->multiaddr, 0, sizeof(struct in_addr));
+ memset(¶ms->interface, 0, sizeof(struct in_addr));
+
+ params->query_type = IGMP_GENERAL_QUERY;
+ memset(¶ms->sourceaddr, 0, sizeof(struct in_addr));
+ memset(¶ms->destaddr, 0, sizeof(struct in_addr));
+ params->max_resp_time = 0;
+}
+
+void usage(char *program_name, int retval)
+{
+ printf("usage: %s\n", program_name);
+ printf(" -h | --help print this\n");
+ printf(" -v | --verbose print additional information during the runtime\n");
+ printf(" -i | --interface a.b.c.d local interface to use for communication\n");
+
+ printf("\n");
+
+ printf(" -a | --multicast_address a.b.c.d multicast group address (v2 and v3 only)\n");
+ printf(" -s | --source_address a.b.c.d multicast source (v3 only)\n");
+ printf(" -d | --dest_address a.b.c.d destination address of the IP packet\n");
+
+ printf("\n");
+
+ printf(" -q | --query_type query type [1,2,3]\n");
+ printf(" -r | --max_resp_time x maximum response time\n");
+ exit(retval);
+}
+
+/** Generic function for parsing arguments */
+void parse_args(int argc, char** argv, struct parameters* args)
+{
+ int dest_was_set = 0;
+
+ static const char* opts = "i:a:q:s:d:r:hv";
+ static struct option long_options[] =
+ {
+ {"interface", required_argument, NULL, 'i'},
+ {"multicast_address", required_argument, NULL, 'a'},
+ {"query_type", required_argument, NULL, 'q'},
+ {"source_address", required_argument, NULL, 's'},
+ {"dest_address", required_argument, NULL, 'd'},
+ {"max_resp_time", required_argument, NULL, 'r'},
+ {"help", no_argument, NULL, 'h'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, NULL, 0}
+ };
+
+ default_parameters(args);
+
+ int opt;
+ int option_index = 0;
+ while((opt = getopt_long(argc, argv, opts, long_options,
+ &option_index)) != -1) {
+ switch (opt) {
+ case 'i':
+ inet_pton(AF_INET, optarg, &(args->interface));
+ break;
+ case 'a':
+ inet_pton(AF_INET, optarg, &(args->multiaddr));
+ break;
+ case 'q':
+ args->query_type = atoi(optarg);
+ break;
+ case 's':
+ inet_pton(AF_INET, optarg, &(args->sourceaddr));
+ break;
+ case 'd':
+ inet_pton(AF_INET, optarg, &(args->destaddr));
+ dest_was_set = 1;
+ break;
+ case 'r':
+ args->max_resp_time = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0], EXIT_SUCCESS);
+ break;
+ case 'v':
+ __verbosity = 1;
+ break;
+ default: /* '?' */
+ fprintf(stderr, "%s: invalid options\n", argv[0]);
+ usage(argv[0], EXIT_FAILURE);
+ }
+ }
+
+ if (!dest_was_set)
+ args->destaddr = args->multiaddr;
+}
+
+#endif
diff --git a/test_tools/multicast/parameters.h b/test_tools/multicast/parameters_multicast.h
similarity index 51%
rename from test_tools/multicast/parameters.h
rename to test_tools/multicast/parameters_multicast.h
index a9fda9d..ecaaf79 100644
--- a/test_tools/multicast/parameters.h
+++ b/test_tools/multicast/parameters_multicast.h
@@ -1,5 +1,6 @@
/*
- * parameters.h - common code for parsing sender/receiver parameters
+ * parameters_multicast.h - common code for parsing sender/receiver
+ * parameters
* Copyright (C) 2012 Red Hat Inc.
*
* Author: Radek Pazdera (rpazdera(a)redhat.com)
@@ -20,8 +21,8 @@
* 02110-1301, USA.
*/
-#ifndef __PARAMETERS_H__
-#define __PARAMETERS_H__
+#ifndef __PARAMETERS_MULTICAST_H__
+#define __PARAMETERS_MULTICAST_H__
#include <stdio.h>
#include <string.h>
@@ -40,24 +41,16 @@
extern int __verbosity;
-#ifdef IGMP
-enum __igmp_query_types {
- IGMP_GENERAL_QUERY = 1,
- IGMP_GROUP_SPECIFIC_QUERY = 2,
- IGMP_GROUP_AND_SOURCE_SPECIFIC_QUERY = 3
-};
-#endif
-
/** Structure that carries test parameters */
struct parameters
{
- int duration; /* seconds */
-
struct in_addr multiaddr;
- short port;
struct in_addr interface;
-#if defined(RECEIVE) || defined(IGMP)
+ int duration; /* seconds */
+ short port;
+
+#ifdef RECEIVE
struct in_addr sourceaddr;
#endif
@@ -66,80 +59,46 @@ struct parameters
int ttl;
int loop;
#endif
-
-#ifdef IGMP
- short query_type;
- struct in_addr destaddr;
- int max_resp_time;
-#endif
};
/** Initialize parameters struct with default values. */
void default_parameters(struct parameters* params)
{
- params->duration = 10;
+ params->duration = 0;
params->port = 0;
memset(¶ms->multiaddr, 0, sizeof(struct in_addr));
memset(¶ms->interface, 0, sizeof(struct in_addr));
-
-#if defined(RECEIVE) || defined(IGMP)
+#ifdef RECEIVE
memset(¶ms->sourceaddr, 0, sizeof(struct in_addr));
#endif
-
#ifdef SEND
params->delay = 0.1;
params->ttl = 1;
params->loop = 1;
#endif
-
-#ifdef IGMP
- params->query_type = IGMP_GENERAL_QUERY;
- memset(¶ms->destaddr, 0, sizeof(struct in_addr));
- params->max_resp_time = 10;
-#endif
}
void usage(char *program_name, int retval)
{
printf("usage: %s\n", program_name);
- printf(" -h | --help print this\n");
- printf(" -i | --interface a.b.c.d local interface to use for communication\n");
- printf(" -v | --verbose print additional information during the runtime\n");
-
- printf("\n");
-
- printf(" -d | --duration x test duration\n");
-
-#ifdef SEND
- printf(" -f | --delay x delay between messages\n");
-#endif
+ printf(" -h | --help print this\n");
+ printf(" -v | --verbose print additional information during the runtime\n");
+ printf(" -i | --interface a.b.c.d local interface to use for communication\n");
+ printf(" -d | --duration x test duration\n");
printf("\n");
- printf(" -a | --address a.b.c.d multicast group address\n");
-
-#if defined(SEND) || defined(IGMP)
- printf(" -s | --source_address a.b.c.d source address\n");
+ printf(" -a | --multicast_address a.b.c.d multicast group address\n");
+#ifdef RECEIVE
+ printf(" -s | --source_address a.b.c.d multicast source (for SSM)\n");
#endif
-
-#ifdef IGMP
- printf(" -z | --dest_address a.b.c.d destination address\n");
-#endif
-
-#if defined(SEND) || defined(RECEIVE)
- printf(" -p | --port x port number\n");
-#endif
-
+ printf(" -p | --port x port number\n");
+#ifdef SEND
printf("\n");
-#ifdef IGMP
- printf(" -q | --query_type query type\n");
- printf(" -r | --max_resp_time x maximum response time\n");
-#endif
-
-#ifdef SEND
- printf(" -t | --ttl x time to live for IP packet\n");
- printf(" -l | --loop x loopback multicast communication\n");
+ printf(" -t | --ttl x time to live for IP packet\n");
+ printf(" -l | --loop x loopback multicast communication\n");
+ printf(" -f | --delay x delay between messages\n");
#endif
exit(retval);
@@ -149,60 +108,37 @@ void usage(char *program_name, int retval)
void parse_args(int argc, char** argv, struct parameters* args)
{
#ifdef SEND
- #define __send_opts "f:t:l:p:"
+ #define __send_opts "f:t:l:"
#else
#define __send_opts ""
#endif
-#if defined(RECEIVE) || defined(IGMP)
- #define __recv_opts "s:p:"
+#ifdef RECEIVE
+ #define __recv_opts "s:"
#else
#define __recv_opts ""
#endif
-#ifdef IGMP
- #define __igmp_opts "q:z:r:"
-#else
- #define __igmp_opts ""
-#endif
-
-#ifdef IGMP
- int dest_was_set = 0;
-#endif
-
- static const char* opts = "d:a:i:v" __send_opts __recv_opts
- __igmp_opts;
+ static const char* opts = __send_opts __recv_opts "d:a:p:i:hv";
static struct option long_options[] =
{
- {"help", required_argument, NULL, 'h'},
- {"interface", required_argument, NULL, 'i'},
- {"verbose", no_argument, NULL, 'v'},
- {"duration", required_argument, NULL, 'd'},
- {"multicast_address", required_argument, NULL, 'a'},
-
-#if defined(RECEIVE) || defined(IGMP)
- {"source_address", required_argument, NULL, 's'},
-#endif
-
#ifdef SEND
{"delay", required_argument, NULL, 'f'},
{"ttl", required_argument, NULL, 't'},
{"loop", required_argument, NULL, 'l'},
#endif
-
-#if defined(SEND) || defined(RECEIVE)
- {"port", required_argument, NULL, 'p'},
-#endif
-
-#ifdef IGMP
- {"query_type", required_argument, NULL, 'q'},
- {"dest_address", required_argument, NULL, 'z'},
- {"max_resp_time", required_argument, NULL, 'r'},
-
+#ifdef RECEIVE
+ {"source_address", required_argument, NULL, 's'},
#endif
- {0, 0, NULL, 0}
+ {"duration", required_argument, NULL, 'd'},
+ {"multicast_address", required_argument, NULL, 'a'},
+ {"port", required_argument, NULL, 'p'},
+ {"interface", required_argument, NULL, 'i'},
+ {"help", no_argument, NULL, 'h'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, NULL, 0}
};
default_parameters(args);
@@ -212,6 +148,22 @@ void parse_args(int argc, char** argv, struct parameters* args)
while((opt = getopt_long(argc, argv, opts, long_options,
&option_index)) != -1) {
switch (opt) {
+#ifdef SEND
+ case 'f':
+ args->delay = atof(optarg);
+ break;
+ case 't':
+ args->ttl = atoi(optarg);
+ break;
+ case 'l':
+ args->loop = atoi(optarg);
+ break;
+#endif
+#ifdef RECEIVE
+ case 's':
+ inet_pton(AF_INET, optarg, &(args->sourceaddr));
+ break;
+#endif
case 'd':
args->duration = atoi(optarg);
break;
@@ -221,67 +173,20 @@ void parse_args(int argc, char** argv, struct parameters* args)
case 'p':
args->port = atoi(optarg);
break;
- case 'h':
- usage(argv[1], EXIT_SUCCESS);
- break;
case 'i':
inet_pton(AF_INET, optarg, &(args->interface));
break;
+ case 'h':
+ usage(argv[0], EXIT_SUCCESS);
+ break;
case 'v':
__verbosity = 1;
break;
-#if defined(RECEIVE) || defined(IGMP)
- case 's':
- inet_pton(AF_INET, optarg, &(args->sourceaddr));
- break;
-#endif
-
-#ifdef SEND
- case 'f':
- args->delay = atof(optarg);
- break;
- case 't':
- args->ttl = atoi(optarg);
- break;
- case 'l':
- args->loop = atoi(optarg);
- break;
-#endif
-
-#ifdef IGMP
- case 'q':
- args->query_type = atoi(optarg);
- /*if (strcmp(optarg, "general") == 0) {
- args->query_type = IGMP_GENERAL_QUERY;
- } else if (strcmp(optarg, "group_specific") == 0) {
- args->query_type = IGMP_GROUP_SPECIFIC_QUERY;
- } else if (strcmp(optarg, "group_and_source_specific") == 0) {
- args->query_type = IGMP_GROUP_AND_SOURCE_SPECIFIC_QUERY;
- } else {
- fprintf(stderr, "%s: undefined query type\n",
- argv[0]);
- exit(EXIT_FAILURE);
- }*/
- break;
- case 'z':
- inet_pton(AF_INET, optarg, &(args->destaddr));
- dest_was_set = 1;
- break;
- case 'r':
- args->max_resp_time = atoi(optarg);
- break;
-#endif
default: /* '?' */
- fprintf(stderr, "%s: invalid test options\n", argv[0]);
+ fprintf(stderr, "%s: invalid options\n", argv[0]);
usage(argv[0], EXIT_FAILURE);
}
}
-
-#ifdef IGMP
- if (!dest_was_set)
- args->destaddr = args->multiaddr;
-#endif
-
}
#endif
11 years, 4 months
[lnst] Documentation: Update to reflect recent changes
by Jiří Pírko
commit 3f3ce7907d21f7945780ddcff6a6d87117b0a413
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 17:37:09 2012 +0200
Documentation: Update to reflect recent changes
* New section on 'System Configuration'
* Moved 'Defining aliases' and 'Splitting recipe into multiple files
under the 'Writing recipe' section
* New section on 'Template Functions'
* A few tiny formating changes
* Added a shade under all code segments to split them visualy
from the surrounding text
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Documentation/LNSTIntro.html | 192 ++++++++++++++++++++++++++++++++++--------
1 files changed, 157 insertions(+), 35 deletions(-)
---
diff --git a/Documentation/LNSTIntro.html b/Documentation/LNSTIntro.html
index 227b560..baea586 100644
--- a/Documentation/LNSTIntro.html
+++ b/Documentation/LNSTIntro.html
@@ -6,6 +6,10 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>LNST - Linux Network Stack Test</title>
<meta name="generator" content="Amaya, see http://www.w3.org/Amaya/" />
+
+ <style>
+ pre {background-color: #eaeaea;}
+ </style>
</head>
<body>
@@ -119,6 +123,7 @@ traffic generated in tests executed on test machines.</p>
SshUtils.py
TestsCommon.py
Utils.py
+ XmlPreprocessor.py
XmlRpc.py
[./example_recipes] (inspiration for test setups – netconfigs, machineconfigs, recipes)
@@ -148,9 +153,13 @@ traffic generated in tests executed on test machines.</p>
TestIcmp6Ping.py
TestIcmpPing.py
TestIperf.py
+ TestMulticast.py
TestNetCat.py
TestPktCounter.py
TestPktgenTx.py
+
+[./test_tools] (non-python testing tools and scripts)
+ multicast/
</pre>
<p></p>
@@ -203,7 +212,7 @@ repository on it.</p>
<machines>
<machine id="1">
<span style="background-color:#ffc0cb"><netmachineconfig source="example_recipes/machine_configs/config-f14peanut.xml"/></span>
- <span style="background-color:#90ee90"><netconfig source="example_recipes/net_configs/netconfig1.xml"/></span>
+ <span style="background-color:#90ee90"><netconfig source="example_recipes/net_configs/netconfig1.xml"/></span>
</machine>
<machine id="2">
<span style="background-color:#ffc0cb"><netmachineconfig source="my_recipes/config-f15.xml"/></span>
@@ -212,8 +221,8 @@ repository on it.</p>
</machines>
<span style="background-color:#add8e6"><command_sequence></span>
- <span style="background-color:#add8e6"><command type="exec" value="sleep 4"/></span></pre>
-<pre> <span style="background-color:#add8e6"><command type="test" machine_id="1" value="IcmpPing" timeout="30"></span>
+ <span style="background-color:#add8e6"><command type="exec" value="sleep 4"/></span>
+ <span style="background-color:#add8e6"><command type="test" machine_id="1" value="IcmpPing" timeout="30"></span>
<span style="background-color:#add8e6"><options></span>
<span style="background-color:#add8e6"><option type="recipe_eval" name="addr" value="['machines'][2]['netconfig'][1]['addresses'][0]"/></span>
<span style="background-color:#add8e6"><option name="count" value="40"/></span>
@@ -303,28 +312,7 @@ defined in <strong>addresses</strong> element.</p>
src="machineconfig-netconfig-mapping.png" width="793" height="318" /></p>
<p></p>
-
-<h3><em>Defining aliases</em></h3>
-<p>LNST allows you to define arbitrary <strong>aliases</strong> and use
-them to access certain values from the whole recipe file while the value
-itself is included in the file only once. Definition of an alias occurs
-in the <code><define></code> tag anywhere in the document:</p>
-<pre>
-<define>
- <span style="background-color:#90ee90"><alias name="ip_addr" value="192.168.0.1" /></span>
- <span style="background-color:#add8e6"><alias name="mask" value="24" /></span>
-</define>
-</pre>
-
-<p>Defined alias can be referenced from any element's attribute or text.
-For instance:</p>
-<pre>
-<netdevice id="2" type="eth">
- <addresses>
- <address value="<span style="background-color:#90ee90">{$ip_addr}</span>/<span style="background-color:#add8e6">{$mask}</span>"/>
- </addresses>
-</netdevice>
-</pre>
+<h4><strong></strong></h4>
<h3><em>Command sequences</em></h3>
@@ -388,6 +376,146 @@ assigned address from netconfig of <em>first</em> device on <em>second</em>
machine.
</p>
+<h3><em>System Configuration</em></h3>
+<p>
+LNST provides a native way of changing system configuration of the slave machines from within the recipe.
+This can be achieved by <strong>system_config</strong> command. There are two versions
+of <strong>system_config</strong> command:
+</p>
+<h4>Inline version</h4>
+<pre>
+ <command <span style="background-color:#add8e6">type="system_config"</span> option="/proc/sys/net/ipv4/igmp_max_memberships" value="50" machine_id="2" persistent="true" />
+</pre>
+
+<h4>Multiline version</h4>
+<pre>
+ <command <span style="background-color:#add8e6">type="system_config"</span> machine_id="1">
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="10" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="5" />
+ </options>
+ </commang>
+</pre>
+
+<p>
+ In the multiline version you can set a several options at once.
+</p>
+<p>
+ Unless <strong>persistent</strong> flag is set to <strong>true</strong>, all modified
+ options are restored to their previous values <strong>at the end of the command sequence</strong>.
+ The following examlpe illustrates how this works:
+<pre>
+ <command_sequence>
+ <command type="system_config" machine_id="1" <span style="background-color:#ffc0cb">persistent="true"</span>>
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="10" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="5" />
+ </options>
+ </commang>
+ </command_sequence>
+ <command_sequence>
+ <command type="system_config" option="/proc/sys/net/ipv4/igmp_max_memberships" value="50" />
+
+ execute some test here ...
+ </command_sequence> <span style="background-color:#90ee90"><!-- At this point, igmp_max_memberships is set back to 10 --></span>
+ <command_sequence>
+ <command type="system_config" machine_id="1" <span style="background-color:#ffc0cb">persistent="true"</span>>
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="20" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="10" />
+ </options>
+ </commang>
+ </command_sequence>
+</pre>
+<p>
+ The first command sequence serves as a global system setup phase, persistent flag is set to true,
+ so the options <strong>will not</strong> be restored when the command sequence finishes.
+</p>
+<p>
+ In the second command sequence, one option is modified for purposes of the next test, but it's
+ not marked persistent, so the change will be automatically reverted when the command sequence
+ comes to end.
+</p>
+<p>
+ And the final command sequences issues a persistent command again, to make sure that system is left
+ in a consistent state when recipe execution is over.
+</p>
+
+<hr />
+
+<h2>Writing a test</h2>
+<p>
+ This section introduces several features you can use when you decide to create your own recipe.
+</p>
+
+<h3><em>Defining aliases</em></h3>
+<p>LNST allows you to define arbitrary <strong>aliases</strong> and use
+them to access certain values from the whole recipe file while the value
+itself is included in the file only once. Definition of an alias occurs
+in the <code><define></code> tag anywhere in the document:</p>
+<pre>
+<define>
+ <span style="background-color:#90ee90"><alias name="ip_addr" value="192.168.0.1" /></span>
+ <span style="background-color:#add8e6"><alias name="mask" value="24" /></span>
+</define>
+</pre>
+
+<p>Defined alias can be referenced from any element's attribute or text.
+For instance:</p>
+<pre>
+<netdevice id="2" type="eth">
+ <addresses>
+ <address value="<span style="background-color:#90ee90">{$ip_addr}</span>/<span style="background-color:#add8e6">{$mask}</span>"/>
+ </addresses>
+</netdevice>
+</pre>
+
+<h3><em>Template functions</em></h3>
+<p>
+ Template functions are conceptually quite similar to aliases, but instead of a assigned value, they
+ represent an action that will be executed when the recipe is parsed. They can be used the same way
+ as aliases - inside of curly braces. Currently, there are three template functions available in LNST:
+</p>
+<ul>
+ <li><strong>ip</strong>(<em>machine_id</em>, <em>interface_id</em><em>[, address_id]</em>)
+ <p>
+ Returns IP address for a specific machine and interface.
+ Third argument is optional and can be used when there are
+ multiple IP addresses associated with a single interface.
+ </p>
+ </li>
+ <li><strong>hwaddr</strong>(<em>machine_id</em>, <em>interface_id</em>)
+ <p>
+ Returns hardware address of specified interface.
+ </p>
+ </li>
+ <li><strong>devname</strong>(<em>machine_id</em>, <em>interface_id</em>)
+ <p>
+ Returns device name of specified interface.
+ </p>
+ </li>
+</ul>
+<p>
+ All three above mentioned functions can be used for retrieving information from machine
+ configs, therefore calling them is only valid within a command sequence. See the following
+ example on how this templates can be used:
+</p>
+<pre>
+ <command type="system_config" option="/proc/sys/net/ipv4/conf/<span style="background-color:#ffc0cb">{devname(1,1)}</span>/forwarding" value="1" machine_id="1" />
+ <command type="test" value="Multicast" machine_id="1" timeout="30">
+ <options>
+ <option name="setup" value="max_groups" />
+ <option name="interface" value="<span style="background-color:#ffc0cb">{ip(1,1)}</span>" />
+ <option name="condition" value="max_groups > 0" />
+ </options>
+ </command>
+</pre>
+<p>
+ Aliases can be passed to functions as parameters, but the preprocessor
+does not support nesting (e.g. function cannot have another function
+passed as an argument).
+</p>
+
<h3><em>Splitting recipes into multiple files</em></h3>
<p>
LNST also offers a possibility of splitting the recipe into several
@@ -408,12 +536,6 @@ Example (<em>peanut.xml</em>):
</pre>
<p>Note that parts of the included machine config are again external.</p>
-<hr />
-
-<h2>Writing a test</h2>
-
-<p>[TODO]</p>
-
<p></p>
<hr />
@@ -460,8 +582,8 @@ up as <strong>type='bridge'</strong>.</p>
<domain type='kvm'>
<name>rhel6ga</name>
- ...</pre>
-<pre> <devices>
+ ...
+ <devices>
...
<interface type='bridge'>
<mac address='52:54:00:9f:be:73'/>
@@ -502,7 +624,7 @@ configuration, that means removal of relevant kernel module (bonding, bridge,
<h3><em>Running LNST without remote execution</em></h3>
<p>In this case you have to start nettestslave.py processes first on all
-machines that are defined in recipe by yourself. Let's assume there are
+machines that are defined in recipe by yourself. Let's assume there are
2 machines participating in the test.</p>
<p>On both of these machines you have to run following command:</p>
@@ -523,7 +645,7 @@ in a recipe:</p>
<h3><em>Using LNST to configure interfaces only</em></h3>
-<p>You can also use LNST to do just the network configuration of the test
+<p>You can also use LNST to do just the network configuration of the test
machines. None of the tests inside your recipe file will get executed.</p>
<p>To do this pass <strong>config_only</strong> instead of 'run' argument to
11 years, 4 months
[lnst] NetTestParse: Adding XML Preprocessor
by Jiří Pírko
commit 310697dde2210af229cb0d435480b67593d63f22
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri May 25 13:10:38 2012 +0200
NetTestParse: Adding XML Preprocessor
Code that handles parsing aliases was refactored and moved from
NetTestParse into a new class in Common module - XmlPreprocessor.
In the process of this transition it was extended with a new type
of template - functions.
Template functions can be used the same way as aliases - inside of
curly braces. For instance:
{ip(1,2,3)}
{function(argument1, $alias_argument)}
There are three template functions available at the moment. All three
can be used for retrieving information from machine configs:
hwaddr(machine_id, if_id) - get hw address of an interface
devname(machine_id, if_id) - get interface name
ip(machine_id, if_id, addr_id) - get IP address (if there's a mask
present in the configuration it
will be stripped). The third
argument is optional, defaults to
zero if omitted.
Aliases can be passed to functions as parameters, but the preprocessor
does not support nesting (e.g. function cannot have another function
passed as an argument).
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Common/XmlPreprocessor.py | 226 +++++++++++++++++++++++++++++++++++++++++++++
NetTest/NetTestParse.py | 69 +++-----------
2 files changed, 238 insertions(+), 57 deletions(-)
---
diff --git a/Common/XmlPreprocessor.py b/Common/XmlPreprocessor.py
new file mode 100644
index 0000000..88ae758
--- /dev/null
+++ b/Common/XmlPreprocessor.py
@@ -0,0 +1,226 @@
+"""
+This module contains code for preprocessing templates in XML files/recipes
+before they are parsed.
+
+Templates are strings enclosed in curly braces {} and can be present
+in all text elements of the XML file (this includes tag values or
+attribute values). Templates cannot be used as a stubstitution for tag
+names, attribute names or any other structural elements of the document.
+
+There are two supported types of templates:
+
+ * aliases - $alias_name
+ * functions - function_name(param1, param2)
+
+Copyright 2012 Red Hat, Inc.
+Licensed under the GNU General Public License, version 2 as
+published by the Free Software Foundation; see COPYING for details.
+"""
+
+__author__ = """
+rpazdera(a)redhat.com (Radek Pazdera)
+"""
+
+import re
+
+class XmlTemplateError(Exception):
+ pass
+
+class XmlPreprocessor:
+ """
+ This class serves as template processor within a XML DOM tree object.
+ """
+
+ _template_re = "\{([^\{\}]+)\}"
+ _alias_re = "^\$([a-zA-Z0-9_]+)(\[.+\])*$"
+ _func_re = "^([a-zA-Z0-9_]+)\(([^\(\)]*)\)$"
+
+ def __init__(self):
+ self._definitions = {}
+ self._reserved_aliases = ["recipe"]
+
+ def define_alias(self, name, value, skip_reserved_check=False):
+ """
+ Associate an alias name with some value. The value can be of
+ an atomic type or an array.
+ """
+
+ if not name in self._reserved_aliases \
+ or skip_reserved_check == True:
+ self._definitions[name] = value
+ else:
+ raise XmlTemplateError("Alias name '%s' is reserved" % name)
+
+ def expand(self, node):
+ """
+ Traverse DOM tree from `node' down and expand any
+ templates along the way.
+ """
+
+ if node.nodeType == node.ELEMENT_NODE:
+ i = 0
+ num_attributes = node.attributes.length
+ while(i < num_attributes):
+ attr = node.attributes.item(i)
+ attr.value = self._expand_string(str(attr.value))
+ i += 1
+ elif node.nodeType == node.TEXT_NODE:
+ node.data = self._expand_string(str(node.data))
+
+ for child in node.childNodes:
+ self.expand(child)
+
+ def expand_group(self, group):
+ """
+ Behaves exactly the same as the `expand' method, but it
+ operates on a group of DOM nodes stored within a list,
+ rather than a single node.
+ """
+
+ for node in group:
+ self.expand(node)
+
+ def _expand_string(self, string):
+ while True:
+ template_match = re.search(self._template_re, string)
+ if template_match:
+ template_string = template_match.group(0)
+ template = template_match.group(1)
+ template_result = self._process_template(template)
+
+ string = string.replace(template_string, template_result)
+ else:
+ break
+
+ return string
+
+ def _process_template(self, string):
+ string = string.strip()
+ result = None
+
+ if re.match(self._alias_re, string):
+ result = self._process_alias_template(string)
+ return result
+
+ if re.match(self._func_re, string):
+ result = self._process_func_template(string)
+ return result
+
+ raise XmlTemplateError("Unknown template type '%s'" % string)
+
+ def _process_alias_template(self, string):
+ result = None
+
+ alias_match = re.match(self._alias_re, string)
+ if alias_match:
+ alias_name = alias_match.group(1)
+ array_subscript = alias_match.group(2)
+
+ if not alias_name in self._definitions:
+ err = "Alias '%s' is not defined here" % alias_name
+ raise XmlTemplateError(err)
+
+ if array_subscript != None:
+ try:
+ result = str(eval("self._definitions['%s']%s" \
+ % (alias_name, array_subscript)))
+ except (KeyError, IndexError):
+ err = "Wrong array subscript in '%s[%s]'" \
+ % (alias_name, array_subscript)
+ raise XmlTemplateError(err)
+ else:
+ result = self._definitions[alias_name]
+
+ return result
+
+ def _process_func_template(self, string):
+ result = None
+
+ func_match = re.match(self._func_re, string)
+ if func_match:
+ func_name = func_match.group(1)
+ func_params = func_match.group(2)
+
+ if func_params == None:
+ func_params = []
+ else:
+ func_params = func_params.split(",")
+
+ param_values = []
+ for param in func_params:
+ param = param.strip()
+ if re.match(self._alias_re, param):
+ param = self._process_alias_template(param)
+ param_values.append(param)
+
+ result = self._call_preprocessor_func(func_name, param_values)
+
+ return result
+
+ def _call_preprocessor_func(self, name, params):
+ if name == "ip":
+ result = self._ip_func(params)
+ elif name == "hwaddr":
+ result = self._hwaddr_func(params)
+ elif name == "devname":
+ result = self._devname_func(params)
+ else:
+ raise XmlTemplateError("Unknown preprocessor function '%s'" % name)
+
+ return result
+
+ def _ip_func(self, params):
+ self._validate_func_params("ip", params, 2, 1)
+ self._check_recipe_data("ip")
+
+ m_id = int(params[0])
+ if_id = int(params[1])
+ ip_id = int(params[2]) if len(params) == 3 else 0
+
+ machines = self._definitions["recipe"]["machines"]
+ ip_addr = machines[m_id]['netconfig'][if_id]['addresses'][ip_id]
+
+ return ip_addr.split('/')[0]
+
+ def _hwaddr_func(self, params):
+ self._validate_func_params("hwaddr", params, 2, 0)
+ self._check_recipe_data("hwaddr")
+ m_id = int(params[0])
+ if_id = int(params[1])
+
+ machines = self._definitions["recipe"]["machines"]
+ return machines[m_id]['netconfig'][if_id]['hwaddr']
+
+
+ def _devname_func(self, params):
+ self._validate_func_params("devname", params, 2, 0)
+ self._check_recipe_data("devname")
+ m_id = int(params[0])
+ if_id = int(params[1])
+
+ machines = self._definitions["recipe"]["machines"]
+ return machines[m_id]['netconfig'][if_id]['name']
+
+ @staticmethod
+ def _validate_func_params(name, params, mandatory, optional):
+ num_params = len(params)
+ if num_params > (mandatory + optional) or num_params < mandatory:
+ if optional:
+ err = "Function %s takes between %d-%d arguments, %d passed" \
+ % (name, mandatory, mandatory + optional, num_params)
+ else:
+ err = "Function %s takes %d arguments, %d passed" \
+ % (name, mandatory, num_params)
+ raise XmlTemplateError(err)
+ for param in params:
+ try:
+ int(param)
+ except ValueError:
+ err = "Non-integer parameter passed to '%s'" % name
+ raise XmlTemplateError(err)
+
+ def _check_recipe_data(self, template_name):
+ if not "recipe" in self._definitions:
+ err = "Cannot resolve %s() here, recipe data not available yet" \
+ % template_name
+ raise XmlTemplateError(err)
diff --git a/NetTest/NetTestParse.py b/NetTest/NetTestParse.py
index 69833b1..5b5101a 100644
--- a/NetTest/NetTestParse.py
+++ b/NetTest/NetTestParse.py
@@ -16,6 +16,7 @@ import os
import re
from NetConfig.NetConfigParse import NetConfigParse
from NetTest.NetTestCommand import str_command
+from Common.XmlPreprocessor import XmlPreprocessor
def load_file(filename):
handle = open(filename, "r")
@@ -36,6 +37,8 @@ class NetTestParse:
self._dirpath = os.path.dirname(recipe_path)
self._recipe = None
+ self._xml_prep = XmlPreprocessor()
+
def _get_referenced_xml_path(self, filename):
return os.path.join(self._dirpath, os.path.expanduser(filename))
@@ -64,38 +67,40 @@ class NetTestParse:
return machines
def _parse_definitions(self, dom_definitions_grp):
+ xml_prep = self._xml_prep
definitions = {}
for dom_definitions_item in dom_definitions_grp:
dom_aliases = dom_definitions_item.getElementsByTagName("alias")
for dom_alias in dom_aliases:
alias_name = str(dom_alias.getAttribute("name"))
alias_value = str(dom_alias.getAttribute("value"))
- definitions[alias_name] = alias_value
- return definitions
+ xml_prep.define_alias(alias_name, alias_value)
def parse_recipe(self):
recipe = {}
dom = parseString(self._recipe_xml_string)
+ xml_prep = self._xml_prep
self._load_included_parts(dom)
dom_nettestrecipe = dom.getElementsByTagName("nettestrecipe")[0]
dom_definitions_grp = dom_nettestrecipe.getElementsByTagName("define")
- self._definitions = self._parse_definitions(dom_definitions_grp)
+ self._parse_definitions(dom_definitions_grp)
for define_tag in dom_definitions_grp:
parent = define_tag.parentNode
parent.removeChild(define_tag)
dom_machines_grp = dom_nettestrecipe.getElementsByTagName("machines")
- self._expand_group(dom_machines_grp)
+ xml_prep.expand_group(dom_machines_grp)
recipe["machines"] = self._parse_machines(dom_machines_grp)
dom_switches_grp = dom_nettestrecipe.getElementsByTagName("switches")
- self._expand_group(dom_switches_grp)
+ xml_prep.expand_group(dom_switches_grp)
recipe["switches"] = self._parse_machines(dom_switches_grp)
self._recipe = recipe
self._dom_nettestrecipe = dom_nettestrecipe
+ xml_prep.define_alias("recipe", recipe, skip_reserved_check=True)
def get_recipe(self):
return self._recipe
@@ -261,7 +266,8 @@ class NetTestParse:
def parse_recipe_command_sequence(self):
dom_sequences = self._dom_nettestrecipe.getElementsByTagName("command_sequence")
- self._expand_group(dom_sequences, recipe_eval=True)
+ xml_prep = self._xml_prep
+ xml_prep.expand_group(dom_sequences)
self._recipe["sequences"] = []
for dom_sequence in dom_sequences:
@@ -272,54 +278,3 @@ class NetTestParse:
self._check_sequence(sequence)
self._recipe["sequences"].append(sequence)
-
- def _expand(self, node, recipe_eval=False):
- if node.nodeType == node.ELEMENT_NODE:
- i = 0
- num_attributes = node.attributes.length
- while(i < num_attributes):
- attr = node.attributes.item(i)
- attr.value = self._expand_string(str(attr.value), recipe_eval)
- i += 1
- elif node.nodeType == node.TEXT_NODE:
- node.data = self._expand_string(str(node.data), recipe_eval)
-
- for child in node.childNodes:
- self._expand(child, recipe_eval)
-
- def _expand_group(self, group, recipe_eval=False):
- for node in group:
- self._expand(node, recipe_eval)
-
- def _expand_string(self, string, recipe_eval):
- eval_re = "\{\$recipe([^\{\}]+)\}"
- alias_re = "\{\$([^\{\}]*)\}"
- while True:
- eval_match = re.search(eval_re, string)
- if eval_match:
- eval_string = eval_match.group(0)
- eval_data = eval_match.group(1)
- if recipe_eval:
- string = string.replace(eval_string,
- self._recipe_eval(eval_data))
- continue
- else:
- err = ("Accessing $recipe allowed only from command sequence: %s"
- % string)
- raise KeyError(err)
- alias_match = re.search(alias_re, string)
- if alias_match:
- alias = alias_match.group(0)
- alias_name = alias_match.group(1)
- try:
- string = string.replace(alias,
- self._definitions[alias_name])
- continue
- except KeyError, err:
- raise Exception("Alias '%s' doesn't exist!" % str(err))
-
-
- if not (eval_match and alias_match):
- break
-
- return string
11 years, 4 months
[PATCH] Documentation: Update to reflect recent changes
by Radek Pazdera
From: Radek Pazdera <rpazdera(a)redhat.com>
* New section on 'System Configuration'
* Moved 'Defining aliases' and 'Splitting recipe into multiple files
under the 'Writing recipe' section
* New section on 'Template Functions'
* A few tiny formating changes
* Added a shade under all code segments to split them visualy
from the surrounding text
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
Documentation/LNSTIntro.html | 192 ++++++++++++++++++++++++++++++++++--------
1 files changed, 157 insertions(+), 35 deletions(-)
diff --git a/Documentation/LNSTIntro.html b/Documentation/LNSTIntro.html
index 227b560..baea586 100644
--- a/Documentation/LNSTIntro.html
+++ b/Documentation/LNSTIntro.html
@@ -6,6 +6,10 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>LNST - Linux Network Stack Test</title>
<meta name="generator" content="Amaya, see http://www.w3.org/Amaya/" />
+
+ <style>
+ pre {background-color: #eaeaea;}
+ </style>
</head>
<body>
@@ -119,6 +123,7 @@ traffic generated in tests executed on test machines.</p>
SshUtils.py
TestsCommon.py
Utils.py
+ XmlPreprocessor.py
XmlRpc.py
[./example_recipes] (inspiration for test setups – netconfigs, machineconfigs, recipes)
@@ -148,9 +153,13 @@ traffic generated in tests executed on test machines.</p>
TestIcmp6Ping.py
TestIcmpPing.py
TestIperf.py
+ TestMulticast.py
TestNetCat.py
TestPktCounter.py
TestPktgenTx.py
+
+[./test_tools] (non-python testing tools and scripts)
+ multicast/
</pre>
<p></p>
@@ -203,7 +212,7 @@ repository on it.</p>
<machines>
<machine id="1">
<span style="background-color:#ffc0cb"><netmachineconfig source="example_recipes/machine_configs/config-f14peanut.xml"/></span>
- <span style="background-color:#90ee90"><netconfig source="example_recipes/net_configs/netconfig1.xml"/></span>
+ <span style="background-color:#90ee90"><netconfig source="example_recipes/net_configs/netconfig1.xml"/></span>
</machine>
<machine id="2">
<span style="background-color:#ffc0cb"><netmachineconfig source="my_recipes/config-f15.xml"/></span>
@@ -212,8 +221,8 @@ repository on it.</p>
</machines>
<span style="background-color:#add8e6"><command_sequence></span>
- <span style="background-color:#add8e6"><command type="exec" value="sleep 4"/></span></pre>
-<pre> <span style="background-color:#add8e6"><command type="test" machine_id="1" value="IcmpPing" timeout="30"></span>
+ <span style="background-color:#add8e6"><command type="exec" value="sleep 4"/></span>
+ <span style="background-color:#add8e6"><command type="test" machine_id="1" value="IcmpPing" timeout="30"></span>
<span style="background-color:#add8e6"><options></span>
<span style="background-color:#add8e6"><option type="recipe_eval" name="addr" value="['machines'][2]['netconfig'][1]['addresses'][0]"/></span>
<span style="background-color:#add8e6"><option name="count" value="40"/></span>
@@ -303,28 +312,7 @@ defined in <strong>addresses</strong> element.</p>
src="machineconfig-netconfig-mapping.png" width="793" height="318" /></p>
<p></p>
-
-<h3><em>Defining aliases</em></h3>
-<p>LNST allows you to define arbitrary <strong>aliases</strong> and use
-them to access certain values from the whole recipe file while the value
-itself is included in the file only once. Definition of an alias occurs
-in the <code><define></code> tag anywhere in the document:</p>
-<pre>
-<define>
- <span style="background-color:#90ee90"><alias name="ip_addr" value="192.168.0.1" /></span>
- <span style="background-color:#add8e6"><alias name="mask" value="24" /></span>
-</define>
-</pre>
-
-<p>Defined alias can be referenced from any element's attribute or text.
-For instance:</p>
-<pre>
-<netdevice id="2" type="eth">
- <addresses>
- <address value="<span style="background-color:#90ee90">{$ip_addr}</span>/<span style="background-color:#add8e6">{$mask}</span>"/>
- </addresses>
-</netdevice>
-</pre>
+<h4><strong></strong></h4>
<h3><em>Command sequences</em></h3>
@@ -388,6 +376,146 @@ assigned address from netconfig of <em>first</em> device on <em>second</em>
machine.
</p>
+<h3><em>System Configuration</em></h3>
+<p>
+LNST provides a native way of changing system configuration of the slave machines from within the recipe.
+This can be achieved by <strong>system_config</strong> command. There are two versions
+of <strong>system_config</strong> command:
+</p>
+<h4>Inline version</h4>
+<pre>
+ <command <span style="background-color:#add8e6">type="system_config"</span> option="/proc/sys/net/ipv4/igmp_max_memberships" value="50" machine_id="2" persistent="true" />
+</pre>
+
+<h4>Multiline version</h4>
+<pre>
+ <command <span style="background-color:#add8e6">type="system_config"</span> machine_id="1">
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="10" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="5" />
+ </options>
+ </commang>
+</pre>
+
+<p>
+ In the multiline version you can set a several options at once.
+</p>
+<p>
+ Unless <strong>persistent</strong> flag is set to <strong>true</strong>, all modified
+ options are restored to their previous values <strong>at the end of the command sequence</strong>.
+ The following examlpe illustrates how this works:
+<pre>
+ <command_sequence>
+ <command type="system_config" machine_id="1" <span style="background-color:#ffc0cb">persistent="true"</span>>
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="10" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="5" />
+ </options>
+ </commang>
+ </command_sequence>
+ <command_sequence>
+ <command type="system_config" option="/proc/sys/net/ipv4/igmp_max_memberships" value="50" />
+
+ execute some test here ...
+ </command_sequence> <span style="background-color:#90ee90"><!-- At this point, igmp_max_memberships is set back to 10 --></span>
+ <command_sequence>
+ <command type="system_config" machine_id="1" <span style="background-color:#ffc0cb">persistent="true"</span>>
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="20" />
+ <option name="/proc/sys/net/ipv4/igmp_max_mfs" value="10" />
+ </options>
+ </commang>
+ </command_sequence>
+</pre>
+<p>
+ The first command sequence serves as a global system setup phase, persistent flag is set to true,
+ so the options <strong>will not</strong> be restored when the command sequence finishes.
+</p>
+<p>
+ In the second command sequence, one option is modified for purposes of the next test, but it's
+ not marked persistent, so the change will be automatically reverted when the command sequence
+ comes to end.
+</p>
+<p>
+ And the final command sequences issues a persistent command again, to make sure that system is left
+ in a consistent state when recipe execution is over.
+</p>
+
+<hr />
+
+<h2>Writing a test</h2>
+<p>
+ This section introduces several features you can use when you decide to create your own recipe.
+</p>
+
+<h3><em>Defining aliases</em></h3>
+<p>LNST allows you to define arbitrary <strong>aliases</strong> and use
+them to access certain values from the whole recipe file while the value
+itself is included in the file only once. Definition of an alias occurs
+in the <code><define></code> tag anywhere in the document:</p>
+<pre>
+<define>
+ <span style="background-color:#90ee90"><alias name="ip_addr" value="192.168.0.1" /></span>
+ <span style="background-color:#add8e6"><alias name="mask" value="24" /></span>
+</define>
+</pre>
+
+<p>Defined alias can be referenced from any element's attribute or text.
+For instance:</p>
+<pre>
+<netdevice id="2" type="eth">
+ <addresses>
+ <address value="<span style="background-color:#90ee90">{$ip_addr}</span>/<span style="background-color:#add8e6">{$mask}</span>"/>
+ </addresses>
+</netdevice>
+</pre>
+
+<h3><em>Template functions</em></h3>
+<p>
+ Template functions are conceptually quite similar to aliases, but instead of a assigned value, they
+ represent an action that will be executed when the recipe is parsed. They can be used the same way
+ as aliases - inside of curly braces. Currently, there are three template functions available in LNST:
+</p>
+<ul>
+ <li><strong>ip</strong>(<em>machine_id</em>, <em>interface_id</em><em>[, address_id]</em>)
+ <p>
+ Returns IP address for a specific machine and interface.
+ Third argument is optional and can be used when there are
+ multiple IP addresses associated with a single interface.
+ </p>
+ </li>
+ <li><strong>hwaddr</strong>(<em>machine_id</em>, <em>interface_id</em>)
+ <p>
+ Returns hardware address of specified interface.
+ </p>
+ </li>
+ <li><strong>devname</strong>(<em>machine_id</em>, <em>interface_id</em>)
+ <p>
+ Returns device name of specified interface.
+ </p>
+ </li>
+</ul>
+<p>
+ All three above mentioned functions can be used for retrieving information from machine
+ configs, therefore calling them is only valid within a command sequence. See the following
+ example on how this templates can be used:
+</p>
+<pre>
+ <command type="system_config" option="/proc/sys/net/ipv4/conf/<span style="background-color:#ffc0cb">{devname(1,1)}</span>/forwarding" value="1" machine_id="1" />
+ <command type="test" value="Multicast" machine_id="1" timeout="30">
+ <options>
+ <option name="setup" value="max_groups" />
+ <option name="interface" value="<span style="background-color:#ffc0cb">{ip(1,1)}</span>" />
+ <option name="condition" value="max_groups > 0" />
+ </options>
+ </command>
+</pre>
+<p>
+ Aliases can be passed to functions as parameters, but the preprocessor
+does not support nesting (e.g. function cannot have another function
+passed as an argument).
+</p>
+
<h3><em>Splitting recipes into multiple files</em></h3>
<p>
LNST also offers a possibility of splitting the recipe into several
@@ -408,12 +536,6 @@ Example (<em>peanut.xml</em>):
</pre>
<p>Note that parts of the included machine config are again external.</p>
-<hr />
-
-<h2>Writing a test</h2>
-
-<p>[TODO]</p>
-
<p></p>
<hr />
@@ -460,8 +582,8 @@ up as <strong>type='bridge'</strong>.</p>
<domain type='kvm'>
<name>rhel6ga</name>
- ...</pre>
-<pre> <devices>
+ ...
+ <devices>
...
<interface type='bridge'>
<mac address='52:54:00:9f:be:73'/>
@@ -502,7 +624,7 @@ configuration, that means removal of relevant kernel module (bonding, bridge,
<h3><em>Running LNST without remote execution</em></h3>
<p>In this case you have to start nettestslave.py processes first on all
-machines that are defined in recipe by yourself. Let's assume there are
+machines that are defined in recipe by yourself. Let's assume there are
2 machines participating in the test.</p>
<p>On both of these machines you have to run following command:</p>
@@ -523,7 +645,7 @@ in a recipe:</p>
<h3><em>Using LNST to configure interfaces only</em></h3>
-<p>You can also use LNST to do just the network configuration of the test
+<p>You can also use LNST to do just the network configuration of the test
machines. None of the tests inside your recipe file will get executed.</p>
<p>To do this pass <strong>config_only</strong> instead of 'run' argument to
--
1.7.7.6
11 years, 4 months
[PATCH] NetTestParse: Adding XML Preprocessor
by Radek Pazdera
From: Radek Pazdera <rpazdera(a)redhat.com>
Code that handles parsing aliases was refactored and moved from
NetTestParse into a new class in Common module - XmlPreprocessor.
In the process of this transition it was extended with a new type
of template - functions.
Template functions can be used the same way as aliases - inside of
curly braces. For instance:
{ip(1,2,3)}
{function(argument1, $alias_argument)}
There are three template functions available at the moment. All three
can be used for retrieving information from machine configs:
hwaddr(machine_id, if_id) - get hw address of an interface
devname(machine_id, if_id) - get interface name
ip(machine_id, if_id, addr_id) - get IP address (if there's a mask
present in the configuration it
will be stripped). The third
argument is optional, defaults to
zero if omitted.
Aliases can be passed to functions as parameters, but the preprocessor
does not support nesting (e.g. function cannot have another function
passed as an argument).
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
Common/XmlPreprocessor.py | 226 +++++++++++++++++++++++++++++++++++++++++++++
NetTest/NetTestParse.py | 69 +++-----------
2 files changed, 238 insertions(+), 57 deletions(-)
create mode 100644 Common/XmlPreprocessor.py
diff --git a/Common/XmlPreprocessor.py b/Common/XmlPreprocessor.py
new file mode 100644
index 0000000..88ae758
--- /dev/null
+++ b/Common/XmlPreprocessor.py
@@ -0,0 +1,226 @@
+"""
+This module contains code for preprocessing templates in XML files/recipes
+before they are parsed.
+
+Templates are strings enclosed in curly braces {} and can be present
+in all text elements of the XML file (this includes tag values or
+attribute values). Templates cannot be used as a stubstitution for tag
+names, attribute names or any other structural elements of the document.
+
+There are two supported types of templates:
+
+ * aliases - $alias_name
+ * functions - function_name(param1, param2)
+
+Copyright 2012 Red Hat, Inc.
+Licensed under the GNU General Public License, version 2 as
+published by the Free Software Foundation; see COPYING for details.
+"""
+
+__author__ = """
+rpazdera(a)redhat.com (Radek Pazdera)
+"""
+
+import re
+
+class XmlTemplateError(Exception):
+ pass
+
+class XmlPreprocessor:
+ """
+ This class serves as template processor within a XML DOM tree object.
+ """
+
+ _template_re = "\{([^\{\}]+)\}"
+ _alias_re = "^\$([a-zA-Z0-9_]+)(\[.+\])*$"
+ _func_re = "^([a-zA-Z0-9_]+)\(([^\(\)]*)\)$"
+
+ def __init__(self):
+ self._definitions = {}
+ self._reserved_aliases = ["recipe"]
+
+ def define_alias(self, name, value, skip_reserved_check=False):
+ """
+ Associate an alias name with some value. The value can be of
+ an atomic type or an array.
+ """
+
+ if not name in self._reserved_aliases \
+ or skip_reserved_check == True:
+ self._definitions[name] = value
+ else:
+ raise XmlTemplateError("Alias name '%s' is reserved" % name)
+
+ def expand(self, node):
+ """
+ Traverse DOM tree from `node' down and expand any
+ templates along the way.
+ """
+
+ if node.nodeType == node.ELEMENT_NODE:
+ i = 0
+ num_attributes = node.attributes.length
+ while(i < num_attributes):
+ attr = node.attributes.item(i)
+ attr.value = self._expand_string(str(attr.value))
+ i += 1
+ elif node.nodeType == node.TEXT_NODE:
+ node.data = self._expand_string(str(node.data))
+
+ for child in node.childNodes:
+ self.expand(child)
+
+ def expand_group(self, group):
+ """
+ Behaves exactly the same as the `expand' method, but it
+ operates on a group of DOM nodes stored within a list,
+ rather than a single node.
+ """
+
+ for node in group:
+ self.expand(node)
+
+ def _expand_string(self, string):
+ while True:
+ template_match = re.search(self._template_re, string)
+ if template_match:
+ template_string = template_match.group(0)
+ template = template_match.group(1)
+ template_result = self._process_template(template)
+
+ string = string.replace(template_string, template_result)
+ else:
+ break
+
+ return string
+
+ def _process_template(self, string):
+ string = string.strip()
+ result = None
+
+ if re.match(self._alias_re, string):
+ result = self._process_alias_template(string)
+ return result
+
+ if re.match(self._func_re, string):
+ result = self._process_func_template(string)
+ return result
+
+ raise XmlTemplateError("Unknown template type '%s'" % string)
+
+ def _process_alias_template(self, string):
+ result = None
+
+ alias_match = re.match(self._alias_re, string)
+ if alias_match:
+ alias_name = alias_match.group(1)
+ array_subscript = alias_match.group(2)
+
+ if not alias_name in self._definitions:
+ err = "Alias '%s' is not defined here" % alias_name
+ raise XmlTemplateError(err)
+
+ if array_subscript != None:
+ try:
+ result = str(eval("self._definitions['%s']%s" \
+ % (alias_name, array_subscript)))
+ except (KeyError, IndexError):
+ err = "Wrong array subscript in '%s[%s]'" \
+ % (alias_name, array_subscript)
+ raise XmlTemplateError(err)
+ else:
+ result = self._definitions[alias_name]
+
+ return result
+
+ def _process_func_template(self, string):
+ result = None
+
+ func_match = re.match(self._func_re, string)
+ if func_match:
+ func_name = func_match.group(1)
+ func_params = func_match.group(2)
+
+ if func_params == None:
+ func_params = []
+ else:
+ func_params = func_params.split(",")
+
+ param_values = []
+ for param in func_params:
+ param = param.strip()
+ if re.match(self._alias_re, param):
+ param = self._process_alias_template(param)
+ param_values.append(param)
+
+ result = self._call_preprocessor_func(func_name, param_values)
+
+ return result
+
+ def _call_preprocessor_func(self, name, params):
+ if name == "ip":
+ result = self._ip_func(params)
+ elif name == "hwaddr":
+ result = self._hwaddr_func(params)
+ elif name == "devname":
+ result = self._devname_func(params)
+ else:
+ raise XmlTemplateError("Unknown preprocessor function '%s'" % name)
+
+ return result
+
+ def _ip_func(self, params):
+ self._validate_func_params("ip", params, 2, 1)
+ self._check_recipe_data("ip")
+
+ m_id = int(params[0])
+ if_id = int(params[1])
+ ip_id = int(params[2]) if len(params) == 3 else 0
+
+ machines = self._definitions["recipe"]["machines"]
+ ip_addr = machines[m_id]['netconfig'][if_id]['addresses'][ip_id]
+
+ return ip_addr.split('/')[0]
+
+ def _hwaddr_func(self, params):
+ self._validate_func_params("hwaddr", params, 2, 0)
+ self._check_recipe_data("hwaddr")
+ m_id = int(params[0])
+ if_id = int(params[1])
+
+ machines = self._definitions["recipe"]["machines"]
+ return machines[m_id]['netconfig'][if_id]['hwaddr']
+
+
+ def _devname_func(self, params):
+ self._validate_func_params("devname", params, 2, 0)
+ self._check_recipe_data("devname")
+ m_id = int(params[0])
+ if_id = int(params[1])
+
+ machines = self._definitions["recipe"]["machines"]
+ return machines[m_id]['netconfig'][if_id]['name']
+
+ @staticmethod
+ def _validate_func_params(name, params, mandatory, optional):
+ num_params = len(params)
+ if num_params > (mandatory + optional) or num_params < mandatory:
+ if optional:
+ err = "Function %s takes between %d-%d arguments, %d passed" \
+ % (name, mandatory, mandatory + optional, num_params)
+ else:
+ err = "Function %s takes %d arguments, %d passed" \
+ % (name, mandatory, num_params)
+ raise XmlTemplateError(err)
+ for param in params:
+ try:
+ int(param)
+ except ValueError:
+ err = "Non-integer parameter passed to '%s'" % name
+ raise XmlTemplateError(err)
+
+ def _check_recipe_data(self, template_name):
+ if not "recipe" in self._definitions:
+ err = "Cannot resolve %s() here, recipe data not available yet" \
+ % template_name
+ raise XmlTemplateError(err)
diff --git a/NetTest/NetTestParse.py b/NetTest/NetTestParse.py
index 69833b1..5b5101a 100644
--- a/NetTest/NetTestParse.py
+++ b/NetTest/NetTestParse.py
@@ -16,6 +16,7 @@ import os
import re
from NetConfig.NetConfigParse import NetConfigParse
from NetTest.NetTestCommand import str_command
+from Common.XmlPreprocessor import XmlPreprocessor
def load_file(filename):
handle = open(filename, "r")
@@ -36,6 +37,8 @@ class NetTestParse:
self._dirpath = os.path.dirname(recipe_path)
self._recipe = None
+ self._xml_prep = XmlPreprocessor()
+
def _get_referenced_xml_path(self, filename):
return os.path.join(self._dirpath, os.path.expanduser(filename))
@@ -64,38 +67,40 @@ class NetTestParse:
return machines
def _parse_definitions(self, dom_definitions_grp):
+ xml_prep = self._xml_prep
definitions = {}
for dom_definitions_item in dom_definitions_grp:
dom_aliases = dom_definitions_item.getElementsByTagName("alias")
for dom_alias in dom_aliases:
alias_name = str(dom_alias.getAttribute("name"))
alias_value = str(dom_alias.getAttribute("value"))
- definitions[alias_name] = alias_value
- return definitions
+ xml_prep.define_alias(alias_name, alias_value)
def parse_recipe(self):
recipe = {}
dom = parseString(self._recipe_xml_string)
+ xml_prep = self._xml_prep
self._load_included_parts(dom)
dom_nettestrecipe = dom.getElementsByTagName("nettestrecipe")[0]
dom_definitions_grp = dom_nettestrecipe.getElementsByTagName("define")
- self._definitions = self._parse_definitions(dom_definitions_grp)
+ self._parse_definitions(dom_definitions_grp)
for define_tag in dom_definitions_grp:
parent = define_tag.parentNode
parent.removeChild(define_tag)
dom_machines_grp = dom_nettestrecipe.getElementsByTagName("machines")
- self._expand_group(dom_machines_grp)
+ xml_prep.expand_group(dom_machines_grp)
recipe["machines"] = self._parse_machines(dom_machines_grp)
dom_switches_grp = dom_nettestrecipe.getElementsByTagName("switches")
- self._expand_group(dom_switches_grp)
+ xml_prep.expand_group(dom_switches_grp)
recipe["switches"] = self._parse_machines(dom_switches_grp)
self._recipe = recipe
self._dom_nettestrecipe = dom_nettestrecipe
+ xml_prep.define_alias("recipe", recipe, skip_reserved_check=True)
def get_recipe(self):
return self._recipe
@@ -261,7 +266,8 @@ class NetTestParse:
def parse_recipe_command_sequence(self):
dom_sequences = self._dom_nettestrecipe.getElementsByTagName("command_sequence")
- self._expand_group(dom_sequences, recipe_eval=True)
+ xml_prep = self._xml_prep
+ xml_prep.expand_group(dom_sequences)
self._recipe["sequences"] = []
for dom_sequence in dom_sequences:
@@ -272,54 +278,3 @@ class NetTestParse:
self._check_sequence(sequence)
self._recipe["sequences"].append(sequence)
-
- def _expand(self, node, recipe_eval=False):
- if node.nodeType == node.ELEMENT_NODE:
- i = 0
- num_attributes = node.attributes.length
- while(i < num_attributes):
- attr = node.attributes.item(i)
- attr.value = self._expand_string(str(attr.value), recipe_eval)
- i += 1
- elif node.nodeType == node.TEXT_NODE:
- node.data = self._expand_string(str(node.data), recipe_eval)
-
- for child in node.childNodes:
- self._expand(child, recipe_eval)
-
- def _expand_group(self, group, recipe_eval=False):
- for node in group:
- self._expand(node, recipe_eval)
-
- def _expand_string(self, string, recipe_eval):
- eval_re = "\{\$recipe([^\{\}]+)\}"
- alias_re = "\{\$([^\{\}]*)\}"
- while True:
- eval_match = re.search(eval_re, string)
- if eval_match:
- eval_string = eval_match.group(0)
- eval_data = eval_match.group(1)
- if recipe_eval:
- string = string.replace(eval_string,
- self._recipe_eval(eval_data))
- continue
- else:
- err = ("Accessing $recipe allowed only from command sequence: %s"
- % string)
- raise KeyError(err)
- alias_match = re.search(alias_re, string)
- if alias_match:
- alias = alias_match.group(0)
- alias_name = alias_match.group(1)
- try:
- string = string.replace(alias,
- self._definitions[alias_name])
- continue
- except KeyError, err:
- raise Exception("Alias '%s' doesn't exist!" % str(err))
-
-
- if not (eval_match and alias_match):
- break
-
- return string
--
1.7.7.6
11 years, 4 months