-
Notifications
You must be signed in to change notification settings - Fork 444
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
Implement EBPF deparser #3136
Implement EBPF deparser #3136
Conversation
Co-authored-by: Mateusz Kossakowski <[email protected]> Co-authored-by: Jan Palimąka <[email protected]>
@osinstom Would it be possible to add any test cases with this PR? |
@osinstom is this file also need to be updated ? |
@rst0git what kind of tests do you have in mind? @stuart-chu Please read the PR description carefully. This PR doesn't extend |
It would be good if we could add a P4 program with STF test (e.g. rst0git@a5fdc50) to validate the functionality of the output code. However, it looks like such test would currently fail because |
@rst0git yes, the goal of this PR isn't to extend |
@mbudiu-vmw could I get a review for this PR please? |
@rst0git BTW is the test passing on your branch? I'm asking out of curiosity. If there is a decision from |
Yes, it is passing without STF test, i.e., the compiler works, but doesn't include deparser code in the output C program.
I am happy to approve this PR but I am not sure I understand how this code will be used. |
@osinstom If I want to use this code in ebpf_model for testing, can I modify the ebpf_model.p4 only or any other code which need to be modified? |
@jonny-zzy You also need to extend
|
The solution is not to modify ebpf_model.p4, but to introduce a new model, perhaps ebpf_switch.p4. This can be done in a similar way to xdp_model.p4. Note that p4c-xdp can compile programs for both models, and there is no reason that p4c-ebpf can't do that. It can detect which model is being used from the way main is instantiated. |
backends/ebpf/ebpfDeparser.cpp
Outdated
|
||
bool DeparserPrepareBufferTranslator::preorder(const IR::BlockStatement* s) { | ||
for (auto a : s->components) { | ||
if (auto method = a->to<IR::MethodCallStatement>()) { |
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 already check the function name below, so it may be enough to just call visit(a) for MethodCallStatements.
if (method->method->name.name == p4lib.packetOut.emit.name) { | ||
auto decl = method->object; | ||
if (decl == deparser->packet_out) { | ||
auto expr = method->expr->arguments->at(0)->expression; |
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 should check that enough arguments exist.
The model seems to check that, but people can load the wrong model, and you don't want to crash.
Then you should call modelError.
} | ||
builder->blockEnd(true); | ||
} | ||
} |
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.
Is doing nothing for other methods the right thing?
Should there be an else error
here?
alignment %= 8; | ||
} | ||
builder->blockEnd(true); | ||
} |
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.
and what if this is not packet_out?
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.
does P4 language allow to call emit()
for other fields than packet_out
? Anyway, I'll produce a bug alert in such a case.
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.
emit()
is a method of the extern object packet_out
, so no: https://github.com/p4lang/p4c/blob/main/p4include/core.p4#L60
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, but no one precludes a program writer from defining their own extern with an emit method.
So you should check that it is the right extern and method.
backends/ebpf/ebpfDeparser.cpp
Outdated
return; | ||
} | ||
unsigned widthToEmit = et->widthInBits(); | ||
unsigned loadSize = 0; |
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.
load?
perhaps this should be renamed
BUG_CHECK((bitsToWrite > 0) && (bitsToWrite <= 8), | ||
"invalid bitsToWrite %d", bitsToWrite); | ||
builder->emitIndent(); | ||
if (alignment == 0 && bitsToWrite == 8) { // write whole byte |
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.
looking forward for tests that will validate this.
I got this kind of code several times wrong, so I don't trust myself to validate it by reading it.
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.
yeah, this part is always tricky. We'll have tests for that.
} | ||
builder->blockEnd(true); | ||
} else { | ||
BUG("emit() should only be invoked for packet_out"); |
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 this should be an error, not a bug.
@osinstom ebpf_model.p4 like this: parser parse(packet_in packet, out H headers); package ebpfFilter(parse prs, |
@jonny-zzy you need this change in backends/ebpf/ebpfProgram.cpp as well: |
@osinstom @rst0git I modified the code to support ebpf_model.p4, and compiled .c file finally as expected. The p4 header only included ethernet, arp, ipv4, as the input parameter of deparser at the same time. clang-14 complier according to the compile option of -o2 or -o3, would exceed the limit stack of 512 bytes kernel, and I couldn't understand the compile optimization options, have you any sugestions? tks all. header arp_t{ header arp_ipv4_t { header ipv4_t { struct headers { seems that if write_byte method is called multiple times, the origin stack of struct header will be enlarged for optimization. |
Writing comments on a merged pull request is not the best solution; you should probably open a new issue. |
This PR introduces a common, re-usable implementation of EBPF Deparser that can be used by different architecture models. The implementation is based on https://github.com/vmware/p4c-xdp.
Since
ebpf_model.p4
doesn't define a deparser block, this PR doesn't affect its code. The main use case is PSA implementation for eBPF backend. It would be good to leverage the common deparser implementation in p4c-xdp at some point.This PR is one from the series of PRs bringing the support for the PSA model to eBPF backend. The goal is to shrink the "main PR" with the full implementation of PSA for eBPF to facilitate review.
CC: @kmateuszssak @tatry