-
Notifications
You must be signed in to change notification settings - Fork 447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PSA/ebpf backend: add support for generating programs for XDP hook #3752
Conversation
This PR adds functionality to generate programs for the XDP layer for the PSA/ebpf (part of NIKSS) backend. Update of `libbpf` (new version v0.3) is required for definition of `bpf_devmap_val` struct which is available starting from this version. Co-authored-by: Tomasz Osiński <[email protected]> Co-authored-by: Mateusz Kossakowski <[email protected]> Co-authored-by: Frederic Dang Tran <[email protected]> Co-authored-by: El-Fadel Bonfoh <[email protected]>
@@ -73,7 +73,10 @@ void run_ebpf_backend(const EbpfOptions& options, const IR::ToplevelBlock* tople | |||
|
|||
Target* target; | |||
if (options.target.isNullOrEmpty() || options.target == "kernel") { | |||
target = new KernelSamplesTarget(options.emitTraceMessages); | |||
if (!options.generateToXDP) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not a new target?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the main reason is that we treat XDP as kind of optimization of the default TC-based design, since our design in XDP doesn't implement full PSA spec (see README - no CoS, no CLONE_E2E, no packet recirculation).
But to be honest, I don't have a strong opinion here. We could probably make it a new target pretty easily but then we would require some refactoring of other targets (e.g., kernel
target is not a good name anymore since we have more than 1 kernel-based target, also how to resolve conflicts between PSA-eBPF and p4c-xdp?).
backends/ebpf/ebpfOptions.h
Outdated
std::cout << "Setting XDP2TC 'meta' mode by default." << std::endl; | ||
// Use 'meta' mode by default. | ||
if (generateToXDP && xdp2tcMode == XDP2TC_META) { | ||
std::cerr << "XDP2TC 'meta' mode cannot be used if XDP is enabled. " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the compiler has no nice way to talk to the user - it has warning and error.
I wonder whether we need an additional method...
this is good enough for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These error message require a sophisticated user.
Can you give some URLs where the naive ones could find more information?
backends/ebpf/psa/README.md
Outdated
@@ -11,9 +11,16 @@ This directory implements PSA (Portable Switch Architecture) for the eBPF backen | |||
|
|||
# Design | |||
|
|||
The PSA to eBPF compiler provides two flavors of generated eBPF code: TC-based design and XDP-based design. | |||
The TC-based design leverages eBPF TC (Traffic Control) hook and is able to implement any PSA program at the cost of performance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can probably remove "at the cost of performance".
P4 packet processing is translated into a set of eBPF programs attached to the TC hook. The eBPF programs implement packet processing defined | ||
in a P4 program written according to the PSA model. The TC hook is used as a main engine, because it enables a full implementation of the PSA specification. | ||
We also plan to contribute the XDP-based version of the PSA implementation that does not implement the full specification, but provides better performance. | ||
The XDP-based version of the PSA implementation does not implement the full specification, but provides better performance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you provide a ballpark estimate of the improvement so people can decide which one to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think we could @tatry, but the improvement depends on the P4 program. A ballpark estimate is over 2x improvement in throughput per CPU core measured in MPPS.
You can find an extensive performance evaluation in our recent paper: https://dl.acm.org/doi/10.1145/3555050.3569117. We could also reference this paper in the README?
backends/ebpf/psa/ebpfPipeline.cpp
Outdated
|
||
// if Traffic Manager decided to pass packet to the kernel stack earlier, send it up immediately | ||
builder->emitIndent(); | ||
builder->appendFormat("if (%s->pass_to_kernel == true) return %s;", compilerGlobalMetadata, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually == true does not improve readability
backends/ebpf/psa/ebpfPipeline.cpp
Outdated
builder->append( | ||
" void *data = (void *)(long)skb->data;\n" | ||
" void *data_end = (void *)(long)skb->data_end;\n" | ||
" if (((char *) data + 14 + sizeof(struct xdp2tc_metadata)) > (char *) data_end) {\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
14?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The size of Ethernet header. It could be replaced by a proper sizeof
.
builder->newline(); | ||
builder->blockEnd(true); | ||
builder->append( | ||
" data = (void *)(long)skb->data;\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this pattern shows up a lot, is it worthwhile to factor into a macro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it requires something like that.
I think rather about a function that takes a block of C code. It would split code into lines and for each line emits indent, line of code, and makes some string replace if required. Then it would be applied to a lot of places of PSA/eBPF backend. In such case I think this should be separate PR. What do you think about it?
builder->appendLine("__builtin_memmove(data, data + sizeof(struct xdp2tc_metadata), 14);"); | ||
builder->emitIndent(); | ||
builder->appendLine( | ||
"__builtin_memcpy(data + 14, " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general I think it's good to document these magic constants
backends/ebpf/psa/ebpfPsaGen.cpp
Outdated
void PSAArchTC::emitInitializerSection(CodeBuilder* builder) const { | ||
builder->appendLine("SEC(\"classifier/map-initializer\")"); | ||
void PSAArchXDP::emitDummyProgram(CodeBuilder* builder) const { | ||
// this is static program, so we can just paste a piece of code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this comment
This PR adds functionality to generate programs for the XDP layer for the PSA/ebpf (part of NIKSS) backend.
Update of
libbpf
(new version v0.3) is required for definition ofbpf_devmap_val
struct which is available starting from this version.CC: @osinstom @kmateuszssak @fdangtran @elfadel