1616
1717#include " cube.h"
1818
19+ #include < net/if.h>
1920#include " port_tc.h"
2021#include " port_xdp.h"
22+ #include " utils/ns.h"
23+ #include " polycube/services/utils.h"
24+
25+ const std::string prefix_ns = " pcn-" ;
26+ const std::string prefix_port = " ns_port_" ;
2127
2228namespace polycube {
2329namespace polycubed {
@@ -26,7 +32,7 @@ Cube::Cube(const std::string &name, const std::string &service_name,
2632 PatchPanel &patch_panel_ingress, PatchPanel &patch_panel_egress,
2733 LogLevel level, CubeType type, bool shadow, bool span)
2834 : BaseCube(name, service_name, MASTER_CODE, patch_panel_ingress,
29- patch_panel_egress, level, type) {
35+ patch_panel_egress, level, type), shadow_(shadow), span_(span) {
3036 std::lock_guard<std::mutex> guard (bcc_mutex);
3137
3238 auto forward_ = master_program_->get_array_table <uint32_t >(" forward_chain_" );
@@ -37,14 +43,25 @@ Cube::Cube(const std::string &name, const std::string &service_name,
3743 for (uint16_t i = 0 ; i < _POLYCUBE_MAX_PORTS; i++)
3844 free_ports_.insert (i);
3945
40- shadow_ = shadow;
41- span_ = span;
46+ if (!shadow_ && span_) {
47+ throw std::runtime_error (" Span mode is not present in no-shadow services" );
48+ }
49+ if (shadow_) {
50+ std::string name_ns = prefix_ns + name;
51+ Namespace ns = Namespace::create (name_ns);
52+ ns.set_random_id ();
53+ }
4254}
4355
4456Cube::~Cube () {
4557 for (auto &it : ports_by_name_) {
4658 it.second ->set_peer (" " );
4759 }
60+ if (get_shadow ()) {
61+ std::string name_ns = prefix_ns + get_name ();
62+ Namespace ns = Namespace::open (name_ns);
63+ ns.remove ();
64+ }
4865}
4966
5067std::string Cube::get_wrapper_code () {
@@ -104,6 +121,9 @@ std::shared_ptr<PortIface> Cube::add_port(const std::string &name,
104121 if (ports_by_name_.count (name) != 0 ) {
105122 throw std::runtime_error (" Port " + name + " already exists" );
106123 }
124+ if (get_shadow () && (name.find (prefix_port) != std::string::npos)) {
125+ throw std::runtime_error (" Port name cannot contain '" + prefix_port + " '" );
126+ }
107127 auto id = allocate_port_id ();
108128
109129 std::shared_ptr<PortIface> port;
@@ -133,6 +153,61 @@ std::shared_ptr<PortIface> Cube::add_port(const std::string &name,
133153 throw ;
134154 }
135155
156+ if (get_shadow ()) {
157+ // create a veth and move it in the namespace
158+ std::string name_peerB = get_name () + " -" + name;
159+ std::shared_ptr<Veth> veth = std::make_shared<Veth>(Veth::create (name, name_peerB));
160+ VethPeer peerA = veth->get_peerA ();
161+ VethPeer peerB = veth->get_peerB ();
162+ int ifindex = if_nametoindex (name.c_str ());
163+
164+ peerB.set_status (IFACE_STATUS::UP);
165+ peerA.set_namespace (prefix_ns + get_name ());
166+ peerA.set_status (IFACE_STATUS::UP);
167+ if (conf.count (" ip" ) && conf.count (" netmask" )) {
168+ int prefix = polycube::service::utils::get_netmask_length (conf.at (" netmask" ).get <std::string>());
169+ peerA.set_ip (conf.at (" ip" ).get <std::string>(), prefix);
170+ } else if (conf.count (" ipv6" )) {
171+ peerA.set_ipv6 (conf.at (" ipv6" ).get <std::string>());
172+ }
173+ if (conf.count (" mac" )) {
174+ peerA.set_mac (conf.at (" mac" ).get <std::string>());
175+ }
176+
177+ std::string name2 = prefix_port + name;
178+ nlohmann::json conf2 = nlohmann::json::object ();
179+ conf2[" name" ] = name2;
180+ conf2[" peer" ] = name_peerB;
181+
182+ auto id2 = allocate_port_id ();
183+ std::shared_ptr<PortIface> port2;
184+
185+ switch (type_) {
186+ case CubeType::TC:
187+ port2 = std::make_shared<PortTC>(*this , name2, id2, conf2);
188+ break ;
189+ case CubeType::XDP_SKB:
190+ case CubeType::XDP_DRV:
191+ port2 = std::make_shared<PortXDP>(*this , name2, id2, conf2);
192+ break ;
193+ }
194+
195+ ports_by_name_.emplace (name2, port2);
196+ ports_by_index_.emplace (id2, port2);
197+ veth_by_name_.emplace (name, veth);
198+ ifindex_veth_.emplace (ifindex, name);
199+
200+ try {
201+ port2->set_peer (name_peerB);
202+ } catch (...) {
203+ ports_by_name_.erase (name2);
204+ ports_by_index_.erase (id2);
205+ veth_by_name_.erase (name);
206+ ifindex_veth_.erase (ifindex);
207+ throw ;
208+ }
209+ }
210+
136211 return std::move (port);
137212}
138213
@@ -154,6 +229,32 @@ void Cube::remove_port(const std::string &name) {
154229 ports_by_name_.erase (name);
155230 ports_by_index_.erase (index);
156231 release_port_id (index);
232+
233+ cube_mutex_.unlock ();
234+ if (get_shadow ()) {
235+ // remove the veth
236+ try {
237+ veth_by_name_.at (name)->remove ();
238+ veth_by_name_.erase (name);
239+ } catch (...) {
240+ logger->trace (" veth {0} not found" , name);
241+ }
242+
243+ for (auto const & [key, val] : ifindex_veth_) {
244+ if (val == name) {
245+ ifindex_veth_.erase (key);
246+ break ;
247+ }
248+ }
249+
250+ // remove the second port
251+ std::string name2 = prefix_port + name;
252+ ports_by_name_.at (name2)->set_peer (" " );
253+ auto index2 = ports_by_name_.at (name2)->index ();
254+ ports_by_name_.erase (name2);
255+ ports_by_index_.erase (index2);
256+ release_port_id (index2);
257+ }
157258}
158259
159260std::shared_ptr<PortIface> Cube::get_port (const std::string &name) {
@@ -183,7 +284,21 @@ const bool Cube::get_span() const {
183284}
184285
185286void Cube::set_span (const bool value) {
186- span_ = value;
287+ if (shadow_)
288+ span_ = value;
289+ else
290+ throw std::runtime_error (" Span mode is not present in no-shadow services" );
291+ }
292+
293+ /* returns the name of the veth given the ifindex */
294+ const std::string Cube::get_veth_name_from_index (const int ifindex) {
295+ std::string name;
296+ try {
297+ name = ifindex_veth_.at (ifindex);
298+ } catch (...) {
299+ name = " " ;
300+ }
301+ return name;
187302}
188303
189304const std::string Cube::MASTER_CODE = R"(
0 commit comments