Skip to content

Commit 6716599

Browse files
add list of attached cubes to port
So far there is not a way to know what are the transparent cubes attached to a given port. This commit extends the base datamodel with a list of cubes in the ports and adds all the logic to handle them. This new resource is init-only-config, this commit also handles all the logic when a port or a cube is created. There are two special conditions that are handled, having in mind that when a transparent cube is attached it can query the port for some parameters we have that: - if the parent cube is being created, it's is not visible yet. - if the parent port is being created this is possible that some parameters are not initialized yet. The solution for both conditions is to first create the element (cube or port) and then apply the configuration to attach the transparent cubes. This approach would not be necessary once a proper subscrition mechanishm is implemented. Signed-off-by: Mauricio Vasquez B <mauriciovasquezbernal@gmail.com>
1 parent d679c83 commit 6716599

18 files changed

Lines changed: 286 additions & 47 deletions

File tree

src/libs/polycube/include/polycube/services/cube.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ std::shared_ptr<PortType> Cube<PortType>::add_port(const std::string &port_name,
120120

121121
std::tie(iter, inserted) = ports_by_name_.emplace(port_name, port);
122122
ports_by_id_.emplace(port->index(), port);
123+
/*
124+
* When a transparent cube is attached to a port, it can query the service
125+
* to get some port parameters (e.g., MAC address). If the transparent cube
126+
* is attached while the port is being created these parameters will be not
127+
* configured yet.
128+
* This workaround first creates the port and then passes the configuration
129+
* to attach the transparent cubes. The configuration that is passed
130+
* in the constructor is ignored in the daemon.
131+
* The solution for this workaround would be to implement the notification
132+
* mechanishm, so when the parameters are configured those are pushed to the
133+
* transparent cube.
134+
*/
135+
port->set_conf(conf.getBase());
123136
return iter->second;
124137
} catch (const std::exception &ex) {
125138
cube_->remove_port(port_name);

src/polycubed/src/base_model.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,24 @@ Response BaseModel::set_span(const std::string &cube_name,
244244
return Response{kOk, ::strdup("")};
245245
}
246246

247+
Response BaseModel::get_port_tcubes(const std::string &cube_name,
248+
const std::string &port_name) const {
249+
auto cube_ = ServiceController::get_cube(cube_name);
250+
if (cube_ == nullptr) {
251+
return Response{kNoContent, ::strdup("Cube does not exist")};
252+
}
253+
254+
// TODO: is this case even possible?
255+
auto cube = std::dynamic_pointer_cast<CubeIface>(cube_);
256+
if (cube == nullptr) {
257+
return Response{kNoContent, ::strdup("Cube is transparent")};
258+
}
259+
260+
auto port_ = cube->get_port(port_name);
261+
auto port = std::dynamic_pointer_cast<Port>(port_);
262+
nlohmann::json j = port->get_cubes_names();
263+
264+
return Response{kOk, ::strdup(j.dump().c_str())};
265+
}
266+
247267
} // namespace polycube::polycubed

src/polycubed/src/base_model.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class BaseModel {
5050
Response get_span(const std::string &cube_name) const;
5151
Response set_span(const std::string &cube_name,
5252
const nlohmann::json &json);
53+
Response get_port_tcubes(const std::string &cube_name,
54+
const std::string &port_name) const;
5355
};
5456

5557
} // namespace polycube::polycubed

src/polycubed/src/peer_iface.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ void PeerIface::remove_cube(const std::string &cube_name) {
111111
update_indexes();
112112
}
113113

