-
Notifications
You must be signed in to change notification settings - Fork 428
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
Conditional primitives not supported in actions on simple_switch_grpc target #1515
Comments
In the apply{} section of the P4 control, use if-else. |
Using if-else in the apply{} section of the P4 control won't help here unless we maintain two copies of the same table, as we can apply a given P4 table only once in P4 code. |
You reported two problems. I responded to one of them which was conditional statements are not allowed in action with a MethodCallStatement. The other problem you have is using two tables which is a data structure design issue. Consider adding standard_metadata to table key which also changes the args to the action. table service_req_key_teid_map{ |
Make one action for each of the two if branches and add the IS_CLONE bit to the table key. |
This will work for this specific case but there might be similar use cases where conditional primitives might be required in actions. If possible, please add the conditional support for P4 actions in p4c compiler backend as well. |
The compiler can do nothing if the target you execute your program on does not support conditionals in actions. We can add this to the front end, but each backend will decide for its own. |
I think that's why @coolvikas brought up the "jump" and "conditional jump" primitives in his issue; these were added to bmv2 a while ago. |
@coolvikas I just want to echo a comment from Mihai -- it is relatively straightforward to implement the capability of handling if statements inside of actions in a software switch like BMv2. If you want maximum portability for your P4 program to the highest speed targets, there may be some that will not handle this, no matter what the open source tools do with it. Hence the suggestions from others on ways to write your program that do not require if statements inside the actions, but keep the conditional logic outside actions, e.g. in the table search key. If you are not worried about maximizing portability, well even then there is the current limitation in p4c that may take some time to enhance, so learning about these alternatives is useful even then. |
FWIW, the bmv2 backend for p4c does support ternary expressions. So while
it's slightly painful, you can "fake" a conditional in many cases -- e.g.,
by predicating each assignment on whether the packet is normal or cloned.
…-N
On Sun, Sep 23, 2018 at 2:20 PM Andy Fingerhut ***@***.***> wrote:
@coolvikas <https://github.com/coolvikas> I just want to echo a comment
from Mihai -- it is relatively straightforward to implement the capability
of handling if statements inside of actions in a software switch like BMv2.
If you want maximum portability for your P4 program to the highest speed
targets, there may be some that will not handle this, *no matter what the
open source tools do with it*.
Hence the suggestions from others on ways to write your program that do
not require if statements inside the actions, but keep the conditional
logic outside actions, e.g. in the table search key.
If you are not worried about maximizing portability, well even then there
is the current limitation in p4c that may take some time to enhance, so
learning about these alternatives is useful even then.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1515 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABwi0nMfeoFJchLxuCJHS35PlmEI7A57ks5ud9EDgaJpZM4W1qwq>
.
|
I will tag this as a question; the request itself is a duplicate of #644 |
@coolvikas Looking at the code in your original issue again, I think there is a straightforward way to write it with only one table, shown below. I think this kind of "move the action code after the table apply" transformation is pretty general, and works even if there were N actions other than NoAction.
|
The implementation cost may be quite different between these schemes, depending on the target. |
Understood. That is one reason I stopped myself from suggesting that this was a transformation that a P4 compiler should always make for a developer on their behalf. As far as I can see, there are some targets where this transformation would cause an increase in the temporary storage for the packet to increase by the sum of the sizes of all action parameters for all actions of the affected table. It would only last until the switch statement completed, but that could be bad enough. That plus perhaps an extra stage or two in a pipeline. At east for the BMv2 target, none of those resources are in scarce supply, though, so if it gets Vikas off the ground and running for now, it seemed worth mentioning. |
@jafingerhut Thanks for the suggestion of rewriting the code. I tried it but it seems to be not working for me as I have put the table service_req_key_teid_map in a separate control block named as c_process_normal_clone_packet Also, I am getting the warning |
Instantiating a control inside of another one makes a copy of all structures (inlines) the control. Is your variable initialized on all paths that reach that assignment? |
Yes, I have declared the variable at the start of the control block and initialized the variable inside the action body as suggested by Andy. |
You probably want to initialize the variable before calling .apply() on the table (which could be done where the variable is declared, with an initializer, too). Except in unusual cases, apply'ing a table does not guarantee that a particular action will be called, so there are execution paths that do not invoke that action, as far as the compiler can tell, hence the warning. |
This behavior of not being able to call the same instance of a control from more than one other control in a P4 program is similar to the issue of the current p4c bmv2 back end not allowing a table to be applied more than once, I think. One could imagine a P4 tools chain and target that do allow a single instantiation of a control to be called, even if it contained tables or externs, from more than one other control in your program, and I can imagine that some targets could implement that behavior in a fairly straightfoward way, e.g. software targets on general purpose CPUs, and FPGAs, and some NPUs. Like applying a table multiple times for the same packet, there is an issue that the highest speed targets, e.g. billions of packets per second in a single device, will likely not allow you to do that. If you aren't targeting those, I understand that the current restrictions may seem arbitrary. |
More discussion here on the 'apply a table more than once per packet' issue: #457 |
This behavior is part of the language semantics. If you want a shared control it must be part of the architecture. |
I agree that it would be a change to the P4_16 language spec to allow an instantiation of a control at the top level, and then calling it from multiple other controls, but that is not a big change syntactically or semantically, I think. I know it was considered by the language working group and decided not to be included, but it was a design choice, not some kind of logical contradiction in the spec, that prevented it from being included, wasn't it? |
Indeed, instantiation = allocation. If you instantiate once, you get a single copy. |
Another reason for this restriction is that it limits the flow of information to the in/out parameters in the data plane signature. Suppose that you were allowed to write top-level instantiations: C() c;
control D(...) {
apply {
c.apply(...);
}
control E(...) {
apply {
c.apply(...);
}
Switch(..., D(), E(), ...) main; Now This may not be possible to implement -- e.g., if the data plane signatures of the |
@jnfoster Is limiting the flow of information to the in/out parameters of a data plane signature a design goal of P4_16? I can see it being a desirable property -- I just didn't recall it being mentioned before. Please take a look at the code snippet below. It is similar to the one you gave above, but with no top level instantiations. Is this an example of allowing information flow between I have also attached a complete P4_16 + v1model arch program that I've run through the current p4c and behavioral-model code, and it appears to pass the data through a common instantiation of
|
Mea culpa. That's what I get for asserting a broad property of the language
without thinking about it or better proving it carefully :-)
…-N
On Sat, Oct 27, 2018 at 3:05 PM Andy Fingerhut ***@***.***> wrote:
@jnfoster <https://github.com/jnfoster> Is limiting the flow of
information to the in/out parameters of a data plane signature a design
goal of P4_16? I can see it being a desirable property -- I just didn't
recall it being mentioned before.
Please take a look at the code snippet below. It is similar to the one you
gave above, but with no top level instantiations. Is this an example of
allowing information flow between D and E that uses C as an implicit
channel? If so, it appears to be completely legal P4_16 to me.
I have also attached a complete P4_16 + v1model arch program that I've run
through the current p4c and behavioral-model code, and it appears to pass
the data through a common instantiation of C named c_inst just fine.
control X(in bit<4> idx,
in bit<8> new_val_to_write,
out bit<8> orig_val_before_write);
control C(in bit<4> idx,
in bit<8> new_val_to_write,
out bit<8> orig_val_before_write)
{
register<bit<8>>(16) r1;
bit<8> read_val;
apply {
r1.read(read_val, (bit<32>) idx);
orig_val_before_write = read_val;
r1.write((bit<32>) idx, new_val_to_write);
}
}
control D(in bit<8> rabbit_into_hat)(X c) {
bit<4> idx;
bit<8> new_val_to_write;
bit<8> orig_val_before_write;
apply {
idx = 7;
new_val_to_write = rabbit_into_hat;
c.apply(idx, new_val_to_write, orig_val_before_write);
}
}
control E(out bit<8> rabbit_from_hat)(X c) {
bit<4> idx;
bit<8> new_val_to_write;
bit<8> orig_val_before_write;
apply {
idx = 7;
new_val_to_write = 87;
c.apply(idx, new_val_to_write, orig_val_before_write);
rabbit_from_hat = orig_val_before_write;
}
}
control cIngress(inout Parsed_packet hdr,
inout metadata_t meta,
inout standard_metadata_t stdmeta) {
C() c_inst;
D(c_inst) d_inst;
E(c_inst) e_inst;
bit<8> rabbit_from_hat;
table debug_table {
key = { rabbit_from_hat : exact; }
actions = { NoAction; }
const default_action = NoAction;
}
apply {
d_inst.apply(17);
e_inst.apply(rabbit_from_hat);
debug_table.apply();
}
}
pass-info-outside-of-params.p4.txt
<https://github.com/p4lang/p4c/files/2522116/pass-info-outside-of-params.p4.txt>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1515 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABwi0nLRopnRXQSFvSsRlznRi0mM9wzlks5upK5ngaJpZM4W1qwq>
.
|
I will close this question, but keep the original one open. |
Hi all,
I have a P4 use case, in which I need to utilize the same table and inside the action part I need to take treat NORMAL and CLONED packets differently for which I need a conditional if primitive but unfortunately, the p4c backend throws this error.
error: MethodCallStatement: Conditional execution in actions is not supported on this target
Due to this, I found a possible workaround is to maintain two different tables with exactly the same entries but it causes unnecessary memory overhead and I need to call both tables separately.
Please add the conditional support for P4 actions in p4c compiler backend as bmv2 supports it through jmp and the jmp_ne primitives and I would like the bmv2 backend to generate the JSON accordingly.
My sample P4 program snippet is here
PS I am using simple_switch_grpc bmv2 target to run this code.
The text was updated successfully, but these errors were encountered: