Skip to content

Commit 642c19b

Browse files
authored
Merge pull request #292 from FedeParola/controller-direct
Send packets to controller from the running program
2 parents 7e31261 + ab6e798 commit 642c19b

File tree

21 files changed

+155
-233
lines changed

21 files changed

+155
-233
lines changed

Documentation/developers/dataplane.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,18 @@ Polycube architecture adds a wrapper around the user's code, this wrapper calls
1818

1919
- **pcn_pkt_drop(struct __sk_buff *skb, struct pkt_metadata *md);**: drops the packet. It is the same that just returning `RX_DROP`. [Example](services/pcn-helloworld/src/Helloworld_dp.h#L78)
2020

21-
- **pcn_pkt_controller(struct __sk_buff *skb, struct pkt_metadata *md, u16 reason)**: sends the packet to the control path controller. Reason can be used to indicate why the packet is being sent to the custom code running in the control path. If there is not any reason `RX_CONTROLLER` could be directly returned. [Example](services/pcn-helloworld/src/Helloworld_dp.h#L82)
21+
- **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
2222

23-
- **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.
23+
Processing packets in the slowpath
24+
**********************************
2425

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+
A copy of the packet can be sent to the controller to be processed by the slowpath using the following helpers:
27+
28+
- **pcn_pkt_controller(struct __sk_buff *skb, struct pkt_metadata *md, u16 reason)**: sends a copy of the packet to the controller. Reason can be used to indicate why the packet is being sent to the custom code running in the control path. [Example](services/pcn-helloworld/src/Helloworld_dp.h#L82)
29+
30+
- **pcn_pkt_controller_with_metadata(struct __sk_buff *skb, struct pkt_metadata *md, u16 reason, u32 metadata[3])**: sends a copy of the packet to the custom code running in the control path. In addition to the reason the user can also send some additional metadata.
31+
32+
The packet will be processed by the ``packet_in`` method of the controller.
2633

2734
Checksum calculation
2835
********************

Documentation/services/pcn-packetcapture/packetcapture.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,5 @@ As a example, we list here is the generated C code for the filter ``icmp``:
192192
} else {
193193
goto L5;
194194
}
195-
L4: return pcn_pkt_controller(ctx, md, reason);
195+
L4: pcn_pkt_controller(ctx, md, reason);
196196
L5: return RX_OK;

src/polycubed/src/base_cube.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,6 @@ enum {
408408
RX_REDIRECT,
409409
RX_DROP,
410410
RX_RECIRCULATE,
411-
RX_CONTROLLER,
412411
RX_ERROR,
413412
};
414413

src/polycubed/src/controller.cpp

Lines changed: 22 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -38,65 +38,9 @@ std::map<int, const packet_in_cb &> Controller::cbs_;
3838

3939
std::mutex Controller::cbs_mutex_;
4040

41-
// Sends the packet to the controller
42-
const std::string CTRL_TC_TX = R"(
43-
struct metadata {
44-
u16 cube_id;
45-
u16 port_id;
46-
u32 packet_len;
47-
u32 traffic_class;
48-
u16 reason;
49-
u32 md[3]; // generic metadata
50-
} __attribute__((packed));
51-
52-
BPF_PERF_OUTPUT(controller);
53-
54-
int controller_module_tx(struct __sk_buff *ctx) {
55-
pcn_log(ctx, LOG_TRACE, "[tc-encapsulator]: to controller");
56-
// If the packet is tagged add the tagged in the packet itself, otherwise it
57-
// will be lost
58-
if (ctx->vlan_present) {
59-
volatile __u32 vlan_tci = ctx->vlan_tci;
60-
volatile __u32 vlan_proto = ctx->vlan_proto;
61-
bpf_skb_vlan_push(ctx, vlan_proto, vlan_tci);
62-
}
63-
64-
volatile u32 x; // volatile to avoid verifier error on kernels < 4.10
65-
x = ctx->cb[0];
66-
u16 in_port = x >> 16;
67-
u16 module_index = x & 0x7fff;
68-
u16 pass_to_stack = x & 0x8000;
69-
70-
x = ctx->cb[1];
71-
u16 reason = x & 0xffff;
72-
73-
struct metadata md = {0};
74-
md.cube_id = module_index;
75-
md.port_id = in_port;
76-
md.packet_len = ctx->len;
77-
md.traffic_class = ctx->mark;
78-
md.reason = reason;
79-
80-
x = ctx->cb[2];
81-
md.md[0] = x;
82-
x = ctx->cb[3];
83-
md.md[1] = x;
84-
x = ctx->cb[4];
85-
md.md[2] = x;
86-
87-
int r = controller.perf_submit_skb(ctx, ctx->len, &md, sizeof(md));
88-
if (r != 0) {
89-
pcn_log(ctx, LOG_ERR, "[tc-encapsulator]: perf_submit_skb error: %d", r);
90-
}
91-
if (pass_to_stack) {
92-
pcn_log(ctx, LOG_DEBUG, "[tc-encapsulator]: passing to stack");
93-
return 0;
94-
}
95-
return 7;
96-
ERROR:
97-
pcn_log(ctx, LOG_ERR, "[tc-encapsulator]: unknown error");
98-
return 7; //TODO: check code
99-
}
41+
// Perf buffer used to send packets to the controller
42+
const std::string CTRL_PERF_BUFFER = R"(
43+
BPF_TABLE_PUBLIC("perf_output", int, __u32, _BUFFER_NAME, 0);
10044
)";
10145

10246
// Receives packet from controller and forwards it to the Cube
@@ -168,66 +112,6 @@ int controller_module_rx(struct __sk_buff *ctx) {
168112
}
169113
)";
170114