114+
std::vector<std::string> PeerIface::get_cubes_names() const {
115+
std::lock_guard<std::mutex> guard(mutex_);
116+
117+
std::vector<std::string> cubes_names;
118+
119+
for (auto &cube : cubes_) {
120+
cubes_names.push_back(cube->get_name());
121+
}
122+
123+
return cubes_names;
124+
}
125+
114126
PeerIface::CubePositionComparison PeerIface::compare_position(
115127
const std::string &cube1, const std::string &cube2) {
116128
// cube position, index 0 is the innermost one

src/polycubed/src/peer_iface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class PeerIface {
4343
void add_cube(TransparentCube *cube, const std::string &position,
4444
const std::string &other);
4545
void remove_cube(const std::string &type);
46+
std::vector<std::string> get_cubes_names() const;
4647

4748
protected:
4849
enum class CubePositionComparison {

src/polycubed/src/polycubed_core.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ void PolycubedCore::attach(const std::string &cube_name,
343343
}
344344
break;
345345
case PortType::XDP:
346-
if (cube->get_type() != CubeType::XDP_DRV &&
346+
if (cube->get_type() != CubeType::XDP_SKB &&
347347
cube->get_type() != CubeType::XDP_DRV) {
348348
throw std::runtime_error(cube_name + " and " + port_name +
349349
" have incompatible types");

src/polycubed/src/port.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ void Port::set_conf(const nlohmann::json &conf) {
163163
if (conf.count("peer")) {
164164
set_peer(conf.at("peer").get<std::string>());
165165
}
166+
167+
// attach transparent cubes present on the port
168+
if (conf.count("tcubes")) {
169+
for (auto &cube : conf.at("tcubes")) {
170+
core->attach(cube.get<std::string>(), get_path(), "last", "");
171+
}
172+
}
166173
}
167174

168175
nlohmann::json Port::to_json() const {
@@ -173,6 +180,11 @@ nlohmann::json Port::to_json() const {
173180
val["status"] = port_status_to_string(get_status());
174181
val["peer"] = peer();
175182

183+
const auto &cubes_names = get_cubes_names();
184+
if (cubes_names.size()) {
185+
val["tcubes"] = cubes_names;
186+
}
187+
176188
return val;
177189
}
178190

src/polycubed/src/server/Parser/YangNodes.tcpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,13 @@ void Yang::ParseLeafList(
395395
}
396396
std::shared_ptr<Resources::Body::LeafListResource> resource;
397397
if (generate_endpoint) {
398+
auto base_model = base_model_factory_->IsBaseModel(parsed_names);
399+
auto &&factory__ = base_model ? dynamic_cast<Resources::Data::AbstractFactory*>(base_model_factory_.get()) : factory_.get();
400+
398401
const auto &e_parent =
399402
std::dynamic_pointer_cast<Resources::Endpoint::ParentResource>(parent);
400403
auto endpoint = e_parent->Endpoint() + '/' + leaflist->name;
401-
resource = factory_->RestLeafList(
404+
resource = factory__->RestLeafList(
402405
std::move(parsed_names), leaflist->name, description, cli_example,
403406
endpoint, parent.get(), std::move(value_field), node_fields,
404407
configuration, init_only_config, mandatory,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(base_model_sources
22
${CMAKE_CURRENT_LIST_DIR}/ConcreteFactory.cpp
33
${CMAKE_CURRENT_LIST_DIR}/LeafResource.cpp
4+
${CMAKE_CURRENT_LIST_DIR}/LeafListResource.cpp
45
PARENT_SCOPE)

src/polycubed/src/server/Resources/Data/BaseModel/ConcreteFactory.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@
2222
#include "../../Body/JsonNodeField.h"
2323

2424
#include "../../Endpoint/LeafResource.h"
25+
#include "../../Endpoint/LeafListResource.h"
2526
#include "../../Endpoint/ListResource.h"
2627
#include "../../Endpoint/ParentResource.h"
2728
#include "../../Endpoint/Service.h"
2829

2930
#include "LeafResource.h"
31+
#include "LeafListResource.h"
3032

3133
#include "polycubed_core.h"
3234

@@ -56,7 +58,7 @@ bool ConcreteFactory::IsBaseModel(
5658
tree_names_.pop();
5759
auto leaf = tree_names_.front();
5860

59-
if (leaf == "uuid" || leaf == "status" || leaf == "peer") {
61+
if (leaf == "uuid" || leaf == "status" || leaf == "peer" || leaf == "tcubes") {
6062
return true;
6163
}
6264
}
@@ -228,8 +230,42 @@ std::unique_ptr<Endpoint::LeafListResource> ConcreteFactory::RestLeafList(
228230
const std::vector<Body::JsonNodeField> &node_fields, bool configuration,
229231
bool init_only_config, bool mandatory, Types::Scalar type,
230232
std::vector<std::string> &&default_value) const {
231-
throw std::invalid_argument(
232-
"Yang case leaf-list not supported in base datamodel");
233+
std::function<Response(const std::string &, const ListKeyValues &keys)>
234+
read_handler_;
235+
std::function<Response(const std::string &, const nlohmann::json &,
236+
const ListKeyValues &, Endpoint::Operation)>
237+
replace_handler_;
238+
239+
// TODO: I need to capture this variable inside the lambda functions,
240+
// capturing "this" for me is not working
241+
auto local_core = this->core_;
242+
243+
auto tree_names_ = tree_names;
244+
tree_names_.pop();
245+
246+
if (tree_names_.size() == 2) {
247+
if (tree_names_.front() != "ports") {
248+
throw std::runtime_error("unknown element found in base datamodel");
249+
}
250+
251+
tree_names_.pop();
252+
auto leaf = tree_names_.front();
253+
if (leaf == "tcubes") {
254+
read_handler_ = [local_core](const std::string &cube_name,
255+
const ListKeyValues &keys) -> Response {
256+
return local_core->base_model()->get_port_tcubes(cube_name,
257+
keys[0].value);
258+
};
259+
} else {
260+
throw std::runtime_error("unknown element found in base datamodel: " +
261+
leaf);
262+
}
263+
}
264+
265+
return std::make_unique<LeafListResource>(
266+
std::move(read_handler_), std::move(replace_handler_), name, description,
267+
cli_example, rest_endpoint, parent, configuration, init_only_config,
268+
core_, std::move(value_field), node_fields, mandatory, type, std::move(default_value));
233269
}
234270

235271
std::unique_ptr<Endpoint::ListResource> ConcreteFactory::RestList(

0 commit comments

Comments
 (0)