Comments (10)
Is the support of keyword last still under development? simple_switch
throws an error message if my p4 program tries to access the largest-index valid instance of a header stack (inside of an action):
terminate called after throwing an instance of 'std::out_of_range'
what(): _Map_base::at
My code looks like:
action my_action() {
modify_field(stack[last].field, 1);
}
from behavioral-model.
This is still under development. It is likely that I will wait until the new P4 (P4-16) spec comes out so that I can make sure the bmv2 implementation is consistent with the spec.
from behavioral-model.
I try to access an element of a stack via an index variable. The index variable should be represented by a metadata field. But a metadata field is not an integer data type. Accordingly, the following example won't work:
modify_field(my_metadata.idx, 0);
modify_field(stack[my_metadata.idx].field, 1);
Is there any way to cast an metadata field to an integer?
from behavioral-model.
It would be useful to see what kind of error you are getting.
However, AFAIK:
- this is disallowed in the P4 language
- bmv2 does not support it
In other words, you can only access a header stack element through a compile-time constant.
from behavioral-model.
The compiler gives the following error:
user@desktop:~/behavioral-model/targets/simple_switch$ p4c-bmv2 simple_switch.p4 --json simple_switch.json
parse error in file /[...]/simple_switch.p4 at line 151 : Syntax error while parsing at token my_metadata (ID)
parse error in file /[...]/simple_switch.p4 at line 151 : Invalid index in array header reference
2 errors during parsing
Interrupting compilation
Error while building HLIR
Background:
I try to process a sequence of MPLS labels that are attached to an incomming packet. The number of MPLS labels is unknown until the Parser counts them and stores the result into a metadata field. The labels themselves are serialized to a separate stack. Each label of the determines an output port. The task of the ingress/egress pipeline is to replicate the packet (maybe by clone*
operations) to these ports. However, loops are not allowed in P4, but I need to iterate the stack somehow.
from behavioral-model.
There is probably a workaround that does not involve using a metadata field as an index into the header stack. For example, if you have a reasonable upper bound to the stack depth, you can always hand-write different actions like this:
table mpls_count {
reads {
my_metadata.count : exact;
}
actions { count_is_1; count_is_2; count_is_3; count_is_4; ...}
}
Obviously this is very verbose, but can be reasonable for up to say 8 mpls labels.
When doing replication, you may want to use the Packet Replication Engine. clone
only lets you do one copy per control-flow. But you can always use clone
in a "cascading fashion": clone the original packet, then clone the clone, clone the clone of the clone... This works very well if you are allowed to remove (aka pop) the MPLS label after replicating to the port. Actually if you are allowed to do that, this whole thing becomes much easier because all you ever need to look at is stack[0]
.
from behavioral-model.
Thanks for your suggestions, great workarounds! The second workaround (cascading cloning) seems to be more flexible. I tried to implement this, but it posed another problem ;-) The Parser seems not to reset it's index counter for the MPLS stack. Please take a look at the following log:
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Processing packet received on port 0
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser 'parser': start
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser state 'start' has no switch, going to default next state
[14:43:21.168] [bmv2] [T] [thread 9330] Bytes parsed: 0
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Extracting header 'ethernet'
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser state 'parse_ethernet' has no switch, going to default next state
[14:43:21.168] [bmv2] [T] [thread 9330] Bytes parsed: 14
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Extracting to header stack 0, next header is 1
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser set: setting field (4, 7) from expression, new value is 1
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser state 'parse_stack': key is 04
[14:43:21.168] [bmv2] [T] [thread 9330] Bytes parsed: 34
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Extracting to header stack 0, next header is 2
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser set: setting field (4, 7) from expression, new value is 2
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser state 'parse_stack': key is 00
[14:43:21.168] [bmv2] [T] [thread 9330] Bytes parsed: 54
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Parser 'parser': end
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Pipeline 'ingress': start
[14:43:21.168] [bmv2] [T] [thread 9330] [0.0] [cxt 0] Applying table 'table1'
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Looking up key:[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Table 'table1': miss
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Action entry is action1 -
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Pipeline 'ingress': end
[14:43:21.168] [bmv2] [D] [thread 9330] [0.0] [cxt 0] Cloning packet at ingress
All right, the clone is created.
[14:43:21.168] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser 'parser': start
[14:43:21.168] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser state 'start' has no switch, going to default next state
[14:43:21.168] [bmv2] [T] [thread 9330] Bytes parsed: 0
[14:43:21.168] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Extracting header 'ethernet'
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser state 'parse_ethernet' has no switch, going to default next state
[14:43:21.169] [bmv2] [T] [thread 9330] Bytes parsed: 14
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Extracting to header stack 0, next header is 1
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser set: setting field (4, 7) from expression, new value is 3
My expected value is 1!
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser state 'parse_stack': key is 04
[14:43:21.169] [bmv2] [T] [thread 9330] Bytes parsed: 34
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Extracting to header stack 0, next header is 2
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser set: setting field (4, 7) from expression, new value is 4
My expected value is 2!
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser state 'parse_stack': key is 00
[14:43:21.169] [bmv2] [T] [thread 9330] Bytes parsed: 54
[14:43:21.169] [bmv2] [D] [thread 9330] [0.1] [cxt 0] Parser 'parser': end
[...]
[14:43:21.169] [bmv2] [D] [thread 9330] [0.4] [cxt 0] Extracting header 'ethernet'
[14:43:21.169] [bmv2] [D] [thread 9330] [0.4] [cxt 0] Parser state 'parse_ethernet' has no switch, going to default next state
[14:43:21.169] [bmv2] [T] [thread 9330] Bytes parsed: 14
[14:43:21.169] [bmv2] [D] [thread 9330] [0.4] [cxt 0] Extracting to header stack 0, next header is 1
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
This error might occur because the stack index is out of bounds.
from behavioral-model.
Assuming you are using a metadata field as your index counter, the easiest explanation is that you are including this field (or its parent header) in the cloning field list, which is the second parameter of the clone primitive. When a packet is cloned, all the metadata fields are set to 0 in the copy, except for the fields included in the cloning field list, which are preserved. All you would have to do is remove the metadata field used as an index from the cloning field list.
If this does not explain your issue, you may have to share with me some P4 code so I can reproduce it.
from behavioral-model.
Thanks, this was exactly my problem. I removed the counter from the cloning field list, now it's working fine.
You can find attached the resulting p4 program. Here is how it works: An incoming packet contains a stack of IPv4 addresses. The p4 program processes the stack and generates a separate packet (by clone operations) for each IPv4 address.
from behavioral-model.
Support for s[last]
in expressions was added by #292. s[next]
is IMO only needed in parser when extracting.
from behavioral-model.
Related Issues (20)
- import thrift
- TCP packets seem not to be processed correctly by bmv2 HOT 2
- Problem using multicast in runtime HOT 1
- Empty action-parameter vector is always accessed in ActionFnEntry::execute HOT 3
- How to build behavioral-model on the MacOS(Apple M1 Pro(13.5)) HOT 1
- How to track fileds of metadata with p4dbg? HOT 2
- Approximate conversion of bmv2 p4 performance to hardware performance HOT 3
- Applying the same table twice HOT 2
- Required to set forwarding pipeline before using the dataplane for streaming packets HOT 10
- Update project to require C++17 HOT 9
- Race conditions when passing in a BMv2 JSON config HOT 12
- To Add PNA support into BMv2. HOT 5
- How to build simple_switch / simple_switch_grpc on Ubuntu 24.04 ? HOT 4
- Why bmi_port.c is a C code? HOT 2
- Race conditions when processing packet in the egress pipeline. HOT 6
- Heap Buffer Overflow when installing many table entries HOT 1
- CMake support HOT 2
- Queue metadata with multiqueue HOT 2
- Where is the original p4 source code for recirc.json HOT 8
- Consider implementing something like Tuple Space Search for ternary table lookups
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from behavioral-model.