Skip to content

Commit

Permalink
Merge pull request #158 from francescomessina/align_ifaces
Browse files Browse the repository at this point in the history
 Alignment between port/transparent_cube and netdev (when they are connected)
  • Loading branch information
frisso committed Jul 6, 2019
2 parents bfaf880 + 24d0b69 commit 48bf039
Show file tree
Hide file tree
Showing 24 changed files with 779 additions and 93 deletions.
7 changes: 6 additions & 1 deletion src/libs/polycube/include/polycube/services/cube_iface.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "polycube/services/guid.h"
#include "polycube/services/port_iface.h"
#include "polycube/services/table.h"
#include "polycube/services/types.h"

#include <map>
#include <string>
Expand Down Expand Up @@ -95,14 +96,18 @@ class CubeIface : virtual public BaseCubeIface {
class TransparentCubeIface : virtual public BaseCubeIface {
public:
virtual void set_next(uint16_t next, ProgramType type) = 0;
virtual std::string get_parent_parameter(const std::string &parameter) = 0;
virtual void set_parameter(const std::string &parameter,
const std::string &value) = 0;
virtual void send_packet_out(const std::vector<uint8_t> &packet, Sense sense,
bool recirculate = false) = 0;

virtual void set_conf(const nlohmann::json &conf) = 0;
virtual nlohmann::json to_json() const = 0;

virtual void subscribe_parent_parameter(const std::string &param_name,
ParameterEventCallback &callback) = 0;
virtual void unsubscribe_parent_parameter(const std::string &param_name) = 0;
virtual std::string get_parent_parameter(const std::string &parameter) = 0;
};
}
}
6 changes: 6 additions & 0 deletions src/libs/polycube/include/polycube/services/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class Port {
// this uses a different naming convention
std::string getName() const;

void subscribe_peer_parameter(const std::string &param_name,
ParameterEventCallback &callback);
void unsubscribe_peer_parameter(const std::string &param_name);
void set_peer_parameter(const std::string &param_name,
const std::string &value);

private:
class impl;
std::unique_ptr<impl> pimpl_;
Expand Down
7 changes: 7 additions & 0 deletions src/libs/polycube/include/polycube/services/port_iface.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "polycube/services/cube_iface.h"
#include "polycube/services/guid.h"
#include "polycube/services/types.h"

namespace polycube {
namespace service {
Expand Down Expand Up @@ -55,6 +56,12 @@ class PortIface {

virtual void set_conf(const nlohmann::json &conf) = 0;
virtual nlohmann::json to_json() const = 0;

virtual void subscribe_peer_parameter(const std::string &param_name,
ParameterEventCallback &callback) = 0;
virtual void unsubscribe_peer_parameter(const std::string &param_name) = 0;
virtual void set_peer_parameter(const std::string &param_name,
const std::string &value) = 0;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ class TransparentCube : public BaseCube {
virtual void packet_in(Sense sense, PacketInMetadata &md,
const std::vector<uint8_t> &packet) = 0;

std::string get_parent_parameter(const std::string &parameter);

void send_packet_out(EthernetII &packet, Sense sense,
bool recirculate = false);

Expand All @@ -59,6 +57,11 @@ class TransparentCube : public BaseCube {

virtual void attach();

void subscribe_parent_parameter(const std::string &param_name,
ParameterEventCallback &callback);
void unsubscribe_parent_parameter(const std::string &param_name);
std::string get_parent_parameter(const std::string &param_name);

private:
std::shared_ptr<TransparentCubeIface>
cube_; // pointer to the cube in polycubed
Expand Down
28 changes: 28 additions & 0 deletions src/libs/polycube/include/polycube/services/types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2018 The Polycube Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <functional>

namespace polycube {
namespace service {

typedef std::function<void(const std::string, const std::string)>
ParameterEventCallback;

} // namespace service
} // namespace polycube
34 changes: 34 additions & 0 deletions src/libs/polycube/src/port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class Port::impl {
void set_conf(const nlohmann::json &conf);
nlohmann::json to_json() const;

void subscribe_peer_parameter(const std::string &param_name,
ParameterEventCallback &callback);
void unsubscribe_peer_parameter(const std::string &param_name);
void set_peer_parameter(const std::string &param_name,
const std::string &value);

private:
std::shared_ptr<PortIface> port_; // port in polycubed
// FIXME: Two different constructor needed. Look at BridgePort example
Expand Down Expand Up @@ -109,6 +115,20 @@ void Port::impl::send_packet_ns(EthernetII &packet) {
port_->send_packet_ns(packet.serialize());
}

void Port::impl::subscribe_peer_parameter(const std::string &param_name,
ParameterEventCallback &callback) {
port_->subscribe_peer_parameter(param_name, callback);
}

void Port::impl::unsubscribe_peer_parameter(const std::string &param_name) {
port_->unsubscribe_peer_parameter(param_name);
}

void Port::impl::set_peer_parameter(const std::string &param_name,
const std::string &value) {
port_->set_peer_parameter(param_name, value);
}

PortStatus Port::impl::get_status() const {
return port_->get_status();
}
Expand Down Expand Up @@ -138,6 +158,20 @@ void Port::send_packet_ns(EthernetII &packet) {
return pimpl_->send_packet_ns(packet);
}

void Port::subscribe_peer_parameter(const std::string &param_name,
ParameterEventCallback &callback) {
return pimpl_->subscribe_peer_parameter(param_name, callback);
}

void Port::unsubscribe_peer_parameter(const std::string &param_name) {
return pimpl_->unsubscribe_peer_parameter(param_name);
}

void Port::set_peer_parameter(const std::string &param_name,
const std::string &value) {
return pimpl_->set_peer_parameter(param_name, value);
}

int Port::index() const {
return pimpl_->index();
}
Expand Down
22 changes: 16 additions & 6 deletions src/libs/polycube/src/transparent_cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ TransparentCube::~TransparentCube() {
factory_->destroy_cube(get_name());
}

std::string TransparentCube::get_parent_parameter(
const std::string &parameter) {
return cube_->get_parent_parameter(parameter);
}

void TransparentCube::send_packet_out(EthernetII &packet, Sense sense,
bool recirculate) {
cube_->send_packet_out(packet.serialize(), sense, recirculate);
Expand All @@ -80,5 +75,20 @@ nlohmann::json TransparentCube::to_json() const {

void TransparentCube::attach() {}

void TransparentCube::subscribe_parent_parameter(
const std::string &param_name, ParameterEventCallback &callback) {
cube_->subscribe_parent_parameter(param_name, callback);
}

void TransparentCube::unsubscribe_parent_parameter(
const std::string &param_name) {
cube_->unsubscribe_parent_parameter(param_name);
}

std::string TransparentCube::get_parent_parameter(
const std::string &param_name) {
return cube_->get_parent_parameter(param_name);
}

} // namespace service
} // namespace polycube
} // namespace polycube
146 changes: 142 additions & 4 deletions src/polycubed/src/extiface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
#include "utils/netlink.h"

#include <iostream>
#include <net/if.h>

namespace polycube {
namespace polycubed {

const std::string PARAMETER_MAC = "MAC";
const std::string PARAMETER_IP = "IP";

std::set<std::string> ExtIface::used_ifaces;

ExtIface::ExtIface(const std::string &iface)
Expand All @@ -39,6 +43,9 @@ ExtIface::ExtIface(const std::string &iface)
}

used_ifaces.insert(iface);

// Save the ifindex
ifindex_iface = if_nametoindex(iface.c_str());
}

ExtIface::~ExtIface() {
Expand Down Expand Up @@ -147,10 +154,6 @@ PeerIface *ExtIface::get_peer_iface() {
return peer_;
}

std::string ExtIface::get_parameter(const std::string &parameter) {
throw std::runtime_error("get parameter not implemented in netdev");
}

void ExtIface::set_next_index(uint16_t index) {
std::lock_guard<std::mutex> guard(iface_mutex_);
set_next(index, ProgramType::INGRESS);
Expand Down Expand Up @@ -254,5 +257,140 @@ std::string ExtIface::get_iface_name() const {
return iface_;
}

/* Interfaces alignment */
void ExtIface::subscribe_parameter(const std::string &caller,
const std::string &param_name,
ParameterEventCallback &callback) {
std::string param_upper = param_name;
std::transform(param_upper.begin(), param_upper.end(),
param_upper.begin(), ::toupper);
if (param_upper == PARAMETER_MAC) {
std::lock_guard<std::mutex> lock(event_mutex);
// lambda function netlink notification LINK_ADDED
std::function<void(int, const std::string &)> notification_new_link;
notification_new_link = [&](int ifindex, const std::string &iface) {
// Check if the iface in the notification is that of the ExtIface
if (get_iface_name() == iface) {
std::string mac_iface = Netlink::getInstance().get_iface_mac(iface);
for (auto &map_element : parameter_mac_event_callbacks) {
(map_element.second).first(iface, mac_iface);
}
}
};
// subscribe to the netlink event for MAC
int netlink_index = Netlink::getInstance().registerObserver(
Netlink::Event::LINK_ADDED, notification_new_link);

// Save key and value in the map
parameter_mac_event_callbacks.insert(
std::make_pair(caller, std::make_pair(callback, netlink_index)));

// send first notification with the Mac of the netdev
std::string mac_iface = Netlink::getInstance().get_iface_mac(iface_);
callback(iface_, mac_iface);
} else if (param_upper == PARAMETER_IP) {
std::lock_guard<std::mutex> lock(event_mutex);
// lambda function netlink notification NEW_ADDRESS
std::function<void(int, const std::string &)> notification_new_address;
notification_new_address = [&](int ifindex, const std::string &cidr) {
// Check if the iface in the notification is that of the ExtIface
if (ifindex == ifindex_iface) {
for (auto &map_element : parameter_ip_event_callbacks) {
(map_element.second).first(get_iface_name(), cidr);
}
}
};
// subscribe to the netlink event for Ip and Netmask
int netlink_index = Netlink::getInstance().registerObserver(
Netlink::Event::NEW_ADDRESS, notification_new_address);

// Save key and value in the map
parameter_ip_event_callbacks.insert(
std::make_pair(caller, std::make_pair(callback, netlink_index)));

// send first notification with the Ip/prefix of the netdev
std::string info_ip_address;
info_ip_address = get_parameter(PARAMETER_IP);
callback(iface_, info_ip_address);
} else {
throw std::runtime_error("parameter " + param_upper + " not available");
}
}

void ExtIface::unsubscribe_parameter(const std::string &caller,
const std::string &param_name) {
std::string param_upper = param_name;
std::transform(param_upper.begin(), param_upper.end(),
param_upper.begin(), ::toupper);
if (param_upper == PARAMETER_MAC) {
std::lock_guard<std::mutex> lock(event_mutex);
auto map_element = parameter_mac_event_callbacks.find(caller);
if (map_element != parameter_mac_event_callbacks.end()) {
// unsubscribe to the netlink event
int netlink_index = (map_element->second).second;
Netlink::getInstance().unregisterObserver(
Netlink::Event::LINK_ADDED, netlink_index);
// remove element from the map
parameter_mac_event_callbacks.erase(map_element);
} else {
throw std::runtime_error("there was no subscription for the parameter " +
param_upper + " by " + caller);
}
} else if (param_upper == PARAMETER_IP) {
std::lock_guard<std::mutex> lock(event_mutex);
auto map_element = parameter_ip_event_callbacks.find(caller);
if (map_element != parameter_ip_event_callbacks.end()) {
// unsubscribe to the netlink event
int netlink_index = (map_element->second).second;
Netlink::getInstance().unregisterObserver(
Netlink::Event::NEW_ADDRESS, netlink_index);
// remove element from the map
parameter_ip_event_callbacks.erase(map_element);
} else {
throw std::runtime_error("there was no subscription for the parameter " +
param_upper + " by " + caller);
}
} else {
throw std::runtime_error("parameter " + param_upper + " not available");
}
}

std::string ExtIface::get_parameter(const std::string &param_name) {
std::string param_upper = param_name;
std::transform(param_upper.begin(), param_upper.end(),
param_upper.begin(), ::toupper);
if (param_upper == PARAMETER_MAC) {
return Netlink::getInstance().get_iface_mac(iface_);
} else if(param_upper == PARAMETER_IP) {
try {
std::string ip = Netlink::getInstance().get_iface_ip(iface_);
std::string netmask = Netlink::getInstance().get_iface_netmask(iface_);
int prefix = polycube::service::utils::get_netmask_length(netmask);
std::string info_ip_address = ip + "/" + std::to_string(prefix);
return info_ip_address;
} catch (...) {
// netdev does not have an Ip
return "";
}
} else {
throw std::runtime_error("parameter " + param_upper +
" not available in extiface");
}
}

void ExtIface::set_parameter(const std::string &param_name,
const std::string &value) {
std::string param_upper = param_name;
std::transform(param_upper.begin(), param_upper.end(),
param_upper.begin(), ::toupper);
if (param_upper == PARAMETER_MAC) {
Netlink::getInstance().set_iface_mac(iface_, value);
} else if(param_upper == PARAMETER_IP) {
Netlink::getInstance().set_iface_cidr(iface_, value);
} else {
throw std::runtime_error("parameter " + param_upper + " not available");
}
}

} // namespace polycubed
} // namespace polycube

0 comments on commit 48bf039

Please sign in to comment.