Skip to content

Commit 2341f85

Browse files
authored
Merge pull request #249 from polycube-network/jpi-attach-pr
fix polycubed crash & add a CLI to check the cubes given a interface
2 parents 41c47cf + bf62045 commit 2341f85

File tree

11 files changed

+229
-23
lines changed

11 files changed

+229
-23
lines changed

src/polycubed/src/extiface.cpp

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const std::string PARAMETER_MAC = "MAC";
3232
const std::string PARAMETER_IP = "IP";
3333
const std::string PARAMETER_PEER = "PEER";
3434

35-
std::set<std::string> ExtIface::used_ifaces;
35+
std::map<std::string, ExtIface*> ExtIface::used_ifaces;
3636

3737
ExtIface::ExtIface(const std::string &iface)
3838
: PeerIface(iface_mutex_),
@@ -43,7 +43,7 @@ ExtIface::ExtIface(const std::string &iface)
4343
throw std::runtime_error("Iface already in use");
4444
}
4545

46-
used_ifaces.insert(iface);
46+
used_ifaces.insert({iface, this});
4747

4848
// Save the ifindex
4949
ifindex_iface = if_nametoindex(iface.c_str());
@@ -60,6 +60,14 @@ ExtIface::~ExtIface() {
6060
used_ifaces.erase(iface_);
6161
}
6262

63+
ExtIface* ExtIface::get_extiface(const std::string &iface_name) {
64+
if (used_ifaces.count(iface_name) == 0) {
65+
return NULL;
66+
}
67+
68+
return used_ifaces[iface_name];
69+
}
70+
6371
uint16_t ExtIface::get_index() const {
6472
return index_;
6573
}
@@ -172,39 +180,82 @@ void ExtIface::set_next(uint16_t next, ProgramType type) {
172180
}
173181
}
174182

