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

Rebased version of #1698 #2902

Merged
merged 12 commits into from
Dec 7, 2021
Merged

Rebased version of #1698 #2902

merged 12 commits into from
Dec 7, 2021

Conversation

mihaibudiu
Copy link
Contributor

This is another attempt to fix the problems with recirculate/resubmit/clone3.
The solution is to

  • use an annotation (called @field_list currently) on the user metadata fields that need to be recirculated
  • the annotation has a numeric argument
  • pass the annotation numeric argument as the last argument to the recirculate/etc call
    This will cause the runtime to initialize the specified fields before entering the pipeline.
    This correctly implements the semantics of P4-14 recirculate/etc.
    Here is an excerpt from the resubmit.p4 p4-14 benchmark, as automatically translated by the compiler:
enum bit<8> FieldLists {
    resubmit_FL = 0
}

struct mymeta_t {
    @field_list(FieldLists.resubmit_FL) 
    bit<8> f1;
}

...
    @name("._resubmit") action _resubmit() {
        meta.mymeta.f1 = 8w1;
        resubmit((bit<8>)FieldLists.resubmit_FL);
    }

This changes the signature of the respective v1model functions. We may chose instead to add new functions and deprecate the old ones.

@smolkaj
Copy link
Member

smolkaj commented Oct 4, 2021

Awesome, thanks. I agree that we would want to instead add new functions and deprecate the old ones.
Maybe something like clone3_with_field_list?

EDIT: Or clone_preserving_field_list?

@mihaibudiu
Copy link
Contributor Author

@smolkaj can you please test to see whether this variant works for you?

@smolkaj
Copy link
Member

smolkaj commented Nov 2, 2021

Thanks, @mbudiu-vmw, I will give it a try!

@kheradmandG
Copy link
Contributor

kheradmandG commented Nov 9, 2021

Question, how can one specify not passing any fields to recirculate/resubmit/clone3. E.g., the equivalent of clone3(…, …, {}) ?
I assume we should use a number that is not already used in any @field_list. If true, isn’t that a bit problematic? Say one uses number 0 to specify that clone3_field_list(…, …, 0) and later end up using that number in a @field_list, forgetting that 0 was used as an equivalent of specifying nothing ({}). This can lead to subtle bugs.

@mihaibudiu
Copy link
Contributor Author

Yes, just use a number that has no fields attached. You could use -1, that's less likely to be a common number.
I expect people don't frequently refactor programs in this way.

@kheradmandG
Copy link
Contributor

kheradmandG commented Nov 9, 2021

Thanks for the response @mbudiu-vmw. I still feel this can lead to subtle bugs but @smolkaj mentioned that there is the clone primitive that can be used for this purpose, instead.

* calling clone3 with the same type and session parameter values,
* with empty data.
*/
extern void recirculate_field_list(bit<8> index);
extern void clone(in CloneType type, in bit<32> session);
Copy link
Contributor

Choose a reason for hiding this comment

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

There is another declaration of extern void clone(in CloneType type, in bit<32> session) in line 537. This causes compilation errors:

 [--Werror=duplicate] error: clone: multiple matching declarations
...
v1model.p4(537): [--Werror=duplicate] error: Candidate: clone
extern void clone(in CloneType type, in bit<32> session);
            ^^^^^
v1model.p4(586): [--Werror=duplicate] error: Candidate: clone
extern void clone(in CloneType type, in bit<32> session);
            ^^^^^

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how come our tests pass?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure what flags/options we are using for the compilation (maybe @smolkaj can shed some light?). Anyway that declaration is indeed duplicated in v1model.p4 in this pull request (lines 537 and 586).

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 guess if you never call the method you don't get the error.
I will remove one of the two declarations, in the meantime can you please do the same if you want to try this?

Copy link
Contributor

Choose a reason for hiding this comment

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

That makes sense, also maybe somebody should add a test for clone to p4c's test suite to avoid future regressions. Yeah I commented out that line and the error goes away.

@kheradmandG
Copy link
Contributor

kheradmandG commented Nov 10, 2021

One more question, I have something like:

enum bit<8> PreservedFieldList {
  CLONE_I2E = 8w1
};

struct metadata_t {
  ...
  @field_list(PreservedFieldList.CLONE_I2E)
  ipv4_addr_t ip;
  ...
}

I get the error:

[--Werror=not-found] error: PreservedFieldList: declaration not found
  @field_list(PreservedFieldList.CLONE_I2E)
              ^^^^^^^^^^^^^^^^^^

However, if I change metadata_t to:

struct metadata_t {
  ...
  @field_list(8w1)
  ipv4_addr_t ip;
  ...
}

It works fine (at least in compilation).

I was wondering whether I'm missing something here.

