├── LICENSE ├── README.md ├── figures ├── grafana-example-2.png ├── grafana-example.png ├── hardware_topo.png ├── int-md.png ├── int-mx.png └── int-xd.png ├── int-md-1-0 ├── README.md ├── bfrt_python │ ├── bfswitch1.py │ ├── bfswitch2.py │ └── bfswitch3.py ├── int_telemetry_report.lua └── p4src │ ├── int │ ├── forward.p4 │ ├── headers.p4 │ ├── parsers.p4 │ ├── sink.p4 │ ├── source.p4 │ └── transit.p4 │ └── int_md_1_0.p4 ├── int-md-2-1 ├── README.md ├── bfrt_python │ ├── bfswitch1.py │ ├── bfswitch2.py │ └── bfswitch3.py └── p4src │ ├── int │ ├── forward.p4 │ ├── headers.p4 │ ├── parsers.p4 │ ├── sink.p4 │ ├── source.p4 │ └── transit.p4 │ └── int_md_2_1.p4 ├── int-mx ├── README.md ├── bfrt_python │ ├── bfswitch1.py │ ├── bfswitch2.py │ └── bfswitch3.py └── p4src │ ├── int │ ├── forward.p4 │ ├── headers.p4 │ ├── parsers.p4 │ ├── sink.p4 │ ├── source.p4 │ └── transit.p4 │ └── int_mx.p4 └── int-xd ├── README.md ├── bfrt_python ├── bfswitch1.py ├── bfswitch2.py └── bfswitch3.py └── p4src ├── int ├── forward.p4 ├── headers.p4 ├── parsers.p4 ├── sink.p4 ├── source.p4 └── transit.p4 └── int_xd.p4 /README.md: -------------------------------------------------------------------------------- 1 | # In-Band Network Telemetry Implementation in P4 2 | 3 | **A Prototype Implementation of INT Modes of Operation** 4 | 5 | This project implements the three INT modes of operations as specified in the specifications of [INT v2.1](https://github.com/p4lang/p4-applications/blob/master/docs/INT_v2_1.pdf). INT v2.1 is used, and INT-MD is implemented for INT v1.0 as well. 6 | 7 | The code was tested on `Stordis BF6064X-T` Tofino switches, running SDE version `9.4.0` using `Ubuntu 18.04.5 LTS`. The program used to generate traffic was `TRex`. 8 | 9 | A more detailed description about the tested topology and setup with `TRex` and `INTCollector` can be found in the INT-MD 1.0 directory. 10 | 11 | The p4 programs for the INT-MX and INT-XD are the same, the only difference being the tables that are run on the switches. 12 | 13 | ## Build 14 | 15 | The P4 code can be compiled by using the build script in the SDE, for instance 16 | ``` 17 | ./p4_build.sh int_mx.p4 18 | ``` 19 | 20 | Additional information is provided in the folders for each mode of operation: [INT-MD 1.0](int-md-1-0/README.md), [INT-MD 2.1](int-md-2-1/README.md), [INT-MX](int-mx/README.md) and [INT-XD](int-xd/README.md). Each folder also contains the topology used. 21 | 22 | ## Usage 23 | 24 | Run the P4 code as follows, for example: 25 | ``` 26 | $SDE/run_switchd.sh -p int_mx 27 | ``` 28 | If running with the Tofino model, first run: 29 | ``` 30 | $SDE/run_tofino_model.sh -p int_mx 31 | ``` 32 | 33 | ## Limitations 34 | 35 | The following features have not been implemented: 36 | - Domain namespaces 37 | - Drop reports 38 | 39 | ## Authors 40 | 41 | - Mandar Joshi, Saab/KTH 42 | 43 | ## License 44 | 45 | This project is distributed using GNU GPLv2, see [LICENSE](LICENSE). 46 | -------------------------------------------------------------------------------- /figures/grafana-example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/grafana-example-2.png -------------------------------------------------------------------------------- /figures/grafana-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/grafana-example.png -------------------------------------------------------------------------------- /figures/hardware_topo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/hardware_topo.png -------------------------------------------------------------------------------- /figures/int-md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/int-md.png -------------------------------------------------------------------------------- /figures/int-mx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/int-mx.png -------------------------------------------------------------------------------- /figures/int-xd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandaryoshi/p4-int/3a9e9e5b2686bd7c2c1b98cd8946fcb83abde55d/figures/int-xd.png -------------------------------------------------------------------------------- /int-md-1-0/README.md: -------------------------------------------------------------------------------- 1 | # In-Band Network Telemetry Implementation in P4 2 | 3 | **INT-MD - eMbed Data (version 1.0)** 4 | 5 | ## Build 6 | 7 | The P4 code can be compiled by using the build script in the SDE 8 | ``` 9 | ./p4_build.sh int_md_1_0.p4 10 | ``` 11 | 12 | The following topology can be referred to for the INT-MD mode of operation: 13 | ![INT-MD](../figures/int-md.png) 14 | 15 | ## Usage 16 | 17 | Run the P4 code as follows 18 | ``` 19 | $SDE/run_switchd.sh -p int_md_1_0 20 | ``` 21 | 22 | ### Populating the tables and registers 23 | 24 | In another window for each switch, the following command can be run depending on the role of the INT node 25 | ``` 26 | $SDE/run_bfshell.sh -b $P4-INT/int-md-1-0/bfrt_python/bfswitch1.py 27 | ``` 28 | 29 | ### Testing the INT program 30 | 31 | Packets can be sent from server1, and tcpdump/wireshark can be used to see the output at the monitoring server and the receiver. The wireshark script in the folder can be used to dissect INT data in wireshark. Launch this with 32 | ``` 33 | $ wireshark -X lua_script:int_telemetry_report.lua 34 | ``` 35 | 36 | ### Hardware Setup 37 | 38 | The hardware setup with the two servers and three switches can be seen in the following figure. 39 | ![Hardware setup](../figures/hardware_topo.png) 40 | 41 | 42 | ### TRex 43 | 44 | The [TRex](https://trex-tgn.cisco.com/) program was used to generate traffic in order to test the INT implementation. TRex v2.87 was used as a [GUI](https://github.com/cisco-system-traffic-generator/trex-stateless-gui) was available for this version. The stateless mode of TRex was used. 45 | 46 | These were the steps used to install and run TRex, latest version: 47 | * Download TRex 48 | ``` 49 | [bash]>wget --no-cache https://trex-tgn.cisco.com/trex/release/latest 50 | [bash]>tar -xzvf latest 51 | ``` 52 | * Identify and assign ports. The NIC used in this case was the Intel XXV710. This script lists available interfaces, and it is used to create a TRex config file. 53 | ``` 54 | [bash]>sudo ./dpdk_setup_ports.py -i 55 | ``` 56 | * Once configured, TRex stateless mode can be run on both servers, sender and listener. The -c flag determines how many cores shall be utilised. 57 | ``` 58 | ./t-rex-64 -i -c 4 59 | ``` 60 | * On another window, the TRex console can be run and used to send and receive data. `tui` can be used to launch a user interface 61 | ``` 62 | ./trex-console 63 | tui 64 | ``` 65 | * Example to send data from the sender, packets should be captured on the receiver 66 | ``` 67 | start -f stl/udp_1pkt_simple.py -p 1 -d 10 -m 10kbps 68 | ``` 69 | 70 | 71 | ### INTCollector 72 | 73 | With this mode of operation, traffic can be analysed visually using [INTCollector](https://gitlab.com/tunv_ebpf/BPFCollector/). Install this as per the instructions in the repository. This implementation has been tested with Linux kernel `4.15` using Ubuntu 18.04, it has not been updated for more recent kernels. The InfluxDB implementation was used, along with Grafana. Examples of output from this program can be seen in the Figures below. 74 | 75 | * Install bcc 76 | ``` 77 | # Install build dependencies - For Bionic (18.04 LTS) 78 | sudo apt-get -y install bison build-essential cmake flex git libedit-dev \ 79 | libllvm6.0 llvm-6.0-dev libclang-6.0-dev python zlib1g-dev libelf-dev libfl-dev 80 | 81 | # Install and compile BCC 82 | git clone https://github.com/iovisor/bcc.git 83 | mkdir bcc/build; cd bcc/build 84 | cmake .. 85 | make 86 | sudo make install 87 | cmake -DPYTHON_CMD=python3 .. # build python3 binding 88 | pushd src/python/ 89 | make 90 | sudo make install 91 | popd 92 | ``` 93 | * Clone INTCollector repo 94 | ``` 95 | git clone https://gitlab.com/tunv_ebpf/BPFCollector.git 96 | ``` 97 | * Install requirements 98 | ``` 99 | sudo pip3 install -r requirements.txt 100 | ``` 101 | * Install InfluxDB 102 | ``` 103 | wget https://dl.influxdata.com/influxdb/releases/influxdb_1.2.4_amd64.deb 104 | sudo dpkg -i influxdb_1.2.4_amd64.deb 105 | sudo systemctl start influxdb 106 | ``` 107 | * Install [Grafana](https://grafana.com/docs/grafana/latest/installation/debian/) 108 | ``` 109 | sudo apt-get install -y apt-transport-https 110 | sudo apt-get install -y software-properties-common wget 111 | wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - 112 | echo "deb https://packages.grafana.com/enterprise/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list 113 | sudo apt-get update 114 | sudo apt-get install grafana-enterprise 115 | sudo systemctl start grafana-server 116 | ``` 117 | * Example to run INTCollector for a port that listens to telemetry reports. 118 | ``` 119 | sudo python3 InDBClient.py eth_1 120 | ``` 121 | 122 | * Some fields in INTCollector can be changed 123 | ``` 124 | * Debug flags can be set in InDBCollector.pyx and InDBClient.py. 125 | * The mode between Interval and Threshold can be changed in these files. 126 | * The threshold and interval values can be changed in the BPFCollector.c file. 127 | ``` 128 | 129 | ![Example 1](../figures/grafana-example.png) 130 | ![Example 2](../figures/grafana-example-2.png) 131 | -------------------------------------------------------------------------------- /int-md-1-0/bfrt_python/bfswitch1.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=7) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=5) 5 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source_dscp(dst_addr="10.0.2.2", dst_addr_p_length=32, hop_metadata_len=16, remaining_hop_cnt=3, ins_mask0003=15, ins_mask0407=15) 6 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=1) -------------------------------------------------------------------------------- /int-md-1-0/bfrt_python/bfswitch2.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=11) 4 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=2) -------------------------------------------------------------------------------- /int-md-1-0/bfrt_python/bfswitch3.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=10) 4 | p4.MyIngress.process_int_source_sink.tb_set_sink.add_with_int_set_sink(ucast_egress_port=10) 5 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=10) 6 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=3) 7 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="127.0.0.1", mon_mac="02:42:ac:1c:00:02", mon_port="54321", src_ip="172.26.0.2", src_mac="02:42:ac:1c:00:03") 8 | 9 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=9, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/forward.p4: -------------------------------------------------------------------------------- 1 | // Simple action to forward the packet based on the ipv4 destination address 2 | control port_forward(inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md, 5 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 6 | 7 | action send_to_cpu() { 8 | ig_tm_md.ucast_egress_port = CPU_PORT; 9 | } 10 | 11 | action set_egress_port(port_t port) { 12 | ig_tm_md.ucast_egress_port = port; 13 | } 14 | 15 | action drop() { 16 | ig_dprsr_md.drop_ctl = 1; 17 | } 18 | 19 | table tb_port_forward { 20 | key = { 21 | hdr.ipv4.dst_addr : lpm; 22 | } 23 | actions = { 24 | set_egress_port; 25 | send_to_cpu; 26 | drop; 27 | } 28 | const default_action = drop(); 29 | } 30 | 31 | apply { 32 | tb_port_forward.apply(); 33 | } 34 | } -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ************* C O N S T A N T S A N D T Y P E S ******************* 3 | **************************************************************************/ 4 | 5 | #define MAX_INT_HEADERS 9 6 | #define MAX_HOP_COUNT 3 7 | #define NUM_INSTRUCTIONS 3 8 | 9 | #define ETH_TYPE_IPV4 0x0800 10 | #define IP_VERSION_4 4w4 11 | #define MAX_PORTS 511 12 | #define IPV4_IHL_MIN 4w5 13 | 14 | #ifndef _BOOL 15 | #define _BOOL bool 16 | #endif 17 | #ifndef _TRUE 18 | #define _TRUE true 19 | #endif 20 | #ifndef _FALSE 21 | #define _FALSE false 22 | #endif 23 | 24 | // 1 --> 2 --> 3 Switch hardware ID. This has to be changed depending on the switch 25 | const bit<6> HW_ID = 1; 26 | 27 | // Make this dynamic depending on UDP/IP Header 28 | // This field determines the size of the payload (in bits) that is skipped in order to send telemetry reports without payload data 29 | const bit<32> PACKET_ADVANCE = 40; 30 | 31 | const bit<16> TYPE_IPV4 = 0x0800; 32 | const bit<8> IP_PROTO_UDP = 0x11; 33 | const bit<8> IP_PROTO_TCP = 0x6; 34 | const bit<16> INT_PORT = 5000; 35 | 36 | // These fields need to be made dependent on values in the INT header to determine the length of the packet 37 | const bit<16> SHIM_LEN = 84; // SHIM LEN is INT_DATA_LEN - 8. Change for different bitmap. for 64 bits -> 28 38 | const bit<16> INT_DATA_LEN = 120; // SHIM LEN + 8 for 64 bits -> 36 39 | 40 | const bit<6> DSCP_INT = 0x17; 41 | const bit<6> DSCP_MASK = 0x3F; 42 | const bit<8> HOP_1 = 0x1A; 43 | const bit<8> HOP_2 = 0xC; 44 | const bit<6> DSCP_IP = 0x5c; 45 | 46 | typedef bit<48> mac_t; 47 | typedef bit<32> ip_address_t; 48 | typedef bit<16> l4_port_t; 49 | typedef bit<9> port_t; 50 | typedef bit<16> next_hop_id_t; 51 | 52 | const bit<8> INT_HEADER_LEN_WORD = 3; 53 | const bit<8> REPORT_HDR_TTL = 64; 54 | const port_t CPU_PORT = 255; 55 | 56 | const bit<3> NPROTO_ETHERNET = 0; 57 | const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1; 58 | const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2; 59 | 60 | const bit<5> IPV4_OPTION_INT = 31; 61 | 62 | // Mirroring defs 63 | typedef bit<3> mirror_type_t; 64 | typedef bit<8> pkt_type_t; 65 | 66 | const mirror_type_t MIRROR_TYPE_I2E = 1; 67 | const mirror_type_t MIRROR_TYPE_E2E = 2; 68 | const pkt_type_t PKT_TYPE_NORMAL = 1; 69 | const pkt_type_t PKT_TYPE_MIRROR = 2; 70 | 71 | typedef bit<32> switch_id_t; 72 | typedef bit<48> timestamp_t; 73 | typedef bit<6> output_port_t; 74 | 75 | /************************************************************************* 76 | *********************** H E A D E R S *********************************** 77 | *************************************************************************/ 78 | 79 | header ethernet_t { 80 | bit<48> dst_addr; 81 | bit<48> src_addr; 82 | bit<16> ether_type; 83 | } 84 | 85 | const bit<8> ETH_HEADER_LEN = 14; 86 | 87 | header ipv4_t { 88 | bit<4> version; 89 | bit<4> ihl; 90 | bit<6> dscp; 91 | bit<2> ecn; 92 | bit<16> len; 93 | bit<16> identification; 94 | bit<3> flags; 95 | bit<13> frag_offset; 96 | bit<8> ttl; 97 | bit<8> protocol; 98 | bit<16> hdr_checksum; 99 | bit<32> src_addr; 100 | bit<32> dst_addr; 101 | } 102 | 103 | const bit<8> IPV4_MIN_HEAD_LEN = 20; 104 | 105 | 106 | header udp_t { 107 | bit<16> src_port; 108 | bit<16> dst_port; 109 | bit<16> length_; 110 | bit<16> checksum; 111 | } 112 | const bit<8> UDP_HEADER_LEN = 8; 113 | 114 | 115 | header tcp_t { 116 | bit<16> src_port; 117 | bit<16> dst_port; 118 | bit<32> seq_no; 119 | bit<32> ack_no; 120 | bit<4> data_offset; 121 | bit<3> res; 122 | bit<3> ecn; 123 | bit<6> ctrl; 124 | bit<16> window; 125 | bit<16> checksum; 126 | bit<16> urgent_ptr; 127 | } 128 | 129 | const bit<8> TCP_HEADER_LEN = 20; 130 | 131 | // INT shim header for TCP/UDP 132 | header intl4_shim_t { 133 | bit<8> int_type; 134 | bit<8> rsvd1; 135 | bit<8> len; 136 | bit<6> dscp; 137 | bit<2> rsvd2; 138 | } 139 | 140 | const bit<16> INT_SHIM_HEADER_SIZE = 4; 141 | 142 | // INT header 143 | header int_header_t { 144 | bit<4> ver; 145 | bit<2> rep; 146 | bit<1> c; 147 | bit<1> e; 148 | bit<1> m; 149 | bit<7> rsvd1; 150 | bit<3> rsvd2; 151 | bit<5> hop_metadata_len; 152 | bit<8> remaining_hop_cnt; 153 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 154 | bit<4> instruction_mask_0407; 155 | bit<4> instruction_mask_0811; 156 | bit<4> instruction_mask_1215; 157 | bit<16> rsvd3; 158 | } 159 | 160 | const bit<16> INT_HEADER_SIZE = 8; 161 | 162 | const bit<16> INT_TOTAL_HEADER_SIZE = INT_HEADER_SIZE + INT_SHIM_HEADER_SIZE; 163 | 164 | 165 | // INT meta-value headers - different header for each value type 166 | header int_switch_id_t { 167 | bit<32> switch_id; 168 | } 169 | header int_level1_port_ids_t { 170 | bit<16> ingress_port_id; 171 | bit<16> egress_port_id; 172 | } 173 | header int_hop_latency_t { 174 | bit<32> hop_latency; 175 | } 176 | header int_q_occupancy_t { 177 | bit<8> q_id; 178 | bit<24> q_occupancy; 179 | } 180 | header int_ingress_tstamp_t { 181 | bit<32> ingress_tstamp; 182 | } 183 | header int_egress_tstamp_t { 184 | bit<32> egress_tstamp; 185 | } 186 | header int_level2_port_ids_t { 187 | bit<32> ingress_port_id; 188 | bit<32> egress_port_id; 189 | } 190 | header int_egress_port_tx_util_t { // queueing latency 191 | bit<32> egress_port_tx_util; 192 | } 193 | 194 | header int_data_t { 195 | // varbit data; 196 | // change this depending on the INT data embedded, 576 = 2 hops of all metadata. 128 = 2 hops of 64 bit metadata. 197 | // 8 --> 288 --> 576 198 | // currently this is only needed for the last switch to extract necessary int metadata 199 | bit<576> data; 200 | } 201 | 202 | 203 | // Report Telemetry Headers 204 | header report_fixed_header_t { 205 | bit<4> ver; 206 | bit<4> len; 207 | bit<3> nproto; 208 | bit<6> rep_md_bits; 209 | bit<6> rsvd; 210 | bit<3> d_q_f; 211 | bit<6> hw_id; 212 | bit<32> sw_id; 213 | bit<32> seq_no; 214 | bit<32> ingress_tstamp; 215 | } 216 | const bit<8> REPORT_FIXED_HEADER_LEN = 16; 217 | 218 | // Switch Local Report Header 219 | header local_report_header_t { 220 | bit<32> switch_id; 221 | bit<16> ingress_port_id; 222 | bit<16> egress_port_id; 223 | bit<32> queue_id; 224 | bit<24> queue_occupancy; 225 | //bit<32> egress_tstamp; 226 | bit<48> ingress_global_tstamp; 227 | bool sink; 228 | bool do_report; 229 | bit<6> pad; 230 | pkt_type_t pkt_type; 231 | bit<16> int_shim_len; 232 | } 233 | const bit<8> LOCAL_REPORT_HEADER_LEN = 16; 234 | 235 | header mirror_h { 236 | pkt_type_t pkt_type; 237 | bit<16> ingress_port_id; 238 | bit<32> queue_id; 239 | bit<48> ingress_global_tstamp; 240 | } 241 | 242 | struct headers { 243 | 244 | // Original Packet Headers 245 | ethernet_t ethernet; 246 | ipv4_t ipv4; 247 | udp_t udp; 248 | tcp_t tcp; 249 | 250 | // INT Report Encapsulation 251 | ethernet_t report_ethernet; 252 | ipv4_t report_ipv4; 253 | udp_t report_udp; 254 | 255 | // INT Headers 256 | int_header_t int_header; 257 | intl4_shim_t intl4_shim; 258 | int_data_t int_data; 259 | int_switch_id_t int_switch_id; 260 | int_level1_port_ids_t int_level1_port_ids; 261 | int_hop_latency_t int_hop_latency; 262 | int_q_occupancy_t int_q_occupancy; 263 | int_ingress_tstamp_t int_ingress_tstamp; 264 | int_egress_tstamp_t int_egress_tstamp; 265 | int_level2_port_ids_t int_level2_port_ids; 266 | int_egress_port_tx_util_t int_egress_tx_util; 267 | 268 | // // INT Report Headers 269 | report_fixed_header_t report_fixed_header; 270 | local_report_header_t local_report_header; 271 | 272 | mirror_h mirror_header; 273 | } 274 | 275 | struct int_metadata_t { 276 | switch_id_t switch_id; 277 | bit<16> new_bytes; 278 | bit<8> new_words; 279 | bool source; 280 | bool sink; 281 | bool transit; 282 | bit<8> intl4_shim_len; 283 | bit<16> int_shim_len; 284 | } 285 | 286 | struct local_metadata_t { 287 | bit<16> l4_src_port; 288 | bit<16> l4_dst_port; 289 | int_metadata_t int_meta; 290 | bool mirror; 291 | pkt_type_t pkt_type; 292 | MirrorId_t ing_mir_ses; // Ingress mirror session ID 293 | MirrorId_t egr_mir_ses; // Egress mirror session ID 294 | } 295 | -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/parsers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** P A R S E R ******************************* 3 | *************************************************************************/ 4 | 5 | parser MyIngressParser(packet_in packet, 6 | out headers hdr, 7 | out local_metadata_t local_metadata, 8 | out ingress_intrinsic_metadata_t ig_intr_md) { 9 | 10 | state start { 11 | packet.extract(ig_intr_md); 12 | packet.advance(PORT_METADATA_SIZE); 13 | transition parse_ethernet; 14 | } 15 | 16 | state parse_ethernet { 17 | packet.extract(hdr.ethernet); 18 | transition select(hdr.ethernet.ether_type) { 19 | TYPE_IPV4: parse_ipv4; 20 | default: accept; 21 | } 22 | } 23 | 24 | state parse_ipv4 { 25 | packet.extract(hdr.ipv4); 26 | transition select(hdr.ipv4.protocol) { 27 | IP_PROTO_UDP: parse_udp; 28 | IP_PROTO_TCP: parse_tcp; 29 | default: accept; 30 | } 31 | } 32 | 33 | state parse_udp { 34 | packet.extract(hdr.udp); 35 | local_metadata.l4_src_port = hdr.udp.src_port; 36 | local_metadata.l4_dst_port = hdr.udp.dst_port; 37 | transition select(hdr.ipv4.dscp) { 38 | DSCP_INT &&& DSCP_MASK: parse_shim; 39 | default: accept; 40 | } 41 | } 42 | 43 | state parse_tcp { 44 | packet.extract(hdr.tcp); 45 | local_metadata.l4_src_port = hdr.tcp.src_port; 46 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 47 | transition select(hdr.ipv4.dscp) { 48 | DSCP_INT &&& DSCP_MASK: parse_shim; 49 | default: accept; 50 | } 51 | } 52 | 53 | state parse_shim { 54 | packet.extract(hdr.intl4_shim); 55 | transition parse_int_hdr; 56 | } 57 | 58 | state parse_int_hdr { 59 | packet.extract(hdr.int_header); 60 | transition parse_int_data; 61 | } 62 | 63 | // Need to parse INT data here, but the length of the field needs to be known by looking at the shim header 64 | state parse_int_data { 65 | //, ((bit<32>) (local_metadata.int_meta.intl4_shim_len - INT_HEADER_LEN_WORD)) << 5 66 | // because of int data from previous switches 67 | // bit<8> int_hdr_len_in_words = (bit<8>)(INT_TOTAL_HEADER_SIZE)>>2; 68 | // bit<32> int_data_len_in_words = (bit<32>)(hdr.intl4_shim.len - int_hdr_len_in_words); 69 | // bit<32> int_data_len_in_bits = int_data_len_in_words << 5; 70 | // , ((bit<32>)(hdr.intl4_shim.len - (bit<8>)(INT_TOTAL_HEADER_SIZE)>>2) << 5) 71 | 72 | //packet.extract(hdr.int_data); 73 | transition accept; 74 | } 75 | } 76 | 77 | /************************************************************************* 78 | ************ C H E C K S U M V E R I F I C A T I O N ************* 79 | *************************************************************************/ 80 | 81 | control MyIngressDeparser(packet_out packet, 82 | inout headers hdr, 83 | in local_metadata_t local_metadata, 84 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 85 | 86 | 87 | Mirror() mirror; 88 | 89 | apply { 90 | 91 | if(ig_dprsr_md.mirror_type == 3w1) { 92 | mirror.emit(local_metadata.ing_mir_ses, {local_metadata.pkt_type, hdr.local_report_header.ingress_port_id, hdr.local_report_header.queue_id,hdr.local_report_header.ingress_global_tstamp}); 93 | } 94 | 95 | packet.emit(hdr.local_report_header); 96 | packet.emit(hdr.ethernet); 97 | packet.emit(hdr.ipv4); 98 | packet.emit(hdr.udp); 99 | packet.emit(hdr.tcp); 100 | 101 | packet.emit(hdr.intl4_shim); 102 | packet.emit(hdr.int_header); 103 | packet.emit(hdr.int_switch_id); 104 | packet.emit(hdr.int_level1_port_ids); 105 | packet.emit(hdr.int_hop_latency); 106 | packet.emit(hdr.int_q_occupancy); 107 | packet.emit(hdr.int_ingress_tstamp); 108 | packet.emit(hdr.int_egress_tstamp); 109 | packet.emit(hdr.int_level2_port_ids); 110 | packet.emit(hdr.int_egress_tx_util); 111 | 112 | packet.emit(hdr.int_data); 113 | 114 | } 115 | } 116 | 117 | 118 | /************************************************************************* 119 | **************** E G R E S S P R O C E S S I N G ******************* 120 | *************************************************************************/ 121 | 122 | parser MyEgressParser(packet_in packet, 123 | out headers hdr, 124 | out local_metadata_t local_metadata, 125 | out egress_intrinsic_metadata_t eg_intr_md) { 126 | 127 | state start { 128 | packet.extract(eg_intr_md); 129 | transition parse_metadata; 130 | } 131 | 132 | state parse_metadata { 133 | mirror_h mirror_md = packet.lookahead(); 134 | transition select(mirror_md.pkt_type) { 135 | PKT_TYPE_MIRROR : parse_mirror_md; 136 | default : parse_ethernet; 137 | } 138 | } 139 | 140 | state parse_mirror_md { 141 | mirror_h mirror_md; 142 | packet.extract(hdr.mirror_header); 143 | local_metadata.mirror = _TRUE; 144 | transition parse_ethernet_mirror; 145 | } 146 | 147 | state parse_ethernet { 148 | packet.extract(hdr.local_report_header); 149 | packet.extract(hdr.ethernet); 150 | transition select(hdr.ethernet.ether_type) { 151 | TYPE_IPV4: parse_ipv4; 152 | default: accept; 153 | } 154 | } 155 | 156 | state parse_ethernet_mirror { 157 | packet.extract(hdr.ethernet); 158 | transition select(hdr.ethernet.ether_type) { 159 | TYPE_IPV4: parse_ipv4; 160 | default: accept; 161 | } 162 | } 163 | 164 | state parse_ipv4 { 165 | packet.extract(hdr.ipv4); 166 | transition select(hdr.ipv4.protocol) { 167 | IP_PROTO_UDP: parse_udp; 168 | IP_PROTO_TCP: parse_tcp; 169 | default: accept; 170 | } 171 | } 172 | 173 | state parse_udp { 174 | packet.extract(hdr.udp); 175 | local_metadata.l4_src_port = hdr.udp.src_port; 176 | local_metadata.l4_dst_port = hdr.udp.dst_port; 177 | transition select(hdr.ipv4.dscp) { 178 | DSCP_INT &&& DSCP_MASK: parse_shim; 179 | default: accept; 180 | } 181 | } 182 | 183 | state parse_tcp { 184 | packet.extract(hdr.tcp); 185 | local_metadata.l4_src_port = hdr.tcp.src_port; 186 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 187 | transition select(hdr.ipv4.dscp) { 188 | DSCP_INT &&& DSCP_MASK: parse_shim; 189 | default: accept; 190 | } 191 | } 192 | 193 | state parse_shim { 194 | packet.extract(hdr.intl4_shim); 195 | transition parse_int_hdr; 196 | } 197 | 198 | state parse_int_hdr { 199 | packet.extract(hdr.int_header); 200 | transition parse_int_data; 201 | } 202 | 203 | state parse_int_data { 204 | // packet.extract(hdr.int_data); 205 | // if INT node is a source or transit node, no need to extract int data here. only for sink node. 206 | packet.extract(hdr.int_data); 207 | transition select(hdr.mirror_header.pkt_type) { 208 | PKT_TYPE_MIRROR : parse_advance; 209 | default : accept; 210 | } 211 | } 212 | 213 | // if mirrored packet, skip over the rest of the payload as we are only interested in the int metadata 214 | // size of packet advance needs to be determined by values in the header 215 | state parse_advance { 216 | packet.advance(PACKET_ADVANCE); 217 | transition accept; 218 | } 219 | } 220 | 221 | /************************************************************************* 222 | *********************** D E P A R S E R ******************************* 223 | *************************************************************************/ 224 | 225 | control MyEgressDeparser(packet_out packet, 226 | inout headers hdr, 227 | in local_metadata_t local_metadata, 228 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) { 229 | 230 | Checksum() ipv4Checksum; 231 | 232 | apply { 233 | 234 | hdr.ipv4.hdr_checksum = ipv4Checksum.update( 235 | { 236 | hdr.ipv4.version, 237 | hdr.ipv4.ihl, 238 | hdr.ipv4.dscp, 239 | hdr.ipv4.ecn, 240 | hdr.ipv4.len, 241 | hdr.ipv4.identification, 242 | hdr.ipv4.flags, 243 | hdr.ipv4.frag_offset, 244 | hdr.ipv4.ttl, 245 | hdr.ipv4.protocol, 246 | hdr.ipv4.src_addr, 247 | hdr.ipv4.dst_addr 248 | } 249 | ); 250 | 251 | packet.emit(hdr.report_ethernet); 252 | packet.emit(hdr.report_ipv4); 253 | packet.emit(hdr.report_udp); 254 | packet.emit(hdr.report_fixed_header); 255 | 256 | packet.emit(hdr.ethernet); 257 | packet.emit(hdr.ipv4); 258 | packet.emit(hdr.udp); 259 | packet.emit(hdr.tcp); 260 | 261 | packet.emit(hdr.intl4_shim); 262 | packet.emit(hdr.int_header); 263 | packet.emit(hdr.int_switch_id); 264 | packet.emit(hdr.int_level1_port_ids); 265 | packet.emit(hdr.int_hop_latency); 266 | packet.emit(hdr.int_q_occupancy); 267 | packet.emit(hdr.int_ingress_tstamp); 268 | packet.emit(hdr.int_egress_tstamp); 269 | packet.emit(hdr.int_level2_port_ids); 270 | packet.emit(hdr.int_egress_tx_util); 271 | 272 | packet.emit(hdr.int_data); 273 | 274 | } 275 | } -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/sink.p4: -------------------------------------------------------------------------------- 1 | //Action to set node as INT sink in the egress for mirrored packets, however, this could be made as a flag based on the previous action instead 2 | control process_set_sink ( 3 | inout headers hdr, 4 | inout local_metadata_t local_metadata, 5 | in egress_intrinsic_metadata_t eg_intr_md) { 6 | 7 | action int_set_sink () { 8 | local_metadata.int_meta.sink = _TRUE; 9 | } 10 | 11 | table tb_set_sink { 12 | key = { 13 | eg_intr_md.egress_port: exact; 14 | } 15 | actions = { 16 | int_set_sink; 17 | NoAction(); 18 | } 19 | const default_action = NoAction(); 20 | size = MAX_PORTS; 21 | } 22 | 23 | apply { 24 | tb_set_sink.apply(); 25 | } 26 | } 27 | 28 | // Actions run in the egress of the INT Sink, before packet is forwarded to end-host 29 | control process_int_sink ( 30 | inout headers hdr, 31 | inout local_metadata_t local_metadata) { 32 | 33 | // restore length fields of IPv4 header and UDP header, and IP DSCP which was stored in the INT SHIM Header 34 | action restore_header () { 35 | hdr.ipv4.dscp = hdr.intl4_shim.dscp; 36 | hdr.ipv4.len = hdr.ipv4.len - SHIM_LEN; 37 | hdr.udp.length_ = hdr.udp.length_ - SHIM_LEN; 38 | 39 | } 40 | 41 | 42 | action int_sink() { 43 | // remove all the INT information from the packet 44 | hdr.int_header.setInvalid(); 45 | hdr.int_data.setInvalid(); 46 | hdr.intl4_shim.setInvalid(); 47 | } 48 | 49 | apply { 50 | restore_header(); 51 | int_sink(); 52 | } 53 | } 54 | 55 | // Action for the INT telemetry report, as it is encapsulated with new Ethernet, IP and UDP headers 56 | control process_int_report ( 57 | inout headers hdr, 58 | inout local_metadata_t local_metadata, 59 | in egress_intrinsic_metadata_t eg_intr_md, 60 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 61 | 62 | // Register for sequence number 63 | Register, _>(1) counter; 64 | RegisterAction, _, bit<32>>(counter) counter_incr = { 65 | void apply(inout bit<32> value, out bit<32> read_value){ 66 | bit<32> in_value = value; 67 | value = in_value + 1; 68 | read_value = value; 69 | } 70 | }; 71 | 72 | action do_report_encapsulation(mac_t src_mac, mac_t mon_mac, ip_address_t src_ip, 73 | ip_address_t mon_ip, l4_port_t mon_port) { 74 | //Report Ethernet Header 75 | hdr.report_ethernet.setValid(); 76 | hdr.report_ethernet.dst_addr = mon_mac; 77 | hdr.report_ethernet.src_addr = src_mac; 78 | hdr.report_ethernet.ether_type = ETH_TYPE_IPV4; 79 | 80 | //Report IPV4 Header 81 | hdr.report_ipv4.setValid(); 82 | hdr.report_ipv4.version = IP_VERSION_4; 83 | hdr.report_ipv4.ihl = IPV4_IHL_MIN; 84 | hdr.report_ipv4.dscp = DSCP_IP; 85 | hdr.report_ipv4.ecn = 2w0; 86 | 87 | // 20 + 8 + 16 + 14 + 20 + 8 + / 4 + 8 + (36 * #hops) / 84 88 | hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN + 89 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + INT_DATA_LEN; 90 | 91 | hdr.report_ipv4.identification = 0; 92 | hdr.report_ipv4.flags = 0; 93 | hdr.report_ipv4.frag_offset = 0; 94 | hdr.report_ipv4.ttl = REPORT_HDR_TTL; 95 | hdr.report_ipv4.protocol = IP_PROTO_UDP; 96 | hdr.report_ipv4.src_addr = src_ip; 97 | hdr.report_ipv4.dst_addr = mon_ip; 98 | 99 | //Report UDP Header 100 | hdr.report_udp.setValid(); 101 | hdr.report_udp.src_port = 1234; 102 | hdr.report_udp.dst_port = mon_port; 103 | hdr.report_udp.length_ = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN + 104 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + 105 | INT_DATA_LEN; 106 | 107 | hdr.report_fixed_header.setValid(); 108 | hdr.report_fixed_header.ver = 1; 109 | hdr.report_fixed_header.len = 4; 110 | hdr.report_fixed_header.nproto = NPROTO_ETHERNET; 111 | hdr.report_fixed_header.rep_md_bits = 0; 112 | hdr.report_fixed_header.d_q_f = 1; 113 | // hdr.report_fixed_header.q = 0; 114 | // hdr.report_fixed_header.f = 1; 115 | hdr.report_fixed_header.rsvd = 0; 116 | // get information specific to the switch 117 | hdr.report_fixed_header.hw_id = HW_ID; 118 | hdr.report_fixed_header.sw_id = local_metadata.int_meta.switch_id; 119 | 120 | // save a variable and increment 121 | hdr.report_fixed_header.seq_no = counter_incr.execute(0); 122 | 123 | hdr.report_fixed_header.ingress_tstamp = (bit<32>) eg_prsr_md.global_tstamp; 124 | 125 | } 126 | 127 | table tb_generate_report { 128 | // key = { 129 | // } 130 | actions = { 131 | do_report_encapsulation; 132 | NoAction(); 133 | } 134 | default_action = NoAction(); 135 | } 136 | 137 | apply { 138 | tb_generate_report.apply(); 139 | } 140 | } -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/source.p4: -------------------------------------------------------------------------------- 1 | // This action sets the node as a INT source or INT sink in the ingress pipeline 2 | // INT Source is set by the ingress port and INT Sink is set by the egress port 3 | control process_int_source_sink ( 4 | inout headers hdr, 5 | inout local_metadata_t local_metadata, 6 | in ingress_intrinsic_metadata_t ig_intr_md, 7 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 8 | 9 | action int_set_source () { 10 | local_metadata.int_meta.source = _TRUE; 11 | } 12 | 13 | action int_set_sink () { 14 | local_metadata.int_meta.sink = _TRUE; 15 | } 16 | 17 | table tb_set_source { 18 | key = { 19 | ig_intr_md.ingress_port: exact; 20 | } 21 | actions = { 22 | int_set_source; 23 | NoAction(); 24 | } 25 | const default_action = NoAction(); 26 | size = MAX_PORTS; 27 | } 28 | table tb_set_sink { 29 | key = { 30 | ig_tm_md.ucast_egress_port: exact; 31 | } 32 | actions = { 33 | int_set_sink; 34 | NoAction(); 35 | } 36 | const default_action = NoAction(); 37 | size = MAX_PORTS; 38 | } 39 | 40 | apply { 41 | tb_set_source.apply(); 42 | tb_set_sink.apply(); 43 | } 44 | } 45 | 46 | // Insert INT header to the packet 47 | control process_int_source ( 48 | inout headers hdr, 49 | inout local_metadata_t local_metadata) { 50 | 51 | action int_source(bit<5> hop_metadata_len, bit<8> remaining_hop_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) { 52 | // insert INT shim header 53 | hdr.intl4_shim.setValid(); 54 | // int_type: Hop-by-hop type (1) , destination type (2) 55 | hdr.intl4_shim.int_type = 1; 56 | hdr.intl4_shim.len = INT_HEADER_LEN_WORD; // This is 3 from 0xC (INT_TOTAL_HEADER_SIZE >> 2) 57 | hdr.intl4_shim.dscp = hdr.ipv4.dscp; 58 | 59 | // insert INT header 60 | hdr.int_header.setValid(); 61 | hdr.int_header.ver = 1; 62 | hdr.int_header.rep = 0; 63 | hdr.int_header.c = 0; 64 | hdr.int_header.e = 0; 65 | hdr.int_header.m = 0; 66 | hdr.int_header.rsvd1 = 0; 67 | hdr.int_header.rsvd2 = 0; 68 | hdr.int_header.hop_metadata_len = hop_metadata_len; 69 | hdr.int_header.remaining_hop_cnt = remaining_hop_cnt; 70 | hdr.int_header.instruction_mask_0003 = ins_mask0003; 71 | hdr.int_header.instruction_mask_0407 = ins_mask0407; 72 | hdr.int_header.instruction_mask_0811 = 0; // not supported 73 | hdr.int_header.instruction_mask_1215 = 0; // not supported 74 | 75 | // add the header len (3 words) to total len 76 | hdr.ipv4.len = hdr.ipv4.len + INT_TOTAL_HEADER_SIZE; 77 | hdr.udp.length_ = hdr.udp.length_ + INT_TOTAL_HEADER_SIZE; 78 | } 79 | 80 | action int_source_dscp(bit<5> hop_metadata_len, bit<8> remaining_hop_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) { 81 | int_source(hop_metadata_len, remaining_hop_cnt, ins_mask0003, ins_mask0407); 82 | hdr.ipv4.dscp = DSCP_INT; 83 | } 84 | 85 | table tb_int_source { 86 | key = { 87 | //configure for each flow to be monitored 88 | // 4 fields identifying flow 89 | //include ip src, udp/tcp src and dest too 90 | hdr.ipv4.dst_addr: lpm; 91 | } 92 | actions = { 93 | int_source_dscp; 94 | NoAction; 95 | } 96 | const default_action = NoAction(); 97 | } 98 | 99 | apply { 100 | tb_int_source.apply(); 101 | } 102 | } -------------------------------------------------------------------------------- /int-md-1-0/p4src/int/transit.p4: -------------------------------------------------------------------------------- 1 | // Action to add INT metadata to the packet 2 | // It uses the Instruction bitmap to create a combination of data fields to be added 3 | // The header lengths are updated accordingly 4 | control process_int_transit ( 5 | inout headers hdr, 6 | inout local_metadata_t local_metadata, 7 | in egress_intrinsic_metadata_t eg_intr_md, 8 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 9 | 10 | action init_metadata(switch_id_t switch_id) { 11 | local_metadata.int_meta.transit = _TRUE; 12 | local_metadata.int_meta.switch_id = switch_id; 13 | } 14 | 15 | 16 | action int_set_header_0() { //switch_id 17 | hdr.int_switch_id.setValid(); 18 | hdr.int_switch_id.switch_id = local_metadata.int_meta.switch_id; 19 | } 20 | 21 | action int_set_header_1() { //level1_port_id - physical port 22 | hdr.int_level1_port_ids.setValid(); 23 | hdr.int_level1_port_ids.ingress_port_id = 24 | (bit<16>) hdr.local_report_header.ingress_port_id; 25 | hdr.int_level1_port_ids.egress_port_id = (bit<16>) eg_intr_md.egress_port; 26 | } 27 | 28 | action int_set_header_2() { //hop_latency 29 | hdr.int_hop_latency.setValid(); 30 | hdr.int_hop_latency.hop_latency = (bit<32>) (eg_prsr_md.global_tstamp - 31 | hdr.local_report_header.ingress_global_tstamp); 32 | } 33 | 34 | action int_set_header_3() { //q_occupancy 35 | hdr.int_q_occupancy.setValid(); 36 | hdr.int_q_occupancy.q_id = 37 | (bit<8>) hdr.local_report_header.queue_id; 38 | hdr.int_q_occupancy.q_occupancy = 39 | (bit<24>) eg_intr_md.deq_qdepth; 40 | } 41 | 42 | action int_set_header_4() { //ingress_tstamp 43 | hdr.int_ingress_tstamp.setValid(); 44 | hdr.int_ingress_tstamp.ingress_tstamp = 45 | (bit<32>) hdr.local_report_header.ingress_global_tstamp; 46 | } 47 | 48 | action int_set_header_5() { //egress_timestamp 49 | hdr.int_egress_tstamp.setValid(); 50 | hdr.int_egress_tstamp.egress_tstamp = 51 | (bit<32>) eg_prsr_md.global_tstamp; 52 | } 53 | 54 | action int_set_header_6() { //level2_port_id 55 | hdr.int_level2_port_ids.setValid(); 56 | // level2_port_id indicates Logical port ID - update this! 57 | hdr.int_level2_port_ids.ingress_port_id = (bit<32>) local_metadata.l4_src_port; 58 | hdr.int_level2_port_ids.egress_port_id = (bit<32>) local_metadata.l4_dst_port; 59 | } 60 | 61 | action int_set_header_7() { // queueing latency 62 | hdr.int_egress_tx_util.setValid(); 63 | hdr.int_egress_tx_util.egress_port_tx_util = 64 | (bit<32>) eg_intr_md.deq_timedelta; 65 | } 66 | 67 | // Actions to keep track of the new metadata added. 68 | 69 | action add_1() { 70 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 1; 71 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 4; 72 | } 73 | 74 | 75 | action add_2() { 76 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 2; 77 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 8; 78 | } 79 | 80 | 81 | action add_3() { 82 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 3; 83 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 12; 84 | } 85 | 86 | 87 | action add_4() { 88 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 4; 89 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 16; 90 | } 91 | 92 | 93 | action add_5() { 94 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 5; 95 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 20; 96 | } 97 | 98 | /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */ 99 | /* Each bit set indicates that corresponding INT header should be added */ 100 | 101 | action int_set_header_0003_i0() { 102 | } 103 | 104 | action int_set_header_0003_i1() { 105 | int_set_header_3(); 106 | add_1(); 107 | } 108 | 109 | action int_set_header_0003_i2() { 110 | int_set_header_2(); 111 | add_1(); 112 | } 113 | 114 | action int_set_header_0003_i3() { 115 | int_set_header_3(); 116 | int_set_header_2(); 117 | add_2(); 118 | } 119 | 120 | action int_set_header_0003_i4() { 121 | int_set_header_1(); 122 | add_1(); 123 | } 124 | 125 | action int_set_header_0003_i5() { 126 | int_set_header_3(); 127 | int_set_header_1(); 128 | add_2(); 129 | } 130 | 131 | action int_set_header_0003_i6() { 132 | int_set_header_2(); 133 | int_set_header_1(); 134 | add_2(); 135 | } 136 | 137 | action int_set_header_0003_i7() { 138 | int_set_header_3(); 139 | int_set_header_2(); 140 | int_set_header_1(); 141 | add_3(); 142 | } 143 | 144 | action int_set_header_0003_i8() { 145 | int_set_header_0(); 146 | add_1(); 147 | } 148 | 149 | action int_set_header_0003_i9() { 150 | int_set_header_3(); 151 | int_set_header_0(); 152 | add_2(); 153 | } 154 | 155 | action int_set_header_0003_i10() { 156 | int_set_header_2(); 157 | int_set_header_0(); 158 | add_2(); 159 | } 160 | 161 | action int_set_header_0003_i11() { 162 | int_set_header_3(); 163 | int_set_header_2(); 164 | int_set_header_0(); 165 | add_3(); 166 | } 167 | 168 | action int_set_header_0003_i12() { 169 | int_set_header_1(); 170 | int_set_header_0(); 171 | add_2(); 172 | } 173 | 174 | action int_set_header_0003_i13() { 175 | int_set_header_3(); 176 | int_set_header_1(); 177 | int_set_header_0(); 178 | add_3(); 179 | } 180 | 181 | action int_set_header_0003_i14() { 182 | int_set_header_2(); 183 | int_set_header_1(); 184 | int_set_header_0(); 185 | add_3(); 186 | } 187 | 188 | action int_set_header_0003_i15() { 189 | int_set_header_3(); 190 | int_set_header_2(); 191 | int_set_header_1(); 192 | int_set_header_0(); 193 | add_4(); 194 | } 195 | 196 | /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */ 197 | 198 | action int_set_header_0407_i0() { 199 | } 200 | 201 | action int_set_header_0407_i1() { 202 | int_set_header_7(); 203 | add_1(); 204 | } 205 | 206 | action int_set_header_0407_i2() { 207 | int_set_header_6(); 208 | add_2(); 209 | } 210 | 211 | action int_set_header_0407_i3() { 212 | int_set_header_7(); 213 | int_set_header_6(); 214 | add_3(); 215 | } 216 | 217 | action int_set_header_0407_i4() { 218 | int_set_header_5(); 219 | add_1(); 220 | } 221 | 222 | action int_set_header_0407_i5() { 223 | int_set_header_7(); 224 | int_set_header_5(); 225 | add_2(); 226 | } 227 | 228 | action int_set_header_0407_i6() { 229 | int_set_header_6(); 230 | int_set_header_5(); 231 | add_3(); 232 | } 233 | 234 | action int_set_header_0407_i7() { 235 | int_set_header_7(); 236 | int_set_header_6(); 237 | int_set_header_5(); 238 | add_4(); 239 | } 240 | 241 | action int_set_header_0407_i8() { 242 | int_set_header_4(); 243 | add_1(); 244 | } 245 | 246 | action int_set_header_0407_i9() { 247 | int_set_header_7(); 248 | int_set_header_4(); 249 | add_2(); 250 | } 251 | 252 | action int_set_header_0407_i10() { 253 | int_set_header_6(); 254 | int_set_header_4(); 255 | add_3(); 256 | } 257 | 258 | action int_set_header_0407_i11() { 259 | int_set_header_7(); 260 | int_set_header_6(); 261 | int_set_header_4(); 262 | add_4(); 263 | } 264 | 265 | action int_set_header_0407_i12() { 266 | int_set_header_5(); 267 | int_set_header_4(); 268 | add_2(); 269 | } 270 | 271 | action int_set_header_0407_i13() { 272 | int_set_header_7(); 273 | int_set_header_5(); 274 | int_set_header_4(); 275 | add_3(); 276 | } 277 | 278 | action int_set_header_0407_i14() { 279 | int_set_header_6(); 280 | int_set_header_5(); 281 | int_set_header_4(); 282 | add_4(); 283 | } 284 | 285 | action int_set_header_0407_i15() { 286 | int_set_header_7(); 287 | int_set_header_6(); 288 | int_set_header_5(); 289 | int_set_header_4(); 290 | add_5(); 291 | } 292 | 293 | // Default action used to set switch ID. 294 | table tb_int_insert { 295 | // key = { 296 | // } 297 | actions = { 298 | init_metadata; 299 | NoAction; 300 | } 301 | default_action = NoAction(); 302 | size = 1; 303 | } 304 | 305 | /* Table to process instruction bits 0-3 */ 306 | 307 | table tb_int_inst_0003 { 308 | key = { 309 | hdr.int_header.instruction_mask_0003 : exact; 310 | } 311 | actions = { 312 | int_set_header_0003_i0; 313 | int_set_header_0003_i1; 314 | int_set_header_0003_i2; 315 | int_set_header_0003_i3; 316 | int_set_header_0003_i4; 317 | int_set_header_0003_i5; 318 | int_set_header_0003_i6; 319 | int_set_header_0003_i7; 320 | int_set_header_0003_i8; 321 | int_set_header_0003_i9; 322 | int_set_header_0003_i10; 323 | int_set_header_0003_i11; 324 | int_set_header_0003_i12; 325 | int_set_header_0003_i13; 326 | int_set_header_0003_i14; 327 | int_set_header_0003_i15; 328 | } 329 | 330 | const entries = { 331 | (0x0) : int_set_header_0003_i0(); 332 | (0x1) : int_set_header_0003_i1(); 333 | (0x2) : int_set_header_0003_i2(); 334 | (0x3) : int_set_header_0003_i3(); 335 | (0x4) : int_set_header_0003_i4(); 336 | (0x5) : int_set_header_0003_i5(); 337 | (0x6) : int_set_header_0003_i6(); 338 | (0x7) : int_set_header_0003_i7(); 339 | (0x8) : int_set_header_0003_i8(); 340 | (0x9) : int_set_header_0003_i9(); 341 | (0xA) : int_set_header_0003_i10(); 342 | (0xB) : int_set_header_0003_i11(); 343 | (0xC) : int_set_header_0003_i12(); 344 | (0xD) : int_set_header_0003_i13(); 345 | (0xE) : int_set_header_0003_i14(); 346 | (0xF) : int_set_header_0003_i15(); 347 | } 348 | size = 16; 349 | } 350 | 351 | /* Table to process instruction bits 4-7 */ 352 | 353 | table tb_int_inst_0407 { 354 | key = { 355 | hdr.int_header.instruction_mask_0407 : exact; 356 | } 357 | actions = { 358 | int_set_header_0407_i0; 359 | int_set_header_0407_i1; 360 | int_set_header_0407_i2; 361 | int_set_header_0407_i3; 362 | int_set_header_0407_i4; 363 | int_set_header_0407_i5; 364 | int_set_header_0407_i6; 365 | int_set_header_0407_i7; 366 | int_set_header_0407_i8; 367 | int_set_header_0407_i9; 368 | int_set_header_0407_i10; 369 | int_set_header_0407_i11; 370 | int_set_header_0407_i12; 371 | int_set_header_0407_i13; 372 | int_set_header_0407_i14; 373 | int_set_header_0407_i15; 374 | } 375 | 376 | const entries = { 377 | (0x0) : int_set_header_0407_i0(); 378 | (0x1) : int_set_header_0407_i1(); 379 | (0x2) : int_set_header_0407_i2(); 380 | (0x3) : int_set_header_0407_i3(); 381 | (0x4) : int_set_header_0407_i4(); 382 | (0x5) : int_set_header_0407_i5(); 383 | (0x6) : int_set_header_0407_i6(); 384 | (0x7) : int_set_header_0407_i7(); 385 | (0x8) : int_set_header_0407_i8(); 386 | (0x9) : int_set_header_0407_i9(); 387 | (0xA) : int_set_header_0407_i10(); 388 | (0xB) : int_set_header_0407_i11(); 389 | (0xC) : int_set_header_0407_i12(); 390 | (0xD) : int_set_header_0407_i13(); 391 | (0xE) : int_set_header_0407_i14(); 392 | (0xF) : int_set_header_0407_i15(); 393 | } 394 | size = 16; 395 | } 396 | 397 | apply { 398 | tb_int_insert.apply(); 399 | if (local_metadata.int_meta.transit == _FALSE) { 400 | return; 401 | } 402 | tb_int_inst_0003.apply(); 403 | tb_int_inst_0407.apply(); 404 | 405 | // Decrement remaining hop cnt 406 | hdr.int_header.remaining_hop_cnt = hdr.int_header.remaining_hop_cnt - 1; 407 | 408 | // Update headers lengths. 409 | if (hdr.ipv4.isValid()) { 410 | hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.new_bytes; 411 | } 412 | if (hdr.udp.isValid()) { 413 | hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.new_bytes; 414 | } 415 | if (hdr.intl4_shim.isValid()) { 416 | // 9 words if add 4 + add 5 417 | hdr.intl4_shim.len = hdr.intl4_shim.len + local_metadata.int_meta.new_words; 418 | } 419 | } 420 | } -------------------------------------------------------------------------------- /int-md-1-0/p4src/int_md_1_0.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * This file has been modified. 19 | * Modifications Copyright © 2021 Saab AB / Mandar Joshi 20 | */ 21 | 22 | /* 23 | * This program is free software: you can redistribute it and/or modify 24 | * it under the terms of the GNU General Public License as published by 25 | * the Free Software Foundation, either version 2 of the License, or 26 | * (at your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | * GNU General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program. If not, see . 35 | */ 36 | 37 | /* -*- P4_16 -*- */ 38 | 39 | #include 40 | #include 41 | 42 | #include "int/headers.p4" 43 | #include "int/parsers.p4" 44 | #include "int/sink.p4" 45 | #include "int/transit.p4" 46 | #include "int/source.p4" 47 | #include "int/forward.p4" 48 | 49 | /************************************************************************* 50 | **************** I N G R E S S P R O C E S S I N G ****************** 51 | *************************************************************************/ 52 | 53 | control MyIngress(inout headers hdr, 54 | inout local_metadata_t local_metadata, 55 | in ingress_intrinsic_metadata_t ig_intr_md, 56 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 57 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 58 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 59 | 60 | apply { 61 | 62 | port_forward.apply(hdr, local_metadata, ig_tm_md, ig_dprsr_md); 63 | 64 | process_int_source_sink.apply(hdr, local_metadata, ig_intr_md, ig_tm_md); 65 | 66 | if (local_metadata.int_meta.source == _TRUE) { 67 | process_int_source.apply(hdr, local_metadata); 68 | } 69 | 70 | if (local_metadata.int_meta.sink == _TRUE && hdr.int_header.isValid()) { 71 | // clone packet for Telemetry Report 72 | ig_dprsr_md.mirror_type = MIRROR_TYPE_I2E; 73 | local_metadata.pkt_type = PKT_TYPE_MIRROR; 74 | local_metadata.ing_mir_ses = (bit<10>) MIRROR_TYPE_I2E; 75 | 76 | // set a flag here 77 | hdr.local_report_header.do_report = _TRUE; 78 | } 79 | 80 | // Save ingress parser values for egress / INT Transit 81 | if (hdr.int_header.isValid()) { 82 | hdr.local_report_header.setValid(); 83 | hdr.local_report_header.ingress_port_id = (bit<16>) ig_intr_md.ingress_port; 84 | hdr.local_report_header.queue_id = (bit<32>) ig_tm_md.qid; 85 | hdr.local_report_header.ingress_global_tstamp = ig_intr_md.ingress_mac_tstamp; 86 | } 87 | } 88 | } 89 | 90 | /************************************************************************* 91 | ***************** E G R E S S P R O C E S S I N G ******************* 92 | *************************************************************************/ 93 | 94 | control MyEgress(inout headers hdr, 95 | inout local_metadata_t local_metadata, 96 | in egress_intrinsic_metadata_t eg_intr_md, 97 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 98 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 99 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 100 | 101 | apply { 102 | if(hdr.int_header.isValid()) { 103 | 104 | process_set_sink.apply(hdr, local_metadata, eg_intr_md); 105 | 106 | if (local_metadata.int_meta.sink == _TRUE) { // Switch is a Sink, packet is not a mirror 107 | process_int_sink.apply(hdr, local_metadata); 108 | 109 | } else if (local_metadata.int_meta.sink == _FALSE) { // Switch is a Sink, packet is a mirror, or switch is not a sink 110 | if(hdr.mirror_header.isValid()) { 111 | hdr.local_report_header.ingress_port_id = hdr.mirror_header.ingress_port_id; 112 | hdr.local_report_header.queue_id = hdr.mirror_header.queue_id; 113 | hdr.local_report_header.ingress_global_tstamp = hdr.mirror_header.ingress_global_tstamp; 114 | } 115 | process_int_transit.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 116 | } 117 | 118 | if (local_metadata.mirror == _TRUE) { // Packet is a mirror (only on the sink) 119 | process_int_report.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 120 | } 121 | } 122 | 123 | hdr.local_report_header.setInvalid(); 124 | hdr.mirror_header.setInvalid(); 125 | } 126 | } 127 | 128 | /************************************************************************* 129 | *********************** S W I T C H ******************************* 130 | *************************************************************************/ 131 | 132 | Pipeline( 133 | MyIngressParser(), 134 | MyIngress(), 135 | MyIngressDeparser(), 136 | MyEgressParser(), 137 | MyEgress(), 138 | MyEgressDeparser() 139 | ) pipe; 140 | 141 | Switch(pipe) main; -------------------------------------------------------------------------------- /int-md-2-1/README.md: -------------------------------------------------------------------------------- 1 | # In-Band Network Telemetry Implementation in P4 2 | 3 | **INT-MD - eMbed Data (version 2.1)** 4 | 5 | ## Build 6 | 7 | The P4 code can be compiled by using the build script in the SDE 8 | ``` 9 | ./p4_build.sh int_md_2_1.p4 10 | ``` 11 | 12 | The following topology can be referred to for the INT-MD mode of operation: 13 | ![INT-MD](../figures/int-md.png) 14 | 15 | ## Usage 16 | 17 | Run the P4 code as follows 18 | ``` 19 | $SDE/run_switchd.sh -p int_md_2_1 20 | ``` 21 | 22 | ### Populating the tables and registers 23 | 24 | In another window for each switch, the following command can be run depending on the role of the INT node 25 | ``` 26 | $SDE/run_bfshell.sh -b $P4-INT/int-md-2-1/bfrt_python/bfswitch1.py 27 | ``` 28 | 29 | ### Testing the INT program 30 | 31 | Packets can be sent from server1, and tcpdump/wireshark can be used to see the output at the monitoring server and the receiver 32 | 33 | -------------------------------------------------------------------------------- /int-md-2-1/bfrt_python/bfswitch1.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=7) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=5) 5 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source_dscp(dst_addr="10.0.2.2", dst_addr_p_length=32, hop_metadata_len=16, remaining_hop_cnt=3, ins_mask0003=15, ins_mask0407=15) 6 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=1) -------------------------------------------------------------------------------- /int-md-2-1/bfrt_python/bfswitch2.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=11) 4 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=2) -------------------------------------------------------------------------------- /int-md-2-1/bfrt_python/bfswitch3.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_md_1_0.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.2.2", dst_addr_p_length=32, port=10) 4 | p4.MyIngress.process_int_source_sink.tb_set_sink.add_with_int_set_sink(ucast_egress_port=10) 5 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=10) 6 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=3) 7 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="127.0.0.1", mon_mac="02:42:ac:1c:00:02", mon_port="54321", src_ip="172.26.0.2", src_mac="02:42:ac:1c:00:03") 8 | 9 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=9, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/forward.p4: -------------------------------------------------------------------------------- 1 | control port_forward(inout headers hdr, 2 | inout local_metadata_t local_metadata, 3 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md, 4 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 5 | 6 | action send_to_cpu() { 7 | ig_tm_md.ucast_egress_port = CPU_PORT; 8 | } 9 | 10 | action set_egress_port(port_t port) { 11 | ig_tm_md.ucast_egress_port = port; 12 | } 13 | 14 | action drop() { 15 | ig_dprsr_md.drop_ctl = 1; 16 | } 17 | 18 | table tb_port_forward { 19 | key = { 20 | hdr.ipv4.dst_addr : lpm; 21 | } 22 | actions = { 23 | set_egress_port; 24 | send_to_cpu; 25 | drop; 26 | } 27 | const default_action = drop(); 28 | } 29 | 30 | apply { 31 | tb_port_forward.apply(); 32 | } 33 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ************* C O N S T A N T S A N D T Y P E S ******************* 3 | **************************************************************************/ 4 | 5 | #define MAX_INT_HEADERS 9 6 | #define MAX_HOP_COUNT 3 7 | #define NUM_INSTRUCTIONS 3 8 | 9 | #define ETH_TYPE_IPV4 0x0800 10 | #define IP_VERSION_4 4w4 11 | #define MAX_PORTS 511 12 | #define IPV4_IHL_MIN 4w5 13 | 14 | #ifndef _BOOL 15 | #define _BOOL bool 16 | #endif 17 | #ifndef _TRUE 18 | #define _TRUE true 19 | #endif 20 | #ifndef _FALSE 21 | #define _FALSE false 22 | #endif 23 | 24 | // 1 --> 2 --> 3 Switch hardware ID 25 | const bit<6> HW_ID = 1; 26 | 27 | // Make this dynamic depending on UDP/IP Header 28 | const bit<32> PACKET_ADVANCE = 40; 29 | 30 | const bit<16> TYPE_IPV4 = 0x0800; 31 | const bit<8> IP_PROTO_UDP = 0x11; 32 | const bit<8> IP_PROTO_TCP = 0x6; 33 | const bit<16> INT_PORT = 5000; 34 | const bit<16> SHIM_LEN = 84; // SHIM LEN is INT_DATA_LEN - 8. Change for different bitmap. for 64 bits -> 28 35 | const bit<16> INT_DATA_LEN = 120; // SHIM LEN + 8 for 64 bits -> 36 36 | 37 | const bit<6> DSCP_INT = 0x17; 38 | const bit<6> DSCP_MASK = 0x3F; 39 | const bit<8> HOP_1 = 0x1A; 40 | const bit<8> HOP_2 = 0xC; 41 | 42 | typedef bit<48> mac_t; 43 | typedef bit<32> ip_address_t; 44 | typedef bit<16> l4_port_t; 45 | typedef bit<9> port_t; 46 | typedef bit<16> next_hop_id_t; 47 | 48 | const bit<8> INT_HEADER_LEN_WORD = 3; 49 | const bit<8> REPORT_HDR_TTL = 64; 50 | const port_t CPU_PORT = 255; 51 | 52 | const bit<3> NPROTO_ETHERNET = 0; 53 | const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1; 54 | const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2; 55 | 56 | const bit<5> IPV4_OPTION_INT = 31; 57 | 58 | // Mirroring defs 59 | typedef bit<3> mirror_type_t; 60 | typedef bit<8> pkt_type_t; 61 | 62 | const mirror_type_t MIRROR_TYPE_I2E = 1; 63 | const mirror_type_t MIRROR_TYPE_E2E = 2; 64 | const pkt_type_t PKT_TYPE_NORMAL = 1; 65 | const pkt_type_t PKT_TYPE_MIRROR = 2; 66 | 67 | typedef bit<32> switch_id_t; 68 | typedef bit<48> timestamp_t; 69 | typedef bit<6> output_port_t; 70 | 71 | /************************************************************************* 72 | *********************** H E A D E R S *********************************** 73 | *************************************************************************/ 74 | 75 | header ethernet_t { 76 | bit<48> dst_addr; 77 | bit<48> src_addr; 78 | bit<16> ether_type; 79 | } 80 | 81 | const bit<8> ETH_HEADER_LEN = 14; 82 | 83 | header ipv4_t { 84 | bit<4> version; 85 | bit<4> ihl; 86 | bit<6> dscp; 87 | bit<2> ecn; 88 | bit<16> len; 89 | bit<16> identification; 90 | bit<3> flags; 91 | bit<13> frag_offset; 92 | bit<8> ttl; 93 | bit<8> protocol; 94 | bit<16> hdr_checksum; 95 | bit<32> src_addr; 96 | bit<32> dst_addr; 97 | } 98 | 99 | const bit<8> IPV4_MIN_HEAD_LEN = 20; 100 | 101 | 102 | header udp_t { 103 | bit<16> src_port; 104 | bit<16> dst_port; 105 | bit<16> length_; 106 | bit<16> checksum; 107 | } 108 | const bit<8> UDP_HEADER_LEN = 8; 109 | 110 | 111 | header tcp_t { 112 | bit<16> src_port; 113 | bit<16> dst_port; 114 | bit<32> seq_no; 115 | bit<32> ack_no; 116 | bit<4> data_offset; 117 | bit<3> res; 118 | bit<3> ecn; 119 | bit<6> ctrl; 120 | bit<16> window; 121 | bit<16> checksum; 122 | bit<16> urgent_ptr; 123 | } 124 | 125 | const bit<8> TCP_HEADER_LEN = 20; 126 | 127 | // INT shim header for TCP/UDP 128 | header intl4_shim_t { 129 | bit<4> int_type; // Type of INT Header 130 | bit<2> npt; // Next protocol type 131 | bit<2> rsvd; // Reserved 132 | bit<8> len; // Length of INT Metadata header and INT stack in 4-byte words, not including the shim header (1 word) 133 | bit<6> udp_ip_dscp; // depends on npt field. either original dscp, ip protocol or udp dest port 134 | bit<10> udp_ip; // depends on npt field. either original dscp, ip protocol or udp dest port 135 | } 136 | 137 | const bit<16> INT_SHIM_HEADER_SIZE = 4; 138 | 139 | // INT header 140 | header int_header_t { 141 | bit<4> ver; // Version 142 | bit<1> d; // Discard 143 | bit<1> e; 144 | bit<1> m; 145 | bit<12> rsvd1; 146 | bit<5> hop_metadata_len; 147 | bit<8> remaining_hop_cnt; 148 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 149 | bit<4> instruction_mask_0407; 150 | bit<4> instruction_mask_0811; 151 | bit<4> instruction_mask_1215; 152 | bit<16> domain_specific_id; // Unique INT Domain ID 153 | bit<16> ds_instruction; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 154 | bit<16> ds_flags; // Domain specific flags 155 | } 156 | 157 | const bit<16> INT_HEADER_SIZE = 12; 158 | 159 | const bit<16> INT_TOTAL_HEADER_SIZE = INT_HEADER_SIZE + INT_SHIM_HEADER_SIZE; 160 | 161 | 162 | // INT meta-value headers - different header for each value type 163 | header int_switch_id_t { 164 | bit<32> switch_id; 165 | } 166 | header int_level1_port_ids_t { 167 | bit<16> ingress_port_id; 168 | bit<16> egress_port_id; 169 | } 170 | header int_hop_latency_t { 171 | bit<32> hop_latency; 172 | } 173 | header int_q_occupancy_t { 174 | bit<8> q_id; 175 | bit<24> q_occupancy; 176 | } 177 | header int_ingress_tstamp_t { 178 | bit<64> ingress_tstamp; 179 | } 180 | header int_egress_tstamp_t { 181 | bit<64> egress_tstamp; 182 | } 183 | header int_level2_port_ids_t { 184 | bit<32> ingress_port_id; 185 | bit<32> egress_port_id; 186 | } 187 | 188 | // these two not implemented yet 189 | header int_egress_port_tx_util_t { 190 | bit<32> egress_port_tx_util; 191 | } 192 | header int_buffer_t { 193 | bit<8> buffer_id; 194 | bit<24> buffer_occupancy; 195 | } 196 | 197 | header int_data_t { 198 | // varbit data; 199 | // change this depending on the INT data embedded, 576 = 2 hops of all metadata. 128 = 2 hops of 64 bit metadata. 200 | // 8 --> 288 --> 576 201 | bit<704> data; 202 | } 203 | 204 | 205 | // Report Telemetry Headers 206 | header report_group_header_t { 207 | bit<4> ver; 208 | bit<6> hw_id; 209 | bit<22> seq_no; 210 | bit<32> node_id; 211 | } 212 | const bit<8> REPORT_GROUP_HEADER_LEN = 8; 213 | 214 | header report_individual_header_t { 215 | bit<4> rep_type; 216 | bit<4> in_type; 217 | bit<8> len; 218 | bit<8> rep_md_len; 219 | bit<1> d; 220 | bit<1> q; 221 | bit<1> f; 222 | bit<1> i; 223 | bit<4> rsvd; 224 | // Individual report inner contents for Reptype 1 = INT 225 | bit<16> rep_md_bits; 226 | bit<16> domain_specific_id; 227 | bit<16> domain_specific_md_bits; 228 | bit<16> domain_specific_md_status; 229 | } 230 | const bit<8> REPORT_INDIVIDUAL_HEADER_LEN = 12; 231 | 232 | // Telemetry drop report header 233 | header drop_report_header_t { 234 | bit<32> switch_id; 235 | bit<16> ingress_port_id; 236 | bit<16> egress_port_id; 237 | bit<8> queue_id; 238 | bit<8> drop_reason; 239 | bit<16> pad; 240 | } 241 | const bit<8> DROP_REPORT_HEADER_LEN = 12; 242 | 243 | // Switch Local Report Header 244 | header local_report_header_t { 245 | bit<16> ingress_port_id; 246 | bit<16> egress_port_id; 247 | bit<8> queue_id; 248 | bit<8> pad; 249 | bit<64> ingress_global_tstamp; 250 | } 251 | 252 | const bit<8> LOCAL_REPORT_HEADER_LEN = 16; 253 | 254 | header mirror_h { 255 | pkt_type_t pkt_type; 256 | bit<16> ingress_port_id; 257 | bit<8> queue_id; 258 | bit<64> ingress_global_tstamp; 259 | } 260 | 261 | struct headers { 262 | 263 | // Original Packet Headers 264 | ethernet_t ethernet; 265 | ipv4_t ipv4; 266 | udp_t udp; 267 | tcp_t tcp; 268 | 269 | // INT Report Encapsulation 270 | ethernet_t report_ethernet; 271 | ipv4_t report_ipv4; 272 | udp_t report_udp; 273 | 274 | // INT Headers 275 | int_header_t int_header; 276 | intl4_shim_t intl4_shim; 277 | int_data_t int_data; 278 | int_switch_id_t int_switch_id; 279 | int_level1_port_ids_t int_level1_port_ids; 280 | int_hop_latency_t int_hop_latency; 281 | int_q_occupancy_t int_q_occupancy; 282 | int_ingress_tstamp_t int_ingress_tstamp; 283 | int_egress_tstamp_t int_egress_tstamp; 284 | int_level2_port_ids_t int_level2_port_ids; 285 | int_egress_port_tx_util_t int_egress_tx_util; 286 | 287 | // // INT Report Headers 288 | report_group_header_t report_group_header; 289 | report_individual_header_t report_individual_header; 290 | local_report_header_t local_report_header; 291 | 292 | mirror_h mirror_header; 293 | } 294 | 295 | struct int_metadata_t { 296 | switch_id_t switch_id; 297 | bit<16> new_bytes; 298 | bit<8> new_words; 299 | bool source; 300 | bool sink; 301 | bool transit; 302 | bit<8> intl4_shim_len; 303 | bit<16> int_shim_len; 304 | } 305 | 306 | struct local_metadata_t { 307 | bit<16> l4_src_port; 308 | bit<16> l4_dst_port; 309 | int_metadata_t int_meta; 310 | bool mirror; 311 | pkt_type_t pkt_type; 312 | MirrorId_t ing_mir_ses; // Ingress mirror session ID 313 | MirrorId_t egr_mir_ses; // Egress mirror session ID 314 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/parsers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** P A R S E R ******************************* 3 | *************************************************************************/ 4 | 5 | parser MyIngressParser(packet_in packet, 6 | out headers hdr, 7 | out local_metadata_t local_metadata, 8 | out ingress_intrinsic_metadata_t ig_intr_md) { 9 | 10 | state start { 11 | packet.extract(ig_intr_md); 12 | packet.advance(PORT_METADATA_SIZE); 13 | transition parse_ethernet; 14 | } 15 | 16 | state parse_ethernet { 17 | packet.extract(hdr.ethernet); 18 | transition select(hdr.ethernet.ether_type) { 19 | TYPE_IPV4: parse_ipv4; 20 | default: accept; 21 | } 22 | } 23 | 24 | state parse_ipv4 { 25 | packet.extract(hdr.ipv4); 26 | transition select(hdr.ipv4.protocol) { 27 | IP_PROTO_UDP: parse_udp; 28 | IP_PROTO_TCP: parse_tcp; 29 | default: accept; 30 | } 31 | } 32 | 33 | state parse_udp { 34 | packet.extract(hdr.udp); 35 | local_metadata.l4_src_port = hdr.udp.src_port; 36 | local_metadata.l4_dst_port = hdr.udp.dst_port; 37 | transition select(hdr.ipv4.dscp) { 38 | DSCP_INT &&& DSCP_MASK: parse_shim; 39 | default: accept; 40 | } 41 | } 42 | 43 | state parse_tcp { 44 | packet.extract(hdr.tcp); 45 | local_metadata.l4_src_port = hdr.tcp.src_port; 46 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 47 | transition select(hdr.ipv4.dscp) { 48 | DSCP_INT &&& DSCP_MASK: parse_shim; 49 | default: accept; 50 | } 51 | } 52 | 53 | state parse_shim { 54 | packet.extract(hdr.intl4_shim); 55 | transition parse_int_hdr; 56 | } 57 | 58 | state parse_int_hdr { 59 | packet.extract(hdr.int_header); 60 | transition parse_int_data; 61 | } 62 | 63 | state parse_int_data { 64 | transition accept; 65 | } 66 | } 67 | 68 | /************************************************************************* 69 | ************ C H E C K S U M V E R I F I C A T I O N ************* 70 | *************************************************************************/ 71 | 72 | control MyIngressDeparser(packet_out packet, 73 | inout headers hdr, 74 | in local_metadata_t local_metadata, 75 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 76 | 77 | 78 | Mirror() mirror; 79 | 80 | apply { 81 | 82 | if(ig_dprsr_md.mirror_type == 3w1) { 83 | mirror.emit(local_metadata.ing_mir_ses, {local_metadata.pkt_type, hdr.local_report_header.ingress_port_id, hdr.local_report_header.queue_id,hdr.local_report_header.ingress_global_tstamp}); 84 | } 85 | 86 | packet.emit(hdr.local_report_header); 87 | packet.emit(hdr.ethernet); 88 | packet.emit(hdr.ipv4); 89 | packet.emit(hdr.udp); 90 | packet.emit(hdr.tcp); 91 | 92 | packet.emit(hdr.intl4_shim); 93 | packet.emit(hdr.int_header); 94 | packet.emit(hdr.int_switch_id); 95 | packet.emit(hdr.int_level1_port_ids); 96 | packet.emit(hdr.int_hop_latency); 97 | packet.emit(hdr.int_q_occupancy); 98 | packet.emit(hdr.int_ingress_tstamp); 99 | packet.emit(hdr.int_egress_tstamp); 100 | packet.emit(hdr.int_level2_port_ids); 101 | packet.emit(hdr.int_egress_tx_util); 102 | 103 | packet.emit(hdr.int_data); 104 | 105 | } 106 | } 107 | 108 | /************************************************************************* 109 | **************** E G R E S S P R O C E S S I N G ******************* 110 | *************************************************************************/ 111 | 112 | parser MyEgressParser(packet_in packet, 113 | out headers hdr, 114 | out local_metadata_t local_metadata, 115 | out egress_intrinsic_metadata_t eg_intr_md) { 116 | 117 | state start { 118 | packet.extract(eg_intr_md); 119 | transition parse_metadata; 120 | } 121 | 122 | state parse_metadata { 123 | mirror_h mirror_md = packet.lookahead(); 124 | transition select(mirror_md.pkt_type) { 125 | PKT_TYPE_MIRROR : parse_mirror_md; 126 | default : parse_ethernet; 127 | } 128 | } 129 | 130 | state parse_mirror_md { 131 | mirror_h mirror_md; 132 | packet.extract(hdr.mirror_header); 133 | local_metadata.mirror = _TRUE; 134 | transition parse_ethernet_mirror; 135 | } 136 | 137 | state parse_ethernet { 138 | packet.extract(hdr.local_report_header); 139 | packet.extract(hdr.ethernet); 140 | transition select(hdr.ethernet.ether_type) { 141 | TYPE_IPV4: parse_ipv4; 142 | default: accept; 143 | } 144 | } 145 | 146 | state parse_ethernet_mirror { 147 | packet.extract(hdr.ethernet); 148 | transition select(hdr.ethernet.ether_type) { 149 | TYPE_IPV4: parse_ipv4; 150 | default: accept; 151 | } 152 | } 153 | 154 | state parse_ipv4 { 155 | packet.extract(hdr.ipv4); 156 | transition select(hdr.ipv4.protocol) { 157 | IP_PROTO_UDP: parse_udp; 158 | IP_PROTO_TCP: parse_tcp; 159 | default: accept; 160 | } 161 | } 162 | 163 | state parse_udp { 164 | packet.extract(hdr.udp); 165 | local_metadata.l4_src_port = hdr.udp.src_port; 166 | local_metadata.l4_dst_port = hdr.udp.dst_port; 167 | transition select(hdr.ipv4.dscp) { 168 | DSCP_INT &&& DSCP_MASK: parse_shim; 169 | default: accept; 170 | } 171 | } 172 | 173 | state parse_tcp { 174 | packet.extract(hdr.tcp); 175 | local_metadata.l4_src_port = hdr.tcp.src_port; 176 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 177 | transition select(hdr.ipv4.dscp) { 178 | DSCP_INT &&& DSCP_MASK: parse_shim; 179 | default: accept; 180 | } 181 | } 182 | 183 | state parse_shim { 184 | packet.extract(hdr.intl4_shim); 185 | transition parse_int_hdr; 186 | } 187 | 188 | state parse_int_hdr { 189 | packet.extract(hdr.int_header); 190 | transition parse_int_data; 191 | } 192 | 193 | state parse_int_data { 194 | 195 | // packet.extract(hdr.int_data); // if INT node is a source or transit node, no need to extract int data here. only for sink node. 196 | packet.extract(hdr.int_data); 197 | transition select(hdr.mirror_header.pkt_type) { 198 | PKT_TYPE_MIRROR : parse_advance; 199 | default : accept; 200 | } 201 | } 202 | 203 | // if mirrored packet, skip over the rest of the payload as we are only interested in the int metadata 204 | state parse_advance { 205 | packet.advance(PACKET_ADVANCE); 206 | transition accept; 207 | } 208 | } 209 | 210 | /************************************************************************* 211 | *********************** D E P A R S E R ******************************* 212 | *************************************************************************/ 213 | 214 | control MyEgressDeparser(packet_out packet, 215 | inout headers hdr, 216 | in local_metadata_t local_metadata, 217 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) { 218 | 219 | Checksum() ipv4Checksum; 220 | 221 | apply { 222 | 223 | hdr.ipv4.hdr_checksum = ipv4Checksum.update( 224 | { 225 | hdr.ipv4.version, 226 | hdr.ipv4.ihl, 227 | hdr.ipv4.dscp, 228 | hdr.ipv4.ecn, 229 | hdr.ipv4.len, 230 | hdr.ipv4.identification, 231 | hdr.ipv4.flags, 232 | hdr.ipv4.frag_offset, 233 | hdr.ipv4.ttl, 234 | hdr.ipv4.protocol, 235 | hdr.ipv4.src_addr, 236 | hdr.ipv4.dst_addr 237 | } 238 | ); 239 | 240 | packet.emit(hdr.report_ethernet); 241 | packet.emit(hdr.report_ipv4); 242 | packet.emit(hdr.report_udp); 243 | packet.emit(hdr.report_group_header); 244 | 245 | packet.emit(hdr.ethernet); 246 | packet.emit(hdr.ipv4); 247 | packet.emit(hdr.udp); 248 | packet.emit(hdr.tcp); 249 | 250 | packet.emit(hdr.intl4_shim); 251 | packet.emit(hdr.int_header); 252 | packet.emit(hdr.int_switch_id); 253 | packet.emit(hdr.int_level1_port_ids); 254 | packet.emit(hdr.int_hop_latency); 255 | packet.emit(hdr.int_q_occupancy); 256 | packet.emit(hdr.int_ingress_tstamp); 257 | packet.emit(hdr.int_egress_tstamp); 258 | packet.emit(hdr.int_level2_port_ids); 259 | packet.emit(hdr.int_egress_tx_util); 260 | 261 | packet.emit(hdr.int_data); 262 | 263 | } 264 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/sink.p4: -------------------------------------------------------------------------------- 1 | control process_set_sink ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in egress_intrinsic_metadata_t eg_intr_md) { 5 | 6 | action int_set_sink () { 7 | local_metadata.int_meta.sink = _TRUE; 8 | } 9 | 10 | table tb_set_sink { 11 | key = { 12 | eg_intr_md.egress_port: exact; 13 | } 14 | actions = { 15 | int_set_sink; 16 | NoAction(); 17 | } 18 | const default_action = NoAction(); 19 | size = MAX_PORTS; 20 | } 21 | 22 | apply { 23 | tb_set_sink.apply(); 24 | } 25 | } 26 | 27 | control process_int_sink ( 28 | inout headers hdr, 29 | inout local_metadata_t local_metadata) { 30 | 31 | action restore_header () { 32 | hdr.ipv4.dscp = hdr.intl4_shim.udp_ip_dscp; 33 | hdr.ipv4.len = hdr.ipv4.len - SHIM_LEN; 34 | hdr.udp.length_ = hdr.udp.length_ - SHIM_LEN; 35 | 36 | } 37 | 38 | 39 | action int_sink() { 40 | // remove all the INT information from the packet 41 | hdr.int_header.setInvalid(); 42 | hdr.int_data.setInvalid(); 43 | hdr.intl4_shim.setInvalid(); 44 | } 45 | 46 | apply { 47 | restore_header(); 48 | int_sink(); 49 | } 50 | } 51 | 52 | control process_int_report ( 53 | inout headers hdr, 54 | inout local_metadata_t local_metadata, 55 | in egress_intrinsic_metadata_t eg_intr_md, 56 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 57 | 58 | // Register for sequence number 59 | Register, _>(1) counter; 60 | RegisterAction, _, bit<32>>(counter) counter_incr = { 61 | void apply(inout bit<32> value, out bit<32> read_value){ 62 | bit<32> in_value = value; 63 | value = in_value + 1; 64 | read_value = value; 65 | } 66 | }; 67 | 68 | action do_report_encapsulation(mac_t src_mac, mac_t mon_mac, ip_address_t src_ip, 69 | ip_address_t mon_ip, l4_port_t mon_port) { 70 | //Report Ethernet Header 71 | hdr.report_ethernet.setValid(); 72 | hdr.report_ethernet.dst_addr = mon_mac; 73 | hdr.report_ethernet.src_addr = src_mac; 74 | hdr.report_ethernet.ether_type = ETH_TYPE_IPV4; 75 | 76 | //Report IPV4 Header 77 | hdr.report_ipv4.setValid(); 78 | hdr.report_ipv4.version = IP_VERSION_4; 79 | hdr.report_ipv4.ihl = IPV4_IHL_MIN; 80 | hdr.report_ipv4.dscp = 6w0; 81 | hdr.report_ipv4.ecn = 2w0; 82 | 83 | // 20 + 8 + 16 + 14 + 20 + 8 + / 4 + 8 + (36 * #hops) / 84 84 | hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + 85 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + INT_DATA_LEN; 86 | 87 | hdr.report_ipv4.identification = 0; 88 | hdr.report_ipv4.flags = 0; 89 | hdr.report_ipv4.frag_offset = 0; 90 | hdr.report_ipv4.ttl = REPORT_HDR_TTL; 91 | hdr.report_ipv4.protocol = IP_PROTO_UDP; 92 | hdr.report_ipv4.src_addr = src_ip; 93 | hdr.report_ipv4.dst_addr = mon_ip; 94 | 95 | //Report UDP Header 96 | hdr.report_udp.setValid(); 97 | hdr.report_udp.src_port = 1234; 98 | hdr.report_udp.dst_port = mon_port; 99 | hdr.report_udp.length_ = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + 100 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + 101 | INT_DATA_LEN; 102 | 103 | hdr.report_group_header.setValid(); 104 | hdr.report_group_header.ver = 2; 105 | hdr.report_group_header.hw_id = HW_ID; 106 | hdr.report_group_header.seq_no = 0; 107 | // TODO: 108 | // (bit<22>) counter_incr.execute(0); 109 | hdr.report_group_header.node_id = local_metadata.int_meta.switch_id; 110 | 111 | 112 | /* Telemetry Report Individual Header */ 113 | hdr.report_individual_header.setValid(); 114 | hdr.report_individual_header.rep_type = 1; 115 | hdr.report_individual_header.in_type = 4; 116 | hdr.report_individual_header.len = 0; 117 | hdr.report_individual_header.rep_md_len = 0; 118 | hdr.report_individual_header.d = 0; 119 | hdr.report_individual_header.q = 0; 120 | hdr.report_individual_header.f = 1; 121 | hdr.report_individual_header.i = 1; 122 | hdr.report_individual_header.rsvd = 0; 123 | 124 | /* Individual report inner contents */ 125 | 126 | hdr.report_individual_header.rep_md_bits = 0; 127 | hdr.report_individual_header.domain_specific_id = 0; 128 | hdr.report_individual_header.domain_specific_md_bits = 0; 129 | hdr.report_individual_header.domain_specific_md_status = 0; 130 | 131 | } 132 | 133 | table tb_generate_report { 134 | // key = { 135 | // } 136 | actions = { 137 | do_report_encapsulation; 138 | NoAction(); 139 | } 140 | default_action = NoAction(); 141 | } 142 | 143 | apply { 144 | tb_generate_report.apply(); 145 | } 146 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/source.p4: -------------------------------------------------------------------------------- 1 | control process_int_source_sink ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in ingress_intrinsic_metadata_t ig_intr_md, 5 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 6 | 7 | action int_set_source () { 8 | local_metadata.int_meta.source = _TRUE; 9 | } 10 | 11 | action int_set_sink () { 12 | local_metadata.int_meta.sink = _TRUE; 13 | } 14 | 15 | table tb_set_source { 16 | key = { 17 | ig_intr_md.ingress_port: exact; 18 | } 19 | actions = { 20 | int_set_source; 21 | NoAction(); 22 | } 23 | const default_action = NoAction(); 24 | size = MAX_PORTS; 25 | } 26 | table tb_set_sink { 27 | key = { 28 | ig_tm_md.ucast_egress_port: exact; 29 | } 30 | actions = { 31 | int_set_sink; 32 | NoAction(); 33 | } 34 | const default_action = NoAction(); 35 | size = MAX_PORTS; 36 | } 37 | 38 | apply { 39 | tb_set_source.apply(); 40 | tb_set_sink.apply(); 41 | } 42 | } 43 | 44 | // Insert INT header to the packet 45 | control process_int_source ( 46 | inout headers hdr, 47 | inout local_metadata_t local_metadata) { 48 | 49 | action int_source(bit<5> hop_metadata_len, bit<8> remaining_hop_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) { 50 | 51 | hdr.intl4_shim.setValid(); // insert INT shim header 52 | hdr.intl4_shim.int_type = 3; // int_type: Hop-by-hop type (1) , destination type (2), MX-type (3) 53 | hdr.intl4_shim.npt = 0; // next protocol type: 0 54 | hdr.intl4_shim.len = INT_HEADER_LEN_WORD; // This is 3 from 0xC (INT_TOTAL_HEADER_SIZE >> 2) 55 | hdr.intl4_shim.udp_ip_dscp = hdr.ipv4.dscp; // although should be first 6 bits of the second byte 56 | hdr.intl4_shim.udp_ip = 0; // although should be first 6 bits of the second byte 57 | 58 | // insert INT header 59 | hdr.int_header.setValid(); 60 | hdr.int_header.ver = 2; 61 | hdr.int_header.d = 0; 62 | hdr.int_header.e = 0; 63 | hdr.int_header.m = 0; 64 | hdr.int_header.rsvd1 = 0; 65 | hdr.int_header.hop_metadata_len = hop_metadata_len; 66 | hdr.int_header.remaining_hop_cnt = remaining_hop_cnt; 67 | hdr.int_header.instruction_mask_0003 = ins_mask0003; 68 | hdr.int_header.instruction_mask_0407 = ins_mask0407; 69 | hdr.int_header.instruction_mask_0811 = 0; // not supported 70 | hdr.int_header.instruction_mask_1215 = 0; // not supported 71 | 72 | hdr.int_header.domain_specific_id = 0; // Unique INT Domain ID 73 | hdr.int_header.ds_instruction = 0; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 74 | hdr.int_header.ds_flags = 0; // Domain specific flags 75 | 76 | // add the header len (3 words) to total len 77 | hdr.ipv4.len = hdr.ipv4.len + INT_TOTAL_HEADER_SIZE; 78 | hdr.udp.length_ = hdr.udp.length_ + INT_TOTAL_HEADER_SIZE; 79 | 80 | hdr.ipv4.dscp = DSCP_INT; 81 | } 82 | 83 | table tb_int_source { 84 | key = { 85 | //configure for each flow to be monitored 86 | // 4 fields identifying flow 87 | //include ip src, udp/tcp src and dest too 88 | hdr.ipv4.dst_addr: lpm; 89 | } 90 | actions = { 91 | int_source; 92 | NoAction; 93 | } 94 | const default_action = NoAction(); 95 | } 96 | 97 | apply { 98 | tb_int_source.apply(); 99 | } 100 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int/transit.p4: -------------------------------------------------------------------------------- 1 | control process_int_transit ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in egress_intrinsic_metadata_t eg_intr_md, 5 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 6 | 7 | action init_metadata(switch_id_t switch_id) { 8 | local_metadata.int_meta.transit = _TRUE; 9 | local_metadata.int_meta.switch_id = switch_id; 10 | } 11 | 12 | 13 | action int_set_header_0() { //switch_id 14 | hdr.int_switch_id.setValid(); 15 | hdr.int_switch_id.switch_id = local_metadata.int_meta.switch_id; 16 | } 17 | 18 | action int_set_header_1() { //level1_port_id - physical port 19 | hdr.int_level1_port_ids.setValid(); 20 | hdr.int_level1_port_ids.ingress_port_id = (bit<16>) hdr.local_report_header.ingress_port_id; 21 | hdr.int_level1_port_ids.egress_port_id = (bit<16>) eg_intr_md.egress_port; 22 | } 23 | 24 | action int_set_header_2() { //hop_latency 25 | hdr.int_hop_latency.setValid(); 26 | hdr.int_hop_latency.hop_latency = (bit<32>) ( (bit<64>) eg_prsr_md.global_tstamp - hdr.local_report_header.ingress_global_tstamp); 27 | } 28 | 29 | action int_set_header_3() { //q_occupancy 30 | hdr.int_q_occupancy.setValid(); 31 | hdr.int_q_occupancy.q_id = 32 | (bit<8>) hdr.local_report_header.queue_id; 33 | hdr.int_q_occupancy.q_occupancy = 34 | (bit<24>) eg_intr_md.deq_qdepth; 35 | } 36 | 37 | action int_set_header_4() { //ingress_tstamp 38 | hdr.int_ingress_tstamp.setValid(); 39 | hdr.int_ingress_tstamp.ingress_tstamp = 40 | (bit<64>) hdr.local_report_header.ingress_global_tstamp; 41 | } 42 | 43 | action int_set_header_5() { //egress_timestamp 44 | hdr.int_egress_tstamp.setValid(); 45 | hdr.int_egress_tstamp.egress_tstamp = 46 | (bit<64>) eg_prsr_md.global_tstamp; 47 | } 48 | 49 | action int_set_header_6() { //level2_port_id 50 | hdr.int_level2_port_ids.setValid(); 51 | // level2_port_id indicates Logical port ID - update this! 52 | hdr.int_level2_port_ids.ingress_port_id = (bit<32>) local_metadata.l4_src_port; 53 | hdr.int_level2_port_ids.egress_port_id = (bit<32>) local_metadata.l4_dst_port; 54 | } 55 | 56 | action int_set_header_7() { // queueing latency 57 | hdr.int_egress_tx_util.setValid(); 58 | hdr.int_egress_tx_util.egress_port_tx_util = 59 | (bit<32>) eg_intr_md.deq_timedelta; 60 | } 61 | 62 | // Actions to keep track of the new metadata added. 63 | 64 | action add_1() { 65 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 1; 66 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 4; 67 | } 68 | 69 | 70 | action add_2() { 71 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 2; 72 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 8; 73 | } 74 | 75 | 76 | action add_3() { 77 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 3; 78 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 12; 79 | } 80 | 81 | 82 | action add_4() { 83 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 4; 84 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 16; 85 | } 86 | 87 | 88 | action add_5() { 89 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 5; 90 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 20; 91 | } 92 | 93 | /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */ 94 | /* Each bit set indicates that corresponding INT header should be added */ 95 | 96 | action int_set_header_0003_i0() { 97 | } 98 | 99 | action int_set_header_0003_i1() { 100 | int_set_header_3(); 101 | add_1(); 102 | } 103 | 104 | action int_set_header_0003_i2() { 105 | int_set_header_2(); 106 | add_1(); 107 | } 108 | 109 | action int_set_header_0003_i3() { 110 | int_set_header_3(); 111 | int_set_header_2(); 112 | add_2(); 113 | } 114 | 115 | action int_set_header_0003_i4() { 116 | int_set_header_1(); 117 | add_1(); 118 | } 119 | 120 | action int_set_header_0003_i5() { 121 | int_set_header_3(); 122 | int_set_header_1(); 123 | add_2(); 124 | } 125 | 126 | action int_set_header_0003_i6() { 127 | int_set_header_2(); 128 | int_set_header_1(); 129 | add_2(); 130 | } 131 | 132 | action int_set_header_0003_i7() { 133 | int_set_header_3(); 134 | int_set_header_2(); 135 | int_set_header_1(); 136 | add_3(); 137 | } 138 | 139 | action int_set_header_0003_i8() { 140 | int_set_header_0(); 141 | add_1(); 142 | } 143 | 144 | action int_set_header_0003_i9() { 145 | int_set_header_3(); 146 | int_set_header_0(); 147 | add_2(); 148 | } 149 | 150 | action int_set_header_0003_i10() { 151 | int_set_header_2(); 152 | int_set_header_0(); 153 | add_2(); 154 | } 155 | 156 | action int_set_header_0003_i11() { 157 | int_set_header_3(); 158 | int_set_header_2(); 159 | int_set_header_0(); 160 | add_3(); 161 | } 162 | 163 | action int_set_header_0003_i12() { 164 | int_set_header_1(); 165 | int_set_header_0(); 166 | add_2(); 167 | } 168 | 169 | action int_set_header_0003_i13() { 170 | int_set_header_3(); 171 | int_set_header_1(); 172 | int_set_header_0(); 173 | add_3(); 174 | } 175 | 176 | action int_set_header_0003_i14() { 177 | int_set_header_2(); 178 | int_set_header_1(); 179 | int_set_header_0(); 180 | add_3(); 181 | } 182 | 183 | action int_set_header_0003_i15() { 184 | int_set_header_3(); 185 | int_set_header_2(); 186 | int_set_header_1(); 187 | int_set_header_0(); 188 | add_4(); 189 | } 190 | 191 | /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */ 192 | 193 | action int_set_header_0407_i0() { 194 | } 195 | 196 | action int_set_header_0407_i1() { 197 | int_set_header_7(); 198 | add_1(); 199 | } 200 | 201 | action int_set_header_0407_i2() { 202 | int_set_header_6(); 203 | add_2(); 204 | } 205 | 206 | action int_set_header_0407_i3() { 207 | int_set_header_7(); 208 | int_set_header_6(); 209 | add_3(); 210 | } 211 | 212 | action int_set_header_0407_i4() { 213 | int_set_header_5(); 214 | add_1(); 215 | } 216 | 217 | action int_set_header_0407_i5() { 218 | int_set_header_7(); 219 | int_set_header_5(); 220 | add_2(); 221 | } 222 | 223 | action int_set_header_0407_i6() { 224 | int_set_header_6(); 225 | int_set_header_5(); 226 | add_3(); 227 | } 228 | 229 | action int_set_header_0407_i7() { 230 | int_set_header_7(); 231 | int_set_header_6(); 232 | int_set_header_5(); 233 | add_4(); 234 | } 235 | 236 | action int_set_header_0407_i8() { 237 | int_set_header_4(); 238 | add_1(); 239 | } 240 | 241 | action int_set_header_0407_i9() { 242 | int_set_header_7(); 243 | int_set_header_4(); 244 | add_2(); 245 | } 246 | 247 | action int_set_header_0407_i10() { 248 | int_set_header_6(); 249 | int_set_header_4(); 250 | add_3(); 251 | } 252 | 253 | action int_set_header_0407_i11() { 254 | int_set_header_7(); 255 | int_set_header_6(); 256 | int_set_header_4(); 257 | add_4(); 258 | } 259 | 260 | action int_set_header_0407_i12() { 261 | int_set_header_5(); 262 | int_set_header_4(); 263 | add_2(); 264 | } 265 | 266 | action int_set_header_0407_i13() { 267 | int_set_header_7(); 268 | int_set_header_5(); 269 | int_set_header_4(); 270 | add_3(); 271 | } 272 | 273 | action int_set_header_0407_i14() { 274 | int_set_header_6(); 275 | int_set_header_5(); 276 | int_set_header_4(); 277 | add_4(); 278 | } 279 | 280 | action int_set_header_0407_i15() { 281 | int_set_header_7(); 282 | int_set_header_6(); 283 | int_set_header_5(); 284 | int_set_header_4(); 285 | add_5(); 286 | } 287 | 288 | // Default action used to set switch ID. 289 | table tb_int_insert { 290 | // key = { 291 | // } 292 | actions = { 293 | init_metadata; 294 | NoAction; 295 | } 296 | default_action = NoAction(); 297 | size = 1; 298 | } 299 | 300 | /* Table to process instruction bits 0-3 */ 301 | 302 | table tb_int_inst_0003 { 303 | key = { 304 | hdr.int_header.instruction_mask_0003 : exact; 305 | } 306 | actions = { 307 | int_set_header_0003_i0; 308 | int_set_header_0003_i1; 309 | int_set_header_0003_i2; 310 | int_set_header_0003_i3; 311 | int_set_header_0003_i4; 312 | int_set_header_0003_i5; 313 | int_set_header_0003_i6; 314 | int_set_header_0003_i7; 315 | int_set_header_0003_i8; 316 | int_set_header_0003_i9; 317 | int_set_header_0003_i10; 318 | int_set_header_0003_i11; 319 | int_set_header_0003_i12; 320 | int_set_header_0003_i13; 321 | int_set_header_0003_i14; 322 | int_set_header_0003_i15; 323 | } 324 | 325 | const entries = { 326 | (0x0) : int_set_header_0003_i0(); 327 | (0x1) : int_set_header_0003_i1(); 328 | (0x2) : int_set_header_0003_i2(); 329 | (0x3) : int_set_header_0003_i3(); 330 | (0x4) : int_set_header_0003_i4(); 331 | (0x5) : int_set_header_0003_i5(); 332 | (0x6) : int_set_header_0003_i6(); 333 | (0x7) : int_set_header_0003_i7(); 334 | (0x8) : int_set_header_0003_i8(); 335 | (0x9) : int_set_header_0003_i9(); 336 | (0xA) : int_set_header_0003_i10(); 337 | (0xB) : int_set_header_0003_i11(); 338 | (0xC) : int_set_header_0003_i12(); 339 | (0xD) : int_set_header_0003_i13(); 340 | (0xE) : int_set_header_0003_i14(); 341 | (0xF) : int_set_header_0003_i15(); 342 | } 343 | size = 16; 344 | } 345 | 346 | /* Table to process instruction bits 4-7 */ 347 | 348 | table tb_int_inst_0407 { 349 | key = { 350 | hdr.int_header.instruction_mask_0407 : exact; 351 | } 352 | actions = { 353 | int_set_header_0407_i0; 354 | int_set_header_0407_i1; 355 | int_set_header_0407_i2; 356 | int_set_header_0407_i3; 357 | int_set_header_0407_i4; 358 | int_set_header_0407_i5; 359 | int_set_header_0407_i6; 360 | int_set_header_0407_i7; 361 | int_set_header_0407_i8; 362 | int_set_header_0407_i9; 363 | int_set_header_0407_i10; 364 | int_set_header_0407_i11; 365 | int_set_header_0407_i12; 366 | int_set_header_0407_i13; 367 | int_set_header_0407_i14; 368 | int_set_header_0407_i15; 369 | } 370 | 371 | const entries = { 372 | (0x0) : int_set_header_0407_i0(); 373 | (0x1) : int_set_header_0407_i1(); 374 | (0x2) : int_set_header_0407_i2(); 375 | (0x3) : int_set_header_0407_i3(); 376 | (0x4) : int_set_header_0407_i4(); 377 | (0x5) : int_set_header_0407_i5(); 378 | (0x6) : int_set_header_0407_i6(); 379 | (0x7) : int_set_header_0407_i7(); 380 | (0x8) : int_set_header_0407_i8(); 381 | (0x9) : int_set_header_0407_i9(); 382 | (0xA) : int_set_header_0407_i10(); 383 | (0xB) : int_set_header_0407_i11(); 384 | (0xC) : int_set_header_0407_i12(); 385 | (0xD) : int_set_header_0407_i13(); 386 | (0xE) : int_set_header_0407_i14(); 387 | (0xF) : int_set_header_0407_i15(); 388 | } 389 | size = 16; 390 | } 391 | 392 | apply { 393 | tb_int_insert.apply(); 394 | if (local_metadata.int_meta.transit == _FALSE) { 395 | return; 396 | } 397 | tb_int_inst_0003.apply(); 398 | tb_int_inst_0407.apply(); 399 | 400 | // Decrement remaining hop cnt 401 | hdr.int_header.remaining_hop_cnt = hdr.int_header.remaining_hop_cnt - 1; 402 | 403 | // Update headers lengths. 404 | if (hdr.ipv4.isValid()) { 405 | hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.new_bytes; 406 | } 407 | if (hdr.udp.isValid()) { 408 | hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.new_bytes; 409 | } 410 | if (hdr.intl4_shim.isValid()) { 411 | // 9 words if add 4 + add 5 412 | hdr.intl4_shim.len = hdr.intl4_shim.len + local_metadata.int_meta.new_words; 413 | } 414 | } 415 | } -------------------------------------------------------------------------------- /int-md-2-1/p4src/int_md_2_1.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * This file has been modified. 19 | * Modifications Copyright © 2021 Saab AB / Mandar Joshi 20 | */ 21 | 22 | /* 23 | * This program is free software: you can redistribute it and/or modify 24 | * it under the terms of the GNU General Public License as published by 25 | * the Free Software Foundation, either version 2 of the License, or 26 | * (at your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | * GNU General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program. If not, see . 35 | */ 36 | 37 | 38 | /* -*- P4_16 -*- */ 39 | 40 | #include 41 | #include 42 | 43 | #include "int/headers.p4" 44 | #include "int/parsers.p4" 45 | #include "int/sink.p4" 46 | #include "int/transit.p4" 47 | #include "int/source.p4" 48 | #include "int/forward.p4" 49 | 50 | /************************************************************************* 51 | **************** I N G R E S S P R O C E S S I N G ****************** 52 | *************************************************************************/ 53 | 54 | control MyIngress(inout headers hdr, 55 | inout local_metadata_t local_metadata, 56 | in ingress_intrinsic_metadata_t ig_intr_md, 57 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 58 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 59 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 60 | 61 | 62 | apply { 63 | 64 | port_forward.apply(hdr, local_metadata, ig_tm_md, ig_dprsr_md); 65 | 66 | process_int_source_sink.apply(hdr, local_metadata, ig_intr_md, ig_tm_md); 67 | 68 | if (local_metadata.int_meta.source == _TRUE) { 69 | process_int_source.apply(hdr, local_metadata); 70 | } 71 | 72 | if (local_metadata.int_meta.sink == _TRUE && hdr.int_header.isValid()) { 73 | // clone packet for Telemetry Report 74 | ig_dprsr_md.mirror_type = MIRROR_TYPE_I2E; 75 | local_metadata.pkt_type = PKT_TYPE_MIRROR; 76 | local_metadata.ing_mir_ses = (bit<10>) MIRROR_TYPE_I2E; 77 | } 78 | 79 | if (hdr.int_header.isValid()) { 80 | // Save ingress parser values for egress / INT Transit 81 | hdr.local_report_header.setValid(); 82 | hdr.local_report_header.ingress_port_id = (bit<16>) ig_intr_md.ingress_port; 83 | hdr.local_report_header.queue_id = (bit<8>) ig_tm_md.qid; 84 | hdr.local_report_header.ingress_global_tstamp = (bit<64>) ig_intr_md.ingress_mac_tstamp; 85 | } 86 | } 87 | } 88 | 89 | /************************************************************************* 90 | **************** E G R E S S P R O C E S S I N G ******************* 91 | *************************************************************************/ 92 | 93 | 94 | control MyEgress(inout headers hdr, 95 | inout local_metadata_t local_metadata, 96 | in egress_intrinsic_metadata_t eg_intr_md, 97 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 98 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 99 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 100 | 101 | apply { 102 | if(hdr.int_header.isValid()) { 103 | 104 | process_set_sink.apply(hdr, local_metadata, eg_intr_md); 105 | 106 | if (local_metadata.int_meta.sink == _TRUE) { 107 | process_int_sink.apply(hdr, local_metadata); 108 | 109 | } else if (local_metadata.int_meta.sink == _FALSE) { 110 | if(hdr.mirror_header.isValid()) { 111 | hdr.local_report_header.ingress_port_id = hdr.mirror_header.ingress_port_id; 112 | hdr.local_report_header.queue_id = hdr.mirror_header.queue_id; 113 | hdr.local_report_header.ingress_global_tstamp = hdr.mirror_header.ingress_global_tstamp; 114 | } 115 | process_int_transit.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 116 | } 117 | 118 | if (local_metadata.mirror == _TRUE) { // Packet is a mirror 119 | process_int_report.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 120 | } 121 | } 122 | 123 | hdr.local_report_header.setInvalid(); 124 | hdr.mirror_header.setInvalid(); 125 | } 126 | } 127 | 128 | /************************************************************************* 129 | *********************** S W I T C H ******************************* 130 | *************************************************************************/ 131 | 132 | Pipeline( 133 | MyIngressParser(), 134 | MyIngress(), 135 | MyIngressDeparser(), 136 | MyEgressParser(), 137 | MyEgress(), 138 | MyEgressDeparser() 139 | ) pipe; 140 | 141 | Switch(pipe) main; -------------------------------------------------------------------------------- /int-mx/README.md: -------------------------------------------------------------------------------- 1 | # In-Band Network Telemetry Implementation in P4 2 | 3 | **INT-MX - eMbed Instruct(X)ions** 4 | 5 | ## Build 6 | 7 | The P4 code can be compiled by using the build script in the SDE 8 | ``` 9 | ./p4_build.sh int_mx.p4 10 | ``` 11 | 12 | The following topology can be referred to for the INT-MX mode of operation: 13 | ![INT-MX](../figures/int-mx.png) 14 | 15 | ## Usage 16 | 17 | Run the P4 code as follows 18 | ``` 19 | $SDE/run_switchd.sh -p int_mx 20 | ``` 21 | 22 | ### Populating the tables and registers 23 | 24 | In another window for each switch, the following command can be run depending on the role of the INT node 25 | ``` 26 | $SDE/run_bfshell.sh -b $P4-INT/int-mx/bfrt_python/bfswitch1.py 27 | ``` 28 | 29 | ### Testing the INT program 30 | 31 | Packets can be sent from server1, and tcpdump/wireshark can be used to see the output at the monitoring server and the receiver 32 | 33 | -------------------------------------------------------------------------------- /int-mx/bfrt_python/bfswitch1.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_mx.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=32) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=48) 5 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source(dst_addr="10.0.0.0", dst_addr_p_length=24, ins_mask0003=15, ins_mask0407=15) 6 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=1) 7 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.2", src_mac="02:42:ac:1c:00:03") 8 | 9 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=292, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-mx/bfrt_python/bfswitch2.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_mx.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=144) 4 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=2) 5 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.3", src_mac="02:42:ac:1c:00:45") 6 | 7 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=292, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-mx/bfrt_python/bfswitch3.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_mx.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=396) 4 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=396) 5 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=3) 6 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.4", src_mac="02:42:ac:1c:00:67") 7 | 8 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=397, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-mx/p4src/int/forward.p4: -------------------------------------------------------------------------------- 1 | control port_forward(inout headers hdr, 2 | inout local_metadata_t local_metadata, 3 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md, 4 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 5 | 6 | action send_to_cpu() { 7 | ig_tm_md.ucast_egress_port = CPU_PORT; 8 | } 9 | 10 | action set_egress_port(port_t port) { 11 | ig_tm_md.ucast_egress_port = port; 12 | } 13 | 14 | action drop() { 15 | ig_dprsr_md.drop_ctl = 1; 16 | } 17 | 18 | table tb_port_forward { 19 | key = { 20 | hdr.ipv4.dst_addr : lpm; 21 | } 22 | actions = { 23 | set_egress_port; 24 | send_to_cpu; 25 | drop; 26 | } 27 | const default_action = drop(); 28 | } 29 | 30 | apply { 31 | tb_port_forward.apply(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /int-mx/p4src/int/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ************* C O N S T A N T S A N D T Y P E S ******************* 3 | **************************************************************************/ 4 | 5 | #define MAX_INT_HEADERS 9 6 | #define MAX_HOP_COUNT 3 7 | #define NUM_INSTRUCTIONS 3 8 | 9 | #define ETH_TYPE_IPV4 0x0800 10 | #define IP_VERSION_4 4w4 11 | #define MAX_PORTS 511 12 | #define IPV4_IHL_MIN 4w5 13 | 14 | #ifndef _BOOL 15 | #define _BOOL bool 16 | #endif 17 | #ifndef _TRUE 18 | #define _TRUE true 19 | #endif 20 | #ifndef _FALSE 21 | #define _FALSE false 22 | #endif 23 | 24 | const bit<6> HW_ID = 1; 25 | 26 | const bit<16> TYPE_IPV4 = 0x0800; 27 | const bit<8> IP_PROTO_UDP = 0x11; 28 | const bit<8> IP_PROTO_TCP = 0x6; 29 | const bit<16> INT_PORT = 5000; 30 | const bit<16> SHIM_LEN = 12; 31 | 32 | const bit<6> DSCP_INT = 0x17; 33 | const bit<6> DSCP_MASK = 0x3F; 34 | 35 | typedef bit<48> mac_t; 36 | typedef bit<32> ip_address_t; 37 | typedef bit<16> l4_port_t; 38 | typedef bit<9> port_t; 39 | 40 | const bit<8> INT_HEADER_LEN_WORD = 3; 41 | const bit<8> REPORT_HDR_TTL = 64; 42 | const port_t CPU_PORT = 255; 43 | 44 | const bit<3> NPROTO_ETHERNET = 0; 45 | const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1; 46 | const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2; 47 | 48 | const bit<5> IPV4_OPTION_INT = 31; 49 | 50 | // Mirroring defs 51 | typedef bit<3> mirror_type_t; 52 | typedef bit<8> pkt_type_t; 53 | 54 | const mirror_type_t MIRROR_TYPE_I2E = 1; 55 | const mirror_type_t MIRROR_TYPE_E2E = 2; 56 | const pkt_type_t PKT_TYPE_NORMAL = 1; 57 | const pkt_type_t PKT_TYPE_MIRROR = 2; 58 | 59 | typedef bit<32> switch_id_t; 60 | typedef bit<48> timestamp_t; 61 | typedef bit<6> output_port_t; 62 | 63 | /************************************************************************* 64 | *********************** H E A D E R S *********************************** 65 | *************************************************************************/ 66 | 67 | header ethernet_t { 68 | bit<48> dst_addr; 69 | bit<48> src_addr; 70 | bit<16> ether_type; 71 | } 72 | 73 | const bit<8> ETH_HEADER_LEN = 14; 74 | 75 | header ipv4_t { 76 | bit<4> version; 77 | bit<4> ihl; 78 | bit<6> dscp; 79 | bit<2> ecn; 80 | bit<16> len; 81 | bit<16> identification; 82 | bit<3> flags; 83 | bit<13> frag_offset; 84 | bit<8> ttl; 85 | bit<8> protocol; 86 | bit<16> hdr_checksum; 87 | bit<32> src_addr; 88 | bit<32> dst_addr; 89 | } 90 | 91 | const bit<8> IPV4_MIN_HEAD_LEN = 20; 92 | 93 | 94 | header udp_t { 95 | bit<16> src_port; 96 | bit<16> dst_port; 97 | bit<16> length_; 98 | bit<16> checksum; 99 | } 100 | const bit<8> UDP_HEADER_LEN = 8; 101 | 102 | 103 | header tcp_t { 104 | bit<16> src_port; 105 | bit<16> dst_port; 106 | bit<32> seq_no; 107 | bit<32> ack_no; 108 | bit<4> data_offset; 109 | bit<3> res; 110 | bit<3> ecn; 111 | bit<6> ctrl; 112 | bit<16> window; 113 | bit<16> checksum; 114 | bit<16> urgent_ptr; 115 | } 116 | 117 | const bit<8> TCP_HEADER_LEN = 20; 118 | 119 | // INT shim header for TCP/UDP 120 | header intl4_shim_t { 121 | bit<4> int_type; // Type of INT Header 122 | bit<2> npt; // Next protocol type 123 | bit<2> rsvd; // Reserved 124 | bit<8> len; // Length of INT Metadata header and INT stack in 4-byte words, not including the shim header (1 word) 125 | bit<6> udp_ip_dscp; // depends on npt field. either original dscp, ip protocol or udp dest port 126 | bit<10> udp_ip; // depends on npt field. either original dscp, ip protocol or udp dest port 127 | } 128 | 129 | const bit<16> INT_SHIM_HEADER_SIZE = 4; 130 | 131 | // INT header 132 | header int_header_t { 133 | bit<4> ver; // Version 134 | bit<1> d; // Discard 135 | bit<27> rsvd; // 12 bits reserved, set to 0 136 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 137 | bit<4> instruction_mask_0407; 138 | bit<4> instruction_mask_0811; 139 | bit<4> instruction_mask_1215; 140 | bit<16> domain_specific_id; // Unique INT Domain ID 141 | bit<16> ds_instruction; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 142 | bit<16> ds_flags; // Domain specific flags 143 | // Optional domain specific 'source only' metadata 144 | } 145 | 146 | const bit<16> INT_HEADER_SIZE = 12; 147 | 148 | const bit<16> INT_TOTAL_HEADER_SIZE = 16; // 12 + 4 149 | 150 | 151 | // INT meta-value headers - different header for each value type 152 | header int_switch_id_t { 153 | bit<32> switch_id; 154 | } 155 | header int_level1_port_ids_t { 156 | bit<16> ingress_port_id; 157 | bit<16> egress_port_id; 158 | } 159 | header int_hop_latency_t { 160 | bit<32> hop_latency; 161 | } 162 | header int_q_occupancy_t { 163 | bit<8> q_id; 164 | bit<24> q_occupancy; 165 | } 166 | header int_ingress_tstamp_t { 167 | bit<64> ingress_tstamp; 168 | } 169 | header int_egress_tstamp_t { 170 | bit<64> egress_tstamp; 171 | } 172 | header int_level2_port_ids_t { 173 | bit<32> ingress_port_id; 174 | bit<32> egress_port_id; 175 | } 176 | 177 | // these two not implemented yet 178 | header int_egress_port_tx_util_t { 179 | bit<32> egress_port_tx_util; 180 | } 181 | header int_buffer_t { 182 | bit<8> buffer_id; 183 | bit<24> buffer_occupancy; 184 | } 185 | 186 | // Report Telemetry Headers 187 | header report_group_header_t { 188 | bit<4> ver; 189 | bit<6> hw_id; 190 | bit<22> seq_no; 191 | bit<32> node_id; 192 | } 193 | const bit<8> REPORT_GROUP_HEADER_LEN = 8; 194 | 195 | header report_individual_header_t { 196 | bit<4> rep_type; 197 | bit<4> in_type; 198 | bit<8> len; 199 | bit<8> rep_md_len; 200 | bit<1> d; 201 | bit<1> q; 202 | bit<1> f; 203 | bit<1> i; 204 | bit<4> rsvd; 205 | // Individual report inner contents for Reptype 1 = INT 206 | bit<16> rep_md_bits; 207 | bit<16> domain_specific_id; 208 | bit<16> domain_specific_md_bits; 209 | bit<16> domain_specific_md_status; 210 | } 211 | const bit<8> REPORT_INDIVIDUAL_HEADER_LEN = 12; 212 | 213 | // Telemetry drop report header 214 | header drop_report_header_t { 215 | bit<32> switch_id; 216 | bit<16> ingress_port_id; 217 | bit<16> egress_port_id; 218 | bit<8> queue_id; 219 | bit<8> drop_reason; 220 | bit<16> pad; 221 | } 222 | const bit<8> DROP_REPORT_HEADER_LEN = 12; 223 | 224 | // Switch Local Report Header 225 | header local_report_header_t { 226 | bit<16> ingress_port_id; 227 | bit<16> egress_port_id; 228 | bit<8> queue_id; 229 | bit<8> pad; 230 | bit<64> ingress_global_tstamp; 231 | } 232 | 233 | const bit<8> LOCAL_REPORT_HEADER_LEN = 16; 234 | 235 | header mirror_h { 236 | pkt_type_t pkt_type; 237 | bit<16> ingress_port_id; 238 | bit<16> egress_port_id; 239 | bit<8> queue_id; 240 | bit<64> ingress_global_tstamp; 241 | 242 | bit<4> int_type; // Type of INT Header 243 | bit<2> npt; // Next protocol type 244 | bit<2> int_l4_rsvd; // Reserved 245 | bit<8> len; // Length of INT Metadata header and INT stack in 4-byte words, not including the shim header (1 word) 246 | bit<6> udp_ip_dscp; // depends on npt field. either original dscp, ip protocol or udp dest port 247 | bit<10> udp_ip; // depends on npt field. either original dscp, ip protocol or udp dest port 248 | 249 | bit<4> ver; // Version 250 | bit<1> d; // Discard 251 | bit<27> rsvd; // 12 bits reserved, set to 0 252 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 253 | bit<4> instruction_mask_0407; 254 | bit<4> instruction_mask_0811; 255 | bit<4> instruction_mask_1215; 256 | bit<16> domain_specific_id; // Unique INT Domain ID 257 | bit<16> ds_instruction; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 258 | bit<16> ds_flags; // Domain specific flags 259 | // Optional domain specific 'source only' metadata 260 | } 261 | 262 | struct headers { 263 | 264 | // Original Packet Headers 265 | ethernet_t ethernet; 266 | ipv4_t ipv4; 267 | udp_t udp; 268 | tcp_t tcp; 269 | 270 | // INT Report Encapsulation 271 | ethernet_t report_ethernet; 272 | ipv4_t report_ipv4; 273 | udp_t report_udp; 274 | 275 | // INT Headers 276 | int_header_t int_header; 277 | intl4_shim_t intl4_shim; 278 | int_switch_id_t int_switch_id; 279 | int_level1_port_ids_t int_level1_port_ids; 280 | int_hop_latency_t int_hop_latency; 281 | int_q_occupancy_t int_q_occupancy; 282 | int_ingress_tstamp_t int_ingress_tstamp; 283 | int_egress_tstamp_t int_egress_tstamp; 284 | int_level2_port_ids_t int_level2_port_ids; 285 | int_egress_port_tx_util_t int_egress_tx_util; 286 | 287 | // // INT Report Headers 288 | report_group_header_t report_group_header; 289 | report_individual_header_t report_individual_header; 290 | local_report_header_t local_report_header; 291 | 292 | mirror_h mirror_header; 293 | } 294 | 295 | struct int_metadata_t { 296 | switch_id_t switch_id; 297 | bit<16> new_bytes; 298 | bit<8> new_words; 299 | bool source; 300 | bool sink; 301 | bool transit; 302 | bit<8> intl4_shim_len; 303 | bit<16> int_shim_len; 304 | } 305 | 306 | struct local_metadata_t { 307 | bit<16> l4_src_port; 308 | bit<16> l4_dst_port; 309 | int_metadata_t int_meta; 310 | bool mirror; 311 | pkt_type_t pkt_type; 312 | MirrorId_t ing_mir_ses; // Ingress mirror session ID 313 | MirrorId_t egr_mir_ses; // Egress mirror session ID 314 | } -------------------------------------------------------------------------------- /int-mx/p4src/int/parsers.p4: -------------------------------------------------------------------------------- 1 | 2 | /************************************************************************* 3 | *********************** P A R S E R ******************************* 4 | *************************************************************************/ 5 | 6 | parser MyIngressParser(packet_in packet, 7 | out headers hdr, 8 | out local_metadata_t local_metadata, 9 | out ingress_intrinsic_metadata_t ig_intr_md) { 10 | 11 | state start { 12 | packet.extract(ig_intr_md); 13 | packet.advance(PORT_METADATA_SIZE); 14 | transition parse_ethernet; 15 | } 16 | 17 | state parse_ethernet { 18 | packet.extract(hdr.ethernet); 19 | transition select(hdr.ethernet.ether_type) { 20 | TYPE_IPV4: parse_ipv4; 21 | default: accept; 22 | } 23 | } 24 | 25 | state parse_ipv4 { 26 | packet.extract(hdr.ipv4); 27 | transition select(hdr.ipv4.protocol) { 28 | IP_PROTO_UDP: parse_udp; 29 | IP_PROTO_TCP: parse_tcp; 30 | default: accept; 31 | } 32 | } 33 | 34 | state parse_udp { 35 | packet.extract(hdr.udp); 36 | local_metadata.l4_src_port = hdr.udp.src_port; 37 | local_metadata.l4_dst_port = hdr.udp.dst_port; 38 | transition select(hdr.ipv4.dscp) { 39 | DSCP_INT &&& DSCP_MASK: parse_shim; 40 | default: accept; 41 | } 42 | } 43 | 44 | state parse_tcp { 45 | packet.extract(hdr.tcp); 46 | local_metadata.l4_src_port = hdr.tcp.src_port; 47 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 48 | transition select(hdr.ipv4.dscp) { 49 | DSCP_INT &&& DSCP_MASK: parse_shim; 50 | default: accept; 51 | } 52 | } 53 | 54 | state parse_shim { 55 | packet.extract(hdr.intl4_shim); 56 | transition parse_int_hdr; 57 | } 58 | 59 | state parse_int_hdr { 60 | packet.extract(hdr.int_header); 61 | transition accept; 62 | } 63 | } 64 | 65 | /************************************************************************* 66 | *********************** P A R S E R ******************************* 67 | *************************************************************************/ 68 | 69 | parser MyEgressParser(packet_in packet, 70 | out headers hdr, 71 | out local_metadata_t local_metadata, 72 | out egress_intrinsic_metadata_t eg_intr_md) { 73 | 74 | state start { 75 | packet.extract(eg_intr_md); 76 | transition parse_metadata; 77 | } 78 | 79 | state parse_metadata { 80 | mirror_h mirror_md = packet.lookahead(); 81 | transition select(mirror_md.pkt_type) { 82 | PKT_TYPE_MIRROR : parse_mirror_md; 83 | default : parse_ethernet; 84 | } 85 | } 86 | 87 | state parse_mirror_md { 88 | mirror_h mirror_md; 89 | packet.extract(hdr.mirror_header); 90 | local_metadata.mirror = _TRUE; 91 | transition parse_ethernet_mirror; 92 | } 93 | 94 | state parse_ethernet { 95 | packet.extract(hdr.local_report_header); 96 | packet.extract(hdr.ethernet); 97 | transition select(hdr.ethernet.ether_type) { 98 | TYPE_IPV4: parse_ipv4; 99 | default: accept; 100 | } 101 | } 102 | 103 | state parse_ethernet_mirror { 104 | packet.extract(hdr.ethernet); 105 | transition select(hdr.ethernet.ether_type) { 106 | TYPE_IPV4: parse_ipv4; 107 | default: accept; 108 | } 109 | } 110 | 111 | state parse_ipv4 { 112 | packet.extract(hdr.ipv4); 113 | transition select(hdr.ipv4.protocol) { 114 | IP_PROTO_UDP: parse_udp; 115 | IP_PROTO_TCP: parse_tcp; 116 | default: accept; 117 | } 118 | } 119 | 120 | state parse_udp { 121 | packet.extract(hdr.udp); 122 | local_metadata.l4_src_port = hdr.udp.src_port; 123 | local_metadata.l4_dst_port = hdr.udp.dst_port; 124 | transition select(hdr.ipv4.dscp) { 125 | DSCP_INT &&& DSCP_MASK: parse_shim; 126 | default: accept; 127 | } 128 | } 129 | 130 | state parse_tcp { 131 | packet.extract(hdr.tcp); 132 | local_metadata.l4_src_port = hdr.tcp.src_port; 133 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 134 | transition select(hdr.ipv4.dscp) { 135 | DSCP_INT &&& DSCP_MASK: parse_shim; 136 | default: accept; 137 | } 138 | } 139 | 140 | state parse_shim { 141 | packet.extract(hdr.intl4_shim); 142 | transition parse_int_hdr; 143 | } 144 | 145 | state parse_int_hdr { 146 | packet.extract(hdr.int_header); 147 | } 148 | } 149 | 150 | /************************************************************************* 151 | ************ C H E C K S U M V E R I F I C A T I O N ************* 152 | *************************************************************************/ 153 | 154 | control MyIngressDeparser(packet_out packet, 155 | inout headers hdr, 156 | in local_metadata_t local_metadata, 157 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 158 | 159 | 160 | Mirror() mirror; 161 | 162 | apply { 163 | 164 | if(ig_dprsr_md.mirror_type == 3w1) { 165 | mirror.emit(local_metadata.ing_mir_ses, 166 | {local_metadata.pkt_type, 167 | hdr.local_report_header.ingress_port_id, 168 | hdr.local_report_header.egress_port_id, 169 | hdr.local_report_header.queue_id, 170 | hdr.local_report_header.ingress_global_tstamp, 171 | hdr.intl4_shim.int_type, 172 | hdr.intl4_shim.npt, 173 | hdr.intl4_shim.rsvd, 174 | hdr.intl4_shim.len, 175 | hdr.intl4_shim.udp_ip_dscp, 176 | hdr.intl4_shim.udp_ip, 177 | hdr.int_header.ver, 178 | hdr.int_header.d, 179 | hdr.int_header.rsvd, 180 | hdr.int_header.instruction_mask_0003, 181 | hdr.int_header.instruction_mask_0407, 182 | hdr.int_header.instruction_mask_0811, 183 | hdr.int_header.instruction_mask_1215, 184 | hdr.int_header.domain_specific_id, 185 | hdr.int_header.ds_instruction, 186 | hdr.int_header.ds_flags 187 | }); 188 | } 189 | 190 | //packet.emit(hdr); 191 | packet.emit(hdr.local_report_header); 192 | packet.emit(hdr.ethernet); 193 | packet.emit(hdr.ipv4); 194 | packet.emit(hdr.udp); 195 | packet.emit(hdr.tcp); 196 | 197 | packet.emit(hdr.intl4_shim); 198 | packet.emit(hdr.int_header); 199 | } 200 | } 201 | 202 | /************************************************************************* 203 | *********************** D E P A R S E R ******************************* 204 | *************************************************************************/ 205 | 206 | control MyEgressDeparser(packet_out packet, 207 | inout headers hdr, 208 | in local_metadata_t local_metadata, 209 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) { 210 | 211 | // Mirror() mirror; 212 | 213 | Checksum() ipv4Checksum; 214 | 215 | apply { 216 | 217 | // Egress mirroring if ncessary 218 | 219 | 220 | // if(eg_dprsr_md.mirror_type == MIRROR_TYPE_E2E) { 221 | // mirror.emit(local_metadata.egr_mir_ses, {local_metadata.pkt_type, hdr.local_report_header.ingress_port_id, 222 | // hdr.local_report_header.queue_id, hdr.local_report_header.ingress_global_tstamp}); 223 | // } 224 | 225 | hdr.ipv4.hdr_checksum = ipv4Checksum.update( 226 | { 227 | hdr.ipv4.version, 228 | hdr.ipv4.ihl, 229 | hdr.ipv4.dscp, 230 | hdr.ipv4.ecn, 231 | hdr.ipv4.len, 232 | hdr.ipv4.identification, 233 | hdr.ipv4.flags, 234 | hdr.ipv4.frag_offset, 235 | hdr.ipv4.ttl, 236 | hdr.ipv4.protocol, 237 | hdr.ipv4.src_addr, 238 | hdr.ipv4.dst_addr 239 | } 240 | ); 241 | 242 | // //parsed headers have to be added again into the packet. 243 | //packet.emit(hdr); 244 | packet.emit(hdr.report_ethernet); 245 | packet.emit(hdr.report_ipv4); 246 | packet.emit(hdr.report_udp); 247 | packet.emit(hdr.report_group_header); 248 | packet.emit(hdr.report_individual_header); 249 | 250 | packet.emit(hdr.ethernet); 251 | packet.emit(hdr.ipv4); 252 | packet.emit(hdr.udp); 253 | packet.emit(hdr.tcp); 254 | 255 | packet.emit(hdr.intl4_shim); 256 | packet.emit(hdr.int_header); 257 | packet.emit(hdr.int_switch_id); 258 | packet.emit(hdr.int_level1_port_ids); 259 | packet.emit(hdr.int_hop_latency); 260 | packet.emit(hdr.int_q_occupancy); 261 | packet.emit(hdr.int_ingress_tstamp); 262 | packet.emit(hdr.int_egress_tstamp); 263 | packet.emit(hdr.int_level2_port_ids); 264 | packet.emit(hdr.int_egress_tx_util); 265 | 266 | } 267 | } -------------------------------------------------------------------------------- /int-mx/p4src/int/sink.p4: -------------------------------------------------------------------------------- 1 | control process_set_sink ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in egress_intrinsic_metadata_t eg_intr_md) { 5 | 6 | action int_set_sink () { 7 | local_metadata.int_meta.sink = _TRUE; 8 | } 9 | 10 | table tb_set_sink { 11 | key = { 12 | eg_intr_md.egress_port: exact; 13 | } 14 | actions = { 15 | int_set_sink; 16 | NoAction(); 17 | } 18 | const default_action = NoAction(); 19 | size = MAX_PORTS; 20 | } 21 | 22 | apply { 23 | tb_set_sink.apply(); 24 | } 25 | } 26 | 27 | control process_int_sink ( 28 | inout headers hdr, 29 | inout local_metadata_t local_metadata) { 30 | 31 | action restore_header () { 32 | // restore length fields of IPv4 header and UDP header, and IP DSCP which was stored in the INT SHIM Header 33 | hdr.ipv4.dscp = hdr.mirror_header.udp_ip_dscp; 34 | hdr.ipv4.len = hdr.ipv4.len - INT_TOTAL_HEADER_SIZE; 35 | hdr.udp.length_ = hdr.udp.length_ - INT_TOTAL_HEADER_SIZE; 36 | 37 | } 38 | 39 | 40 | action int_sink() { 41 | // remove all the INT information from the packet 42 | hdr.int_header.setInvalid(); 43 | hdr.intl4_shim.setInvalid(); 44 | hdr.mirror_header.setInvalid(); 45 | } 46 | 47 | apply { 48 | restore_header(); 49 | int_sink(); 50 | } 51 | } 52 | 53 | control process_int_header ( 54 | inout headers hdr, 55 | inout local_metadata_t local_metadata) { 56 | 57 | action add_int_header() { 58 | 59 | // insert INT header from mirror data 60 | 61 | hdr.intl4_shim.setValid(); 62 | hdr.intl4_shim.int_type = hdr.mirror_header.int_type; 63 | hdr.intl4_shim.npt = hdr.mirror_header.npt; 64 | hdr.intl4_shim.len = hdr.mirror_header.len; 65 | hdr.intl4_shim.udp_ip_dscp = hdr.mirror_header.udp_ip_dscp; 66 | hdr.intl4_shim.udp_ip = hdr.mirror_header.udp_ip; 67 | 68 | 69 | hdr.int_header.setValid(); 70 | hdr.int_header.ver = hdr.mirror_header.ver; 71 | hdr.int_header.d = hdr.mirror_header.d; 72 | hdr.int_header.instruction_mask_0003 = hdr.mirror_header.instruction_mask_0003; 73 | hdr.int_header.instruction_mask_0407 = hdr.mirror_header.instruction_mask_0407; 74 | hdr.int_header.instruction_mask_0811 = hdr.mirror_header.instruction_mask_0811; 75 | hdr.int_header.instruction_mask_1215 = hdr.mirror_header.instruction_mask_1215; 76 | } 77 | 78 | apply { 79 | add_int_header(); 80 | } 81 | } 82 | 83 | control process_int_report ( 84 | inout headers hdr, 85 | inout local_metadata_t local_metadata, 86 | in egress_intrinsic_metadata_t eg_intr_md) { 87 | 88 | action do_report_encapsulation(mac_t src_mac, mac_t mon_mac, ip_address_t src_ip, 89 | ip_address_t mon_ip, l4_port_t mon_port) { 90 | //Report Ethernet Header 91 | hdr.report_ethernet.setValid(); 92 | hdr.report_ethernet.dst_addr = mon_mac; 93 | hdr.report_ethernet.src_addr = src_mac; 94 | hdr.report_ethernet.ether_type = ETH_TYPE_IPV4; 95 | 96 | //Report IPV4 Header 97 | hdr.report_ipv4.setValid(); 98 | hdr.report_ipv4.version = IP_VERSION_4; 99 | hdr.report_ipv4.ihl = IPV4_IHL_MIN; 100 | hdr.report_ipv4.dscp = 6w0; 101 | hdr.report_ipv4.ecn = 2w0; 102 | /* Total Len is */ 103 | // 8 + 8 + 8 + 8 + 8 + 8 104 | hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + (bit<16>) REPORT_INDIVIDUAL_HEADER_LEN + 105 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + SHIM_LEN; 106 | 107 | hdr.report_ipv4.identification = 0; 108 | hdr.report_ipv4.flags = 0; 109 | hdr.report_ipv4.frag_offset = 0; 110 | hdr.report_ipv4.ttl = REPORT_HDR_TTL; 111 | hdr.report_ipv4.protocol = IP_PROTO_UDP; 112 | hdr.report_ipv4.src_addr = src_ip; 113 | hdr.report_ipv4.dst_addr = mon_ip; 114 | 115 | //Report UDP Header 116 | hdr.report_udp.setValid(); 117 | hdr.report_udp.src_port = 1234; 118 | hdr.report_udp.dst_port = mon_port; 119 | hdr.report_udp.length_ = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + (bit<16>) REPORT_INDIVIDUAL_HEADER_LEN + 120 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + SHIM_LEN; 121 | 122 | /* Telemetry Group Header */ 123 | 124 | hdr.report_group_header.setValid(); 125 | hdr.report_group_header.ver = 1; 126 | hdr.report_group_header.hw_id = HW_ID; 127 | hdr.report_group_header.seq_no = 0; 128 | hdr.report_group_header.node_id = local_metadata.int_meta.switch_id; 129 | 130 | /* Telemetry Report Individual Header */ 131 | hdr.report_individual_header.setValid(); 132 | hdr.report_individual_header.rep_type = 1; 133 | hdr.report_individual_header.in_type = 4; 134 | hdr.report_individual_header.len = 0; 135 | hdr.report_individual_header.rep_md_len = 0; 136 | hdr.report_individual_header.d = 0; 137 | hdr.report_individual_header.q = 0; 138 | hdr.report_individual_header.f = 1; 139 | hdr.report_individual_header.i = 1; 140 | hdr.report_individual_header.rsvd = 0; 141 | 142 | /* Individual report inner contents */ 143 | 144 | hdr.report_individual_header.rep_md_bits = 0; 145 | hdr.report_individual_header.domain_specific_id = 0; 146 | hdr.report_individual_header.domain_specific_md_bits = 0; 147 | hdr.report_individual_header.domain_specific_md_status = 0; 148 | } 149 | 150 | // Cloned packet is forwarded according to the mirroring_add command 151 | table tb_generate_report { 152 | // key = { 153 | // } 154 | actions = { 155 | do_report_encapsulation; 156 | NoAction(); 157 | } 158 | default_action = NoAction(); 159 | } 160 | 161 | apply { 162 | tb_generate_report.apply(); 163 | } 164 | } -------------------------------------------------------------------------------- /int-mx/p4src/int/source.p4: -------------------------------------------------------------------------------- 1 | control process_int_source_sink ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in ingress_intrinsic_metadata_t ig_intr_md, 5 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 6 | 7 | action int_set_source () { 8 | local_metadata.int_meta.source = _TRUE; 9 | } 10 | 11 | action int_set_sink () { 12 | local_metadata.int_meta.sink = _TRUE; 13 | } 14 | 15 | table tb_set_source { 16 | key = { 17 | ig_intr_md.ingress_port: exact; 18 | } 19 | actions = { 20 | int_set_source; 21 | NoAction(); 22 | } 23 | const default_action = NoAction(); 24 | size = MAX_PORTS; 25 | } 26 | table tb_set_sink { 27 | key = { 28 | ig_tm_md.ucast_egress_port: exact; 29 | } 30 | actions = { 31 | int_set_sink; 32 | NoAction(); 33 | } 34 | const default_action = NoAction(); 35 | size = MAX_PORTS; 36 | } 37 | 38 | apply { 39 | tb_set_source.apply(); 40 | tb_set_sink.apply(); 41 | } 42 | } 43 | 44 | // Insert INT header to the packet 45 | control process_int_source ( 46 | inout headers hdr, 47 | inout local_metadata_t local_metadata) { 48 | 49 | action int_source(bit<4> ins_mask0003, bit<4> ins_mask0407) { 50 | 51 | hdr.intl4_shim.setValid(); // insert INT shim header 52 | hdr.intl4_shim.int_type = 3; // int_type: Hop-by-hop type (1) , destination type (2), MX-type (3) 53 | hdr.intl4_shim.npt = 0; // next protocol type: 0 54 | hdr.intl4_shim.len = INT_HEADER_LEN_WORD; // This is 3 from 0xC (INT_TOTAL_HEADER_SIZE >> 2) 55 | hdr.intl4_shim.udp_ip_dscp = hdr.ipv4.dscp; // although should be first 6 bits of the second byte 56 | hdr.intl4_shim.udp_ip = 0; // although should be first 6 bits of the second byte 57 | 58 | // insert INT header 59 | hdr.int_header.setValid(); 60 | hdr.int_header.ver = 2; 61 | hdr.int_header.d = 0; 62 | hdr.int_header.instruction_mask_0003 = ins_mask0003; 63 | hdr.int_header.instruction_mask_0407 = ins_mask0407; 64 | hdr.int_header.instruction_mask_0811 = 0; // bit 8 is buffer related, rest are reserved 65 | hdr.int_header.instruction_mask_1215 = 0; // rsvd 66 | 67 | hdr.int_header.domain_specific_id = 0; // Unique INT Domain ID 68 | hdr.int_header.ds_instruction = 0; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 69 | hdr.int_header.ds_flags = 0; // Domain specific flags 70 | 71 | // add the header len (3 words) to total len 72 | hdr.ipv4.len = hdr.ipv4.len + INT_TOTAL_HEADER_SIZE; 73 | hdr.udp.length_ = hdr.udp.length_ + INT_TOTAL_HEADER_SIZE; 74 | 75 | hdr.ipv4.dscp = DSCP_INT; 76 | } 77 | 78 | table tb_int_source { 79 | key = { 80 | //configure for each flow to be monitored 81 | // 4 fields identifying flow 82 | //include ip src, udp/tcp src and dest too 83 | hdr.ipv4.dst_addr: lpm; 84 | } 85 | actions = { 86 | int_source; 87 | NoAction; 88 | } 89 | const default_action = NoAction(); 90 | } 91 | 92 | apply { 93 | tb_int_source.apply(); 94 | } 95 | } -------------------------------------------------------------------------------- /int-mx/p4src/int/transit.p4: -------------------------------------------------------------------------------- 1 | control process_int_transit ( 2 | inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | in egress_intrinsic_metadata_t eg_intr_md, 5 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 6 | 7 | action init_metadata(switch_id_t switch_id) { 8 | local_metadata.int_meta.transit = _TRUE; 9 | local_metadata.int_meta.switch_id = switch_id; 10 | } 11 | 12 | 13 | action int_set_header_0() { //switch_id 14 | hdr.int_switch_id.setValid(); 15 | hdr.int_switch_id.switch_id = local_metadata.int_meta.switch_id; 16 | } 17 | 18 | action int_set_header_1() { //level1_port_id - physical port 19 | hdr.int_level1_port_ids.setValid(); 20 | hdr.int_level1_port_ids.ingress_port_id = 21 | (bit<16>) hdr.mirror_header.ingress_port_id; 22 | hdr.int_level1_port_ids.egress_port_id = (bit<16>) hdr.mirror_header.egress_port_id; 23 | } 24 | 25 | action int_set_header_2() { //hop_latency 26 | hdr.int_hop_latency.setValid(); 27 | hdr.int_hop_latency.hop_latency = (bit<32>) ((bit<64>) eg_prsr_md.global_tstamp - 28 | hdr.mirror_header.ingress_global_tstamp); 29 | } 30 | 31 | action int_set_header_3() { //q_occupancy 32 | hdr.int_q_occupancy.setValid(); 33 | hdr.int_q_occupancy.q_id = 34 | (bit<8>) hdr.mirror_header.queue_id; 35 | hdr.int_q_occupancy.q_occupancy = 36 | (bit<24>) eg_intr_md.deq_qdepth; 37 | } 38 | 39 | action int_set_header_4() { //ingress_tstamp 40 | hdr.int_ingress_tstamp.setValid(); 41 | hdr.int_ingress_tstamp.ingress_tstamp = 42 | hdr.mirror_header.ingress_global_tstamp; 43 | } 44 | 45 | action int_set_header_5() { //egress_timestamp 46 | hdr.int_egress_tstamp.setValid(); 47 | hdr.int_egress_tstamp.egress_tstamp = 48 | (bit<64>) eg_prsr_md.global_tstamp; 49 | } 50 | 51 | action int_set_header_6() { //level2_port_id 52 | hdr.int_level2_port_ids.setValid(); 53 | // level2_port_id indicates Logical port ID - update this! 54 | hdr.int_level2_port_ids.ingress_port_id = (bit<32>) local_metadata.l4_src_port; 55 | hdr.int_level2_port_ids.egress_port_id = (bit<32>) local_metadata.l4_dst_port; 56 | } 57 | 58 | action int_set_header_7() { //egress_port_tx_utilization - tofino implementation 59 | hdr.int_egress_tx_util.setValid(); 60 | hdr.int_egress_tx_util.egress_port_tx_util = 61 | (bit<32>) eg_intr_md.deq_timedelta; 62 | } 63 | 64 | // Actions to keep track of the new metadata added. 65 | 66 | action add_1() { 67 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 1; 68 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 4; 69 | } 70 | 71 | 72 | action add_2() { 73 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 2; 74 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 8; 75 | } 76 | 77 | 78 | action add_3() { 79 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 3; 80 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 12; 81 | } 82 | 83 | 84 | action add_4() { 85 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 4; 86 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 16; 87 | } 88 | 89 | 90 | action add_5() { 91 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 5; 92 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 20; 93 | } 94 | 95 | /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */ 96 | /* Each bit set indicates that corresponding INT header should be added */ 97 | 98 | action int_set_header_0003_i0() { 99 | } 100 | 101 | action int_set_header_0003_i1() { 102 | int_set_header_3(); 103 | add_1(); 104 | } 105 | 106 | action int_set_header_0003_i2() { 107 | int_set_header_2(); 108 | add_1(); 109 | } 110 | 111 | action int_set_header_0003_i3() { 112 | int_set_header_3(); 113 | int_set_header_2(); 114 | add_2(); 115 | } 116 | 117 | action int_set_header_0003_i4() { 118 | int_set_header_1(); 119 | add_1(); 120 | } 121 | 122 | action int_set_header_0003_i5() { 123 | int_set_header_3(); 124 | int_set_header_1(); 125 | add_2(); 126 | } 127 | 128 | action int_set_header_0003_i6() { 129 | int_set_header_2(); 130 | int_set_header_1(); 131 | add_2(); 132 | } 133 | 134 | action int_set_header_0003_i7() { 135 | int_set_header_3(); 136 | int_set_header_2(); 137 | int_set_header_1(); 138 | add_3(); 139 | } 140 | 141 | action int_set_header_0003_i8() { 142 | int_set_header_0(); 143 | add_1(); 144 | } 145 | 146 | action int_set_header_0003_i9() { 147 | int_set_header_3(); 148 | int_set_header_0(); 149 | add_2(); 150 | } 151 | 152 | action int_set_header_0003_i10() { 153 | int_set_header_2(); 154 | int_set_header_0(); 155 | add_2(); 156 | } 157 | 158 | action int_set_header_0003_i11() { 159 | int_set_header_3(); 160 | int_set_header_2(); 161 | int_set_header_0(); 162 | add_3(); 163 | } 164 | 165 | action int_set_header_0003_i12() { 166 | int_set_header_1(); 167 | int_set_header_0(); 168 | add_2(); 169 | } 170 | 171 | action int_set_header_0003_i13() { 172 | int_set_header_3(); 173 | int_set_header_1(); 174 | int_set_header_0(); 175 | add_3(); 176 | } 177 | 178 | action int_set_header_0003_i14() { 179 | int_set_header_2(); 180 | int_set_header_1(); 181 | int_set_header_0(); 182 | add_3(); 183 | } 184 | 185 | action int_set_header_0003_i15() { 186 | int_set_header_3(); 187 | int_set_header_2(); 188 | int_set_header_1(); 189 | int_set_header_0(); 190 | add_4(); 191 | } 192 | 193 | /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */ 194 | 195 | action int_set_header_0407_i0() { 196 | } 197 | 198 | action int_set_header_0407_i1() { 199 | int_set_header_7(); 200 | add_1(); 201 | } 202 | 203 | action int_set_header_0407_i2() { 204 | int_set_header_6(); 205 | add_2(); 206 | } 207 | 208 | action int_set_header_0407_i3() { 209 | int_set_header_7(); 210 | int_set_header_6(); 211 | add_3(); 212 | } 213 | 214 | action int_set_header_0407_i4() { 215 | int_set_header_5(); 216 | add_1(); 217 | } 218 | 219 | action int_set_header_0407_i5() { 220 | int_set_header_7(); 221 | int_set_header_5(); 222 | add_2(); 223 | } 224 | 225 | action int_set_header_0407_i6() { 226 | int_set_header_6(); 227 | int_set_header_5(); 228 | add_3(); 229 | } 230 | 231 | action int_set_header_0407_i7() { 232 | int_set_header_7(); 233 | int_set_header_6(); 234 | int_set_header_5(); 235 | add_4(); 236 | } 237 | 238 | action int_set_header_0407_i8() { 239 | int_set_header_4(); 240 | add_1(); 241 | } 242 | 243 | action int_set_header_0407_i9() { 244 | int_set_header_7(); 245 | int_set_header_4(); 246 | add_2(); 247 | } 248 | 249 | action int_set_header_0407_i10() { 250 | int_set_header_6(); 251 | int_set_header_4(); 252 | add_3(); 253 | } 254 | 255 | action int_set_header_0407_i11() { 256 | int_set_header_7(); 257 | int_set_header_6(); 258 | int_set_header_4(); 259 | add_4(); 260 | } 261 | 262 | action int_set_header_0407_i12() { 263 | int_set_header_5(); 264 | int_set_header_4(); 265 | add_2(); 266 | } 267 | 268 | action int_set_header_0407_i13() { 269 | int_set_header_7(); 270 | int_set_header_5(); 271 | int_set_header_4(); 272 | add_3(); 273 | } 274 | 275 | action int_set_header_0407_i14() { 276 | int_set_header_6(); 277 | int_set_header_5(); 278 | int_set_header_4(); 279 | add_4(); 280 | } 281 | 282 | action int_set_header_0407_i15() { 283 | int_set_header_7(); 284 | int_set_header_6(); 285 | int_set_header_5(); 286 | int_set_header_4(); 287 | add_5(); 288 | } 289 | 290 | // Default action used to set switch ID. 291 | table tb_int_insert { 292 | // key = { 293 | // } 294 | actions = { 295 | init_metadata; 296 | NoAction; 297 | } 298 | default_action = NoAction(); 299 | size = 1; 300 | } 301 | 302 | /* Table to process instruction bits 0-3 */ 303 | 304 | table tb_int_inst_0003 { 305 | key = { 306 | hdr.mirror_header.instruction_mask_0003 : exact; 307 | } 308 | actions = { 309 | int_set_header_0003_i0; 310 | int_set_header_0003_i1; 311 | int_set_header_0003_i2; 312 | int_set_header_0003_i3; 313 | int_set_header_0003_i4; 314 | int_set_header_0003_i5; 315 | int_set_header_0003_i6; 316 | int_set_header_0003_i7; 317 | int_set_header_0003_i8; 318 | int_set_header_0003_i9; 319 | int_set_header_0003_i10; 320 | int_set_header_0003_i11; 321 | int_set_header_0003_i12; 322 | int_set_header_0003_i13; 323 | int_set_header_0003_i14; 324 | int_set_header_0003_i15; 325 | } 326 | 327 | const entries = { 328 | (0x0) : int_set_header_0003_i0(); 329 | (0x1) : int_set_header_0003_i1(); 330 | (0x2) : int_set_header_0003_i2(); 331 | (0x3) : int_set_header_0003_i3(); 332 | (0x4) : int_set_header_0003_i4(); 333 | (0x5) : int_set_header_0003_i5(); 334 | (0x6) : int_set_header_0003_i6(); 335 | (0x7) : int_set_header_0003_i7(); 336 | (0x8) : int_set_header_0003_i8(); 337 | (0x9) : int_set_header_0003_i9(); 338 | (0xA) : int_set_header_0003_i10(); 339 | (0xB) : int_set_header_0003_i11(); 340 | (0xC) : int_set_header_0003_i12(); 341 | (0xD) : int_set_header_0003_i13(); 342 | (0xE) : int_set_header_0003_i14(); 343 | (0xF) : int_set_header_0003_i15(); 344 | } 345 | 346 | size = 16; 347 | } 348 | 349 | /* Table to process instruction bits 4-7 */ 350 | 351 | table tb_int_inst_0407 { 352 | key = { 353 | hdr.mirror_header.instruction_mask_0407 : exact; 354 | } 355 | actions = { 356 | int_set_header_0407_i0; 357 | int_set_header_0407_i1; 358 | int_set_header_0407_i2; 359 | int_set_header_0407_i3; 360 | int_set_header_0407_i4; 361 | int_set_header_0407_i5; 362 | int_set_header_0407_i6; 363 | int_set_header_0407_i7; 364 | int_set_header_0407_i8; 365 | int_set_header_0407_i9; 366 | int_set_header_0407_i10; 367 | int_set_header_0407_i11; 368 | int_set_header_0407_i12; 369 | int_set_header_0407_i13; 370 | int_set_header_0407_i14; 371 | int_set_header_0407_i15; 372 | } 373 | 374 | const entries = { 375 | (0x0) : int_set_header_0407_i0(); 376 | (0x1) : int_set_header_0407_i1(); 377 | (0x2) : int_set_header_0407_i2(); 378 | (0x3) : int_set_header_0407_i3(); 379 | (0x4) : int_set_header_0407_i4(); 380 | (0x5) : int_set_header_0407_i5(); 381 | (0x6) : int_set_header_0407_i6(); 382 | (0x7) : int_set_header_0407_i7(); 383 | (0x8) : int_set_header_0407_i8(); 384 | (0x9) : int_set_header_0407_i9(); 385 | (0xA) : int_set_header_0407_i10(); 386 | (0xB) : int_set_header_0407_i11(); 387 | (0xC) : int_set_header_0407_i12(); 388 | (0xD) : int_set_header_0407_i13(); 389 | (0xE) : int_set_header_0407_i14(); 390 | (0xF) : int_set_header_0407_i15(); 391 | } 392 | 393 | size = 16; 394 | } 395 | 396 | apply { 397 | tb_int_insert.apply(); 398 | if (local_metadata.int_meta.transit == _FALSE) { 399 | return; 400 | } 401 | tb_int_inst_0003.apply(); 402 | tb_int_inst_0407.apply(); 403 | 404 | // Update headers lengths. 405 | if (hdr.ipv4.isValid()) { 406 | hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.new_bytes; 407 | } 408 | if (hdr.udp.isValid()) { 409 | hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.new_bytes; 410 | } 411 | if (hdr.mirror_header.isValid()) { 412 | hdr.mirror_header.len = hdr.mirror_header.len + local_metadata.int_meta.new_words; 413 | } 414 | } 415 | } -------------------------------------------------------------------------------- /int-mx/p4src/int_mx.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * This file has been modified. 19 | * Modifications Copyright © 2021 Saab AB / Mandar Joshi 20 | */ 21 | 22 | /* 23 | * This program is free software: you can redistribute it and/or modify 24 | * it under the terms of the GNU General Public License as published by 25 | * the Free Software Foundation, either version 2 of the License, or 26 | * (at your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | * GNU General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program. If not, see . 35 | */ 36 | 37 | /* -*- P4_16 -*- */ 38 | 39 | #include 40 | #include 41 | 42 | #include "int/headers.p4" 43 | #include "int/parsers.p4" 44 | #include "int/sink.p4" 45 | #include "int/transit.p4" 46 | #include "int/source.p4" 47 | #include "int/forward.p4" 48 | 49 | /************************************************************************* 50 | **************** I N G R E S S P R O C E S S I N G ****************** 51 | *************************************************************************/ 52 | 53 | control MyIngress(inout headers hdr, 54 | inout local_metadata_t local_metadata, 55 | in ingress_intrinsic_metadata_t ig_intr_md, 56 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 57 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 58 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 59 | 60 | apply { 61 | 62 | port_forward.apply(hdr, local_metadata, ig_tm_md, ig_dprsr_md); 63 | 64 | process_int_source_sink.apply(hdr, local_metadata, ig_intr_md, ig_tm_md); 65 | 66 | if (local_metadata.int_meta.source == _TRUE) { 67 | process_int_source.apply(hdr, local_metadata); 68 | } 69 | 70 | if (hdr.int_header.isValid()) { // Mirror the packet 71 | 72 | //MIRROR_TYPE_I2E = 1 from /home/int/bf-sde-9.4.0/pkgsrc/p4-examples/p4_16_programs/tna_mirror 73 | ig_dprsr_md.mirror_type = MIRROR_TYPE_I2E; 74 | local_metadata.pkt_type = PKT_TYPE_MIRROR; 75 | local_metadata.ing_mir_ses = (bit<10>) MIRROR_TYPE_I2E; 76 | } 77 | 78 | // Save ingress parser values for egress / INT Transit 79 | if (hdr.int_header.isValid()) { 80 | hdr.local_report_header.setValid(); 81 | hdr.local_report_header.ingress_port_id = (bit<16>) ig_intr_md.ingress_port; 82 | hdr.local_report_header.egress_port_id = (bit<16>) ig_tm_md.ucast_egress_port; 83 | hdr.local_report_header.queue_id = (bit<8>) ig_tm_md.qid; 84 | hdr.local_report_header.ingress_global_tstamp = (bit<64>) ig_prsr_md.global_tstamp; 85 | } 86 | } 87 | } 88 | 89 | /************************************************************************* 90 | **************** E G R E S S P R O C E S S I N G ******************** 91 | *************************************************************************/ 92 | 93 | control MyEgress(inout headers hdr, 94 | inout local_metadata_t local_metadata, 95 | in egress_intrinsic_metadata_t eg_intr_md, 96 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 97 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 98 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 99 | 100 | 101 | apply { 102 | if(hdr.int_header.isValid() && local_metadata.mirror == _FALSE) { 103 | 104 | process_set_sink.apply(hdr, local_metadata, eg_intr_md); 105 | 106 | if (local_metadata.int_meta.sink == _TRUE) { 107 | 108 | process_int_sink.apply(hdr, local_metadata); 109 | 110 | } 111 | 112 | // eg_dprsr_md.mirror_type = MIRROR_TYPE_E2E; 113 | // local_metadata.pkt_type = PKT_TYPE_MIRROR; 114 | // local_metadata.egr_mir_ses = (bit<10>) MIRROR_TYPE_E2E; 115 | 116 | } 117 | 118 | if (local_metadata.mirror == _TRUE) { 119 | process_int_transit.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 120 | process_int_report.apply(hdr, local_metadata, eg_intr_md); 121 | } 122 | 123 | if (hdr.int_header.isValid() == _FALSE && local_metadata.int_meta.sink == _FALSE) { 124 | process_int_header.apply(hdr, local_metadata); 125 | } 126 | 127 | hdr.local_report_header.setInvalid(); 128 | hdr.mirror_header.setInvalid(); 129 | 130 | } 131 | } 132 | 133 | /************************************************************************* 134 | *********************** S W I T C H ******************************* 135 | *************************************************************************/ 136 | 137 | Pipeline( 138 | MyIngressParser(), 139 | MyIngress(), 140 | MyIngressDeparser(), 141 | MyEgressParser(), 142 | MyEgress(), 143 | MyEgressDeparser() 144 | ) pipe; 145 | 146 | Switch(pipe) main; -------------------------------------------------------------------------------- /int-xd/README.md: -------------------------------------------------------------------------------- 1 | # In-Band Network Telemetry Implementation in P4 2 | 3 | **INT-XD - eXport Data** 4 | 5 | ## Build 6 | 7 | The P4 code can be compiled by using the build script in the SDE 8 | ``` 9 | ./p4_build.sh int_xd.p4 10 | ``` 11 | 12 | The following topology can be referred to for the INT-XD mode of operation: 13 | ![INT-XD](../figures/int-xd.png) 14 | 15 | ## Usage 16 | 17 | Run the P4 code as follows 18 | ``` 19 | $SDE/run_switchd.sh -p int_xd 20 | ``` 21 | 22 | ### Populating the tables and registers 23 | 24 | In another window for each switch, the following command can be run depending on the role of the INT node 25 | ``` 26 | $SDE/run_bfshell.sh -b $P4-INT/int-xd/bfrt_python/bfswitch1.py 27 | ``` 28 | 29 | ### Testing the INT program 30 | 31 | Packets can be sent from server1, and tcpdump/wireshark can be used to see the output at the monitoring server and the receiver 32 | 33 | -------------------------------------------------------------------------------- /int-xd/bfrt_python/bfswitch1.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_xd.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=32) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=48) 5 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=32) 6 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source(dst_addr="10.0.0.0", dst_addr_p_length=24, ins_mask0003=15, ins_mask0407=15) 7 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=1) 8 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.2", src_mac="02:42:ac:1c:00:03") 9 | 10 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=292, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-xd/bfrt_python/bfswitch2.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_xd.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=144) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=0) 5 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=144) 6 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source(dst_addr="10.0.0.0", dst_addr_p_length=24, ins_mask0003=15, ins_mask0407=15) 7 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=2) 8 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.3", src_mac="02:42:ac:1c:00:45") 9 | 10 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=292, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-xd/bfrt_python/bfswitch3.py: -------------------------------------------------------------------------------- 1 | p4 = bfrt.int_tna.pipe 2 | 3 | p4.MyIngress.port_forward.tb_port_forward.add_with_set_egress_port(dst_addr="10.0.0.0", dst_addr_p_length=24, port=396) 4 | p4.MyIngress.process_int_source_sink.tb_set_source.add_with_int_set_source(ingress_port=296) 5 | p4.MyEgress.process_set_sink.tb_set_sink.add_with_int_set_sink(egress_port=396) 6 | p4.MyIngress.process_int_source.tb_int_source.add_with_int_source(dst_addr="10.0.0.0", dst_addr_p_length=24, ins_mask0003=15, ins_mask0407=15) 7 | p4.MyEgress.process_int_transit.tb_int_insert.set_default_with_init_metadata(switch_id=3) 8 | p4.MyEgress.process_int_report.tb_generate_report.set_default_with_do_report_encapsulation(mon_ip="10.0.3.3", mon_mac="3c:fd:fe:ed:1d:c1", mon_port="4321", src_ip="172.26.0.4", src_mac="02:42:ac:1c:00:67") 9 | 10 | bfrt.mirror.cfg.add_with_normal(sid=1, session_enable=True, direction='BOTH', ucast_egress_port=397, ucast_egress_port_valid=True, max_pkt_len=16000) -------------------------------------------------------------------------------- /int-xd/p4src/int/forward.p4: -------------------------------------------------------------------------------- 1 | // Simple action to forward the packet based on the ipv4 destination address 2 | control port_forward(inout headers hdr, 3 | inout local_metadata_t local_metadata, 4 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md, 5 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 6 | 7 | action send_to_cpu() { 8 | ig_tm_md.ucast_egress_port = CPU_PORT; 9 | } 10 | 11 | action set_egress_port(port_t port) { 12 | ig_tm_md.ucast_egress_port = port; 13 | } 14 | 15 | action drop() { 16 | ig_dprsr_md.drop_ctl = 1; 17 | } 18 | 19 | table tb_port_forward { 20 | key = { 21 | hdr.ipv4.dst_addr : lpm; 22 | } 23 | actions = { 24 | set_egress_port; 25 | send_to_cpu; 26 | drop; 27 | } 28 | const default_action = drop(); 29 | } 30 | 31 | apply { 32 | tb_port_forward.apply(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /int-xd/p4src/int/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ************* C O N S T A N T S A N D T Y P E S ******************* 3 | **************************************************************************/ 4 | 5 | #define MAX_INT_HEADERS 9 6 | #define MAX_HOP_COUNT 3 7 | #define NUM_INSTRUCTIONS 3 8 | 9 | #define ETH_TYPE_IPV4 0x0800 10 | #define IP_VERSION_4 4w4 11 | #define MAX_PORTS 511 12 | #define IPV4_IHL_MIN 4w5 13 | 14 | #ifndef _BOOL 15 | #define _BOOL bool 16 | #endif 17 | #ifndef _TRUE 18 | #define _TRUE true 19 | #endif 20 | #ifndef _FALSE 21 | #define _FALSE false 22 | #endif 23 | 24 | const bit<6> HW_ID = 1; 25 | 26 | const bit<16> TYPE_IPV4 = 0x0800; 27 | const bit<8> IP_PROTO_UDP = 0x11; 28 | const bit<8> IP_PROTO_TCP = 0x6; 29 | const bit<16> INT_PORT = 5000; 30 | const bit<16> SHIM_LEN = 12; 31 | 32 | const bit<6> DSCP_INT = 0x17; 33 | const bit<6> DSCP_MASK = 0x3F; 34 | 35 | typedef bit<48> mac_t; 36 | typedef bit<32> ip_address_t; 37 | typedef bit<16> l4_port_t; 38 | typedef bit<9> port_t; 39 | 40 | const bit<8> INT_HEADER_LEN_WORD = 3; 41 | const bit<8> REPORT_HDR_TTL = 64; 42 | const port_t CPU_PORT = 255; 43 | 44 | const bit<3> NPROTO_ETHERNET = 0; 45 | const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1; 46 | const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2; 47 | 48 | const bit<5> IPV4_OPTION_INT = 31; 49 | 50 | // Mirroring defs 51 | typedef bit<3> mirror_type_t; 52 | typedef bit<8> pkt_type_t; 53 | 54 | const mirror_type_t MIRROR_TYPE_I2E = 1; 55 | const mirror_type_t MIRROR_TYPE_E2E = 2; 56 | const pkt_type_t PKT_TYPE_NORMAL = 1; 57 | const pkt_type_t PKT_TYPE_MIRROR = 2; 58 | 59 | typedef bit<32> switch_id_t; 60 | typedef bit<48> timestamp_t; 61 | typedef bit<6> output_port_t; 62 | 63 | /************************************************************************* 64 | *********************** H E A D E R S *********************************** 65 | *************************************************************************/ 66 | 67 | header ethernet_t { 68 | bit<48> dst_addr; 69 | bit<48> src_addr; 70 | bit<16> ether_type; 71 | } 72 | 73 | const bit<8> ETH_HEADER_LEN = 14; 74 | 75 | header ipv4_t { 76 | bit<4> version; 77 | bit<4> ihl; 78 | bit<6> dscp; 79 | bit<2> ecn; 80 | bit<16> len; 81 | bit<16> identification; 82 | bit<3> flags; 83 | bit<13> frag_offset; 84 | bit<8> ttl; 85 | bit<8> protocol; 86 | bit<16> hdr_checksum; 87 | bit<32> src_addr; 88 | bit<32> dst_addr; 89 | } 90 | 91 | const bit<8> IPV4_MIN_HEAD_LEN = 20; 92 | 93 | 94 | header udp_t { 95 | bit<16> src_port; 96 | bit<16> dst_port; 97 | bit<16> length_; 98 | bit<16> checksum; 99 | } 100 | const bit<8> UDP_HEADER_LEN = 8; 101 | 102 | 103 | header tcp_t { 104 | bit<16> src_port; 105 | bit<16> dst_port; 106 | bit<32> seq_no; 107 | bit<32> ack_no; 108 | bit<4> data_offset; 109 | bit<3> res; 110 | bit<3> ecn; 111 | bit<6> ctrl; 112 | bit<16> window; 113 | bit<16> checksum; 114 | bit<16> urgent_ptr; 115 | } 116 | 117 | const bit<8> TCP_HEADER_LEN = 20; 118 | 119 | // INT shim header for TCP/UDP 120 | header intl4_shim_t { 121 | bit<4> int_type; // Type of INT Header 122 | bit<2> npt; // Next protocol type 123 | bit<2> rsvd; // Reserved 124 | bit<8> len; // Length of INT Metadata header and INT stack in 4-byte words, not including the shim header (1 word) 125 | bit<6> udp_ip_dscp; // depends on npt field. either original dscp, ip protocol or udp dest port 126 | bit<10> udp_ip; // depends on npt field. either original dscp, ip protocol or udp dest port 127 | } 128 | 129 | const bit<16> INT_SHIM_HEADER_SIZE = 4; 130 | 131 | // INT header 132 | header int_header_t { 133 | bit<4> ver; // Version 134 | bit<1> d; // Discard 135 | bit<27> rsvd; // 12 bits reserved, set to 0 136 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 137 | bit<4> instruction_mask_0407; 138 | bit<4> instruction_mask_0811; 139 | bit<4> instruction_mask_1215; 140 | bit<16> domain_specific_id; // Unique INT Domain ID 141 | bit<16> ds_instruction; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 142 | bit<16> ds_flags; // Domain specific flags 143 | // Optional domain specific 'source only' metadata 144 | } 145 | 146 | const bit<16> INT_HEADER_SIZE = 12; 147 | 148 | const bit<16> INT_TOTAL_HEADER_SIZE = 16; // 12 (INT Header) + 4 (Shim Header) 149 | 150 | 151 | // INT meta-value headers - different header for each value type 152 | header int_switch_id_t { 153 | bit<32> switch_id; 154 | } 155 | header int_level1_port_ids_t { 156 | bit<16> ingress_port_id; 157 | bit<16> egress_port_id; 158 | } 159 | header int_hop_latency_t { 160 | bit<32> hop_latency; 161 | } 162 | header int_q_occupancy_t { 163 | bit<8> q_id; 164 | bit<24> q_occupancy; 165 | } 166 | header int_ingress_tstamp_t { 167 | bit<64> ingress_tstamp; 168 | } 169 | header int_egress_tstamp_t { 170 | bit<64> egress_tstamp; 171 | } 172 | header int_level2_port_ids_t { 173 | bit<32> ingress_port_id; 174 | bit<32> egress_port_id; 175 | } 176 | 177 | // these two not implemented yet 178 | header int_egress_port_tx_util_t { 179 | bit<32> egress_port_tx_util; // This is used but the queue latency is gathered instead 180 | } 181 | header int_buffer_t { 182 | bit<8> buffer_id; 183 | bit<24> buffer_occupancy; 184 | } 185 | 186 | // Report Telemetry Headers - Group Header 187 | header report_group_header_t { 188 | bit<4> ver; 189 | bit<6> hw_id; 190 | bit<22> seq_no; 191 | bit<32> node_id; 192 | } 193 | const bit<8> REPORT_GROUP_HEADER_LEN = 8; 194 | 195 | // Report Telemetry Headers - Individual Header 196 | header report_individual_header_t { 197 | bit<4> rep_type; 198 | bit<4> in_type; 199 | bit<8> len; 200 | bit<8> rep_md_len; 201 | bit<1> d; 202 | bit<1> q; 203 | bit<1> f; 204 | bit<1> i; 205 | bit<4> rsvd; 206 | // Individual report inner contents for Reptype 1 = INT 207 | bit<16> rep_md_bits; 208 | bit<16> domain_specific_id; 209 | bit<16> domain_specific_md_bits; 210 | bit<16> domain_specific_md_status; 211 | } 212 | const bit<8> REPORT_INDIVIDUAL_HEADER_LEN = 12; 213 | 214 | // Telemetry drop report header - not implemented yet 215 | header drop_report_header_t { 216 | bit<32> switch_id; 217 | bit<16> ingress_port_id; 218 | bit<16> egress_port_id; 219 | bit<8> queue_id; 220 | bit<8> drop_reason; 221 | bit<16> pad; 222 | } 223 | const bit<8> DROP_REPORT_HEADER_LEN = 12; 224 | 225 | // Switch Local Report Header - Used as a bridge header between ingress and egress pipelines 226 | header local_report_header_t { 227 | bit<16> ingress_port_id; 228 | bit<16> egress_port_id; 229 | bit<8> queue_id; 230 | bit<8> pad; 231 | bit<64> ingress_global_tstamp; 232 | } 233 | 234 | const bit<8> LOCAL_REPORT_HEADER_LEN = 16; 235 | 236 | // This mirrored header is passed for the ingress to egress mirror of the packet 237 | // This contains the bridged data and int headers (shim and instruction header) 238 | header mirror_h { 239 | pkt_type_t pkt_type; 240 | bit<16> ingress_port_id; 241 | bit<16> egress_port_id; 242 | bit<8> queue_id; 243 | bit<64> ingress_global_tstamp; 244 | 245 | bit<4> int_type; // Type of INT Header 246 | bit<2> npt; // Next protocol type 247 | bit<2> int_l4_rsvd; // Reserved 248 | bit<8> len; // Length of INT Metadata header and INT stack in 4-byte words, not including the shim header (1 word) 249 | bit<6> udp_ip_dscp; // depends on npt field. either original dscp, ip protocol or udp dest port 250 | bit<10> udp_ip; // depends on npt field. either original dscp, ip protocol or udp dest port 251 | 252 | bit<4> ver; // Version 253 | bit<1> d; // Discard 254 | bit<27> rsvd; // 12 bits reserved, set to 0 255 | bit<4> instruction_mask_0003; /* split the bits for lookup */ 256 | bit<4> instruction_mask_0407; 257 | bit<4> instruction_mask_0811; 258 | bit<4> instruction_mask_1215; 259 | bit<16> domain_specific_id; // Unique INT Domain ID 260 | bit<16> ds_instruction; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 261 | bit<16> ds_flags; // Domain specific flags 262 | // Optional domain specific 'source only' metadata 263 | } 264 | 265 | struct headers { 266 | 267 | // Original Packet Headers 268 | ethernet_t ethernet; 269 | ipv4_t ipv4; 270 | udp_t udp; 271 | tcp_t tcp; 272 | 273 | // INT Report Encapsulation 274 | ethernet_t report_ethernet; 275 | ipv4_t report_ipv4; 276 | udp_t report_udp; 277 | 278 | // INT Headers 279 | int_header_t int_header; 280 | intl4_shim_t intl4_shim; 281 | int_switch_id_t int_switch_id; 282 | int_level1_port_ids_t int_level1_port_ids; 283 | int_hop_latency_t int_hop_latency; 284 | int_q_occupancy_t int_q_occupancy; 285 | int_ingress_tstamp_t int_ingress_tstamp; 286 | int_egress_tstamp_t int_egress_tstamp; 287 | int_level2_port_ids_t int_level2_port_ids; 288 | int_egress_port_tx_util_t int_egress_tx_util; 289 | 290 | // // INT Report Headers 291 | report_group_header_t report_group_header; 292 | report_individual_header_t report_individual_header; 293 | local_report_header_t local_report_header; 294 | 295 | mirror_h mirror_header; 296 | } 297 | 298 | struct int_metadata_t { 299 | switch_id_t switch_id; 300 | bit<16> new_bytes; 301 | bit<8> new_words; 302 | bool source; 303 | bool sink; 304 | bool transit; 305 | bit<8> intl4_shim_len; 306 | bit<16> int_shim_len; 307 | } 308 | 309 | struct local_metadata_t { 310 | bit<16> l4_src_port; 311 | bit<16> l4_dst_port; 312 | int_metadata_t int_meta; 313 | bool mirror; 314 | pkt_type_t pkt_type; 315 | MirrorId_t ing_mir_ses; // Ingress mirror session ID 316 | MirrorId_t egr_mir_ses; // Egress mirror session ID 317 | } -------------------------------------------------------------------------------- /int-xd/p4src/int/parsers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** P A R S E R ******************************* 3 | *************************************************************************/ 4 | 5 | parser MyIngressParser(packet_in packet, 6 | out headers hdr, 7 | out local_metadata_t local_metadata, 8 | out ingress_intrinsic_metadata_t ig_intr_md) { 9 | 10 | state start { 11 | packet.extract(ig_intr_md); 12 | packet.advance(PORT_METADATA_SIZE); 13 | transition parse_ethernet; 14 | } 15 | 16 | state parse_ethernet { 17 | packet.extract(hdr.ethernet); 18 | transition select(hdr.ethernet.ether_type) { 19 | TYPE_IPV4: parse_ipv4; 20 | default: accept; 21 | } 22 | } 23 | 24 | state parse_ipv4 { 25 | packet.extract(hdr.ipv4); 26 | transition select(hdr.ipv4.protocol) { 27 | IP_PROTO_UDP: parse_udp; 28 | IP_PROTO_TCP: parse_tcp; 29 | default: accept; 30 | } 31 | } 32 | 33 | state parse_udp { 34 | packet.extract(hdr.udp); 35 | local_metadata.l4_src_port = hdr.udp.src_port; 36 | local_metadata.l4_dst_port = hdr.udp.dst_port; 37 | transition select(hdr.ipv4.dscp) { 38 | DSCP_INT &&& DSCP_MASK: parse_shim; 39 | default: accept; 40 | } 41 | } 42 | 43 | state parse_tcp { 44 | packet.extract(hdr.tcp); 45 | local_metadata.l4_src_port = hdr.tcp.src_port; 46 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 47 | transition select(hdr.ipv4.dscp) { 48 | DSCP_INT &&& DSCP_MASK: parse_shim; 49 | default: accept; 50 | } 51 | } 52 | 53 | state parse_shim { 54 | packet.extract(hdr.intl4_shim); 55 | transition parse_int_hdr; 56 | } 57 | 58 | state parse_int_hdr { 59 | packet.extract(hdr.int_header); 60 | transition accept; 61 | } 62 | } 63 | 64 | 65 | /************************************************************************* 66 | ************ C H E C K S U M V E R I F I C A T I O N ************* 67 | *************************************************************************/ 68 | 69 | control MyIngressDeparser(packet_out packet, 70 | inout headers hdr, 71 | in local_metadata_t local_metadata, 72 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 73 | 74 | 75 | Mirror() mirror; 76 | 77 | apply { 78 | 79 | if(ig_dprsr_md.mirror_type == 3w1) { 80 | mirror.emit(local_metadata.ing_mir_ses, 81 | {local_metadata.pkt_type, 82 | hdr.local_report_header.ingress_port_id, 83 | hdr.local_report_header.egress_port_id, 84 | hdr.local_report_header.queue_id, 85 | hdr.local_report_header.ingress_global_tstamp, 86 | hdr.intl4_shim.int_type, 87 | hdr.intl4_shim.npt, 88 | hdr.intl4_shim.rsvd, 89 | hdr.intl4_shim.len, 90 | hdr.intl4_shim.udp_ip_dscp, 91 | hdr.intl4_shim.udp_ip, 92 | hdr.int_header.ver, 93 | hdr.int_header.d, 94 | hdr.int_header.rsvd, 95 | hdr.int_header.instruction_mask_0003, 96 | hdr.int_header.instruction_mask_0407, 97 | hdr.int_header.instruction_mask_0811, 98 | hdr.int_header.instruction_mask_1215, 99 | hdr.int_header.domain_specific_id, 100 | hdr.int_header.ds_instruction, 101 | hdr.int_header.ds_flags 102 | }); 103 | } 104 | 105 | //packet.emit(hdr); 106 | packet.emit(hdr.local_report_header); 107 | packet.emit(hdr.ethernet); 108 | packet.emit(hdr.ipv4); 109 | packet.emit(hdr.udp); 110 | packet.emit(hdr.tcp); 111 | 112 | packet.emit(hdr.intl4_shim); 113 | packet.emit(hdr.int_header); 114 | } 115 | } 116 | 117 | 118 | /************************************************************************* 119 | **************** E G R E S S P R O C E S S I N G ******************* 120 | *************************************************************************/ 121 | 122 | parser MyEgressParser(packet_in packet, 123 | out headers hdr, 124 | out local_metadata_t local_metadata, 125 | out egress_intrinsic_metadata_t eg_intr_md) { 126 | 127 | state start { 128 | packet.extract(eg_intr_md); 129 | transition parse_metadata; 130 | } 131 | 132 | state parse_metadata { 133 | mirror_h mirror_md = packet.lookahead(); 134 | transition select(mirror_md.pkt_type) { 135 | PKT_TYPE_MIRROR : parse_mirror_md; 136 | default : parse_ethernet; 137 | } 138 | } 139 | 140 | state parse_mirror_md { 141 | mirror_h mirror_md; 142 | packet.extract(hdr.mirror_header); 143 | local_metadata.mirror = _TRUE; 144 | transition parse_ethernet_mirror; 145 | } 146 | 147 | state parse_ethernet { 148 | packet.extract(hdr.local_report_header); 149 | packet.extract(hdr.ethernet); 150 | transition select(hdr.ethernet.ether_type) { 151 | TYPE_IPV4: parse_ipv4; 152 | default: accept; 153 | } 154 | } 155 | 156 | state parse_ethernet_mirror { 157 | packet.extract(hdr.ethernet); 158 | transition select(hdr.ethernet.ether_type) { 159 | TYPE_IPV4: parse_ipv4; 160 | default: accept; 161 | } 162 | } 163 | 164 | state parse_ipv4 { 165 | packet.extract(hdr.ipv4); 166 | transition select(hdr.ipv4.protocol) { 167 | IP_PROTO_UDP: parse_udp; 168 | IP_PROTO_TCP: parse_tcp; 169 | default: accept; 170 | } 171 | } 172 | 173 | state parse_udp { 174 | packet.extract(hdr.udp); 175 | local_metadata.l4_src_port = hdr.udp.src_port; 176 | local_metadata.l4_dst_port = hdr.udp.dst_port; 177 | transition select(hdr.ipv4.dscp) { 178 | DSCP_INT &&& DSCP_MASK: parse_shim; 179 | default: accept; 180 | } 181 | } 182 | 183 | state parse_tcp { 184 | packet.extract(hdr.tcp); 185 | local_metadata.l4_src_port = hdr.tcp.src_port; 186 | local_metadata.l4_dst_port = hdr.tcp.dst_port; 187 | transition select(hdr.ipv4.dscp) { 188 | DSCP_INT &&& DSCP_MASK: parse_shim; 189 | default: accept; 190 | } 191 | } 192 | 193 | state parse_shim { 194 | packet.extract(hdr.intl4_shim); 195 | transition parse_int_hdr; 196 | } 197 | 198 | state parse_int_hdr { 199 | packet.extract(hdr.int_header); 200 | } 201 | } 202 | 203 | /************************************************************************* 204 | *********************** D E P A R S E R ******************************* 205 | *************************************************************************/ 206 | 207 | control MyEgressDeparser(packet_out packet, 208 | inout headers hdr, 209 | in local_metadata_t local_metadata, 210 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) { 211 | 212 | // Mirror() mirror; 213 | 214 | Checksum() ipv4Checksum; 215 | 216 | apply { 217 | 218 | // Egress mirroring if ncessary 219 | 220 | 221 | // if(eg_dprsr_md.mirror_type == MIRROR_TYPE_E2E) { 222 | // mirror.emit(local_metadata.egr_mir_ses, {local_metadata.pkt_type, hdr.local_report_header.ingress_port_id, 223 | // hdr.local_report_header.queue_id, hdr.local_report_header.ingress_global_tstamp}); 224 | // } 225 | 226 | hdr.ipv4.hdr_checksum = ipv4Checksum.update( 227 | { 228 | hdr.ipv4.version, 229 | hdr.ipv4.ihl, 230 | hdr.ipv4.dscp, 231 | hdr.ipv4.ecn, 232 | hdr.ipv4.len, 233 | hdr.ipv4.identification, 234 | hdr.ipv4.flags, 235 | hdr.ipv4.frag_offset, 236 | hdr.ipv4.ttl, 237 | hdr.ipv4.protocol, 238 | hdr.ipv4.src_addr, 239 | hdr.ipv4.dst_addr 240 | } 241 | ); 242 | 243 | // //parsed headers have to be added again into the packet. 244 | //packet.emit(hdr); 245 | packet.emit(hdr.report_ethernet); 246 | packet.emit(hdr.report_ipv4); 247 | packet.emit(hdr.report_udp); 248 | packet.emit(hdr.report_group_header); 249 | packet.emit(hdr.report_individual_header); 250 | 251 | packet.emit(hdr.ethernet); 252 | packet.emit(hdr.ipv4); 253 | packet.emit(hdr.udp); 254 | packet.emit(hdr.tcp); 255 | 256 | packet.emit(hdr.intl4_shim); 257 | packet.emit(hdr.int_header); 258 | packet.emit(hdr.int_switch_id); 259 | packet.emit(hdr.int_level1_port_ids); 260 | packet.emit(hdr.int_hop_latency); 261 | packet.emit(hdr.int_q_occupancy); 262 | packet.emit(hdr.int_ingress_tstamp); 263 | packet.emit(hdr.int_egress_tstamp); 264 | packet.emit(hdr.int_level2_port_ids); 265 | packet.emit(hdr.int_egress_tx_util); 266 | 267 | } 268 | } -------------------------------------------------------------------------------- /int-xd/p4src/int/sink.p4: -------------------------------------------------------------------------------- 1 | //Action to set node as INT sink in the egress for mirrored packets, however, this could be made as a flag based on the previous action instead 2 | control process_set_sink ( 3 | inout headers hdr, 4 | inout local_metadata_t local_metadata, 5 | in egress_intrinsic_metadata_t eg_intr_md) { 6 | 7 | action int_set_sink () { 8 | local_metadata.int_meta.sink = _TRUE; 9 | } 10 | 11 | table tb_set_sink { 12 | key = { 13 | eg_intr_md.egress_port: exact; 14 | } 15 | actions = { 16 | int_set_sink; 17 | NoAction(); 18 | } 19 | const default_action = NoAction(); 20 | size = MAX_PORTS; 21 | } 22 | 23 | apply { 24 | tb_set_sink.apply(); 25 | } 26 | } 27 | 28 | // Actions run in the egress of the INT Sink, before packet is forwarded to end-host 29 | control process_int_sink ( 30 | inout headers hdr, 31 | inout local_metadata_t local_metadata) { 32 | 33 | action restore_header () { 34 | // restore length fields of IPv4 header and UDP header, and IP DSCP which was stored in the INT SHIM Header 35 | hdr.ipv4.dscp = hdr.mirror_header.udp_ip_dscp; 36 | hdr.ipv4.len = hdr.ipv4.len - INT_TOTAL_HEADER_SIZE; 37 | hdr.udp.length_ = hdr.udp.length_ - INT_TOTAL_HEADER_SIZE; 38 | 39 | } 40 | 41 | action int_sink() { 42 | // remove all the INT information from the packet 43 | hdr.int_header.setInvalid(); 44 | hdr.intl4_shim.setInvalid(); 45 | hdr.mirror_header.setInvalid(); 46 | } 47 | 48 | apply { 49 | restore_header(); 50 | int_sink(); 51 | } 52 | } 53 | 54 | // This is an action to insert INT header from the mirror header into the new packet 55 | control process_int_header ( 56 | inout headers hdr, 57 | inout local_metadata_t local_metadata) { 58 | 59 | action add_int_header() { 60 | 61 | hdr.intl4_shim.setValid(); 62 | hdr.intl4_shim.int_type = hdr.mirror_header.int_type; 63 | hdr.intl4_shim.npt = hdr.mirror_header.npt; 64 | hdr.intl4_shim.len = hdr.mirror_header.len; 65 | hdr.intl4_shim.udp_ip_dscp = hdr.mirror_header.udp_ip_dscp; 66 | hdr.intl4_shim.udp_ip = hdr.mirror_header.udp_ip; 67 | 68 | 69 | hdr.int_header.setValid(); 70 | hdr.int_header.ver = hdr.mirror_header.ver; 71 | hdr.int_header.d = hdr.mirror_header.d; 72 | hdr.int_header.instruction_mask_0003 = hdr.mirror_header.instruction_mask_0003; 73 | hdr.int_header.instruction_mask_0407 = hdr.mirror_header.instruction_mask_0407; 74 | hdr.int_header.instruction_mask_0811 = hdr.mirror_header.instruction_mask_0811; 75 | hdr.int_header.instruction_mask_1215 = hdr.mirror_header.instruction_mask_1215; 76 | } 77 | 78 | apply { 79 | add_int_header(); 80 | } 81 | } 82 | 83 | 84 | // Action for the INT telemetry report, as it is encapsulated with new Ethernet, IP and UDP headers 85 | control process_int_report ( 86 | inout headers hdr, 87 | inout local_metadata_t local_metadata, 88 | in egress_intrinsic_metadata_t eg_intr_md) { 89 | 90 | action do_report_encapsulation(mac_t src_mac, mac_t mon_mac, ip_address_t src_ip, 91 | ip_address_t mon_ip, l4_port_t mon_port) { 92 | //Report Ethernet Header 93 | hdr.report_ethernet.setValid(); 94 | hdr.report_ethernet.dst_addr = mon_mac; 95 | hdr.report_ethernet.src_addr = src_mac; 96 | hdr.report_ethernet.ether_type = ETH_TYPE_IPV4; 97 | 98 | //Report IPV4 Header 99 | hdr.report_ipv4.setValid(); 100 | hdr.report_ipv4.version = IP_VERSION_4; 101 | hdr.report_ipv4.ihl = IPV4_IHL_MIN; 102 | hdr.report_ipv4.dscp = 6w0; 103 | hdr.report_ipv4.ecn = 2w0; 104 | /* Total Len is */ 105 | // 8 + 8 + 8 + 8 + 8 + 8 106 | hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + (bit<16>) REPORT_INDIVIDUAL_HEADER_LEN + 107 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + SHIM_LEN; 108 | 109 | hdr.report_ipv4.identification = 0; 110 | hdr.report_ipv4.flags = 0; 111 | hdr.report_ipv4.frag_offset = 0; 112 | hdr.report_ipv4.ttl = REPORT_HDR_TTL; 113 | hdr.report_ipv4.protocol = IP_PROTO_UDP; 114 | hdr.report_ipv4.src_addr = src_ip; 115 | hdr.report_ipv4.dst_addr = mon_ip; 116 | 117 | //Report UDP Header 118 | hdr.report_udp.setValid(); 119 | hdr.report_udp.src_port = 1234; 120 | hdr.report_udp.dst_port = mon_port; 121 | hdr.report_udp.length_ = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_GROUP_HEADER_LEN + (bit<16>) REPORT_INDIVIDUAL_HEADER_LEN + 122 | (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + SHIM_LEN; 123 | 124 | /* Telemetry Group Header */ 125 | 126 | hdr.report_group_header.setValid(); 127 | hdr.report_group_header.ver = 1; 128 | hdr.report_group_header.hw_id = HW_ID; 129 | hdr.report_group_header.seq_no = 0; 130 | hdr.report_group_header.node_id = local_metadata.int_meta.switch_id; 131 | 132 | /* Telemetry Report Individual Header */ 133 | hdr.report_individual_header.setValid(); 134 | hdr.report_individual_header.rep_type = 1; 135 | hdr.report_individual_header.in_type = 4; 136 | hdr.report_individual_header.len = 0; 137 | hdr.report_individual_header.rep_md_len = 0; 138 | hdr.report_individual_header.d = 0; 139 | hdr.report_individual_header.q = 0; 140 | hdr.report_individual_header.f = 1; 141 | hdr.report_individual_header.i = 1; 142 | hdr.report_individual_header.rsvd = 0; 143 | 144 | /* Individual report inner contents */ 145 | 146 | hdr.report_individual_header.rep_md_bits = 0; 147 | hdr.report_individual_header.domain_specific_id = 0; 148 | hdr.report_individual_header.domain_specific_md_bits = 0; 149 | hdr.report_individual_header.domain_specific_md_status = 0; 150 | } 151 | 152 | table tb_generate_report { 153 | // key = { 154 | // } 155 | actions = { 156 | do_report_encapsulation; 157 | NoAction(); 158 | } 159 | default_action = NoAction(); 160 | } 161 | 162 | apply { 163 | tb_generate_report.apply(); 164 | } 165 | } -------------------------------------------------------------------------------- /int-xd/p4src/int/source.p4: -------------------------------------------------------------------------------- 1 | // This action sets the node as a INT source or INT sink in the ingress pipeline 2 | // INT Source is set by the ingress port and INT Sink is set by the egress port 3 | control process_int_source_sink ( 4 | inout headers hdr, 5 | inout local_metadata_t local_metadata, 6 | in ingress_intrinsic_metadata_t ig_intr_md, 7 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 8 | 9 | action int_set_source () { 10 | local_metadata.int_meta.source = _TRUE; 11 | } 12 | 13 | action int_set_sink () { 14 | local_metadata.int_meta.sink = _TRUE; 15 | } 16 | 17 | table tb_set_source { 18 | key = { 19 | ig_intr_md.ingress_port: exact; 20 | } 21 | actions = { 22 | int_set_source; 23 | NoAction(); 24 | } 25 | const default_action = NoAction(); 26 | size = MAX_PORTS; 27 | } 28 | table tb_set_sink { 29 | key = { 30 | ig_tm_md.ucast_egress_port: exact; 31 | } 32 | actions = { 33 | int_set_sink; 34 | NoAction(); 35 | } 36 | const default_action = NoAction(); 37 | size = MAX_PORTS; 38 | } 39 | 40 | apply { 41 | tb_set_source.apply(); 42 | tb_set_sink.apply(); 43 | } 44 | } 45 | 46 | // Insert INT header to the packet 47 | control process_int_source ( 48 | inout headers hdr, 49 | inout local_metadata_t local_metadata) { 50 | 51 | action int_source(bit<4> ins_mask0003, bit<4> ins_mask0407) { 52 | 53 | hdr.intl4_shim.setValid(); // insert INT shim header 54 | hdr.intl4_shim.int_type = 3; // int_type: Hop-by-hop type (1) , destination type (2), MX-type (3) 55 | hdr.intl4_shim.npt = 0; // next protocol type: 0 56 | hdr.intl4_shim.len = INT_HEADER_LEN_WORD; // This is 3 from 0xC (INT_TOTAL_HEADER_SIZE >> 2) 57 | hdr.intl4_shim.udp_ip_dscp = hdr.ipv4.dscp; // although should be first 6 bits of the second byte 58 | hdr.intl4_shim.udp_ip = 0; // although should be first 6 bits of the second byte 59 | 60 | // insert INT header 61 | hdr.int_header.setValid(); 62 | hdr.int_header.ver = 2; 63 | hdr.int_header.d = 0; 64 | hdr.int_header.instruction_mask_0003 = ins_mask0003; 65 | hdr.int_header.instruction_mask_0407 = ins_mask0407; 66 | hdr.int_header.instruction_mask_0811 = 0; // bit 8 is buffer related, rest are reserved 67 | hdr.int_header.instruction_mask_1215 = 0; // rsvd 68 | 69 | hdr.int_header.domain_specific_id = 0; // Unique INT Domain ID 70 | hdr.int_header.ds_instruction = 0; // Instruction bitmap specific to the INT Domain identified by the Domain specific ID 71 | hdr.int_header.ds_flags = 0; // Domain specific flags 72 | 73 | // add the header len (3 words) to total len 74 | hdr.ipv4.len = hdr.ipv4.len + INT_TOTAL_HEADER_SIZE; 75 | hdr.udp.length_ = hdr.udp.length_ + INT_TOTAL_HEADER_SIZE; 76 | 77 | hdr.ipv4.dscp = DSCP_INT; 78 | } 79 | 80 | table tb_int_source { 81 | key = { 82 | //configure for each flow to be monitored 83 | // 4 fields identifying flow 84 | //include ip src, udp/tcp src and dest too 85 | hdr.ipv4.dst_addr: lpm; 86 | } 87 | actions = { 88 | int_source; 89 | NoAction; 90 | } 91 | const default_action = NoAction(); 92 | } 93 | 94 | apply { 95 | tb_int_source.apply(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /int-xd/p4src/int/transit.p4: -------------------------------------------------------------------------------- 1 | // Action to add INT metadata to the packet 2 | // It uses the Instruction bitmap to create a combination of data fields to be added 3 | // The header lengths are updated accordingly 4 | control process_int_transit ( 5 | inout headers hdr, 6 | inout local_metadata_t local_metadata, 7 | in egress_intrinsic_metadata_t eg_intr_md, 8 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md) { 9 | 10 | action init_metadata(switch_id_t switch_id) { 11 | local_metadata.int_meta.transit = _TRUE; 12 | local_metadata.int_meta.switch_id = switch_id; 13 | } 14 | 15 | 16 | action int_set_header_0() { //switch_id 17 | hdr.int_switch_id.setValid(); 18 | hdr.int_switch_id.switch_id = local_metadata.int_meta.switch_id; 19 | } 20 | 21 | action int_set_header_1() { //level1_port_id - physical port 22 | hdr.int_level1_port_ids.setValid(); 23 | hdr.int_level1_port_ids.ingress_port_id = 24 | (bit<16>) hdr.mirror_header.ingress_port_id; 25 | hdr.int_level1_port_ids.egress_port_id = (bit<16>) hdr.mirror_header.egress_port_id; 26 | } 27 | 28 | action int_set_header_2() { //hop_latency 29 | hdr.int_hop_latency.setValid(); 30 | hdr.int_hop_latency.hop_latency = (bit<32>) ((bit<64>) eg_prsr_md.global_tstamp - 31 | hdr.mirror_header.ingress_global_tstamp); 32 | } 33 | 34 | action int_set_header_3() { //q_occupancy 35 | hdr.int_q_occupancy.setValid(); 36 | hdr.int_q_occupancy.q_id = 37 | (bit<8>) hdr.mirror_header.queue_id; 38 | hdr.int_q_occupancy.q_occupancy = 39 | (bit<24>) eg_intr_md.deq_qdepth; 40 | } 41 | 42 | action int_set_header_4() { //ingress_tstamp 43 | hdr.int_ingress_tstamp.setValid(); 44 | hdr.int_ingress_tstamp.ingress_tstamp = 45 | hdr.mirror_header.ingress_global_tstamp; 46 | } 47 | 48 | action int_set_header_5() { //egress_timestamp 49 | hdr.int_egress_tstamp.setValid(); 50 | hdr.int_egress_tstamp.egress_tstamp = 51 | (bit<64>) eg_prsr_md.global_tstamp; 52 | } 53 | 54 | action int_set_header_6() { //level2_port_id 55 | hdr.int_level2_port_ids.setValid(); 56 | // level2_port_id indicates Logical port ID - update this! 57 | hdr.int_level2_port_ids.ingress_port_id = (bit<32>) local_metadata.l4_src_port; 58 | hdr.int_level2_port_ids.egress_port_id = (bit<32>) local_metadata.l4_dst_port; 59 | } 60 | 61 | action int_set_header_7() { //egress_port_tx_utilization - tofino implementation 62 | hdr.int_egress_tx_util.setValid(); 63 | hdr.int_egress_tx_util.egress_port_tx_util = 64 | (bit<32>) eg_intr_md.deq_timedelta; 65 | } 66 | 67 | // Actions to keep track of the new metadata added. 68 | 69 | action add_1() { 70 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 1; 71 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 4; 72 | } 73 | 74 | 75 | action add_2() { 76 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 2; 77 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 8; 78 | } 79 | 80 | 81 | action add_3() { 82 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 3; 83 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 12; 84 | } 85 | 86 | 87 | action add_4() { 88 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 4; 89 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 16; 90 | } 91 | 92 | 93 | action add_5() { 94 | local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 5; 95 | local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 20; 96 | } 97 | 98 | /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */ 99 | /* Each bit set indicates that corresponding INT header should be added */ 100 | 101 | action int_set_header_0003_i0() { 102 | } 103 | 104 | action int_set_header_0003_i1() { 105 | int_set_header_3(); 106 | add_1(); 107 | } 108 | 109 | action int_set_header_0003_i2() { 110 | int_set_header_2(); 111 | add_1(); 112 | } 113 | 114 | action int_set_header_0003_i3() { 115 | int_set_header_3(); 116 | int_set_header_2(); 117 | add_2(); 118 | } 119 | 120 | action int_set_header_0003_i4() { 121 | int_set_header_1(); 122 | add_1(); 123 | } 124 | 125 | action int_set_header_0003_i5() { 126 | int_set_header_3(); 127 | int_set_header_1(); 128 | add_2(); 129 | } 130 | 131 | action int_set_header_0003_i6() { 132 | int_set_header_2(); 133 | int_set_header_1(); 134 | add_2(); 135 | } 136 | 137 | action int_set_header_0003_i7() { 138 | int_set_header_3(); 139 | int_set_header_2(); 140 | int_set_header_1(); 141 | add_3(); 142 | } 143 | 144 | action int_set_header_0003_i8() { 145 | int_set_header_0(); 146 | add_1(); 147 | } 148 | 149 | action int_set_header_0003_i9() { 150 | int_set_header_3(); 151 | int_set_header_0(); 152 | add_2(); 153 | } 154 | 155 | action int_set_header_0003_i10() { 156 | int_set_header_2(); 157 | int_set_header_0(); 158 | add_2(); 159 | } 160 | 161 | action int_set_header_0003_i11() { 162 | int_set_header_3(); 163 | int_set_header_2(); 164 | int_set_header_0(); 165 | add_3(); 166 | } 167 | 168 | action int_set_header_0003_i12() { 169 | int_set_header_1(); 170 | int_set_header_0(); 171 | add_2(); 172 | } 173 | 174 | action int_set_header_0003_i13() { 175 | int_set_header_3(); 176 | int_set_header_1(); 177 | int_set_header_0(); 178 | add_3(); 179 | } 180 | 181 | action int_set_header_0003_i14() { 182 | int_set_header_2(); 183 | int_set_header_1(); 184 | int_set_header_0(); 185 | add_3(); 186 | } 187 | 188 | action int_set_header_0003_i15() { 189 | int_set_header_3(); 190 | int_set_header_2(); 191 | int_set_header_1(); 192 | int_set_header_0(); 193 | add_4(); 194 | } 195 | 196 | /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */ 197 | 198 | action int_set_header_0407_i0() { 199 | } 200 | 201 | action int_set_header_0407_i1() { 202 | int_set_header_7(); 203 | add_1(); 204 | } 205 | 206 | action int_set_header_0407_i2() { 207 | int_set_header_6(); 208 | add_2(); 209 | } 210 | 211 | action int_set_header_0407_i3() { 212 | int_set_header_7(); 213 | int_set_header_6(); 214 | add_3(); 215 | } 216 | 217 | action int_set_header_0407_i4() { 218 | int_set_header_5(); 219 | add_1(); 220 | } 221 | 222 | action int_set_header_0407_i5() { 223 | int_set_header_7(); 224 | int_set_header_5(); 225 | add_2(); 226 | } 227 | 228 | action int_set_header_0407_i6() { 229 | int_set_header_6(); 230 | int_set_header_5(); 231 | add_3(); 232 | } 233 | 234 | action int_set_header_0407_i7() { 235 | int_set_header_7(); 236 | int_set_header_6(); 237 | int_set_header_5(); 238 | add_4(); 239 | } 240 | 241 | action int_set_header_0407_i8() { 242 | int_set_header_4(); 243 | add_1(); 244 | } 245 | 246 | action int_set_header_0407_i9() { 247 | int_set_header_7(); 248 | int_set_header_4(); 249 | add_2(); 250 | } 251 | 252 | action int_set_header_0407_i10() { 253 | int_set_header_6(); 254 | int_set_header_4(); 255 | add_3(); 256 | } 257 | 258 | action int_set_header_0407_i11() { 259 | int_set_header_7(); 260 | int_set_header_6(); 261 | int_set_header_4(); 262 | add_4(); 263 | } 264 | 265 | action int_set_header_0407_i12() { 266 | int_set_header_5(); 267 | int_set_header_4(); 268 | add_2(); 269 | } 270 | 271 | action int_set_header_0407_i13() { 272 | int_set_header_7(); 273 | int_set_header_5(); 274 | int_set_header_4(); 275 | add_3(); 276 | } 277 | 278 | action int_set_header_0407_i14() { 279 | int_set_header_6(); 280 | int_set_header_5(); 281 | int_set_header_4(); 282 | add_4(); 283 | } 284 | 285 | action int_set_header_0407_i15() { 286 | int_set_header_7(); 287 | int_set_header_6(); 288 | int_set_header_5(); 289 | int_set_header_4(); 290 | add_5(); 291 | } 292 | 293 | // Default action used to set switch ID. 294 | table tb_int_insert { 295 | // key = { 296 | // } 297 | actions = { 298 | init_metadata; 299 | NoAction; 300 | } 301 | default_action = NoAction(); 302 | size = 1; 303 | } 304 | 305 | /* Table to process instruction bits 0-3 */ 306 | 307 | table tb_int_inst_0003 { 308 | key = { 309 | hdr.mirror_header.instruction_mask_0003 : exact; 310 | } 311 | actions = { 312 | int_set_header_0003_i0; 313 | int_set_header_0003_i1; 314 | int_set_header_0003_i2; 315 | int_set_header_0003_i3; 316 | int_set_header_0003_i4; 317 | int_set_header_0003_i5; 318 | int_set_header_0003_i6; 319 | int_set_header_0003_i7; 320 | int_set_header_0003_i8; 321 | int_set_header_0003_i9; 322 | int_set_header_0003_i10; 323 | int_set_header_0003_i11; 324 | int_set_header_0003_i12; 325 | int_set_header_0003_i13; 326 | int_set_header_0003_i14; 327 | int_set_header_0003_i15; 328 | } 329 | 330 | const entries = { 331 | (0x0) : int_set_header_0003_i0(); 332 | (0x1) : int_set_header_0003_i1(); 333 | (0x2) : int_set_header_0003_i2(); 334 | (0x3) : int_set_header_0003_i3(); 335 | (0x4) : int_set_header_0003_i4(); 336 | (0x5) : int_set_header_0003_i5(); 337 | (0x6) : int_set_header_0003_i6(); 338 | (0x7) : int_set_header_0003_i7(); 339 | (0x8) : int_set_header_0003_i8(); 340 | (0x9) : int_set_header_0003_i9(); 341 | (0xA) : int_set_header_0003_i10(); 342 | (0xB) : int_set_header_0003_i11(); 343 | (0xC) : int_set_header_0003_i12(); 344 | (0xD) : int_set_header_0003_i13(); 345 | (0xE) : int_set_header_0003_i14(); 346 | (0xF) : int_set_header_0003_i15(); 347 | } 348 | 349 | size = 16; 350 | } 351 | 352 | /* Table to process instruction bits 4-7 */ 353 | 354 | table tb_int_inst_0407 { 355 | key = { 356 | hdr.mirror_header.instruction_mask_0407 : exact; 357 | } 358 | actions = { 359 | int_set_header_0407_i0; 360 | int_set_header_0407_i1; 361 | int_set_header_0407_i2; 362 | int_set_header_0407_i3; 363 | int_set_header_0407_i4; 364 | int_set_header_0407_i5; 365 | int_set_header_0407_i6; 366 | int_set_header_0407_i7; 367 | int_set_header_0407_i8; 368 | int_set_header_0407_i9; 369 | int_set_header_0407_i10; 370 | int_set_header_0407_i11; 371 | int_set_header_0407_i12; 372 | int_set_header_0407_i13; 373 | int_set_header_0407_i14; 374 | int_set_header_0407_i15; 375 | } 376 | 377 | const entries = { 378 | (0x0) : int_set_header_0407_i0(); 379 | (0x1) : int_set_header_0407_i1(); 380 | (0x2) : int_set_header_0407_i2(); 381 | (0x3) : int_set_header_0407_i3(); 382 | (0x4) : int_set_header_0407_i4(); 383 | (0x5) : int_set_header_0407_i5(); 384 | (0x6) : int_set_header_0407_i6(); 385 | (0x7) : int_set_header_0407_i7(); 386 | (0x8) : int_set_header_0407_i8(); 387 | (0x9) : int_set_header_0407_i9(); 388 | (0xA) : int_set_header_0407_i10(); 389 | (0xB) : int_set_header_0407_i11(); 390 | (0xC) : int_set_header_0407_i12(); 391 | (0xD) : int_set_header_0407_i13(); 392 | (0xE) : int_set_header_0407_i14(); 393 | (0xF) : int_set_header_0407_i15(); 394 | } 395 | 396 | size = 16; 397 | } 398 | 399 | apply { 400 | tb_int_insert.apply(); 401 | if (local_metadata.int_meta.transit == _FALSE) { 402 | return; 403 | } 404 | tb_int_inst_0003.apply(); 405 | tb_int_inst_0407.apply(); 406 | 407 | // Update headers lengths. 408 | if (hdr.ipv4.isValid()) { 409 | hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.new_bytes; 410 | } 411 | if (hdr.udp.isValid()) { 412 | hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.new_bytes; 413 | } 414 | if (hdr.mirror_header.isValid()) { 415 | hdr.mirror_header.len = hdr.mirror_header.len + local_metadata.int_meta.new_words; 416 | } 417 | } 418 | } -------------------------------------------------------------------------------- /int-xd/p4src/int_xd.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * This file has been modified. 19 | * Modifications Copyright © 2021 Saab AB / Mandar Joshi 20 | */ 21 | 22 | /* 23 | * This program is free software: you can redistribute it and/or modify 24 | * it under the terms of the GNU General Public License as published by 25 | * the Free Software Foundation, either version 2 of the License, or 26 | * (at your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | * GNU General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program. If not, see . 35 | */ 36 | 37 | /* -*- P4_16 -*- */ 38 | 39 | #include 40 | #include 41 | 42 | #include "int/headers.p4" 43 | #include "int/parsers.p4" 44 | #include "int/sink.p4" 45 | #include "int/transit.p4" 46 | #include "int/source.p4" 47 | #include "int/forward.p4" 48 | 49 | /************************************************************************* 50 | **************** I N G R E S S P R O C E S S I N G ****************** 51 | *************************************************************************/ 52 | 53 | control MyIngress(inout headers hdr, 54 | inout local_metadata_t local_metadata, 55 | in ingress_intrinsic_metadata_t ig_intr_md, 56 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 57 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 58 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 59 | 60 | apply { 61 | 62 | port_forward.apply(hdr, local_metadata, ig_tm_md, ig_dprsr_md); 63 | 64 | process_int_source_sink.apply(hdr, local_metadata, ig_intr_md, ig_tm_md); 65 | 66 | if (local_metadata.int_meta.source == _TRUE) { 67 | process_int_source.apply(hdr, local_metadata); 68 | } 69 | 70 | if (hdr.int_header.isValid()) { // Mirror the packet 71 | 72 | //MIRROR_TYPE_I2E = 1 from bf-sde-9.4.0/pkgsrc/p4-examples/p4_16_programs/tna_mirror 73 | ig_dprsr_md.mirror_type = MIRROR_TYPE_I2E; 74 | local_metadata.pkt_type = PKT_TYPE_MIRROR; 75 | local_metadata.ing_mir_ses = (bit<10>) MIRROR_TYPE_I2E; 76 | } 77 | 78 | // Save ingress parser values for egress / INT Transit 79 | if (hdr.int_header.isValid()) { 80 | hdr.local_report_header.setValid(); 81 | hdr.local_report_header.ingress_port_id = (bit<16>) ig_intr_md.ingress_port; 82 | hdr.local_report_header.egress_port_id = (bit<16>) ig_tm_md.ucast_egress_port; 83 | hdr.local_report_header.queue_id = (bit<8>) ig_tm_md.qid; 84 | hdr.local_report_header.ingress_global_tstamp = (bit<64>) ig_prsr_md.global_tstamp; 85 | } 86 | } 87 | } 88 | 89 | /************************************************************************* 90 | ***************** E G R E S S P R O C E S S I N G ******************* 91 | *************************************************************************/ 92 | 93 | control MyEgress(inout headers hdr, 94 | inout local_metadata_t local_metadata, 95 | in egress_intrinsic_metadata_t eg_intr_md, 96 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 97 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 98 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 99 | 100 | apply { 101 | if(hdr.int_header.isValid() && local_metadata.mirror == _FALSE) { 102 | 103 | process_set_sink.apply(hdr, local_metadata, eg_intr_md); 104 | 105 | if (local_metadata.int_meta.sink == _TRUE) { 106 | 107 | process_int_sink.apply(hdr, local_metadata); 108 | 109 | } 110 | } 111 | 112 | if (local_metadata.mirror == _TRUE) { 113 | process_int_transit.apply(hdr, local_metadata, eg_intr_md, eg_prsr_md); 114 | process_int_report.apply(hdr, local_metadata, eg_intr_md); 115 | } 116 | 117 | if (hdr.int_header.isValid() == _FALSE && local_metadata.int_meta.sink == _FALSE) { 118 | process_int_header.apply(hdr, local_metadata); 119 | } 120 | 121 | hdr.local_report_header.setInvalid(); 122 | hdr.mirror_header.setInvalid(); 123 | 124 | } 125 | } 126 | 127 | /************************************************************************* 128 | *********************** S W I T C H ******************************* 129 | *************************************************************************/ 130 | 131 | Pipeline( 132 | MyIngressParser(), 133 | MyIngress(), 134 | MyIngressDeparser(), 135 | MyEgressParser(), 136 | MyEgress(), 137 | MyEgressDeparser() 138 | ) pipe; 139 | 140 | Switch(pipe) main; --------------------------------------------------------------------------------