Skip to content
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

Merged
merged 6 commits into from
Dec 5, 2022

Conversation

tatry
Copy link
Contributor

@tatry tatry commented Dec 2, 2022

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.

CC: @osinstom @kmateuszssak @fdangtran @elfadel

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)
Copy link
Contributor

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?

Copy link
Contributor

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?).

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. "
Copy link
Contributor

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

Copy link
Contributor

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?

@@ -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.
Copy link
Contributor

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.
Copy link
Contributor

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?

Copy link
Contributor

@osinstom osinstom Dec 3, 2022

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?


// 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,
Copy link
Contributor

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

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14?

Copy link
Contributor Author

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"
Copy link
Contributor

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?

Copy link
Contributor Author

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, "
Copy link
Contributor

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

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.
Copy link
Contributor

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

@mihaibudiu mihaibudiu merged commit 00d76bc into p4lang:main Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants