Skip to content

Commit 2692c3f

Browse files
authored
Merge pull request #140 from francescomessina/shadow_mode
Add Shadow Services
2 parents 19b8ab7 + ca8f301 commit 2692c3f

40 files changed

Lines changed: 1266 additions & 34 deletions

Documentation/cubes.rst

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ A standard cube:
2525
| +----------+ |
2626
port1---|-| |-|---port3
2727
| | core | |
28-
port2---|-| |-|---port3
28+
port2---|-| |-|---port4
2929
| +----------+ |
3030
| |
3131
+--------------+
@@ -71,6 +71,44 @@ Following is example topology composed by standard and transparent cubes.
7171

7272
``polycubectl ?`` shows available cubes installed on your system.
7373

74+
75+
A shadow cube:
76+
Only a standard cube can be **Shadow** type;
77+
- ``polycubectl <cubetype> add <cubename> shadow=true``.
78+
79+
A shadow cube is associated with a Linux network namespace;
80+
81+
The parameters between the shadow cube and the namespace are aligned;
82+
83+
A port defined on a shadow cube is also visible from the network namespace:
84+
- the user can decide to configure the ports using Linux (e.g. ifconfig or the ip command) or polycubectl;
85+
86+
for example: "``polycubectl <cubename> ports <PortName> set ip=<IpAddress>``" it is the same as "``ip netns exec pcn-<cubename> ifconfig <PortName> <IpAddress>``".
87+
- the developer can let Linux handle some traffic by sending it to the namespace (e.g. ARP, ICMP, but in general all those protocols able to be managed by a tool running inside the namespace);
88+
89+
::
90+
91+
+--------------+
92+
port1---| |---port3
93+
| namespace |
94+
port2---| |---port4
95+
Linux +--------------+
96+
____________________________________________________________
97+
98+
::
99+
100+
Polycube shadow cube
101+
+--------------+
102+
| |
103+
| +----------+ |
104+
port1---|-| |-|---port3
105+
| | core | |
106+
port2---|-| |-|---port4
107+
| +----------+ |
108+
| |
109+
+--------------+
110+
111+
74112
Cubes structure
75113
---------------
76114

@@ -177,3 +215,19 @@ These primitives allow to associate transparent cubes to standard cube's ports o
177215
polycubectl attach firewall1 r1:port2
178216

179217
polycubectl attach firewall0 veth1
218+
219+
220+
Span Mode
221+
---------
222+
223+
The shadow cubes have a mode called **span**.
224+
225+
The span mode when activated shows all the traffic seen by the service also to the namespace.
226+
- To activate the span mode the command used is "``polycubectl <cubename> set span=true``".
227+
228+
Span mode is very useful for debugging; On a shadow cube in span mode programs such as Wireshark or Tcpdump can sniff the traffic.
229+
230+
However, the span mode consumes many resources when it is active, so it is disabled by default and it is recommended to use it only when necessary.
231+
232+
N.B. Span mode duplicates traffic so that it is shown by the namespace, the cube continues to handle traffic.
233+
For this reason, for example, if we have a shadow router with active span mode we should not have Ip forwarding active on Linux, otherwise the router service forwards packets and copies them to the namespace, the namespace forwards again packets and there will be duplications.

Documentation/developers/controlplane.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ Generating PacketOut events
9595

9696
The ``Port`` class contains the ``send_packet_out(EthernetII &packet, bool recirculate = false)`` method that allows to inject packets into the datapath, the recirculate parameter allows to specify if the packet should be sent out of the port (`recirculate = false`) or received through the port (`recirculate = true`).
9797

98+
Only in shadow services the ``Port`` class contains the ``send_packet_ns(EthernetII &packet)`` method that allows to send packets into the service namespace.
99+
98100
A reference to a port can be got using the `get_port` function of the Cube base class.
99101

100102
Debugging and logging in the control plane
@@ -106,4 +108,4 @@ Usage example:
106108

107109
::
108110

109-
logger()->info("Connected port {0}", port_name);
111+
logger()->info("Connected port {0}", port_name);

Documentation/developers/datapath.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Polycube architecture adds a wrapper around the user's code, this wrapper calls
2222

2323
- **pcn_pkt_controller_with_metadata(struct __sk_buff *skb, struct pkt_metadata *md, u16 reason, u32 metadata[3])**: Sends the packet to the custom code running in the control path. In addition to the reason the user can also send some additional medatada.
2424

25+
- **pcn_pkt_redirect_ns(struct __sk_buff *skb, struct pkt_metadata *md, u16 port)**: (it is only available for shadow services) sends the packet to the namespace as if it came from the port indicated as parameter
26+
2527
Checksum calculation
2628
********************
2729

@@ -107,4 +109,3 @@ Usage example:
107109
::
108110

