Closed dingrui37 closed 6 years ago
In your question, I think you may be mixing up mcast_grp and clone session id values. mcast_grp should be set to a multicast group id value, which numerically might happen to be equal to one of the valid clone session id values, but mcast_grp never refers to or uses a clone session id.
See this documentation to see if it answers your questions for P4_16+v1model, at least, which as it mentions early in the doc, is not identical to the behavior defined in PSA, but should be what the open source bmv2 simple_switch code does: https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md
@jafingerhut is correct. Cloning to a multicast group is very similar to cloning to a unicast port. You need to call the clone
primitive, which will set standard_metadata.clone_spec
. The value you pass to the clone
primitive is the clone session id. At runtime, you need to map that clone session id to either a unicast port number or a multicast group id, using P4Runtime or the thrift CLI (P4Runtime actually lets you do both!). When you clone to a multicast group, you do not set mcast_grp
in your P4 program. If you set mcast_grp
in addition to calling clone
, the original packet will be multicast in addition to the clone packet, so you will end up with 2xN packets in egress, where N is the size of your multicast group. You can also multicast the original packet to one group and multicast the cloned packet to a different multicast group. So mcast_grp
and clone_spec
are not mutually exclusive.
Thanks @jafingerhut @antoninbas this document is very helpful for me. I have another question.
_You need to call the clone primitive, which will set standard_metadata.clonespec. The value you pass to the clone primitive is the clone session id.
Is this description only just for P4_14? In P4_16 version, I can set the clone_spec field directly.
standard_metadata.clone_spec = 1;
Yes you need to call the clone
or clone3
primitive for P4_16 v1model programs, you should not be accessing the clone_spec
field directly. bmv2 simple_switch uses the field to encode more than just the session id.
I write a little code to test multicast, I want to multicast arp request packet to all port(only two ports), my code is as below:
control MyIngress(inout my_headers_t hdr,
inout my_metadata_t meta,
inout standard_metadata_t standard_metadata) {
action drop() {
mark_to_drop();
exit;
}
//use data-plane bound parameter only for test
action multicast(in bit<32> multicast_group_id) {
clone(CloneType.I2E, multicast_group_id);
}
table forward {
key = {
hdr.arp.isValid() : exact;
hdr.arp.oper : ternary;
hdr.arp_ipv4.isValid() : exact;
}
actions = {
drop;
multicast(1);
}
const default_action = drop();
const entries = {
(true, ARP_OPER_REQUEST, true) : multicast(1);
}
}
apply {
forward.apply();
}
}
Multicast group entry from the controller:
P4Runtime Write
updates {
type: INSERT
entity {
packet_replication_engine_entry {
multicast_group_entry {
multicast_group_id: 1
replicas {
egress_port: 1
instance: 1
}
replicas {
egress_port: 2
instance: 2
}
}
}
}
}
The question is I don't find any packet clone to egress as expected, I capture packet at port 2 but find nothing. Log:
[19:49:52.478] [bmv2] [D] [thread 19405] mgrp node created for mgid 1
[19:49:52.478] [bmv2] [D] [thread 19405] node created for rid 2
[19:49:52.478] [bmv2] [D] [thread 19405] node associated with mgid 1
[19:49:52.487] [bmv2] [D] [thread 19405] node created for rid 1
[19:49:52.487] [bmv2] [D] [thread 19405] node associated with mgid 1
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Processing packet received on port 1
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser 'parser': start
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser 'parser' entering state 'start'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Extracting header 'ethernet'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser state 'start': key is 0806
[19:51:28.988] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Bytes parsed: 14
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser 'parser' entering state 'parse_arp'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Extracting header 'arp'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser state 'parse_arp': key is 000108000604
[19:51:28.988] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Bytes parsed: 22
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser 'parser' entering state 'parse_arp_ipv4'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Extracting header 'arp_ipv4'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser state 'parse_arp_ipv4' has no switch, going to default next state
[19:51:28.988] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Bytes parsed: 42
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Parser 'parser': end
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Pipeline 'ingress': start
[19:51:28.988] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Applying table 'MyIngress.forward'
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Looking up key:
* hdr.arp.$valid$ : 01
* hdr.arp.oper : 0001
* hdr.arp_ipv4.$valid$: 01
[19:51:28.988] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Table 'MyIngress.forward': hit with handle 0
[19:51:28.989] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Dumping entry 0
Match key:
* hdr.arp.$valid$ : EXACT 01
* hdr.arp.oper : TERNARY 0001 &&& ffff
* hdr.arp_ipv4.$valid$: EXACT 01
Priority: 1
Action entry: MyIngress.multicast -
[19:51:28.989] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Action entry is MyIngress.multicast -
[19:51:28.989] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Action MyIngress.multicast
[19:51:28.989] [bmv2] [T] [thread 19438] [17.0] [cxt 0] Primitive (no source info)
[19:51:28.989] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Pipeline 'ingress': end
[19:51:28.989] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Cloning packet at ingress
[19:51:28.989] [bmv2] [D] [thread 19438] [17.0] [cxt 0] Egress port is 0
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Pipeline 'egress': start
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Pipeline 'egress': end
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Deparser 'deparser': start
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Deparsing header 'ethernet'
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Deparsing header 'arp'
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Deparsing header 'arp_ipv4'
[19:51:28.989] [bmv2] [D] [thread 19439] [17.0] [cxt 0] Deparser 'deparser': end
[19:51:28.989] [bmv2] [D] [thread 19443] [17.0] [cxt 0] Transmitting packet of size 42 out of port 0
Maybe I misunderstand your advice @antoninbas, I change my code as below, it works. That is to say, when you need to clone a packet, you need to use clone
or clone3
, while for multicast, you can set the mcast_grp directly?
action multicast(in bit<32> multicast_group_id) {
standard_metadata.mcast_grp = 1;
}
[21:01:00.309] [bmv2] [T] [thread 21562] [20.0] [cxt 0] Action MyIngress.multicast
[21:01:00.309] [bmv2] [T] [thread 21562] [20.0] [cxt 0] packet-replication.p4(155) Primitive standard_metadata.mcast_grp = 1
[21:01:00.309] [bmv2] [D] [thread 21562] [20.0] [cxt 0] Pipeline 'ingress': end
[21:01:00.309] [bmv2] [D] [thread 21562] [20.0] [cxt 0] Multicast requested for packet
[21:01:00.309] [bmv2] [D] [thread 21562] number of packets replicated : 2
[21:01:00.309] [bmv2] [D] [thread 21562] [20.0] [cxt 0] Replicating packet on port 2
[21:01:00.309] [bmv2] [D] [thread 21562] [20.0] [cxt 0] Replicating packet on port 1
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Pipeline 'egress': start
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Pipeline 'egress': start
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Pipeline 'egress': end
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Deparser 'deparser': start
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Deparsing header 'ethernet'
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Deparsing header 'arp'
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Deparsing header 'arp_ipv4'
[21:01:00.309] [bmv2] [D] [thread 21564] [20.2] [cxt 0] Deparser 'deparser': end
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Pipeline 'egress': end
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Deparser 'deparser': start
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Deparsing header 'ethernet'
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Deparsing header 'arp'
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Deparsing header 'arp_ipv4'
[21:01:00.309] [bmv2] [D] [thread 21565] [20.1] [cxt 0] Deparser 'deparser': end
[21:01:00.309] [bmv2] [D] [thread 21567] [20.2] [cxt 0] Transmitting packet of size 42 out of port 1
[21:01:00.309] [bmv2] [D] [thread 21567] [20.1] [cxt 0] Transmitting packet of size 42 out of port 2
I may not have been very clear. Here are the different things you can do:
1) multicast packet. You need to set standard_metadata.mcast_grp
to a multicast group id and configure that multicast group id with a P4Runtime MulticastGroupEntry
message.
2) clone packet to a set of ports. You need to call clone
or clone3
and provide a clone session id. You need to configure that session id with a P4Runtime CloneSessionEntry
message. The packet will be cloned to every port you include in the replicas
Protobuf field. It can be a single port or several ports. Behind the scenes, bmv2 will implement the P4Runtime message by creating a multicast group, so you will see mentions of multicast groups in the logs, but this is just how bmv2 implements cloning to multiple ports.
For a given packet, you can do both 1 & 2. As mentioned by both Andy and I, you do not call clone with a multicast group id, you always provide a clone session id that is configured at runtime.
There are examples for both 1 & 2 here: https://github.com/p4lang/behavioral-model/blob/master/targets/simple_switch_grpc/tests/test_pre.cpp
Does bmv2 not support clone currently? The write RPC give an exception.
P4Runtime Write
updates {
type: INSERT
entity {
packet_replication_engine_entry {
clone_session_entry {
session_id: 2
replicas {
egress_port: 1
instance: 1
}
replicas {
egress_port: 2
instance: 2
}
class_of_service: 2
packet_length_bytes: 64
}
}
}
}
[09:01:23.860] [bmv2] [E] [thread 1367] [P4Runtime] The only PRE operations currently supported are for multicast
You need to update your PI code
Your question was: "After cloning a packet in ingress stage, does the cloned version of the packet again goes to parser before being processed in egress stage?"
The answer for the BMv2 v1model architecture implementation using the simple_switch or simple_switch_grpc command is: yes, it does. This detail was added to the "after-ingress pseudocode" in this file on 2020-Feb-02, after I realized that it does happen:
https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md
In particular, this paragraph:
Each cloned packet will be processed by your parser code again. In many cases this will result in exactly the same headers being parsed as when the packet was most recently parsed, but if your parser code uses the value of standard_metadata.instance_type to affect its behavior, it could be different.
Regards, Andy
On Sat, Mar 21, 2020 at 10:23 AM Debobroto Das Robin < notifications@github.com> wrote:
I have a slightly different question, but it is relevant that's why asking it here.
Question: After cloning a packet in ingress stage, does the cloned version of the packet again goes to parser before being processed in egress stage?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/p4lang/behavioral-model/issues/667#issuecomment-602075401, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2YPPD7G73NETMLFE4SADRITZYPANCNFSM4FZTAV2A .
Are multicasted packets also goes through the parser again, just like cloned packets?
No. Packets cloned from ingress are intended to be as nearly like they were when they arrived at the beginning of ingress processing, with no modifications made to them during ingress processing.
Multicast packets are more like unicast packets, in that any and all changes made to them during ingress processing should take effect on them, before they are sent onwards to egress processing.
Hi @antoninbas , I want to try multicast and clone function on the bmv2, but the description about multicast and clone in the p4runtime spec is based on the PSA arch, while the simple_switch target is on the top of v1model, so I want to confirm whether bmv2 supports these functions and how to use.
When I want to use multicasting, the
mcast_grp
field in thestandard_metadata
must be set. The value is equal to thesession_id
field inCloneSessionEntry
message from control plane. The type ofsession_id
is uint32, while the type ofmcast_grp
is bit<16>, does this means thesession_id
must be bit<16> for bmv2, even though its type is uint32?What is the priority between the three fields, egress_spec, clone_spec and mcast_grp? In other words, when I set
egress_spec
,clone_spec
andmcast_grp
on the same time, which one will take effect?