blob: 2bdd45ab33bb993abb957f8d07befca67091a4de [file] [log] [blame]
Carmelo Cascone9ab40612017-09-19 16:31:55 +09001// Copyright (c) 2017, Google Inc.
2//
3// P4_16 specification for packet punting behavior.
4// Note: This code has not been tested and is expected to contain bugs.
5
6#ifndef P4_SPEC_PUNT_P4_
7#define P4_SPEC_PUNT_P4_
8
9#include "headers.p4"
10#include "parser.p4"
11
12//------------------------------------------------------------------------------
13// Global defines
14//------------------------------------------------------------------------------
15
16#define CPU_MIRROR_SESSION_ID 1023
17// TODO(samarabdi): Make sure this is also the behavior of the v1model extern
18#define METER_GREEN 0
19
20//------------------------------------------------------------------------------
21// Control Pipelines
22//------------------------------------------------------------------------------
23
24control punt(inout parsed_packet_t hdr,
25 inout local_metadata_t local_metadata,
26 inout standard_metadata_t standard_metadata) {
27
28 @proto_package("punt")
29 direct_meter<bit<2>>(MeterType.bytes) ingress_port_meter;
30
31 @proto_package("punt")
32 direct_counter(CounterType.packets) punt_packet_counter;
33
34 @proto_package("punt")
35 action set_queue_and_clone_to_cpu(@proto_tag(1) bit<5> queue_id) {
36 local_metadata.cpu_cos_queue_id = queue_id;
37 local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
38 clone3<tuple<bit<9>>>(CloneType.I2E, CPU_MIRROR_SESSION_ID,
39 {standard_metadata.ingress_port});
40 ingress_port_meter.read(local_metadata.color);
41 punt_packet_counter.count();
42 }
43
44 @proto_package("punt")
45 action set_queue_and_send_to_cpu(@proto_tag(1) bit<5> queue_id) {
46 local_metadata.cpu_cos_queue_id = queue_id;
47 local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
48 standard_metadata.egress_spec = CPU_PORT;
49 ingress_port_meter.read(local_metadata.color);
50 punt_packet_counter.count();
51 }
52
53 // Combined punt table.
54 @proto_package("punt")
55 table punt_table {
56 key = {
57 standard_metadata.ingress_port: ternary @proto_tag(1);
58 standard_metadata.egress_spec: ternary @proto_tag(2);
59
60 hdr.ethernet.ether_type: ternary @proto_tag(3);
61
62 hdr.ipv4_base.diffserv: ternary @proto_tag(4);
63 hdr.ipv6_base.traffic_class: ternary @proto_tag(5);
64 hdr.ipv4_base.ttl: ternary @proto_tag(6);
65 hdr.ipv6_base.hop_limit: ternary @proto_tag(7);
66 hdr.ipv4_base.src_addr: ternary @proto_tag(8);
67 hdr.ipv4_base.dst_addr: ternary @proto_tag(9);
68 hdr.ipv6_base.src_addr: ternary @proto_tag(10);
69 hdr.ipv6_base.dst_addr: ternary @proto_tag(11);
70 hdr.ipv4_base.protocol: ternary @proto_tag(12);
71 hdr.ipv6_base.next_header: ternary @proto_tag(13);
72
73 hdr.arp.target_proto_addr: ternary @proto_tag(14);
74 local_metadata.icmp_code: ternary @proto_tag(15);
75
76 hdr.vlan_tag[0].vid: ternary @proto_tag(16);
77 hdr.vlan_tag[0].pcp: ternary @proto_tag(17);
78
79 local_metadata.class_id: ternary @proto_tag(18);
80 local_metadata.vrf_id: ternary @proto_tag(19);
81 }
82 actions = {
83 @proto_tag(1) set_queue_and_clone_to_cpu;
84 @proto_tag(2) set_queue_and_send_to_cpu;
85 }
86 meters = ingress_port_meter;
87 counters = punt_packet_counter;
88 }
89
90 apply {
91 punt_table.apply();
92 if(local_metadata.color != METER_GREEN) {
93 mark_to_drop();
94 }
95 }
96} // end punt
97
98#endif // P4_SPEC_PUNT_P4_