109111
pcn_pkt_log(ctx, LOG_DEBUG);
110-

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class Cube : public BaseCube {
4848
void set_conf(const nlohmann::json &conf);
4949
nlohmann::json to_json() const;
5050

51+
const bool get_shadow() const;
52+
const bool get_span() const;
53+
void set_span(const bool value);
54+
55+
const std::string get_veth_name_from_index(const int ifindex);
5156
private:
5257
std::shared_ptr<CubeIface> cube_; // pointer to the cube in polycubed
5358
packet_in_cb handle_packet_in;
@@ -174,5 +179,25 @@ nlohmann::json Cube<PortType>::to_json() const {
174179
return cube_->to_json();
175180
}
176181

182+
template <class PortType>
183+
const bool Cube<PortType>::get_shadow() const {
184+
return cube_->get_shadow();
185+
}
186+
187+
template <class PortType>
188+
const bool Cube<PortType>::get_span() const {
189+
return cube_->get_span();
190+
}
191+
192+
template <class PortType>
193+
void Cube<PortType>::set_span(const bool value) {
194+
return cube_->set_span(value);
195+
}
196+
197+
template <class PortType>
198+
const std::string Cube<PortType>::get_veth_name_from_index(const int ifindex) {
199+
return cube_->get_veth_name_from_index(ifindex);
200+
}
201+
177202
} // namespace service
178203
} // namespace polycube

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ class CubeIface : virtual public BaseCubeIface {
8484

8585
virtual void set_conf(const nlohmann::json &conf) = 0;
8686
virtual nlohmann::json to_json() const = 0;
87+
88+
virtual const bool get_shadow() const = 0;
89+
virtual const bool get_span() const = 0;
90+
virtual void set_span(const bool value) = 0;
91+
92+
virtual const std::string get_veth_name_from_index(const int ifindex) = 0;
8793
};
8894

8995
class TransparentCubeIface : virtual public BaseCubeIface {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Port {
4040
Port(std::shared_ptr<PortIface> port);
4141
~Port();
4242
void send_packet_out(EthernetII &packet, bool recirculate = false);
43+
void send_packet_ns(EthernetII &packet);
4344
int index() const;
4445
std::string name() const;
4546
void set_peer(const std::string &peer);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class PortIface {
4242
public:
4343
virtual void send_packet_out(const std::vector<uint8_t> &packet,
4444
bool recirculate = false) = 0;
45+
virtual void send_packet_ns(const std::vector<uint8_t> &packet) = 0;
4546
virtual uint16_t index() const = 0;
4647
virtual bool operator==(const PortIface &rhs) const = 0;
4748
virtual std::string name() const = 0;

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ std::string get_ip_from_string(const std::string &ipv_net);
5959
* length" -> 24 in this case */
6060
std::string get_netmask_from_string(const std::string &ipv_net);
6161

62+
/* Take in ingress a string like 255.255.255.0 and return the "prefix
63+
* length" -> 24 in this case */
64+
uint32_t get_netmask_length(const std::string &netmask_string);
65+
66+
/* Take in ingress a prefix length like 24 and return the
67+
* "netmask" -> 255.255.255.0 in this case */
68+
std::string get_netmask_from_CIDR(const int cidr);
69+
6270
/*
6371
* formats a debug string, custom specifiers are evaluated by a
6472
* custom implemented logic

src/libs/polycube/src/port.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Port::impl {
3232
impl(Port &op);
3333
~impl();
3434
void send_packet_out(EthernetII &packet, bool recirculate);
35+
void send_packet_ns(EthernetII &packet);
3536
int index() const;
3637
std::string name() const;
3738
void set_peer(const std::string &peer);
@@ -104,6 +105,10 @@ void Port::impl::send_packet_out(EthernetII &packet, bool recirculate) {
104105
port_->send_packet_out(packet.serialize(), recirculate);
105106
}
106107

108+
void Port::impl::send_packet_ns(EthernetII &packet) {
109+
port_->send_packet_ns(packet.serialize());
110+
}
111+
107112
PortStatus Port::impl::get_status() const {
108113
return port_->get_status();
109114
}
@@ -129,6 +134,10 @@ void Port::send_packet_out(EthernetII &packet, bool recirculate) {
129134
return pimpl_->send_packet_out(packet, recirculate);
130135
}
131136

137+
void Port::send_packet_ns(EthernetII &packet) {
138+
return pimpl_->send_packet_ns(packet);
139+
}
140+
132141
int Port::index() const {
133142
return pimpl_->index();
134143
}

src/libs/polycube/src/utils.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,36 @@ std::string get_netmask_from_string(const std::string &ipv) {
277277
return ipv_net.substr(pos + 1, std::string::npos);
278278
}
279279

280+
uint32_t get_netmask_length(const std::string &netmask_string) {
281+
struct in_addr buf;
282+
char address[100];
283+
int res = inet_pton(
284+
AF_INET, netmask_string.c_str(),
285+
&buf); /*convert ip address in binary form in network byte order */
286+
287+
if (res == 1) {
288+
uint32_t counter = 0;
289+
int n = buf.s_addr;
290+
while (n) {
291+
counter++;
292+
n &= (n - 1);
293+
}
294+
return counter;
295+
} else
296+
throw std::runtime_error("IP Address is not in a valid format");
297+
}
298+
299+
std::string get_netmask_from_CIDR(const int cidr) {
300+
uint32_t ipv4Netmask;
301+
302+
ipv4Netmask = 0xFFFFFFFF;
303+
ipv4Netmask <<= 32 - cidr;
304+
ipv4Netmask = ntohl(ipv4Netmask);
305+
struct in_addr addr = {ipv4Netmask};
306+
307+
return inet_ntoa(addr);
308+
}
309+
280310
} // namespace utils
281311
} // namespace service
282312
} // namespace polycube

0 commit comments

Comments
 (0)