blob: 2bdd45ab33bb993abb957f8d07befca67091a4de [file] [log] [blame]
// Copyright (c) 2017, Google Inc.
//
// P4_16 specification for packet punting behavior.
// Note: This code has not been tested and is expected to contain bugs.
#ifndef P4_SPEC_PUNT_P4_
#define P4_SPEC_PUNT_P4_
#include "headers.p4"
#include "parser.p4"
//------------------------------------------------------------------------------
// Global defines
//------------------------------------------------------------------------------
#define CPU_MIRROR_SESSION_ID 1023
// TODO(samarabdi): Make sure this is also the behavior of the v1model extern
#define METER_GREEN 0
//------------------------------------------------------------------------------
// Control Pipelines
//------------------------------------------------------------------------------
control punt(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata,
inout standard_metadata_t standard_metadata) {
@proto_package("punt")
direct_meter<bit<2>>(MeterType.bytes) ingress_port_meter;
@proto_package("punt")
direct_counter(CounterType.packets) punt_packet_counter;
@proto_package("punt")
action set_queue_and_clone_to_cpu(@proto_tag(1) bit<5> queue_id) {
local_metadata.cpu_cos_queue_id = queue_id;
local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
clone3<tuple<bit<9>>>(CloneType.I2E, CPU_MIRROR_SESSION_ID,
{standard_metadata.ingress_port});
ingress_port_meter.read(local_metadata.color);
punt_packet_counter.count();
}
@proto_package("punt")
action set_queue_and_send_to_cpu(@proto_tag(1) bit<5> queue_id) {
local_metadata.cpu_cos_queue_id = queue_id;
local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
standard_metadata.egress_spec = CPU_PORT;
ingress_port_meter.read(local_metadata.color);
punt_packet_counter.count();
}
// Combined punt table.
@proto_package("punt")
table punt_table {
key = {
standard_metadata.ingress_port: ternary @proto_tag(1);
standard_metadata.egress_spec: ternary @proto_tag(2);
hdr.ethernet.ether_type: ternary @proto_tag(3);
hdr.ipv4_base.diffserv: ternary @proto_tag(4);
hdr.ipv6_base.traffic_class: ternary @proto_tag(5);
hdr.ipv4_base.ttl: ternary @proto_tag(6);
hdr.ipv6_base.hop_limit: ternary @proto_tag(7);
hdr.ipv4_base.src_addr: ternary @proto_tag(8);
hdr.ipv4_base.dst_addr: ternary @proto_tag(9);
hdr.ipv6_base.src_addr: ternary @proto_tag(10);
hdr.ipv6_base.dst_addr: ternary @proto_tag(11);
hdr.ipv4_base.protocol: ternary @proto_tag(12);
hdr.ipv6_base.next_header: ternary @proto_tag(13);
hdr.arp.target_proto_addr: ternary @proto_tag(14);
local_metadata.icmp_code: ternary @proto_tag(15);
hdr.vlan_tag[0].vid: ternary @proto_tag(16);
hdr.vlan_tag[0].pcp: ternary @proto_tag(17);
local_metadata.class_id: ternary @proto_tag(18);
local_metadata.vrf_id: ternary @proto_tag(19);
}
actions = {
@proto_tag(1) set_queue_and_clone_to_cpu;
@proto_tag(2) set_queue_and_send_to_cpu;
}
meters = ingress_port_meter;
counters = punt_packet_counter;
}
apply {
punt_table.apply();
if(local_metadata.color != METER_GREEN) {
mark_to_drop();
}
}
} // end punt
#endif // P4_SPEC_PUNT_P4_