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

Add ExactMap and TernaryMap extern definitions to pna.p4 #52

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

jfingerh
Copy link
Contributor

No description provided.

@jfingerh
Copy link
Contributor Author

See #45 for some notes on an earlier discussion of these externs.

@mihaibudiu
Copy link

I think this should be a separate library file, which can be included in pna.p4 if it is deemed to be standard.

@mihaibudiu
Copy link

This was discussed in the LDWG in May 2021: p4lang/p4c#2739

@jfingerh
Copy link
Contributor Author

"I think this should be a separate library file, which can be included in pna.p4 if it is deemed to be standard." Making it part of the PNA standard is exactly the reason this is being proposed and discussed. It might not meet with wide enough approval to become part of pna.p4, but that is my hope.

Of course we could make N optional parts of PNA. If that is met with reasonably wide agreement, we might do that. In practice, the larger N is, and the more often P4 developers use the optional features that are not implemented by all target devices, the less portable their programs will be. That doesn't automatically make every optional thing "bad", just less desirable than something all vendors agree to implement.

@jfingerh
Copy link
Contributor Author

@apinski-cavium Is it quick for you to point out the way in which this code violates the current P4 language spec?

@mbudiu-vmw If you or Andrew have any thoughts on changes to this proposal that would enable an argument like const_entries to be specified, I am curious to learn about them. I would prefer one that did NOT require defining a separate constructor for each different number of entries, as that seems doomed to fail whenever someone wants to specify one more entry than the maximum someone picked when defining the constructors.

As you can tell from this proposal, I am OK if a proposal does not enable the p4c front/mid-end code to type check the value of const_entries, and any such type checking is relegated to the back end code of the target. Once that checking is done for one target in open source, other implementations could hopefully reuse it.

@apinski-cavium
Copy link
Contributor

So it looks like I was wrong about _ types. See 7.2.13 Don't care types but I am still not 100% understand the semantics here.
The example given in Section 17.1 only allows them on generics type while doing type unification on the generic type's paramaters (basically an anymous generic paramater type). When this was added, there was a good example and what seemed like a better explaination of it but it was changed and the example was moved and explanation changed.

@jafingerhut
Copy link
Collaborator

