p4 spec v1.1 (1185620), страница 16
Текст из файла (страница 16)
method_name ( [ arg_list ] )17.5 P4 Reserved WordsThe following are reserved words in P4 and should not be used as identifiers.9actionaction_function_declarationaction_profileaction_selectoralgorithmandapplyattributeattributesbitbytesbytes_and_packetscalculated_fieldcontrolcounterdirectdynamic_action_selection9There is an open issue whether all P4 keywords will in fact be reserved.9517.5 P4 Reserved Words17 APPENDICESelseexternextern_typeextractfalsefield_listfield_list_calculationfieldsheaderheader_typehitifininoutinputinstance_countintlastlayoutmaskmaxmetadatametermethodminmin_widthmissnextnotoptionaloroutput_widthpacketsparse_errorparserparser_dropparser_exceptionparser_value_setprimitive_action_declarationrangeregisterresult9617.6 Examples17 APPENDICESreturnsaturatingselectselection_keyset_metadatasignedstatictabletrueupdatevalidvarbitverifywidth17.6 Examples17.6.1 The Annotated mTag ExampleThis section presents the mTag example.
The example describes two separate P4 programs, mtag-edge and mtag-aggregation, as described in the introduction in Section 1.2.The code is written in P4 whose syntax allows the application of a C preprocessor to P4files. Thus directives such as #define and #include are used in the program with thesame effects as if writing C code.
This is a convention used by these examples; the P4language does not mandate this syntax.The example code is split into the following files• headers.p4: The declaration of all header types used in both programs.• parser.p4: The parser program shared by both programs.• actions.p4: Common actions used by both programs.• mtag-edge.p4: The main program for the edge switch• mtag-aggregation.p4: The main program for any aggregation switchThe full source for all files is provided on the P4 website [2].We start with header.p4.////////////////////////////////////////////////////////////////// Header type definitions////////////////////////////////////////////////////////////////9717.6 Examples17 APPENDICES// Standard L2 Ethernet headerheader_type ethernet_t {fields {bit<48> dst_addr;bit<48> src_addr;bit<16> ethertype;}}// Standard VLAN tagheader_type vlan_t {fields {bit<3>pcp;bitcfi;bit<12> vid;bit<16> ethertype;}}// The special m-tag used to control forwarding through the// aggregation layer ofdata centerheader_type mTag_t {fields {bit<8>up1;bit<8>up2;bit<8>down1;bit<8>down2;bit<16> ethertype;}}// Standard IPv4 headerheader_type ipv4_t {fields {bit<4> version;bit<4> ihl;bit<8> diffserv;bit<16> totalLen;bit<16> identification;bit<3> flags;bit<13> fragOffset;bit<8> ttl;9817.6 Examples17 APPENDICESbit<8> protocol;bit<16> hdrChecksum;bit<32> srcAddr;bit<32> dstAddr;varbit<320> options;}length : ihl * 4;}// Assume standard metadata from compiler.// Define local metadata here.//// copy_to_cpu is an example of target specific intrinsic metadata// It has special significance to the target resulting in a// copy of the packet being forwarded to the management CPU.header_type local_metadata_t {fields {bit<16> cpu_code// Code for packet going to CPUbit<4> port_type// Type of port: up, down, local...bit ingress_error// An error in ingress port checkbit was_mtagged// Track if pkt was mtagged on ingrbit copy_to_cpu// Special code resulting in copy to CPUbit bad_packet// Other error indicationbit<8> color// For metering}}The parser function shared by the programs is as follows.////////////////////////////////////////////////////////////////// Parser functions and related definitions////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Header instance definitions//// Header instances are usually defined with the parser as// that is where they are initialized.//////////////////////////////////////////////////////////////////9917.6 Examples17 APPENDICESheader ethernet_t ethernet;header vlan_t vlan;header mTag_t mtag;header ipv4_t ipv4;// Local metadata instance declarationmetadata local_metadata_t local_metadata;////////////////////////////////////////////////////////////////// Parser state machine description////////////////////////////////////////////////////////////////// Start with ethernet always.parser start {return ethernet;}parser ethernet {extract(ethernet);// Start with the ethernet headerreturn select(latest.ethertype) {0x8100:vlan;0x800:ipv4;default:ingress;}}// Extract the VLAN tag and check for an mTagparser vlan {extract(vlan);return select(latest.ethertype) {0xaaaa:mtag;0x800:ipv4;default:ingress;}}// mTag is allowed after a VLAN tag only (see above)parser mtag {extract(mtag);return select(latest.ethertype) {0x800:ipv4;10017.6 Examplesdefault:17 APPENDICESingress;}}parser ipv4 {extract(ipv4);return ingress;// All done with parsing; start matching}Here are the common actions for the two programs.//////////////////////////////////////////////////////////////////// actions.p4//// This file defines the common actions that can be exercised by// either an edge or an aggregation switch.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Actions used by tables////////////////////////////////////////////////////////////////// Copy the packet to the CPU;action common_copy_pkt_to_cpu(in bit<8> cpu_code, in bit bad_packet) {modify_field(local_metadata.copy_to_cpu, 1);modify_field(local_metadata.cpu_code, cpu_code);modify_field(local_metadata.bad_packet, bad_packet);}// Drop the packet; optionally send to CPU and mark badaction common_drop_pkt(in bit do_copy, in bit<8> cpu_code, in bit bad_packet) {modify_field(local_metadata.copy_to_cpu, do_copy);modify_field(local_metadata.cpu_code, cpu_code);modify_field(local_metadata.bad_packet, bad_packet);drop();}// Set the port type; see run time mtag_port_type.// Allow error indication.action common_set_port_type(in bit<4> port_type, in bit ingress_error) {10117.6 Examples17 APPENDICESmodify_field(local_metadata.port_type, port_type);modify_field(local_metadata.ingress_error, ingress_error);}Here are excerpts from the edge program.//////////////////////////////////////////////////////////////////// mtag-edge.p4//// This file defines the behavior of the edge switch in an mTag// example.////////////////////////////////////////////////////////////////////// Include the header definitions and parser// (with header instances)#include "headers.p4"#include "parser.p4"#include "actions.p4"// For actions marked "common_"#define PORT_COUNT 64// Total ports in the switch////////////////////////////////////////////////////////////////// Table definitions////////////////////////////////////////////////////////////////// Remove the mtag for local processing/switchingaction _strip_mtag() {// Strip the tag from the packet...remove_header(mtag);// but keep state that it was mtagged.modify_field(local_metadata.was_mtagged, 1);}// Always strip the mtag if present on the edge switchtable strip_mtag {reads {mtag: valid; // Was mtag parsed?}actions {10217.6 Examples17 APPENDICES_strip_mtag;// Strip mtag and record metadatano_op;// Pass thru otherwise}}////////////////////////////////////////////////////////////////// Identify ingress port: local, up1, up2, down1, down2table identify_port {reads {standard_metadata.ingress_port : exact;}actions { // Each table entry specifies *one* actioncommon_set_port_type;common_drop_pkt;no_op;// If unknown port// Allow packet to continue}max_size : 64; // One rule per port}.
. .// Removed code related to local switching// Add an mTag to the packet; select egress spec based on up1action add_mTag(in bit<8> up1, in bit<8> up2,in bit<8> down1, in bit<8> down2) {add_header(mtag);// Copy VLAN ethertype to mTagmodify_field(mtag.ethertype, vlan.ethertype);// Set VLAN’s ethertype to signal mTagmodify_field(vlan.ethertype, 0xaaaa);// Add the tag source routing informationmodify_field(mtag.up1, up1);modify_field(mtag.up2, up2);modify_field(mtag.down1, down1);modify_field(mtag.down2, down2);// Set the destination egress port as well from the tag infomodify_field(standard_metadata.egress_spec, up1);}10317.6 Examples17 APPENDICES// Count packets and bytes by mtag instance addedcounter pkts_by_dest {type : packets;direct : mTag_table;}counter bytes_by_dest {type : bytes;direct : mTag_table;}// Check if the packet needs an mtag and add one if it does.table mTag_table {reads {ethernet.dst_addr: exact;vlan.vid: exact;}actions {add_mTag;// Action called if pkt needs an mtag.// Option: If no mtag setup, forward to the CPUcommon_copy_pkt_to_cpu;no_op;}max_size: 20000;}// Packets from agg layer must stay local; enforce that heretable egress_check {reads {standard_metadata.ingress_port : exact;local_metadata.was_mtagged : exact;}actions {common_drop_pkt;no_op;}max_size : PORT_COUNT; // At most one rule per port}// Egress metering; this could be direct, but we let SW// use whatever mapping it might like to associate the10417.6 Examples17 APPENDICES// meter cell with the source/dest pairmeter per_dest_by_source {type : bytes;result : local_metadata.color;instance_count : PORT_COUNT * PORT_COUNT;// Per source/dest pair}action meter_pkt(in int<12> meter_idx) {execute_meter(per_dest_by_source, meter_idx, local_metadata.color);}// Mark packet color, for uplink ports onlytable egress_meter {reads {standard_metadata.ingress_port : exact;mtag.up1 : exact;}actions {meter_pkt;no_op;}size : PORT_COUNT * PORT_COUNT;// Could be smaller}// Apply meter policycounter per_color_drops {type : packets;direct : meter_policy;}table meter_policy {reads {metadata.ingress_port : exact;local_metadata.color : exact;}actions {drop; // Automatically counted by direct counter aboveno_op;}size : 4 * PORT_COUNT;}10517.6 Examples17 APPENDICES////////////////////////////////////////////////////////////////// Control function definitions////////////////////////////////////////////////////////////////// The ingress control functioncontrol ingress {// Always strip mtag if present, save stateapply(strip_mtag);// Identify the source port typeapply(identify_port);// If no error from source_check, continueif (local_metadata.ingress_error == 0) {// Attempt to switch to end hostsapply(local_switching); // not shown; matches on dest addr// If not locally switched, try to setup mtagif (standard_metadata.egress_spec == 0) {apply(mTag_table);}}}// The egress control functioncontrol egress {// Check for unknown egress state or bad retagging with mTag.apply(egress_check);// Apply egress_meter table; if hit, apply meter policyapply(egress_meter) {hit {apply(meter_policy);}}}The key table for mtag-aggregation is shown below.////////////////////////////////////////////////////////////////10617.6 Examples17 APPENDICES//// mtag-aggregation.p4//////////////////////////////////////////////////////////////////// Include the header definitions and parser (with header instances)#include "headers.p4"#include "parser.p4"#include "actions.p4"// For actions marked "common_"////////////////////////////////////////////////////////////////// check_mtag table://Make sure pkt has mtag; Apply drop or to-cpu policy if not////////////////////////////////////////////////////////////////table check_mtag { // Statically programmed w/ one entry.