Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Port from chassis config file #3

Open
wants to merge 23 commits into
base: main-nikss
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ USER $USER_NAME
RUN (test "$GIT_GLOBAL_NAME" = "" || git config --global user.name "$GIT_GLOBAL_NAME") && \
(test "$GIT_GLOBAL_EMAIL" = "" || git config --global user.email "$GIT_GLOBAL_EMAIL") && \
(test "$GIT_GLOBAL_EDITOR" = "" || git config --global code.editor "$GIT_GLOBAL_EDITOR")

RUN sudo pip3 install scapy
RUN sudo apt-get install tcpdump
34 changes: 34 additions & 0 deletions stratum/hal/bin/nikss/chassis_config.pb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
description: "Sample config for nikss"
chassis {
platform: PLT_P4_SOFT_SWITCH
name: "nikss"
}
nodes {
id: 1
slot: 1
index: 1
}
singleton_ports {
id: 1
name: "veth1"
slot: 1
port: 1
channel: 1
speed_bps: 100000000000
config_params {
admin_state: ADMIN_STATE_ENABLED
}
node: 1
}
singleton_ports {
id: 2
name: "veth3"
slot: 1
port: 2
channel: 1
speed_bps: 100000000000
config_params {
admin_state: ADMIN_STATE_ENABLED
}
node: 1
}
2 changes: 1 addition & 1 deletion stratum/hal/bin/nikss/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ ::util::Status Main(int argc, char* argv[]) {
{node_id, nikss_node.get()},
};
auto nikss_chassis_manager =
NikssChassisManager::CreateInstance(phal_sim);
NikssChassisManager::CreateInstance(phal_sim, nikss_wrapper);

