-
Notifications
You must be signed in to change notification settings - Fork 452
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
1 parent
e42ec22
commit 00cf6c8
Showing
8 changed files
with
2,036 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.