171-
const std::string CTRL_XDP_TX = R"(
172-
#include <bcc/helpers.h>
173-
#include <bcc/proto.h>
174-
175-
#include <uapi/linux/bpf.h>
176-
#include <uapi/linux/if_ether.h>
177-
178-
struct pkt_metadata {
179-
u16 cube_id;
180-
u16 in_port;
181-
u32 packet_len;
182-
u32 traffic_class;
183-
184-
// used to send data to controller
185-
u16 reason;
186-
u32 md[3]; // generic metadata
187-
} __attribute__((packed));
188-
189-
BPF_PERF_OUTPUT(controller);
190-
BPF_TABLE_PUBLIC("percpu_array", u32, struct pkt_metadata, port_md, 1);
191-
192-
int controller_module_tx(struct xdp_md *ctx) {
193-
pcn_log(ctx, LOG_TRACE, "[xdp-encapsulator]: to controller");
194-
void* data_end = (void*)(long)ctx->data_end;
195-
void* data = (void*)(long)ctx->data;
196-
u32 inport_key = 0;
197-
struct pkt_metadata *int_md;
198-
struct pkt_metadata md = {0};
199-
volatile u32 x;
200-
201-
int_md = port_md.lookup(&inport_key);
202-
if (int_md == NULL) {
203-
goto ERROR;
204-
}
205-
206-
md.cube_id = int_md->cube_id;
207-
md.in_port = int_md->in_port;
208-
md.packet_len = (u32)(data_end - data);
209-
md.traffic_class = int_md->traffic_class;
210-
md.reason = int_md->reason;
211-
212-
x = int_md->md[0];
213-
md.md[0] = x;
214-
x = int_md->md[1];
215-
md.md[1] = x;
216-
x = int_md->md[2];
217-
md.md[2] = x;
218-
219-
int r = controller.perf_submit_skb(ctx, md.packet_len, &md, sizeof(md));
220-
if (r != 0) {
221-
pcn_log(ctx, LOG_ERR, "[xdp-encapsulator]: perf_submit_skb error: %d", r);
222-
}
223-
224-
return BPF_REDIRECT;
225-
ERROR:
226-
pcn_log(ctx, LOG_ERR, "[xdp-encapsulator]: unknown error");
227-
return XDP_DROP;
228-
}
229-
)";
230-
231115
// Receives packet from controller and forwards it to the CubeXDP
232116
const std::string CTRL_XDP_RX = R"(
233117
#include <bcc/helpers.h>
@@ -255,7 +139,7 @@ struct pkt_metadata {
255139
} __attribute__((packed));
256140
257141
BPF_TABLE("extern", int, int, xdp_nodes, _POLYCUBE_MAX_NODES);
258-
BPF_TABLE("extern", u32, struct pkt_metadata, port_md, 1);
142+
BPF_TABLE_PUBLIC("percpu_array", u32, struct pkt_metadata, port_md, 1);
259143
BPF_TABLE("array", u32, struct xdp_metadata, md_map_rx, MD_MAP_SIZE);
260144
BPF_TABLE("array", u32, u32, xdp_index_map_rx, 1);
261145
@@ -324,38 +208,34 @@ void Controller::call_back_proxy(void *cb_cookie, void *data, int data_size) {
324208
}
325209

