Skip to content

Commit 9122fa7

Browse files
kishanpsVSuryaprasad-HCL
authored andcommitted
Add a check in reboot test to make sure PORT_INDEX_TABLE is populated before sending traffic.Enhance ValidateSutState to ValidateTestbedState by additionally checking Control Switch for MirrorTestbed.
1 parent 633922e commit 9122fa7

File tree

5 files changed

+109
-14
lines changed

5 files changed

+109
-14
lines changed

tests/sflow/BUILD.bazel

+3-2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ cc_library(
9090
"//lib/validator:validator_lib",
9191
"//p4_pdpi/netaddr:ipv4_address",
9292
"//p4_pdpi/netaddr:ipv6_address",
93+
"//thinkit:ssh_client",
9394
"@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto",
9495
"@com_github_google_glog//:glog",
9596
"@com_github_nlohmann_json//:nlohmann_json",
@@ -100,6 +101,7 @@ cc_library(
100101
"@com_google_absl//absl/status:statusor",
101102
"@com_google_absl//absl/strings",
102103
"@com_google_absl//absl/time",
104+
"@com_google_absl//absl/types:span",
103105
"@com_googlesource_code_re2//:re2",
104106
],
105107
)
@@ -140,8 +142,7 @@ cc_test(
140142
":sflow_util",
141143
"//gutil:status_matchers",
142144
"//gutil:testing",
143-
"//p4_pdpi/packetlib",
144-
"//p4_pdpi/packetlib:packetlib_cc_proto",
145+
"//thinkit:mock_ssh_client",
145146
"@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto",
146147
"@com_google_absl//absl/container:flat_hash_set",
147148
"@com_google_absl//absl/status",

tests/sflow/sflow_test.cc

+8-12
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,6 @@ void SflowTestFixture::TearDown() {
12231223
// 2. Collect sFlow samples via sflowtool on SUT.
12241224
// 3. Validate the result is as expected.
12251225
TEST_P(SflowTestFixture, VerifyIngressSamplingForNoMatchPackets) {
1226-
testbed_->Environment().SetTestCaseID("6c980337-c187-4f19-99a9-e03b6dcf24b5");
12271226

12281227
const IxiaLink& ingress_link = ready_links_[0];
12291228
Port ingress_port = Port{
@@ -1293,7 +1292,6 @@ TEST_P(SflowTestFixture, VerifyIngressSamplingForNoMatchPackets) {
12931292

12941293
// Verifies ingress sampling could work when forwarding traffic.
12951294
TEST_P(SflowTestFixture, VerifyIngressSamplingForForwardedPackets) {
1296-
testbed_->Environment().SetTestCaseID("909e2260-d4ca-4018-8c6a-2bd7891ee686");
12971295

12981296
const IxiaLink& ingress_link = ready_links_[0];
12991297
Port ingress_port = Port{
@@ -1384,7 +1382,6 @@ TEST_P(SflowTestFixture, VerifyIngressSamplingForForwardedPackets) {
13841382

13851383
// Verifies ingress sampling could work when dropping packets.
13861384
TEST_P(SflowTestFixture, VerifyIngressSamplesForDropPackets) {
1387-
testbed_->Environment().SetTestCaseID("6d567c91-d018-4fb3-85fc-c75c5f425d15");
13881385

13891386
const IxiaLink& ingress_link = ready_links_[0];
13901387
Port ingress_port = Port{
@@ -1460,7 +1457,6 @@ TEST_P(SflowTestFixture, VerifyIngressSamplesForDropPackets) {
14601457
// 3. Send traffic from Ixia.
14611458
// 4. Validate the packets are all get punted and sFlowtool has expected result.
14621459
TEST_P(SflowTestFixture, VerifyIngressSamplesForP4rtPuntTraffic) {
1463-
testbed_->Environment().SetTestCaseID("70a4e3e1-f3ae-416e-99a7-24f259942981");
14641460

14651461
const IxiaLink& ingress_link = ready_links_[0];
14661462
Port ingress_port = Port{
@@ -1590,7 +1586,6 @@ TEST_P(SflowTestFixture, VerifyIngressSamplesForP4rtPuntTraffic) {
15901586
// Traffic packet size size_a, sFlow sampling size size_b: expects sample header
15911587
// size equals to min(size_a, size_b).
15921588
TEST_P(SampleSizeTest, VerifySamplingSizeWorks) {
1593-
testbed_->Environment().SetTestCaseID("d1e8ae2a-0595-4b33-9743-7dbff8eaf48a");
15941589

15951590
const int packet_size = GetParam().packet_size,
15961591
sample_size = GetParam().sample_size;
@@ -1651,7 +1646,6 @@ TEST_P(SampleSizeTest, VerifySamplingSizeWorks) {
16511646
// send traffic to two interfaces with different sampling rate and verifies
16521647
// samples count.
16531648
TEST_P(SampleRateTest, VerifySamplingRateWorks) {
1654-
testbed_->Environment().SetTestCaseID("a143121e-c90f-4892-bd6b-897c3d9f9ff3");
16551649

16561650
const IxiaLink& ingress_link = ready_links_[0];
16571651
const int sample_rate = GetParam().sample_rate;
@@ -1735,7 +1729,6 @@ TEST_P(SampleRateTest, VerifySamplingRateWorks) {
17351729
// 3. Send traffic at a normal rate which would not trigger sFlow backoff.
17361730
// Verify that sample rate is still doubled on all interfaces and samples.
17371731
TEST_P(BackoffTest, VerifyBackoffWorks) {
1738-
testbed_->Environment().SetTestCaseID("58653895-219a-4b9e-b6af-03f6a33b5959");
17391732

17401733
const IxiaLink& ingress_link = ready_links_[0];
17411734

@@ -2470,6 +2463,11 @@ TEST_P(SflowRebootTestFixture, ChangeCollectorConfigOnNsfReboot) {
24702463
pins_test::Testbed testbed_variant;
24712464
testbed_variant.emplace<thinkit::MirrorTestbed*>(&testbed);
24722465
ASSERT_OK(pins_test::NsfReboot(testbed_variant));
2466+
ASSERT_OK(
2467+
pins_test::WaitForNsfReboot(testbed_variant, *GetParam().ssh_client));
2468+
ASSERT_OK(pins_test::ValidateTestbedState(
2469+
/*version=*/"", testbed_variant, *GetParam().ssh_client,
2470+
/*gnmi_config=*/std::nullopt));
24732471
// Wait until all sFlow gNMI states are converged.
24742472
ASSERT_OK(pins_test::WaitForCondition(
24752473
VerifySflowStatesConverged, absl::Seconds(60), sut_gnmi_stub_.get(),
@@ -2628,7 +2626,6 @@ TEST_P(SflowRebootTestFixture, ChangeCollectorConfigOnNsfReboot) {
26282626
TEST_P(SflowMirrorTestFixture, TestInbandPathToSflowCollector) {
26292627
thinkit::MirrorTestbed& testbed =
26302628
GetParam().testbed_interface->GetMirrorTestbed();
2631-
testbed.Environment().SetTestCaseID("3948ef62-67d9-42e2-8cc6-30dc10cb382f");
26322629

26332630
const int packets_num = 10000;
26342631

@@ -2812,7 +2809,6 @@ TEST_P(SflowMirrorTestFixture, TestInbandPathToSflowCollector) {
28122809
TEST_P(SflowMirrorTestFixture, TestSflowDscpValue) {
28132810
thinkit::MirrorTestbed& testbed =
28142811
GetParam().testbed_interface->GetMirrorTestbed();
2815-
testbed.Environment().SetTestCaseID("38694bb8-2a82-4379-8b85-96dcda824a14");
28162812

28172813
const int packets_num = 10000;
28182814

@@ -2919,7 +2915,6 @@ TEST_P(SflowMirrorTestFixture, TestSflowDscpValue) {
29192915
TEST_P(SflowMirrorTestFixture, TestSamplingWorksOnAllInterfaces) {
29202916
thinkit::MirrorTestbed& testbed =
29212917
GetParam().testbed_interface->GetMirrorTestbed();
2922-
testbed.Environment().SetTestCaseID("03bdb9da-387a-4256-9323-60d4503ce3c0");
29232918

29242919
const int packets_num = 10000;
29252920
ASSERT_OK_AND_ASSIGN(
@@ -3039,7 +3034,6 @@ TEST_P(SflowRebootTestFixture, TestSamplingWorksAfterReboot) {
30393034

30403035
thinkit::MirrorTestbed& testbed =
30413036
GetParam().testbed_interface->GetMirrorTestbed();
3042-
testbed.Environment().SetTestCaseID("6cd622a1-2d95-4e07-9c7d-77a2faad4bc0");
30433037

30443038
ASSERT_OK_AND_ASSIGN(
30453039
auto port_id_per_port_name,
@@ -3192,6 +3186,9 @@ TEST_P(SflowRebootTestFixture, TestSamplingWorksAfterReboot) {
31923186
VerifySflowStatesConverged, absl::Minutes(2), sut_gnmi_stub_.get(),
31933187
agent_address_, kInbandSamplingRate, kSampleHeaderSize,
31943188
collector_address_and_port, sflow_enabled_interfaces));
3189+
ASSERT_OK(pins_test::WaitForCondition(
3190+
CheckStateDbPortIndexTableExists, absl::Minutes(2),
3191+
*GetParam().ssh_client, testbed.Sut().ChassisName(), interface_names));
31953192

31963193
for (const auto& [interface_name, unused] : sflow_enabled_interfaces) {
31973194
ASSERT_OK_AND_ASSIGN(packets_sampled_per_interface[interface_name],
@@ -3282,7 +3279,6 @@ TEST_P(SflowRebootTestFixture, TestSamplingWorksAfterReboot) {
32823279
TEST_P(SflowMirrorTestFixture, TestIp2MePacketsAreSampledAndPunted) {
32833280
thinkit::MirrorTestbed& testbed =
32843281
GetParam().testbed_interface->GetMirrorTestbed();
3285-
testbed.Environment().SetTestCaseID("7f765661-840e-4913-b210-8bbf9d5a0e8f");
32863282

32873283
const absl::string_view kSrcIp6Address = "2001:db8:0:12::1";
32883284
const int packets_num = 3000;

tests/sflow/sflow_util.cc

+40
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@
1616

1717
#include <cstdint>
1818
#include <string>
19+
#include <vector>
1920

2021
#include "absl/container/btree_map.h"
2122
#include "absl/container/flat_hash_map.h"
23+
#include "absl/container/flat_hash_set.h"
2224
#include "absl/status/status.h"
2325
#include "absl/status/statusor.h"
2426
#include "absl/strings/ascii.h"
2527
#include "absl/strings/numbers.h"
2628
#include "absl/strings/str_cat.h"
29+
#include "absl/strings/str_join.h"
30+
#include "absl/strings/str_split.h"
2731
#include "absl/strings/string_view.h"
2832
#include "absl/strings/substitute.h"
2933
#include "absl/time/time.h"
34+
#include "absl/types/span.h"
3035
#include "glog/logging.h"
3136
#include "gutil/status.h"
3237
#include "include/nlohmann/json.hpp"
@@ -36,6 +41,7 @@
3641
#include "p4_pdpi/netaddr/ipv4_address.h"
3742
#include "p4_pdpi/netaddr/ipv6_address.h"
3843
#include "re2/re2.h"
44+
#include "thinkit/ssh_client.h"
3945

4046
namespace pins {
4147
namespace {
@@ -568,4 +574,38 @@ absl::StatusOr<int> GetSflowCollectorPort(absl::string_view gnmi_config) {
568574
return collector_json["config"]["port"];
569575
}
570576

577+
absl::Status CheckStateDbPortIndexTableExists(
578+
thinkit::SSHClient& ssh_client, absl::string_view device_name,
579+
absl::Span<const std::string> interfaces) {
580+
ASSIGN_OR_RETURN(
581+
std::string ssh_result,
582+
ssh_client.RunCommand(
583+
device_name,
584+
/*command=*/"/usr/tools/bin/redis-cli -n 6 keys PORT_INDEX_TABLE*",
585+
/*timeout=*/absl::Seconds(5)));
586+
LOG(INFO) << "ssh_result: " << ssh_result;
587+
absl::flat_hash_set<std::string> port_index_table_interfaces;
588+
for (absl::string_view interface_str :
589+
absl::StrSplit(ssh_result, "PORT_INDEX_TABLE")) {
590+
interface_str = absl::StripAsciiWhitespace(interface_str);
591+
auto pos = interface_str.find("Ethernet");
592+
if (pos == std::string::npos) {
593+
continue;
594+
}
595+
port_index_table_interfaces.insert(std::string(interface_str.substr(pos)));
596+
}
597+
std::vector<std::string> missing_interfaces;
598+
for (const auto& interface : interfaces) {
599+
if (!port_index_table_interfaces.contains(interface)) {
600+
missing_interfaces.push_back(interface);
601+
}
602+
}
603+
if (missing_interfaces.empty()) {
604+
return absl::OkStatus();
605+
}
606+
return absl::FailedPreconditionError(
607+
absl::StrCat("Failed to find PORT_INDEX_TABLE for interface ",
608+
absl::StrJoin(missing_interfaces, ", ")));
609+
}
610+
571611
} // namespace pins

tests/sflow/sflow_util.h

+7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#include "absl/status/status.h"
2525
#include "absl/status/statusor.h"
2626
#include "absl/strings/string_view.h"
27+
#include "absl/types/span.h"
2728
#include "proto/gnmi/gnmi.grpc.pb.h"
29+
#include "thinkit/ssh_client.h"
2830

2931
namespace pins {
3032

@@ -142,5 +144,10 @@ absl::StatusOr<bool> IsSameIpAddressStr(const std::string& ip1,
142144
// Returns the collector port from `gnmi_config` collector config first
143145
absl::StatusOr<int> GetSflowCollectorPort(absl::string_view gnmi_config);
144146

147+
// Checks if state db port index table exists for `interfaces`.
148+
absl::Status CheckStateDbPortIndexTableExists(
149+
thinkit::SSHClient& ssh_client, absl::string_view device_name,
150+
absl::Span<const std::string> interfaces);
151+
145152
} // namespace pins
146153
#endif // PINS_TESTS_SFLOW_SFLOW_UTIL_H_

tests/sflow/sflow_util_test.cc

+51
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
#include "tests/sflow/sflow_util.h"
1616

17+
#include <string>
18+
#include <vector>
19+
1720
#include "absl/container/flat_hash_set.h"
1821
#include "absl/status/status.h"
1922
#include "absl/strings/string_view.h"
@@ -23,11 +26,13 @@
2326
#include "gutil/status_matchers.h"
2427
#include "gutil/testing.h"
2528
#include "proto/gnmi/gnmi_mock.grpc.pb.h"
29+
#include "thinkit/mock_ssh_client.h"
2630

2731
namespace pins {
2832
namespace {
2933
using ::gutil::IsOkAndHolds;
3034
using ::gutil::StatusIs;
35+
using ::testing::AllOf;
3136
using ::testing::DoAll;
3237
using ::testing::Eq;
3338
using ::testing::HasSubstr;
@@ -1080,5 +1085,51 @@ TEST(IpAddressTest, SameIpv6AddressDifferentFormat4) {
10801085
IsOkAndHolds(true));
10811086
}
10821087

1088+
TEST(PortIndexTest, SshCommandFailCheckFail) {
1089+
thinkit::MockSSHClient mock_ssh_client;
1090+
ON_CALL(mock_ssh_client, RunCommand)
1091+
.WillByDefault(Return(absl::InternalError("No ssh client")));
1092+
const std::vector<std::string> port_names = {"Ethernet1/1/1",
1093+
"Ethernet1/1/2"};
1094+
EXPECT_THAT(
1095+
CheckStateDbPortIndexTableExists(mock_ssh_client, "switch_x", port_names),
1096+
StatusIs(absl::StatusCode::kInternal));
1097+
}
1098+
1099+
TEST(PortIndexTest, SshCommandNoNilCheckSuccess) {
1100+
thinkit::MockSSHClient mock_ssh_client;
1101+
ON_CALL(mock_ssh_client, RunCommand)
1102+
.WillByDefault(Return(R"(PORT_INDEX_TABLE|Ethernet1/10/1
1103+
PORT_INDEX_TABLE|Ethernet1/9/1
1104+
PORT_INDEX_TABLE|Ethernet1/31/1
1105+
PORT_INDEX_TABLE|Ethernet1/2/5
1106+
PORT_INDEX_TABLE|Ethernet1/13/1)"));
1107+
const std::vector<std::string> port_names = {
1108+
"Ethernet1/10/1", "Ethernet1/31/1", "Ethernet1/13/1"};
1109+
EXPECT_OK(CheckStateDbPortIndexTableExists(mock_ssh_client, "switch_x",
1110+
port_names));
1111+
}
1112+
1113+
TEST(PortIndexTest, SshCommandNilCheckFail) {
1114+
thinkit::MockSSHClient mock_ssh_client;
1115+
ON_CALL(mock_ssh_client, RunCommand).WillByDefault(Return("nil"));
1116+
const std::vector<std::string> port_names = {"Ethernet1/1/1",
1117+
"Ethernet1/1/2"};
1118+
EXPECT_THAT(
1119+
CheckStateDbPortIndexTableExists(mock_ssh_client, "switch_x", port_names),
1120+
StatusIs(absl::StatusCode::kFailedPrecondition));
1121+
}
1122+
1123+
TEST(PortIndexTest, SshCommandEmptyCheckFail) {
1124+
thinkit::MockSSHClient mock_ssh_client;
1125+
ON_CALL(mock_ssh_client, RunCommand).WillByDefault(Return(""));
1126+
const std::vector<std::string> port_names = {"Ethernet1/1/1",
1127+
"Ethernet1/1/2"};
1128+
EXPECT_THAT(
1129+
CheckStateDbPortIndexTableExists(mock_ssh_client, "switch_x", port_names),
1130+
StatusIs(absl::StatusCode::kFailedPrecondition,
1131+
AllOf(HasSubstr("Ethernet1/1/1"), HasSubstr("Ethernet1/1/2"))));
1132+
}
1133+
10831134
} // namespace
10841135
} // namespace pins

0 commit comments

Comments
 (0)