Skip to content

Commit

Permalink
Add option to skip non ethernet interfaces to CheckAllInterfaceOperSt…
Browse files Browse the repository at this point in the history
…ateOverGnmi. Added packet injection to ControlInterface interfaces. (sonic-net#364)

Co-authored-by: Srikishen Pondicherry Shanmugam <kishanps@google.com>
  • Loading branch information
bibhuprasad-hcl and kishanps authored Jul 23, 2024
1 parent c6cf552 commit 8ee2802
Show file tree
Hide file tree
Showing 12 changed files with 431 additions and 75 deletions.
14 changes: 14 additions & 0 deletions lib/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,31 @@ cc_library(
deps = [
"//gutil:status",
"//lib/gnmi:gnmi_helper",
"//lib/p4rt:packet_listener",
"//lib/validator:validator_lib",
"//p4_pdpi:p4_runtime_session",
"//p4_pdpi:ir",
"//p4_pdpi:ir_cc_proto",
"//p4_pdpi:pd",
"//p4_pdpi/packetlib",
"//p4_pdpi/packetlib:packetlib_cc_proto",
"//sai_p4/instantiations/google:instantiations",
"//sai_p4/instantiations/google:sai_p4info_cc",
"//tests/forwarding:util",
"//thinkit:control_interface",
"//thinkit:packet_generation_finalizer",
"//thinkit:switch",
"@com_github_gnmi//proto/gnmi:gnmi_cc_proto",
"@com_github_gnoi//diag:diag_cc_grpc_proto",
"@com_github_gnoi//system:system_cc_grpc_proto",
"@com_github_google_glog//:glog",
"@com_github_nlohmann_json//:nlohmann_json",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
],
)

Expand Down
66 changes: 63 additions & 3 deletions lib/gnmi/gnmi_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,13 @@ absl::Status PushGnmiConfig(thinkit::Switch& chassis,
return pins_test::PushGnmiConfig(*stub, chassis.ChassisName(), gnmi_config);
}

absl::Status CanGetAllInterfaceOverGnmi(gnmi::gNMI::Stub& stub,
absl::Status CanGetAllInterfaceOverGnmi(gnmi::gNMI::StubInterface& stub,
absl::Duration timeout) {
return GetAllInterfaceOverGnmi(stub).status();
}

absl::StatusOr<gnmi::GetResponse> GetAllInterfaceOverGnmi(
gnmi::gNMI::Stub& stub, absl::Duration timeout) {
gnmi::gNMI::StubInterface& stub, absl::Duration timeout) {
ASSIGN_OR_RETURN(auto req, BuildGnmiGetRequest("", gnmi::GetRequest::ALL));
gnmi::GetResponse resp;
grpc::ClientContext context;
Expand Down Expand Up @@ -285,12 +285,17 @@ GetInterfaceToOperStatusMapOverGnmi(gnmi::gNMI::StubInterface& stub,

absl::Status CheckAllInterfaceOperStateOverGnmi(
gnmi::gNMI::StubInterface& stub, absl::string_view interface_oper_state,
absl::Duration timeout) {
bool skip_non_ethernet_interfaces, absl::Duration timeout) {
ASSIGN_OR_RETURN(const auto interface_to_oper_status_map,
GetInterfaceToOperStatusMapOverGnmi(stub, timeout));

std::vector<std::string> unavailable_interfaces;
for (const auto& [interface, oper_status] : interface_to_oper_status_map) {
if (skip_non_ethernet_interfaces &&
!absl::StrContains(interface, "Ethernet")) {
LOG(INFO) << "Skipping check on interface: " << interface;
continue;
}
if (oper_status != interface_oper_state) {
unavailable_interfaces.push_back(interface);
}
Expand Down Expand Up @@ -413,6 +418,61 @@ absl::StatusOr<OperStatus> GetInterfaceOperStatusOverGnmi(
return OperStatus::kUnknown;
}

absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
GetAllInterfaceNameToPortId(gnmi::gNMI::StubInterface& stub) {
ASSIGN_OR_RETURN(
gnmi::GetResponse response,
pins_test::GetAllInterfaceOverGnmi(stub, absl::ZeroDuration()));
if (response.notification_size() < 1) {
return absl::InternalError(
absl::StrCat("Invalid response: ", response.DebugString()));
}

const auto response_json = nlohmann::json::parse(
response.notification(0).update(0).val().json_ietf_val());
const auto oc_intf_json =
response_json.find("openconfig-interfaces:interfaces");
if (oc_intf_json == response_json.end()) {
return absl::NotFoundError(
absl::StrCat("'openconfig-interfaces:interfaces' not found: ",
response_json.dump()));
}
const auto oc_intf_list_json = oc_intf_json->find("interface");
if (oc_intf_list_json == oc_intf_json->end()) {
return absl::NotFoundError(
absl::StrCat("'interface' not found: ", oc_intf_json->dump()));
}

absl::flat_hash_map<std::string, std::string> interface_name_to_port_id;
for (auto const& element : oc_intf_list_json->items()) {
const auto element_name_json = element.value().find("name");
if (element_name_json == element.value().end()) {
return absl::NotFoundError(
absl::StrCat("'name' not found: ", element.value().dump()));
}
std::string name = element_name_json->get<std::string>();

// TODO: Remove once CpuX contains the oper-state subtree.
if (absl::StartsWith(name, "Cpu")) {
LOG(INFO) << "Skipping " << name << ".";
continue;
}

const auto element_interface_state_json = element.value().find("state");
if (element_interface_state_json == element.value().end()) {
return absl::NotFoundError(
absl::StrCat("'state' not found: ", element.value().dump()));
}
const auto element_id_json = element_interface_state_json->find("id");
if (element_id_json == element_interface_state_json->end()) {
return absl::NotFoundError(
absl::StrCat("'id' not found: ", element.value().dump()));
}
interface_name_to_port_id[name] = element_id_json->get<std::string>();
}
return interface_name_to_port_id;
}

absl::StatusOr<std::vector<std::string>> ParseAlarms(
const std::string& alarms_json) {
auto alarms_array = json::parse(alarms_json);
Expand Down
11 changes: 9 additions & 2 deletions lib/gnmi/gnmi_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ absl::Status PushGnmiConfig(thinkit::Switch& chassis,
const std::string& gnmi_config);

absl::Status CanGetAllInterfaceOverGnmi(
gnmi::gNMI::Stub& stub, absl::Duration timeout = absl::Seconds(60));
gnmi::gNMI::StubInterface& stub,
absl::Duration timeout = absl::Seconds(60));

absl::StatusOr<gnmi::GetResponse> GetAllInterfaceOverGnmi(
gnmi::gNMI::Stub& stub, absl::Duration timeout = absl::Seconds(60));
gnmi::gNMI::StubInterface& stub,
absl::Duration timeout = absl::Seconds(60));

// Gets the interface to oper status map.
absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
Expand All @@ -118,6 +120,7 @@ GetInterfaceToOperStatusMapOverGnmi(gnmi::gNMI::StubInterface& stub,
// Checks if all interfaces oper-status is up/down.
absl::Status CheckAllInterfaceOperStateOverGnmi(
gnmi::gNMI::StubInterface& stub, absl::string_view interface_oper_state,
bool skip_non_ethernet_interfaces = false,
absl::Duration timeout = absl::Seconds(60));

// Returns gNMI Path for OC strings.
Expand All @@ -132,6 +135,10 @@ absl::StatusOr<std::vector<std::string>> GetUpInterfacesOverGnmi(
absl::StatusOr<OperStatus> GetInterfaceOperStatusOverGnmi(
gnmi::gNMI::Stub& stub, absl::string_view if_name);

// Gets the interface name to port id map.
absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
GetAllInterfaceNameToPortId(gnmi::gNMI::StubInterface& stub);

// Parses the alarms JSON array returned from a gNMI Get request to
// "openconfig-system:system/alarms/alarm". Returns the list of alarms.
absl::StatusOr<std::vector<std::string>> ParseAlarms(
Expand Down
Loading

0 comments on commit 8ee2802

Please sign in to comment.