326210
Controller &Controller::get_tc_instance() {
327-
PatchPanel::get_tc_instance();
328-
static Controller instance(CTRL_TC_TX, CTRL_TC_RX, BPF_PROG_TYPE_SCHED_CLS);
211+
static Controller instance("controller_tc", CTRL_TC_RX,
212+
BPF_PROG_TYPE_SCHED_CLS);
329213
static bool initialized = false;
330214
if (!initialized) {
331215
Netlink::getInstance().attach_to_tc(instance.iface_->getName(),
332216
instance.fd_rx_);
333-
PatchPanel::get_tc_instance().add(instance.get_fd(),
334-
PatchPanel::_POLYCUBE_MAX_NODES - 1);
335217
initialized = true;
336218
}
337219
return instance;
338220
}
339221

340222
Controller &Controller::get_xdp_instance() {
341-
PatchPanel::get_xdp_instance();
342-
static Controller instance(CTRL_XDP_TX, CTRL_XDP_RX, BPF_PROG_TYPE_XDP);
223+
static Controller instance("controller_xdp", CTRL_XDP_RX, BPF_PROG_TYPE_XDP);
343224
static bool initialized = false;
344225
if (!initialized) {
345226
int attach_flags = 0;
346227
attach_flags |= 2 << 0;
347228
Netlink::getInstance().attach_to_xdp(instance.iface_->getName(),
348229
instance.fd_rx_, attach_flags);
349-
PatchPanel::get_xdp_instance().add(instance.get_fd(),
350-
PatchPanel::_POLYCUBE_MAX_NODES - 1);
351230
initialized = true;
352231
}
353232
return instance;
354233
}
355234