@mihaibudiu
Copy link
Contributor Author

This is a bit strange, because this exactly the kind of code that is generated by the P4-14 front-end.
It must be a bug related to name resolution.
Can you please post a complete example and I will make sure it compiles and add it as a test?

@kheradmandG
Copy link
Contributor

I randomly selected testdata/p4_14_samples_outputs/packet_redirect-frontend.p4 and ran into the same problem. Do you run that test successfully?

@mihaibudiu
Copy link
Contributor Author

If you look at this web page you will see that all tests have passed. I will give it a shot.

@castilhorosa
Copy link

Sorry if this is not the right place for this kind of question but I'd like to get a sneak peek of this version of p4c, with the extern resubmit_field_list, and I wondering if there is any script that I can use to compile this branch. I've been trying unsuccefully to adapt the script install-p4dev-v2.sh by using the command
git clone -b recirculate --single-branch https://github.com/mbudiu-vmw/p4c-clone.git
I would really appreciate if someone could provide me such script/commands...

@mihaibudiu
Copy link
Contributor Author

Can you already build the main branch of the compiler?
Is yes, then the only thing you need to do is to switch to this branch (git checkout -b recirculate) and then run the same steps.
For me the steps are cmake ..; make

@mihaibudiu
Copy link
Contributor Author

Don't use my clone of the repository, use the official one from https://github.com/p4lang/p4c
My clone is just for development and the main branch may be behind the origin.

@castilhorosa
Copy link

Can you already build the main branch of the compiler? Is yes, then the only thing you need to do is to switch to this branch (git checkout -b recirculate) and then run the same steps. For me the steps are cmake ..; make

Great. It worked. Thanks @mbudiu-vmw

@kheradmandG
Copy link
Contributor

kheradmandG commented Nov 20, 2021

@mbudiu-vmw @smolkaj
I did some internal testing and seems like (beside the 2 issues mentioned above), the pull request works as expected.
A suggestion: might be good idea to name the the action with something that conveys that the field list is being preserved. E.g. clone_preserve_field_list or something like that.

@smolkaj
Copy link
Member

smolkaj commented Nov 20, 2021

+1, how about clone_preserving_field_list to make it roll off the tongue a bit easier?

@smolkaj
Copy link
Member

smolkaj commented Nov 20, 2021

(As you might be able to tell, Google has trained me to advocate for long, descriptive function names... 😆)

@mihaibudiu
Copy link
Contributor Author

I will submit soon an update which fixes the issues you discussed. There is a new test using an enum, and that passes too, I could not reproduce Ali's error. Make sure that the enum is declared prior to its first use.

@kheradmandG
Copy link
Contributor

kheradmandG commented Dec 2, 2021

@mbudiu-vmw Thanks for the changes. One question regarding the naming: what does 3 in clone3 mean? And does it make sense to keep it in clone3_preserving_field_list ?

@mihaibudiu
Copy link
Contributor Author

It comes from the fact that there was a clone with 2 arguments, and one with 3.

* Treat error type as string in p4RuntimeSerializer
@kheradmandG
Copy link
Contributor

@mbudiu-vmw Thanks for the info. nit: now that this action is completely distinguishable from the clone with 2 arguments, would it make sense to rename it to clone_preserving_field_list (i.e. drop 3)?

@mihaibudiu
Copy link
Contributor Author

I will make the change to clone3, but we won't be able to merge this until someone approves it.
I asked @jafingerhut for a review. Hopefully he can find the time.

/* Treat error type as string */
if (type->is<IR::Type_Error>())
return 0;

Copy link

Choose a reason for hiding this comment

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

I'm not reviewing the C++ implementation code parts of this PR very carefully -- simply scanning through them looking for anything odd. Is this change something that was discovered as a small side issue while developing the fixes for preserving user-defined metadata fields for resubmit/recirculate/clone? Perhaps something that was needed for the failing test cases exercising those features to pass, so good to combine them into this PR while you were at it? I don't have any objection, main curious why it is thrown in with this PR.

Copy link
Contributor Author

@mihaibudiu mihaibudiu Dec 6, 2021

Choose a reason for hiding this comment

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

I think that this is coming from the main branch from a rebase.

@@ -2588,9 +2675,12 @@ void ProgramStructure::populateOutputNames() {
"mark_to_drop",
"hash",
"resubmit",
"resubmit_preserving_field_list",
Copy link

Choose a reason for hiding this comment

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

I will double-check this with my own small tests, but is resubmit_preserving_field_list a new primitive internal to p4c only, or do these changes also require new primitives in the BMv2 JSON file that BMv2 reads?

Copy link
Contributor Author

@mihaibudiu mihaibudiu Dec 4, 2021

Choose a reason for hiding this comment

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

This is compiled to the standard recirculate bmv2 primitive

Copy link

Choose a reason for hiding this comment

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

Sounds good. Thanks.

* @field_list(1, 2)
* bit<32> y;
* bit<32> z;
* }
Copy link

