| // 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_ |