356-
Controller::Controller(const std::string &tx_code, const std::string &rx_code,
357-
enum bpf_prog_type type)
358-
: ctrl_rx_md_index_(0),
235+
Controller::Controller(const std::string &buffer_name,
236+
const std::string &rx_code, enum bpf_prog_type type)
237+
: buffer_name_(buffer_name),
238+
ctrl_rx_md_index_(0),
359239
logger(spdlog::get("polycubed")),
360240
id_(PatchPanel::_POLYCUBE_MAX_NODES - 1) {
361241
ebpf::StatusTuple res(0);
@@ -382,23 +262,18 @@ Controller::Controller(const std::string &tx_code, const std::string &rx_code,
382262

383263
datapath_log.register_cb(get_id(), handle_log_msg);
384264

385-
std::string tx_code_(datapath_log.parse_log(tx_code));
386-
std::string rx_code_(datapath_log.parse_log(rx_code));
387-
388-
res = tx_module_.init(tx_code_, flags);
389-
if (res.code() != 0) {
390-
logger->error("cannot init ctrl_tx: {0}", res.msg());
391-
throw BPFError("cannot init controller tx program");
392-
}
393-
394-
res = tx_module_.load_func("controller_module_tx", type, fd_tx_);
265+
// Load perf buffer
266+
std::string buffer_code(CTRL_PERF_BUFFER);
267+
buffer_code.replace(buffer_code.find("_BUFFER_NAME"), 12, buffer_name);
268+
269+
res = buffer_module_.init(buffer_code, flags);
395270
if (res.code() != 0) {
396-
logger->error("cannot load ctrl_tx: {0}", res.msg());
397-
throw BPFError("cannot load controller_module_tx");
271+
logger->error("cannot init ctrl perf buffer: {0}", res.msg());
272+
throw BPFError("cannot init controller perf buffer");
398273
}
399274

400-
res =
401-
tx_module_.open_perf_buffer("controller", call_back_proxy, nullptr, this);
275+
res = buffer_module_.open_perf_buffer(buffer_name_, call_back_proxy, nullptr,
276+
this);
402277
if (res.code() != 0) {
403278
logger->error("cannot open perf ring buffer for controller: {0}",
404279
res.msg());
@@ -411,7 +286,7 @@ Controller::Controller(const std::string &tx_code, const std::string &rx_code,
411286
iface_->setMTU(9000);
412287
iface_->up();
413288

414-
res = rx_module_.init(rx_code_, flags);
289+
res = rx_module_.init(datapath_log.parse_log(rx_code), flags);
415290
if (res.code() != 0) {
416291
logger->error("cannot init ctrl_rx: {0}", res.msg());
417292
throw BPFError("cannot init controller rx program");
@@ -483,7 +358,7 @@ void Controller::start() {
483358
auto f = [&]() -> void {
484359
stop_ = false;
485360
while (!stop_) {
486-
tx_module_.poll_perf_buffer("controller", 500);
361+
buffer_module_.poll_perf_buffer(buffer_name_, 500);
487362
}
488363

489364
// TODO: this causes a segmentation fault

src/polycubed/src/controller.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class Controller {
9393

9494
bool stop_;
9595

96-
ebpf::BPF tx_module_;
96+
std::string buffer_name_;
97+
ebpf::BPF buffer_module_;
9798
ebpf::BPF rx_module_;
9899
int fd_tx_;
99100
int fd_rx_;

src/polycubed/src/cube_tc.cpp

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,16 @@ BPF_TABLE("extern", int, int, nodes, _POLYCUBE_MAX_NODES);
198198
BPF_PERF_OUTPUT(span_slowpath);
199199
#endif
200200
201-
static __always_inline
202-
int to_controller(struct CTXTYPE *skb, u16 reason) {
203-
skb->cb[1] = reason;
204-
nodes.call(skb, CONTROLLER_MODULE_INDEX);
205-
//bpf_trace_printk("to controller miss\n");
206-
return TC_ACT_OK;
207-
}
201+
struct controller_table_t {
202+
int key;
203+
u32 leaf;
204+
/* map.perf_submit(ctx, data, data_size) */
205+
int (*perf_submit) (void *, void *, u32);
206+
int (*perf_submit_skb) (void *, u32, void *, u32);
207+
u32 data[0];
208+
};
209+
__attribute__((section("maps/extern")))
210+
struct controller_table_t controller_tc;
208211
209212
#if defined(SHADOW) && defined(SPAN)
210213
static __always_inline
@@ -219,33 +222,14 @@ int pcn_pkt_drop(struct CTXTYPE *skb, struct pkt_metadata *md) {
219222
return RX_DROP;
220223
}
221224
222-
static __always_inline
223-
int pcn_pkt_controller(struct CTXTYPE *skb, struct pkt_metadata *md,
224-
u16 reason) {
225-
md->reason = reason;
226-
return RX_CONTROLLER;
227-
}
228-
229-
static __always_inline
230-
int pcn_pkt_controller_with_metadata_stack(struct CTXTYPE *skb,
231-
struct pkt_metadata *md,
232-
u16 reason,
233-
u32 metadata[3]) {
234-
skb->cb[0] |= 0x8000;
235-
skb->cb[2] = metadata[0];
236-
skb->cb[3] = metadata[1];
237-
skb->cb[4] = metadata[2];
238-
return pcn_pkt_controller(skb, md, reason);
239-
}
240-
241225
static __always_inline
242226
int pcn_pkt_controller_with_metadata(struct CTXTYPE *skb,
243227
struct pkt_metadata *md,
244228
u16 reason,
245229
u32 metadata[3]) {
246-
skb->cb[2] = metadata[0];
247-
skb->cb[3] = metadata[1];
248-
skb->cb[4] = metadata[2];
230+
md->md[0] = metadata[0];
231+
md->md[1] = metadata[1];
232+
md->md[2] = metadata[2];
249233
return pcn_pkt_controller(skb, md, reason);
250234
}
251235
@@ -377,9 +361,6 @@ int handle_rx_wrapper(struct CTXTYPE *skb) {
377361
return forward(skb, md.reason);
378362
case RX_DROP:
379363
return TC_ACT_SHOT;
380-
case RX_CONTROLLER:
381-
return to_controller(skb, md.reason);
382-
383364
case RX_OK: {
384365
#if POLYCUBE_PROGRAM_TYPE == 1 // EGRESS
385366
// If there is another egress program call it, otherwise let the packet
@@ -431,6 +412,24 @@ int pcn_pkt_redirect_ns(struct CTXTYPE *skb,
431412
#endif
432413
return TC_ACT_SHOT;
433414
}
415+
416+
static __always_inline
417+
int pcn_pkt_controller(struct CTXTYPE *skb, struct pkt_metadata *md,
418+
u16 reason) {
419+
// If the packet is tagged add the tagged in the packet itself, otherwise it
420+
// will be lost
421+
if (skb->vlan_present) {
422+
volatile __u32 vlan_tci = skb->vlan_tci;
423+
volatile __u32 vlan_proto = skb->vlan_proto;
424+
bpf_skb_vlan_push(skb, vlan_proto, vlan_tci);
425+
}
426+
427+
md->cube_id = CUBE_ID;
428+
md->packet_len = skb->len;
429+
md->reason = reason;
430+
431+
return controller_tc.perf_submit_skb(skb, skb->len, md, sizeof(*md));
432+
}
434433
)";
435434

436435
} // namespace polycubed

0 commit comments

Comments
 (0)