183+
TransparentCube* ExtIface::get_next_cube(ProgramType type) {
184+
auto next = get_next(type);
185+
for (auto &it : cubes_) {
186+
if (it->get_index(type) == next) {
187+
return it;
188+
}
189+
}
190+
return NULL;
191+
}
192+
193+
uint16_t ExtIface::get_next(ProgramType type) {
194+
int zero = 0;
195+
unsigned int value = 0;
196+
auto program = (type == ProgramType::INGRESS) ? &ingress_program_ : &egress_program_;
197+
auto index_map = program->get_array_table<uint32_t>("index_map");
198+
auto st = index_map.get_value(zero, value);
199+
if (st.code() == -1) {
200+
logger->error("failed to get interface {0} nexthop", get_iface_name());
201+
}
202+
203+
return value & 0xffff;
204+
}
205+
206+
std::vector<std::string> ExtIface::get_service_chain(ProgramType type) {
207+
std::vector<std::string> chain;
208+
TransparentCube *cube;
209+
auto nh = get_next(type);
210+
211+
while (nh != 0xffff) {
212+
cube = NULL;
213+
for (auto c : cubes_) {
214+
if (c->get_index(type) == nh) {
215+
cube = c;
216+
break;
217+
}
218+
}
219+
chain.push_back(cube ? cube->get_name() : "unknown");
220+
nh = cube->get_next(type);
221+
}
222+
chain.push_back(nh==0xffff ? "stack" : "unknown");
223+
224+
return chain;
225+
}
226+
175227
void ExtIface::update_indexes() {
176228
int i;
177229

178230
// TODO: could we avoid to recalculate in case there is not peer?
179231

180-
std::vector<uint16_t> ingress_indexes(cubes_.size());
181-
std::vector<uint16_t> egress_indexes(cubes_.size());
232+
std::vector<uint16_t> ingress_indexes(cubes_.size(), 0xffff) ;
233+
std::vector<uint16_t> egress_indexes(cubes_.size(), 0xffff);
182234

183235
for (i = 0; i < cubes_.size(); i++) {
184236
ingress_indexes[i] = cubes_[i]->get_index(ProgramType::INGRESS);
185237
egress_indexes[i] = cubes_[i]->get_index(ProgramType::EGRESS);
186238
}
187239

188-
// ingress chain: NIC -> cube[N-1] -> ... -> cube[0] -> stack (or peer)
240+
// ingress chain: NIC -> cube[0] -> ... -> cube[n-1] -> stack (or peer)
189241
// CASE2: cube[0] -> stack (or)
190-
for (i = 0; i < cubes_.size(); i++) {
191-
if (ingress_indexes[i]) {
242+
for (i = cubes_.size() - 1; i >= 0; i--) {
243+
if (ingress_indexes[i] != 0xffff) {
192244
cubes_[i]->set_next(peer_ ? peer_->get_index() : 0xffff,
193245
ProgramType::INGRESS);
194246
break;
195247
}
196248
}
197249

198-
// cube[N-1] -> ... -> cube[0]
199-
for (int j = i + 1; j < cubes_.size(); j++) {
200-
if (ingress_indexes[j]) {
250+
for (int j = i - 1; j >= 0; j--) {
251+
if (ingress_indexes[j] != 0xffff) {
201252
cubes_[j]->set_next(ingress_indexes[i], ProgramType::INGRESS);
202253
i = j;
203254
}
204255
}
205256

206257
// CASE4: NIC -> cube[N-1] or peer
207-
if (i < cubes_.size() && ingress_indexes[i]) {
258+
if (i >= 0 && ingress_indexes[i] != 0xffff) {
208259
set_next(ingress_indexes[i], ProgramType::INGRESS);
209260
} else {
210261
set_next(peer_ ? peer_->get_index() : 0, ProgramType::INGRESS);
@@ -214,7 +265,7 @@ void ExtIface::update_indexes() {
214265

215266
// cube[0] -> "egress"
216267
for (i = 0; i < cubes_.size(); i++) {
217-
if (egress_indexes[i]) {
268+
if (egress_indexes[i] != 0xffff) {
218269
cubes_[i]->set_next(0xffff, ProgramType::EGRESS);
219270
break;
220271
}
@@ -227,14 +278,14 @@ void ExtIface::update_indexes() {
227278

228279
// cubes[N-1] -> ... -> cube[0]
229280
for (int j = i + 1; j < cubes_.size(); j++) {
230-
if (egress_indexes[j]) {
281+
if (egress_indexes[j] != 0xffff) {
231282
cubes_[j]->set_next(egress_indexes[i], ProgramType::EGRESS);
232283
i = j;
233284
}
234285
}
235286

236287
// "nic" -> cubes[N-1] or peer
237-
if (i < cubes_.size() && egress_indexes[i]) {
288+
if (i < cubes_.size() && egress_indexes[i] != 0xffff) {
238289
set_next(egress_indexes[i], ProgramType::EGRESS);
239290
} else {
240291
Port *peer_port = dynamic_cast<Port *>(peer_);
@@ -243,12 +294,6 @@ void ExtIface::update_indexes() {
243294
}
244295
}
245296

246-
// in external ifaces the cubes must be allocated in the inverse order.
247-
// first is the one that hits ingress traffic.
248-
int ExtIface::calculate_cube_index(int index) {
249-
return 0 - index;
250-
}
251-
252297
bool ExtIface::is_used() const {
253298
std::lock_guard<std::mutex> guard(iface_mutex_);
254299
return cubes_.size() > 0 || peer_ != nullptr;

src/polycubed/src/extiface.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ class ExtIface : public PeerIface {
4141
ExtIface(const ExtIface &) = delete;
4242
ExtIface &operator=(const ExtIface &) = delete;
4343

44+
/* return ExtIface pointer given interface name
45+
* or return null if
46+
* - either the interface name doesn't exist
47+
* - or no extiface created for the interface name
48+
*/
49+
static ExtIface* get_extiface(const std::string &iface_name);
50+
4451
uint16_t get_index() const override;
4552
uint16_t get_port_id() const override;
4653
void set_peer_iface(PeerIface *peer) override;
@@ -59,6 +66,9 @@ class ExtIface : public PeerIface {
5966
std::string get_parameter(const std::string &param_name) override;
6067
void set_parameter(const std::string &param_name,
6168
const std::string &value) override;
69+
uint16_t get_next(ProgramType type);
70+
TransparentCube* get_next_cube(ProgramType type);
71+
std::vector<std::string> get_service_chain(ProgramType type);
6272

6373
protected:
6474
// 2 maps: one for IP events and one for MAC events
@@ -71,7 +81,7 @@ class ExtIface : public PeerIface {
7181

7282
std::mutex event_mutex;
7383

74-
static std::set<std::string> used_ifaces;
84+
static std::map<std::string, ExtIface*> used_ifaces;
7585
int load_ingress();
7686
int load_egress();
7787
int load_tx();
@@ -82,7 +92,6 @@ class ExtIface : public PeerIface {
8292
virtual bpf_prog_type get_program_type() const = 0;
8393

8494
void update_indexes() override;
85-
int calculate_cube_index(int index) override;
8695

8796
ebpf::BPF ingress_program_;
8897
ebpf::BPF egress_program_;

src/polycubed/src/peer_iface.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@ std::vector<std::string> PeerIface::get_cubes_names() const {
124124
return cubes_names;
125125
}
126126

127+
std::vector<uint16_t> PeerIface::get_cubes_ingress_index() const {
128+
std::lock_guard<std::mutex> guard(mutex_);
129+
130+
std::vector<uint16_t> ingress_indices;
131+
132+
for (auto &cube : cubes_) {
133+
ingress_indices.push_back(cube->get_index(ProgramType::INGRESS));
134+
}
135+
136+
return ingress_indices;
137+
}
138+
139+
std::vector<uint16_t> PeerIface::get_cubes_egress_index() const {
140+
std::lock_guard<std::mutex> guard(mutex_);
141+
142+
std::vector<uint16_t> egress_indices;
143+
144+
for (auto &cube : cubes_) {
145+
egress_indices.push_back(cube->get_index(ProgramType::EGRESS));
146+
}
147+
148+
return egress_indices;
149+
}
150+
151+
152+
127153
PeerIface::CubePositionComparison PeerIface::compare_position(
128154
const std::string &cube1, const std::string &cube2) {
129155
// cube position, index 0 is the innermost one
@@ -157,4 +183,4 @@ PeerIface::CubePositionComparison PeerIface::compare_position(
157183
}
158184

159185
} // namespace polycubed
160-
} // namespace polycube
186+
} // namespace polycube

src/polycubed/src/peer_iface.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class PeerIface {
5252
const std::string &other);
5353
void remove_cube(const std::string &type);
5454
std::vector<std::string> get_cubes_names() const;
55+
std::vector<uint16_t> get_cubes_ingress_index() const;
56+
std::vector<uint16_t> get_cubes_egress_index() const;
5557

5658
protected:
5759
enum class CubePositionComparison {

src/polycubed/src/polycubed_core.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,44 @@ std::string PolycubedCore::topology() {
208208
return j.dump(4);
209209
}
210210

211+
std::string PolycubedCore::get_if_topology(const std::string &if_name) {
212+
json j = {{"name", if_name}};
213+
214+
auto extIface = polycube::polycubed::ExtIface::get_extiface(if_name);
215+
if (extIface != NULL) {
216+
auto names = extIface->get_cubes_names();
217+
auto ingress_indices = extIface->get_cubes_ingress_index();
218+
auto egress_indices = extIface->get_cubes_egress_index();
219+
std::vector<std::string> cubes_info;
220+
std::ostringstream stream;
221+
for (int i=0; i<names.size(); i++) {
222+
stream.str("");
223+
stream << names[i] << ",\t" << ingress_indices[i] << ",\t" << egress_indices[i];
224+
cubes_info.push_back(std::string(stream.str()));
225+
}
226+
j["cubes, ingress_index, egress_index"] = cubes_info;
227+
228+
stream.str("");
229+
auto i_serv_chain = extIface->get_service_chain(ProgramType::INGRESS);
230+
for (auto service : i_serv_chain) {
231+
stream << service;
232+
if (service != std::string("stack"))
233+
stream << " ---> ";
234+
}
235+
j["ingress service chain"] = stream.str();
236+
237+
stream.str("");
238+
auto e_serv_chain = extIface->get_service_chain(ProgramType::EGRESS);
239+
for (auto service : e_serv_chain) {
240+
stream << service;
241+
if (service != std::string("stack"))
242+
stream << " ---> ";
243+
}
244+
j["egress service chain"] = stream.str();
245+
}
246+
return j.dump(4);
247+
}
248+
211249
std::string get_port_peer(const std::string &port) {
212250
std::smatch match;
213251
std::regex rule("(\\S+):(\\S+)");

src/polycubed/src/polycubed_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class PolycubedCore {
6464
std::string get_netdevs();
6565

6666
std::string topology();
67+
std::string get_if_topology(const std::string &if_name);
6768

6869
void connect(const std::string &peer1, const std::string &peer2);
6970
void disconnect(const std::string &peer1, const std::string &peer2);

src/polycubed/src/rest_server.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ void RestServer::setup_routes() {
271271
// topology
272272
router_->get(base + std::string("/topology"),
273273
bind(&RestServer::topology, this));
274+
router_->get(base + std::string("/topology/:ifname"),
275+
bind(&RestServer::get_if_topology, this));
274276

275277
router_->options(base + std::string("/topology"),
276278
bind(&RestServer::topology_help, this));
@@ -830,6 +832,19 @@ void RestServer::topology(const Pistache::Rest::Request &request,
830832
}
831833
}
832834

835+
void RestServer::get_if_topology(const Pistache::Rest::Request &request,
836+
Pistache::Http::ResponseWriter response) {
837+
logRequest(request);
838+
try {
839+
auto ifname = request.param(":ifname").as<std::string>();
840+
std::string retJsonStr = core.get_if_topology(ifname);
841+
response.send(Pistache::Http::Code::Ok, retJsonStr);
842+
} catch (const std::runtime_error &e) {
843+
logger->error("{0}", e.what());
844+
response.send(Pistache::Http::Code::Bad_Request, e.what());
845+
}
846+
}
847+
833848
void RestServer::topology_help(const Pistache::Rest::Request &request,
834849
Pistache::Http::ResponseWriter response) {
835850
json j = json::object();

src/polycubed/src/rest_server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class RestServer {
122122
Pistache::Http::ResponseWriter response);
123123
void topology(const Pistache::Rest::Request &request,
124124
Pistache::Http::ResponseWriter response);
125+
void get_if_topology(const Pistache::Rest::Request &request,
126+
Pistache::Http::ResponseWriter response);
125127
void topology_help(const Pistache::Rest::Request &request,
126128
Pistache::Http::ResponseWriter response);
127129

src/polycubed/src/transparent_cube.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ void TransparentCube::set_next(uint16_t next, ProgramType type) {
7171
reload_all();
7272
}
7373

74+
uint16_t TransparentCube::get_next(ProgramType type) {
75+
return type == ProgramType::INGRESS ? ingress_next_ : egress_next_;
76+
}
77+
7478
void TransparentCube::set_parent(PeerIface *parent) {
7579
parent_ = parent;
7680
if (parent_) {

src/polycubed/src/transparent_cube.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class TransparentCube : public BaseCube, public TransparentCubeIface {
3636
virtual ~TransparentCube();
3737

3838
void set_next(uint16_t next, ProgramType type);
39+
uint16_t get_next(ProgramType type);
3940
void set_parent(PeerIface *parent);
4041
PeerIface *get_parent();
4142
void set_parameter(const std::string &parameter, const std::string &value);

0 commit comments

Comments
 (0)