auto nikss_switch = NikssSwitch::CreateInstance(
phal_sim, nikss_chassis_manager.get(), node_id_to_nikss_node);
Expand Down
2 changes: 2 additions & 0 deletions stratum/hal/lib/nikss/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ stratum_cc_library(
"//stratum/glue/status:status_macros",
"//stratum/hal/lib/common:phal_interface",
"//stratum/hal/lib/common:switch_interface",
"//stratum/hal/lib/nikss:nikss_interface",
"//stratum/lib:constants",
"//stratum/lib:macros",
"@com_google_absl//absl/base:core_headers",
Expand Down Expand Up @@ -95,6 +96,7 @@ stratum_cc_library(
hdrs = ["nikss_node.h"],
deps = [
":nikss_interface",
":nikss_chassis_manager",
"//stratum/glue:integral_types",
"//stratum/glue:logging",
"//stratum/glue/status:status_macros",
Expand Down
51 changes: 47 additions & 4 deletions stratum/hal/lib/nikss/nikss_chassis_manager.cc
Original file line number Diff line number Diff line change
@@ -1,21 +1,64 @@
#include "stratum/hal/lib/nikss/nikss_chassis_manager.h"

#include "absl/synchronization/mutex.h"
#include "stratum/glue/gtl/map_util.h"
#include <utility>

namespace stratum {
namespace hal {
namespace nikss {

ABSL_CONST_INIT absl::Mutex chassis_lock(absl::kConstInit);

NikssChassisManager::NikssChassisManager(
PhalInterface* phal_interface)
PhalInterface* phal_interface, NikssInterface* nikss_interface)
: initialized_(false),
phal_interface_(phal_interface) {
phal_interface_(phal_interface),
nikss_interface_(ABSL_DIE_IF_NULL(nikss_interface)) {
}

NikssChassisManager::~NikssChassisManager() = default;

namespace {

::util::Status AddPortHelper(NikssInterface* nikss_interface_, uint64 node_id, const std::string& port_name) {
LOG(INFO) << "Adding port '" << port_name << "' to node " << node_id;
RETURN_IF_ERROR(nikss_interface_->AddPort(node_id, port_name));
return ::util::OkStatus();
}

}

std::unique_ptr<NikssChassisManager> NikssChassisManager::CreateInstance(
PhalInterface* phal_interface) {
PhalInterface* phal_interface, NikssInterface* nikss_interface) {
return absl::WrapUnique(
new NikssChassisManager(phal_interface));
new NikssChassisManager(phal_interface, nikss_interface));
}

::util::Status NikssChassisManager::PushChassisConfig(
const ChassisConfig& config) {
::util::Status status = ::util::OkStatus(); // errors to keep track of.

std::map<uint64, std::map<uint32, PortConfig>> chassis_config;

for (const auto& singleton_port : config.singleton_ports()) {
PortConfig port = {
.port_id = singleton_port.id(),
.name = singleton_port.name(),
.admin_state = singleton_port.config_params().admin_state(),
};

auto node_id = singleton_port.node();
chassis_config[node_id][port.port_id] = port;
}

chassis_config_ = chassis_config;

return status;
}

::util::StatusOr<std::map<uint64, std::map<uint32, NikssChassisManager::PortConfig>>> NikssChassisManager::GetPortConfig() const {
return chassis_config_;
}

} // namespace nikss
Expand Down
24 changes: 22 additions & 2 deletions stratum/hal/lib/nikss/nikss_chassis_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "absl/synchronization/mutex.h"
#include "stratum/hal/lib/common/phal_interface.h"
#include "stratum/hal/lib/nikss/nikss_interface.h"

namespace stratum {
namespace hal {
Expand All @@ -17,9 +18,20 @@ class NikssChassisManager {
public:
virtual ~NikssChassisManager();

struct PortConfig {
uint32 port_id;
std::string name;
AdminState admin_state;
};

virtual ::util::Status PushChassisConfig(const ChassisConfig& config)
EXCLUSIVE_LOCKS_REQUIRED(chassis_lock);

virtual ::util::StatusOr<std::map<uint64, std::map<uint32, PortConfig>>> GetPortConfig() const;

// Factory function for creating the instance of the class.
static std::unique_ptr<NikssChassisManager> CreateInstance(
PhalInterface* phal_interface);
PhalInterface* phal_interface, NikssInterface* nikss_interface);

// NikssChassisManager is neither copyable nor movable.
NikssChassisManager(const NikssChassisManager&) = delete;
Expand All @@ -30,13 +42,21 @@ class NikssChassisManager {
private:
// Private constructor. Use CreateInstance() to create an instance of this
// class.
NikssChassisManager(PhalInterface* phal_interface);
NikssChassisManager(PhalInterface* phal_interface, NikssInterface* nikss_interface);

::util::Status AddPortHelper(NikssInterface* nikss_interface_, uint64 node_id,
const std::string& port_name);

std::map<uint64, std::map<uint32, PortConfig>> chassis_config_;

bool initialized_ GUARDED_BY(chassis_lock);

// Pointer to a PhalInterface implementation.
PhalInterface* phal_interface_; // not owned by this class.

// Pointer to a NikssInterface implementation that wraps all the SDE calls.
// Not owned by this class.
NikssInterface* nikss_interface_ = nullptr;
};

} // namespace nikss
Expand Down
3 changes: 3 additions & 0 deletions stratum/hal/lib/nikss/nikss_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class NikssInterface {
virtual ::util::Status AddPipeline(int pipeline_id,
const std::string filepath) = 0;

// Add a new port with the given parameters.
virtual ::util::Status AddPort(int pipeline_id, const std::string& port_name) = 0;

protected:
// Default constructor. To be called by the Mock class instance only.
NikssInterface() {}
Expand Down
17 changes: 14 additions & 3 deletions stratum/hal/lib/nikss/nikss_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ std::unique_ptr<NikssNode> NikssNode::CreateInstance(
}

::util::Status NikssNode::PushForwardingPipelineConfig(
const ::p4::v1::ForwardingPipelineConfig& config) {
const ::p4::v1::ForwardingPipelineConfig& config,
std::map<uint64, std::map<uint32, NikssChassisManager::PortConfig>> chassis_config) {
// SaveForwardingPipelineConfig + CommitForwardingPipelineConfig
RETURN_IF_ERROR(SaveForwardingPipelineConfig(config));
return CommitForwardingPipelineConfig();
return CommitForwardingPipelineConfig(chassis_config);
}

::util::Status NikssNode::SaveForwardingPipelineConfig(
Expand All @@ -41,8 +42,18 @@ ::util::Status NikssNode::SaveForwardingPipelineConfig(
return ::util::OkStatus();
}

::util::Status NikssNode::CommitForwardingPipelineConfig() {
::util::Status NikssNode::CommitForwardingPipelineConfig(std::map<uint64, std::map<uint32,
NikssChassisManager::PortConfig>> chassis_config) {

RETURN_IF_ERROR(nikss_interface_->AddPipeline(node_id_, config_.p4_device_config()));

for (auto it = chassis_config[node_id_].begin(); it != chassis_config[node_id_].end(); it++) {
uint32 key = it->first;
NikssChassisManager::PortConfig config = it->second;
LOG(INFO) << "Adding new port with name " << config.name << ".";
RETURN_IF_ERROR(nikss_interface_->AddPort(node_id_, config.name));
}

return ::util::OkStatus();
}

Expand Down
7 changes: 5 additions & 2 deletions stratum/hal/lib/nikss/nikss_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "stratum/glue/status/status.h"

#include "stratum/hal/lib/nikss/nikss_interface.h"
#include "stratum/hal/lib/nikss/nikss_chassis_manager.h"

namespace stratum {
namespace hal {
Expand All @@ -18,10 +19,12 @@ class NikssNode {
virtual ~NikssNode();

virtual ::util::Status PushForwardingPipelineConfig(
const ::p4::v1::ForwardingPipelineConfig& config);
const ::p4::v1::ForwardingPipelineConfig& config,
std::map<uint64, std::map<uint32, NikssChassisManager::PortConfig>> chassis_config);
virtual ::util::Status SaveForwardingPipelineConfig(
const ::p4::v1::ForwardingPipelineConfig& config) LOCKS_EXCLUDED(lock_);
virtual ::util::Status CommitForwardingPipelineConfig() LOCKS_EXCLUDED(lock_);
virtual ::util::Status CommitForwardingPipelineConfig(
std::map<uint64, std::map<uint32, NikssChassisManager::PortConfig>> chassis_config) LOCKS_EXCLUDED(lock_);
virtual ::util::Status VerifyForwardingPipelineConfig(
const ::p4::v1::ForwardingPipelineConfig& config) const;

Expand Down
14 changes: 11 additions & 3 deletions stratum/hal/lib/nikss/nikss_switch.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ NikssSwitch::NikssSwitch(PhalInterface* phal_interface,
NikssSwitch::~NikssSwitch() {}

::util::Status NikssSwitch::PushChassisConfig(const ChassisConfig& config) {
LOG(INFO) << "Pushing chassis config";
RETURN_IF_ERROR(nikss_chassis_manager_->PushChassisConfig(config));
return ::util::OkStatus();
}

Expand All @@ -38,7 +40,9 @@ ::util::Status NikssSwitch::PushForwardingPipelineConfig(
LOG(INFO) << "Pushing P4-based forwarding pipeline to NIKSS";

ASSIGN_OR_RETURN(auto* node, GetNikssNodeFromNodeId(node_id));
RETURN_IF_ERROR(node->PushForwardingPipelineConfig(config));
ASSIGN_OR_RETURN(auto chassis_config, nikss_chassis_manager_->GetPortConfig());

RETURN_IF_ERROR(node->PushForwardingPipelineConfig(config, chassis_config));

LOG(INFO) << "P4-based forwarding pipeline config pushed successfully to "
<< "node with ID " << node_id << ".";
Expand All @@ -64,9 +68,13 @@ ::util::Status NikssSwitch::Shutdown() {
return ::util::OkStatus();
}

::util::Status NikssSwitch::Freeze() { return ::util::OkStatus(); }
::util::Status NikssSwitch::Freeze() {
return ::util::OkStatus();
}

::util::Status NikssSwitch::Unfreeze() { return ::util::OkStatus(); }
::util::Status NikssSwitch::Unfreeze() {
return ::util::OkStatus();
}

::util::Status NikssSwitch::WriteForwardingEntries(
const ::p4::v1::WriteRequest& req, std::vector<::util::Status>* results) {
Expand Down
39 changes: 35 additions & 4 deletions stratum/hal/lib/nikss/nikss_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#include "stratum/lib/utils.h"
#include "stratum/lib/macros.h"

#include <nikss/nikss.h>
#include <nikss/nikss_pipeline.h>
#include "nikss/nikss.h"
#include "nikss/nikss_pipeline.h"

// A macro for simplify checking the return value of NIKSS API.
// For now, we always return ERR_INTERNAL.
Expand All @@ -38,25 +38,56 @@ ABSL_CONST_INIT absl::Mutex NikssWrapper::init_lock_(absl::kConstInit);

NikssWrapper::NikssWrapper() {}

::util::Status NikssWrapper::AddPort(int pipeline_id,
const std::string& port_name) {
auto ctx = absl::make_unique<nikss_context_t>();
nikss_context_init(ctx.get());
nikss_context_set_pipeline(ctx.get(), static_cast<nikss_pipeline_id_t>(pipeline_id));

int port_id = -1;
LOG(INFO) << "Adding port " << port_name << " to pipeline " << pipeline_id << ".";
RETURN_IF_NIKSS_ERROR(nikss_pipeline_add_port(ctx.get(), port_name.c_str(), &port_id));
LOG(INFO) << "Port added with port_id=" << port_id << ".";
nikss_context_free(ctx.get());

return ::util::OkStatus();
}

::util::Status NikssWrapper::DelPort(int pipeline_id,
const std::string& port_name) {
auto ctx = absl::make_unique<nikss_context_t>();
nikss_context_init(ctx.get());
nikss_context_set_pipeline(ctx.get(), static_cast<nikss_pipeline_id_t>(pipeline_id));

RETURN_IF_NIKSS_ERROR(nikss_pipeline_del_port(ctx.get(), port_name.c_str()));

nikss_context_free(ctx.get());

return ::util::OkStatus();
}

::util::Status NikssWrapper::AddPipeline(int pipeline_id,
const std::string bpf_obj) {
std::string tmp_filepath = "/tmp/stratum_bpf.o";
std::string tmp_filepath = "/etc/stratum/bpf.o";
// FIXME: nikss currently doesn't support loading BPF programs from memory.
// So, we save it to the disk first and let NIKSS load it from the disk.
RETURN_IF_ERROR(WriteStringToFile(bpf_obj, tmp_filepath));

auto ctx = absl::make_unique<nikss_context_t>();
nikss_context_init(ctx.get());
nikss_context_set_pipeline(ctx.get(), static_cast<nikss_pipeline_id_t>(pipeline_id));

if (nikss_pipeline_exists(ctx.get())) {
LOG(INFO) << "NIKSS pipeline already exists, re-pushing is not supported yet.";
return ::util::OkStatus();
}

// FIXME: file is not removed if the load() fails
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we fix this issue in this PR?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can postpone this for later PR because it is not critical for now

RETURN_IF_NIKSS_ERROR(nikss_pipeline_load(ctx.get(), tmp_filepath.c_str()));

RemoveFile(tmp_filepath);

nikss_context_free(ctx.get());

return ::util::OkStatus();
}

Expand Down
4 changes: 4 additions & 0 deletions stratum/hal/lib/nikss/nikss_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ namespace nikss {
class NikssWrapper : public NikssInterface {
public:
// NikssInterface public methods.
::util::Status AddPort(int pipeline_id,
const std::string& port_name);
::util::Status DelPort(int pipeline_id,
const std::string& port_name);
::util::Status AddPipeline(int pipeline_id,
const std::string filepath) override;

Expand Down