@apinski-cavium Do you mean that Section 7.2.13, and/or Section 17.1, were different in earlier versions of the spec that had a different explanation/example of _ types? I did a quick spot-check of the corresponding sections back to version 1.0.0 of the spec (available in the "Archives" section of this page https://p4.org/specs/) but did not notice any differences there.

@apinski-cavium
Copy link
Contributor

@apinski-cavium Do you mean that Section 7.2.13, and/or Section 17.1, were different in earlier versions of the spec that had a different explanation/example of _ types? I did a quick spot-check of the corresponding sections back to version 1.0.0 of the spec (available in the "Archives" section of this page https://p4.org/specs/) but did not notice any differences there.

I looked into the git history (rather than published version of the spec) on this one to find where it changed. It changed when p4lang/p4-spec@84db458 commit was pulled in. The example was never right to begin with anyways (because control type definition vs control definition).
Note I still think there needs to be a clarification in the language dealing with extern constructors and externs functions because I think the current definition only allows it for (package, control and parser and action) type definitions rather than function calls.

@mihaibudiu
Copy link

The right solution is to extend the p4 type system to support generic lists. The entries is a list literal. The braces notation is somewhat overloaded now: it is used for tuples and structs too.

@jafingerhut
Copy link
Collaborator

@apinski-cavium Do you think that with a clarification in the language spec, that this proposed extern definition would be more clearly according to that clarified definition?

@mihaibudiu
Copy link

Why don't we actually add List or Vector types and literals to the language? May not be that difficult. We can talk about it at the next design working group. I will try to prototype something to make sure it works.

@jafingerhut
Copy link
Collaborator

@mbudiu-vmw @jnfoster How likely do you think extending the P4 type system to support generic lists would be in, say 3 to 6 months? I know that of course the answer depends upon how much effort is put into it, but wondering if you have some kind of guesstimate. If a smaller change to the language spec would make this PR legal using _ as it does (or some small variation), I'm content defining it that way for now.

@mihaibudiu
Copy link

This could be done in a couple of days of work if there are no unexpected surprises.

@jnfoster
Copy link
Contributor

jnfoster commented Sep 1, 2022

Agree. Just adding polymorphic lists would be an easy task.

@mihaibudiu
Copy link

Here is a possible example: p4lang/p4c#3520.
Check out the test files.

@mihaibudiu
Copy link

p4c actually accepts the vectors of tuples, but there's a bug in the tuple elimination pass in the midend which replaces tuples with structs, that one causes the errors reported.

@mihaibudiu
Copy link

I have amended the PR to accept the vectors of tuples correctly.

@jafingerhut
Copy link
Collaborator

jafingerhut commented Nov 13, 2022

Commit 2 on this PR updates the proposed new externs so that they use the new list type that may soon be added to the P4_16 language. For more information, see this PR for the language spec: p4lang/p4-spec#1168, which contains a link to the PR for the p4lang/p4c repo that adds this feature.

As of 2022-Nov-18, this PR has been merged into open source p4c p4lang/p4c#3520 and I have verified that with those changes, this code compiles without any errors.

TernaryMap<tmap2_key, tmap2_val>(
size = 1024,
largest_priority_wins = true,
initial_entries =
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 initial_entries parameter is intended to correspond with the new ability to define initial entries (without const qualifier before the entries table property name) proposed in this PR for the language spec: p4lang/p4-spec#1180

Here I do not see an easy way to make the per-entry const property or the per-entry priority optional, so they are required for each entry.

Copy link

@psivanup psivanup left a comment

Choose a reason for hiding this comment

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

Looks fine.

pna.p4 Outdated Show resolved Hide resolved
}

/**
* The type K must be a struct type. Each of its members becomes a

Choose a reason for hiding this comment

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

K as struct type: It is possible for user to pass any type for this template parameter. There is no restrictions on number of fields, nesting the struct type. Hope, it is up to the target to restrict on these semantics?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, targets can limit the total size and/or type of fields within the struct type K, e.g. if the user wants a 10,000 bit key, that is too much for most targets.

*/
ExactMap<emap1_key, bit<16>>(
size = 1024,
const_entries = (list<exactmap_const_entry_t<emap1_key, bit<16>>>) {

Choose a reason for hiding this comment

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

Isn't this initialization expected to work without cast ((list<exactmap_const_entry_t<emap1_key, bit<16>>>))?

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 current p4c compiler implementation of this feature might NOT work without the (list<...>) there. Maybe it will be enhanced later to work without that there, but it isn't there yet.

Copy link
Member

@thomascalvert-xlnx thomascalvert-xlnx left a comment

Choose a reason for hiding this comment

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

These are so similar to existing tables (the comments even show the equivalence), I think it would be nicer if we could somehow implement this using a table property. A couple ideas:

    table emap2 {
        key = {
            val1: exact;
            val2: exact;
        }
        // notice lack of "actions =" line here
        // lookup would be a special action recognised by the compiler
        default_action = lookup(emap2_val);
        // alternatively, we could introduce this new table property:
        direct_value = emap2_val;
    }
    (...)
    bit<4>  my_val1 = ...;
    bit<12> my_val2 = ...;
    emap2_val my_resp = emap2.lookup(my_val1, my_val2);

Personally I have a slight preference for direct_value, as this is an action-less table (and so default_action doesn't really make sense).

The underlying BCAM/TCAM primitives aren't something which is specific to a NIC as far as I know.


I think this should be a separate library file, which can be included in pna.p4 if it is deemed to be standard.

Of course we could make N optional parts of PNA. If that is met with reasonably wide agreement, we might do that. In practice, the larger N is, and the more often P4 developers use the optional features that are not implemented by all target devices, the less portable their programs will be. That doesn't automatically make every optional thing "bad", just less desirable than something all vendors agree to implement.

The flip side is that once something is in pna.p4 it becomes very hard to change our minds down the road. However going the other way is easier, i.e. moving an optional extern into the main pna.p4 file.


// As far as the control plane API is concerned, there is
// exactly one table.
L2_fwd.apply();
Copy link
Member

Choose a reason for hiding this comment

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

Would be good if this example went on to actually use the maps (i.e. call the lookup() function).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I wanted to get a variety of instantiations into the program first, with heavy comments to explain what is going on. I do not have any functionally useful example that uses these 4 instantiations in the same program, but I can at least use one of them in some made-up sample code.

@jafingerhut
Copy link
Collaborator

These are so similar to existing tables (the comments even show the equivalence), I think it would be nicer if we could somehow implement this using a table property. A couple ideas:

    table emap2 {
        key = {
            val1: exact;
            val2: exact;
        }
        // notice lack of "actions =" line here
        // lookup would be a special action recognised by the compiler
        default_action = lookup(emap2_val);
        // alternatively, we could introduce this new table property:
        direct_value = emap2_val;
    }
    (...)
    bit<4>  my_val1 = ...;
    bit<12> my_val2 = ...;
    emap2_val my_resp = emap2.lookup(my_val1, my_val2);

Personally I have a slight preference for direct_value, as this is an action-less table (and so default_action doesn't really make sense).

The underlying BCAM/TCAM primitives aren't something which is specific to a NIC as far as I know.

I think this should be a separate library file, which can be included in pna.p4 if it is deemed to be standard.

Of course we could make N optional parts of PNA. If that is met with reasonably wide agreement, we might do that. In practice, the larger N is, and the more often P4 developers use the optional features that are not implemented by all target devices, the less portable their programs will be. That doesn't automatically make every optional thing "bad", just less desirable than something all vendors agree to implement.

The flip side is that once something is in pna.p4 it becomes very hard to change our minds down the road. However going the other way is easier, i.e. moving an optional extern into the main pna.p4 file.

I am perfectly OK if we end up just creating more general P4 tables for this purpose, but note one of the original motivations for this in #45, repeated here:

(a) their lookup method can be called from inside the body of a P4 action. The P4_16 language spec explicitly disallows table_name.apply() calls within P4 action calls today, and always has since version 1.0.

I believe it was Roop who asked recently about this same issue, and I pointed out to him this limitation in the current P4 language spec, and our use case for wanting to call these externs within actions, and I also pointed out the following issue on the public p4-spec Github repo where the P4 language spec is discussed: p4lang/p4-spec#947

Roop said he is motivated to raise this issue again, hopefully in the next P4 language design work group meeting on 2022-Dec-05, and I urge you to also attend that meeting to make your case, or support Roop however you can, if you want such a change made in the spec.

}

struct exactmap_initial_entry_t<K,V> {
bool const_entry;
Copy link

@det-intel det-intel Nov 29, 2022

Choose a reason for hiding this comment

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

Adding this bool "const" member to the struct complicates the already challenging semantics of const. It would be worth documenting a bit more clearly what it means. Does it mean it can't be deleted by any runtime API? What about automatic add/del ops? Does it change the table props in any other way (like current const does on tables)?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would assume it would be the same as the table entries handling which is handled in the pull request p4lang/p4-spec#1180 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A short answer is that const entries in P4 tables means all entries are const, and none can be removed, modified, NOR added (this is in the language spec). The constructor with const_entries is for these externs is intended to be like that.

The pull request that Andrew Pinski linked to is a proposed new thing in the language spec defining entries for a P4 table without a const qualifier. See there for details, but the intent is that each of the entries can be independently marked as const or not, and only those marked const are prevented from being removed or modified by the control plane, but the control plane is free to add new entries to the table (up to the size limitation). The constructor for these externs with initial_entries parameter is intended to work like that, and the true/false value for const takes the place of the const keyword.

While it would be nice if the same syntax could be used for P4 tables as here, that would be a bigger change to the spec, e.g. perhaps to define the current syntax in P4 tables as a syntax for a new type of object, perhaps called a 'table entry' object, but I wasn't hoping to go that far here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If any or all of the text in my previous comment could be usefully added to this PR, let me know. I think some of it is said in comments in the pna.p4 include file, e.g. it says elsewere in this PR:

const_entries is a list of entries, similar to the 'const
* entries' table property for tables. This set of entries cannot
* be removed or modified by the control plane, and also, the
* control plane is not allowed to add any entries to an ExactMap
* instance created using this constructor.

And for initial_entries it is commented as:

The same as the ExactMap constructor with a parameter named
* const_entries, except that the control plane is allowed to
* add entries to an ExactMap instance constructed using this
* constructor (subject to capacity constraints, as usual), and
* the control plane can modify or remove any entries that has a
* const_entry field equal to false. Any entries with a
* const_entry field value equal to true cannot be modified or
* removed by the control plane.

defined within a control that have the same name as each other.
Thus we can generate control plane API files, e.g. P4Info files,
assuming that extern instances of ExactMap and TernaryMap will
never have the same names as any P4 tables in the same control.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jamescchoi See the paragraph comment I just added earlier today (2022-Nov-29) following up on a question in a meeting we had earlier today.

@jafingerhut
Copy link
Collaborator

The 2022-Dec-05 P4 language design work group meeting resulted in the list type being added to the P4 language spec, and it is part of open source p4c as I mentioned in an earlier comment, so at least in those ways, there is no impediment to considering this for PNA now.

I am mindful of Thomas Calvert's comment here #52 (review) Unfortunately the topic of generalizing P4 tables was not discussed at the 2022-Dec-05 language design work group meeting, at least partly due to a full plate of topics.

@thomascalvert-xlnx If you would like that issue discussed at the next (2nd Monday of January) language design work group meeting, we may as well suggest adding it to the agenda now. Would you like me to propose the discussion topic there, or would you like to?

@thomascalvert-xlnx
Copy link
Member

@jafingerhut thanks for the poke, I've just sent Mihai an email to suggest adding it to the agenda.

@jfingerh
Copy link
Contributor Author

@jafingerhut Add link to P4 LDWG issue related to this topic for reference.

@jafingerhut
Copy link
Collaborator

Here is link to issue proposing generalizing P4 tables in language design work group, which was discussed early in 2023, but not accepted: p4lang/p4-spec#1209

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.

8 participants