Choose a reason for hiding this comment

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

Thanks for adding a short example to this documentation!

Copy link

Choose a reason for hiding this comment

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

I created a separate issue to remind me to either myself, or find some other volunteer to help, update other documentation inside and outside of the p4lang/p4c repository on how these operations work. I think it is best of those changes are made in their own separate PRs after this one is merged: #2977

@@ -134,16 +134,27 @@ header data_t {
}

struct metadata {
@pa_solitary("ingress", "acl_metadata.if_label")
Copy link

Choose a reason for hiding this comment

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

How were tests passing before without these annotations? The input program had a pragma or P4_14 annotation-like thing since before this PR, so did something change in this PR to make these annotations appear in the output? Or were the tests somehow passing before even though the files did not match?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is probably because I rebased on top of other changes. This pr does not know anything about this annotation. I don't know where it's coming from.

Copy link

Choose a reason for hiding this comment

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

OK, I will not worry about it then. There is a pa_solitary pragma in the original P4_14 program, so something in the P4_14 to P4_16 translation must be picking it up.

@@ -73,7 +77,7 @@ control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
@name(".do_copy_to_cpu") action do_copy_to_cpu() {
clone3<tuple<standard_metadata_t>>(CloneType.I2E, 32w250, { standard_metadata });
clone_preserving_field_list(CloneType.I2E, 32w250, (bit<8>)FieldLists.copy_to_cpu_fields);
Copy link

Choose a reason for hiding this comment

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

Does this implementation work to preserve standard metadata fields? If yes, how does that work, if one cannot add annotations to the standard metadata struct definition?

Copy link

Choose a reason for hiding this comment

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

Regardless of the answer, it seems worth adding a sentence or three on this in the v1model.p4 comments that document how this works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You cannot. The idea is that you should not be able to spoof standard Metadata. It's debatable, but I don't know how to do it anyway.

Copy link

Choose a reason for hiding this comment

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

Seems like a reasonable restriction, and I will put it on a list of details to document elsewhere, including a suggested workaround that of course one is welcome to copy a standard metadata field value into a user-defined metadata field, and preserve the user-defined metadata field.

// Copy another header's data to local variable.
bh.x = h.bvh0.x;
clone3(CloneType.I2E, 0, h);
clone_preserving_field_list(CloneType.I2E, 0, 0);
Copy link

Choose a reason for hiding this comment

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

It seems like if we wanted to remain faithful to the original meaning of this test program, there should be @field_list(0) annotations on all fields of struct parsed_packet_t?

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 clone only preserves metadata fields,. Adding annotations to parsed_packet_t should have no effect.

Copy link

@jfingerh jfingerh left a comment

Choose a reason for hiding this comment

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

Looks good to me. As usual, I have focused on the v1model.p4 include file changes, and the changes to the test programs and their expected outputs. Except for one minor comment where it appears that a test program may have changed its behavior by no longer preserving some fields that the original did, I did not notice any problems.

@mihaibudiu
Copy link
Contributor Author

@jafingerhut if I have your approval please give it officially so we can merge this.
Or suggest alternative reviewers...

@jfingerh
Copy link

jfingerh commented Dec 7, 2021

jafingerh is also my user account, and I approved using that one already. I can add approval using my account jafingerhut in a few minutes, in case that makes a difference for tracking purposes.

Copy link
Contributor

@jafingerhut jafingerhut left a comment

Choose a reason for hiding this comment

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

Looks good to me. As usual, I have focused on the v1model.p4 include file changes, and the changes to the test programs and their expected outputs. Except for one minor comment where it appears that a test program may have changed its behavior by no longer preserving some fields that the original did, I did not notice any problems.

@mihaibudiu mihaibudiu merged commit 2be448f into p4lang:main Dec 7, 2021
@mihaibudiu mihaibudiu deleted the recirculate branch December 7, 2021 00:31
jafingerhut added a commit to jafingerhut/behavioral-model that referenced this pull request Dec 12, 2021
…nges

In particular after this pull request was merged into p4c:
p4lang/p4c#2902
antoninbas pushed a commit to p4lang/behavioral-model that referenced this pull request Dec 17, 2021
#1057)

* Updates to documentation on metdata preservation after recent p4c changes
In particular after this pull request was merged into p4c:
p4lang/p4c#2902

* Remove some unnecessary changes from first commit
Should make this easier to review.

* Fix minor typo

* Update the v1model packet_length documentation based on code changes
done on 2021-Dec-16.
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.

None yet

8 participants