Skip to content

Commit

Permalink
Add XFAIL P4_14 test program that fails because of issue #1694 (#1710)
Browse files Browse the repository at this point in the history
* Add XFAIL P4_14 test program that fails because of issue #1694

It is nearly identical to the test program p414-special-ops.p4
proposed to be added in the PR #1704, except this program explicitly
modifies metadata fields after a resubmit, recirculate, or clone
operation is performed, and the STF tests will only pass if the
behavior of the packet processing is that the metadata fields are
preserved at the _end_ of ingress/egress processing, _not_ the values
that the metadata fields have at the time of the
recirculate/resubmit/clone primitive operation call.

This is consistent with the P4_14 language specification, at least as
of the clarifications made in v1.0.5 of the specification.

* Add expected compiler output
  • Loading branch information
jafingerhut authored and Mihai Budiu committed Feb 5, 2019
1 parent e42ec22 commit 00cf6c8
Show file tree
Hide file tree
Showing 8 changed files with 2,036 additions and 0 deletions.
5 changes: 5 additions & 0 deletions backends/bmv2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ set (XFAIL_TESTS
testdata/p4_14_samples/issue60.p4
# compiler claims (incorrectly?) that c2 has mulitple successors, so is not supported
testdata/p4_14_samples/issue-1426.p4
# As of 2019-Feb-04 latest p4c, this program fails due to the root
# cause of both issues #1694, but is not affected by #1669. I have
# tested it with the proposed fix for issue #1694 that is on PR
# #1704, and it passes.
testdata/p4_14_samples/p414-special-ops-3-bmv2.p4
# As of 2019-Feb-04 latest p4c code, this program fails due to the
# root cause of both issues #1694 and #1669. I have tested it with
# the proposed fix for issue #1694 that is on PR #1704, and while
Expand Down
370 changes: 370 additions & 0 deletions testdata/p4_14_samples/p414-special-ops-3-bmv2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,370 @@
/*
Copyright 2019 Cisco Systems, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#define MAC_DA_DO_RESUBMIT 0x000000000001
#define MAC_DA_DO_RECIRCULATE 0x000000000002
#define MAC_DA_DO_CLONE_E2E 0x000000000003

#define MAX_RESUBMIT_COUNT 6
#define MAX_RECIRCULATE_COUNT 10
#define MAX_CLONE_E2E_COUNT 8

#define ETHERTYPE_VANILLA 0xf00f
#define ETHERTYPE_MAX_RESUBMIT 0xe50b
#define ETHERTYPE_MAX_RECIRCULATE 0xec14
#define ETHERTYPE_MAX_CLONE_E2E 0xce2e


header_type ethernet_t {
fields {
dstAddr : 48;
srcAddr : 48;
etherType : 16;
}
}

header_type intrinsic_metadata_t {
fields {
ingress_global_timestamp : 48;
egress_global_timestamp : 48;
lf_field_list : 8;
mcast_grp : 16;
egress_rid : 16;
resubmit_flag : 8;
recirculate_flag : 8;
}
}

header_type mymeta_t {
fields {
resubmit_count : 8;
recirculate_count : 8;
clone_e2e_count : 8;
last_ing_instance_type : 8;
f1 : 8;
}
}

header_type temporaries_t {
fields {
temp1 : 48;
}
}

header ethernet_t ethernet;
metadata intrinsic_metadata_t intrinsic_metadata;
metadata mymeta_t mymeta;
metadata temporaries_t temporaries;

parser start {
return parse_ethernet;
}

parser parse_ethernet {
extract(ethernet);
return ingress;
}

action _drop() {
drop();
}

action _nop() {
}

#define ENABLE_DEBUG_TABLE
#ifdef ENABLE_DEBUG_TABLE

//standard_metadata.egress_instance: exact;
//standard_metadata.parser_status: exact;
//standard_metadata.parser_error: exact;
//standard_metadata.clone_spec: exact;

#define DEBUG_FIELD_LIST \
standard_metadata.ingress_port: exact; \
standard_metadata.packet_length: exact; \
standard_metadata.egress_spec: exact; \
standard_metadata.egress_port: exact; \
standard_metadata.instance_type: exact; \
intrinsic_metadata.ingress_global_timestamp: exact; \
intrinsic_metadata.egress_global_timestamp: exact; \
intrinsic_metadata.lf_field_list: exact; \
intrinsic_metadata.mcast_grp: exact; \
intrinsic_metadata.egress_rid: exact; \
intrinsic_metadata.resubmit_flag: exact; \
intrinsic_metadata.recirculate_flag: exact; \
mymeta.resubmit_count: exact; \
mymeta.recirculate_count: exact; \
mymeta.clone_e2e_count: exact; \
mymeta.f1: exact; \
mymeta.last_ing_instance_type : exact; \
ethernet.dstAddr: exact; \
ethernet.srcAddr: exact; \
ethernet.etherType: exact;

table t_ing_debug_table1 {
reads { DEBUG_FIELD_LIST }
actions { _nop; }
default_action: _nop;
}

table t_ing_debug_table2 {
reads { DEBUG_FIELD_LIST }
actions { _nop; }
default_action: _nop;
}

table t_egr_debug_table1 {
reads { DEBUG_FIELD_LIST }
actions { _nop; }
default_action: _nop;
}

table t_egr_debug_table2 {
reads { DEBUG_FIELD_LIST }
actions { _nop; }
default_action: _nop;
}
#endif // ENABLE_DEBUG_TABLE

field_list resubmit_FL {
mymeta.resubmit_count;
mymeta.f1;
}

field_list recirculate_FL {
mymeta.recirculate_count;
mymeta.f1;
}

field_list clone_e2e_FL {
mymeta.clone_e2e_count;
mymeta.f1;
}

action do_resubmit() {
subtract_from_field(ethernet.srcAddr, 17);
add_to_field(mymeta.f1, 17);
add_to_field(mymeta.resubmit_count, 1);
resubmit(resubmit_FL);
}

table t_do_resubmit {
reads { }
actions { do_resubmit; }
default_action: do_resubmit;
}

action mark_max_resubmit_packet () {
modify_field(ethernet.etherType, ETHERTYPE_MAX_RESUBMIT);
}

table t_mark_max_resubmit_packet {
reads { }
actions { mark_max_resubmit_packet; }
default_action: mark_max_resubmit_packet;
}

action set_port_to_mac_da_lsbs() {
bit_and(standard_metadata.egress_spec, ethernet.dstAddr, 0xf);
}

table t_ing_mac_da {
reads { }
actions { set_port_to_mac_da_lsbs; }
default_action: set_port_to_mac_da_lsbs;
}

action save_ing_instance_type () {
modify_field(mymeta.last_ing_instance_type,
standard_metadata.instance_type);
}

table t_save_ing_instance_type {
reads { }
actions { save_ing_instance_type; }
default_action: save_ing_instance_type;
}

action ing_inc_mymeta_counts() {
add_to_field(mymeta.resubmit_count, 1);
}

table t_ing_inc_mymeta_counts {
reads { }
actions { ing_inc_mymeta_counts; }
default_action: ing_inc_mymeta_counts;
}

control ingress {
#ifdef ENABLE_DEBUG_TABLE
apply(t_ing_debug_table1);
#endif // ENABLE_DEBUG_TABLE
if (ethernet.dstAddr == MAC_DA_DO_RESUBMIT) {
if (mymeta.resubmit_count < MAX_RESUBMIT_COUNT) {
apply(t_do_resubmit);
} else {
apply(t_mark_max_resubmit_packet);
}
} else {
apply(t_ing_mac_da);
}
apply(t_save_ing_instance_type);
// The only reason this is here is to make a modification to
// metadata fields that are to be preserved for resubmitted or
// recirculated packets, to test that the value that is preserved
// is the current value _at the end of ingress processing_, not
// the value at the time that the recirculate() or resubmit()
// primitive operation is performed. The P4_14 specification says
// that the end of ingress value is what should be preserved.
apply(t_ing_inc_mymeta_counts);
#ifdef ENABLE_DEBUG_TABLE
apply(t_ing_debug_table2);
#endif // ENABLE_DEBUG_TABLE
}

action put_debug_vals_in_eth_dstaddr () {
// By copying values of selected metadata fields into the output
// packet, we enable an automated STF test that checks the output
// packet contents, to also check that the values of these
// intermediate metadata field values are also correct.
modify_field(ethernet.dstAddr, 0);
shift_left(temporaries.temp1, mymeta.resubmit_count, 40);
bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
shift_left(temporaries.temp1, mymeta.recirculate_count, 32);
bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
shift_left(temporaries.temp1, mymeta.clone_e2e_count, 24);
bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
shift_left(temporaries.temp1, mymeta.f1, 16);
bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
shift_left(temporaries.temp1, mymeta.last_ing_instance_type, 8);
bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
// TBD: Commenting out the following lines, since the value that
// they copy into the output packet may change soon, depending
// upon the resolution of this issue:
// https://github.com/p4lang/behavioral-model/issues/706
//bit_and(temporaries.temp1, standard_metadata.instance_type, 0xff);
//bit_or(ethernet.dstAddr, ethernet.dstAddr, temporaries.temp1);
}

action mark_egr_resubmit_packet () {
put_debug_vals_in_eth_dstaddr();
}

table t_egr_mark_resubmit_packet {
reads { }
actions { mark_egr_resubmit_packet; }
default_action: mark_egr_resubmit_packet;
}

action do_recirculate () {
subtract_from_field(ethernet.srcAddr, 19);
add_to_field(mymeta.f1, 19);
add_to_field(mymeta.recirculate_count, 1);
recirculate(recirculate_FL);
}

table t_do_recirculate {
reads { }
actions { do_recirculate; }
default_action: do_recirculate;
}

action mark_max_recirculate_packet () {
put_debug_vals_in_eth_dstaddr();
modify_field(ethernet.etherType, ETHERTYPE_MAX_RECIRCULATE);
}

table t_mark_max_recirculate_packet {
reads { }
actions { mark_max_recirculate_packet; }
default_action: mark_max_recirculate_packet;
}

action do_clone_e2e () {
subtract_from_field(ethernet.srcAddr, 23);
add_to_field(mymeta.f1, 23);
add_to_field(mymeta.clone_e2e_count, 1);
clone_egress_pkt_to_egress(1, clone_e2e_FL);
}

table t_do_clone_e2e {
reads { }
actions { do_clone_e2e; }
default_action: do_clone_e2e;
}

action mark_max_clone_e2e_packet () {
put_debug_vals_in_eth_dstaddr();
modify_field(ethernet.etherType, ETHERTYPE_MAX_CLONE_E2E);
}

table t_mark_max_clone_e2e_packet {
reads { }
actions { mark_max_clone_e2e_packet; }
default_action: mark_max_clone_e2e_packet;
}

action mark_vanilla_packet () {
put_debug_vals_in_eth_dstaddr();
modify_field(ethernet.etherType, ETHERTYPE_VANILLA);
}

table t_mark_vanilla_packet {
reads { }
actions { mark_vanilla_packet; }
default_action: mark_vanilla_packet;
}

action egr_inc_mymeta_counts() {
add_to_field(mymeta.recirculate_count, 1);
add_to_field(mymeta.clone_e2e_count, 1);
}

table t_egr_inc_mymeta_counts {
reads { }
actions { egr_inc_mymeta_counts; }
default_action: egr_inc_mymeta_counts;
}

control egress {
#ifdef ENABLE_DEBUG_TABLE
apply(t_egr_debug_table1);
#endif // ENABLE_DEBUG_TABLE
if (ethernet.dstAddr == MAC_DA_DO_RESUBMIT) {
// Do nothing to the packet in egress, not even marking it
// 'vanilla' as is done below.
apply(t_egr_mark_resubmit_packet);
} else if (ethernet.dstAddr == MAC_DA_DO_RECIRCULATE) {
if (mymeta.recirculate_count < MAX_RECIRCULATE_COUNT) {
apply(t_do_recirculate);
} else {
apply(t_mark_max_recirculate_packet);
}
} else if (ethernet.dstAddr == MAC_DA_DO_CLONE_E2E) {
if (mymeta.clone_e2e_count < MAX_CLONE_E2E_COUNT) {
apply(t_do_clone_e2e);
} else {
apply(t_mark_max_clone_e2e_packet);
}
} else {
apply(t_mark_vanilla_packet);
}
// This is here for the same reason that
// t_ing_inc_mymeta_counts is apply'd near the end of ingress
// processing. See comments there.
apply(t_egr_inc_mymeta_counts);
#ifdef ENABLE_DEBUG_TABLE
apply(t_egr_debug_table2);
#endif // ENABLE_DEBUG_TABLE
}
Loading

0 comments on commit 00cf6c8

Please sign in to comment.