Loading src/service/service/service_handlers/p4/p4_service_handler.py +48 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,48 @@ def create_rule_del(endpoint_a, endpoint_b): } ) def create_int_set(endpoint_a, id): return json_config_rule_set( 'table', { 'table-name': 'EgressPipeImpl.int_table', 'match-fields': [ { 'match-field': 'standard_metadata.ingress_port', 'match-value': endpoint_a } ], 'action-name': 'EgressPipeImpl.add_int_header', 'action-params': [ { 'action-param': 'swid', 'action-value': id } ] } ) def create_int_del(endpoint_a, id): return json_config_rule_delete( 'table', { 'table-name': 'EgressPipeImpl.int_table', 'match-fields': [ { 'match-field': 'standard_metadata.ingress_port', 'match-value': endpoint_a } ], 'action-name': 'EgressPipeImpl.add_int_header', 'action-params': [ { 'action-param': 'swid', 'action-value': id } ] } ) def find_names(uuid_a, uuid_b, device_endpoints): endpoint_a, endpoint_b = None, None for endpoint in device_endpoints: Loading Loading @@ -157,6 +199,9 @@ class P4ServiceHandler(_ServiceHandler): rule = create_rule_set(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) rule = create_int_set(endpoint_a, device.name[-1]) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) results.append(True) Loading Loading @@ -228,6 +273,9 @@ class P4ServiceHandler(_ServiceHandler): rule = create_rule_del(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) rule = create_int_del(endpoint_a, device.name[-1]) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) results.append(True) Loading src/tests/hackfest3/new-probe/install-scapy.sh 0 → 100644 +7 −0 Original line number Diff line number Diff line #!/bin/bash sed -i 's/deb.debian.org/archive.debian.org/g' /etc/apt/sources.list sed -i 's|security.debian.org|archive.debian.org/debian-security/|g' /etc/apt/sources.list sed -i '/stretch-updates/d' /etc/apt/sources.list apt update apt install -y python-scapy src/tests/hackfest3/new-probe/receive2.py 0 → 100644 +60 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 import sys import struct from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr from scapy.all import Packet, IPOption from scapy.all import PacketListField, ShortField, IntField, LongField, BitField, FieldListField, FieldLenField from scapy.all import IP, UDP, Raw from scapy.layers.inet import _IPOption_HDR def get_if(): ifs=get_if_list() iface=None for i in get_if_list(): if "eth0" in i: iface=i break if not iface: print("Cannot find eth0 interface") exit(1) return iface class SwitchTrace(Packet): fields_desc = [ BitField("timestamp", 0, 32)] def extract_padding(self, p): return "", p class IPOption_INT(IPOption): name = "INT" option = 31 fields_desc = [ _IPOption_HDR, FieldLenField("length", None, fmt="B", length_of="int_headers", adjust=lambda pkt,l:l*2+4), ShortField("count", 0), PacketListField("int_headers", [], SwitchTrace, count_from=lambda pkt:(pkt.count*1)) ] def handle_pkt(pkt): print("got a packet") pkt.show2() sys.stdout.flush() def main(): iface = 'server-eth0' print("sniffing on %s" % iface) sys.stdout.flush() sniff(filter="udp and port 4321", iface = iface, prn = lambda x: handle_pkt(x)) if __name__ == '__main__': main() src/tests/hackfest3/p4/main.p4 +6 −8 Original line number Diff line number Diff line Loading @@ -35,8 +35,7 @@ typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; typedef bit<13> switch_id_t; typedef bit<13> queue_depth_t; typedef bit<6> output_port_t; typedef bit<32> queue_depth_t; header ethernet_t { macAddr_t dstAddr; Loading Loading @@ -72,9 +71,7 @@ header int_count_t { } header int_header_t { switch_id_t switch_id; queue_depth_t queue_depth; output_port_t output_port; } Loading Loading @@ -206,9 +203,7 @@ control EgressPipeImpl (inout parsed_headers_t hdr, // This was not needed in older specs. Now by default pushed // invalid elements are hdr.int_headers[0].setValid(); hdr.int_headers[0].switch_id = (bit<13>)swid; hdr.int_headers[0].queue_depth = (bit<13>)standard_metadata.deq_timedelta; hdr.int_headers[0].output_port = (bit<6>)standard_metadata.egress_port; hdr.int_headers[0].queue_depth = (bit<32>)standard_metadata.ingress_global_timestamp; //update ip header length hdr.ipv4.ihl = hdr.ipv4.ihl + 1; Loading @@ -217,11 +212,14 @@ control EgressPipeImpl (inout parsed_headers_t hdr, } table int_table { key = { standard_metadata.ingress_port: exact; } actions = { add_int_header; NoAction; } default_action = NoAction(); default_action = NoAction; } apply { Loading src/tests/hackfest3/p4/qdepth.main.p4 0 → 100644 +281 −0 Original line number Diff line number Diff line /* * Copyright 2019-present Open Networking Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <core.p4> #include <v1model.p4> typedef bit<9> port_num_t; typedef bit<48> mac_addr_t; //------------------------------------------------------------------------------ // HEADER DEFINITIONS //------------------------------------------------------------------------------ #define MAX_INT_HEADERS 9 const bit<16> TYPE_IPV4 = 0x800; const bit<5> IPV4_OPTION_INT = 31; typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; typedef bit<13> switch_id_t; typedef bit<13> queue_depth_t; typedef bit<6> output_port_t; header ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } header ipv4_t { bit<4> version; bit<4> ihl; bit<6> dscp; bit<2> ecn; bit<16> totalLen; bit<16> identification; bit<3> flags; bit<13> fragOffset; bit<8> ttl; bit<8> protocol; bit<16> hdrChecksum; ip4Addr_t srcAddr; ip4Addr_t dstAddr; } header ipv4_option_t { bit<1> copyFlag; bit<2> optClass; bit<5> option; bit<8> optionLength; } header int_count_t { bit<16> num_switches; } header int_header_t { switch_id_t switch_id; queue_depth_t queue_depth; output_port_t output_port; } struct parser_metadata_t { bit<16> num_headers_remaining; } struct local_metadata_t { parser_metadata_t parser_metadata; } struct parsed_headers_t { ethernet_t ethernet; ipv4_t ipv4; ipv4_option_t ipv4_option; int_count_t int_count; int_header_t[MAX_INT_HEADERS] int_headers; } error { IPHeaderWithoutOptions } //------------------------------------------------------------------------------ // INGRESS PIPELINE //------------------------------------------------------------------------------ parser ParserImpl(packet_in packet, out parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { state start { packet.extract(hdr.ethernet); transition select(hdr.ethernet.etherType){ TYPE_IPV4: parse_ipv4; default: accept; } } state parse_ipv4 { packet.extract(hdr.ipv4); //Check if ihl is bigger than 5. Packets without ip options set ihl to 5. verify(hdr.ipv4.ihl >= 5, error.IPHeaderWithoutOptions); transition select(hdr.ipv4.ihl) { 5 : accept; default : parse_ipv4_option; } } state parse_ipv4_option { packet.extract(hdr.ipv4_option); transition select(hdr.ipv4_option.option){ IPV4_OPTION_INT: parse_int; default: accept; } } state parse_int { packet.extract(hdr.int_count); local_metadata.parser_metadata.num_headers_remaining = hdr.int_count.num_switches; transition select(local_metadata.parser_metadata.num_headers_remaining){ 0: accept; default: parse_int_headers; } } state parse_int_headers { packet.extract(hdr.int_headers.next); local_metadata.parser_metadata.num_headers_remaining = local_metadata.parser_metadata.num_headers_remaining -1 ; transition select(local_metadata.parser_metadata.num_headers_remaining){ 0: accept; default: parse_int_headers; } } } control VerifyChecksumImpl(inout parsed_headers_t hdr, inout local_metadata_t meta) { apply { /* EMPTY */ } } control IngressPipeImpl (inout parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { action drop() { mark_to_drop(standard_metadata); } action set_egress_port(port_num_t port) { standard_metadata.egress_spec = port; } // --- l2_exact_table ------------------ table l2_exact_table { key = { standard_metadata.ingress_port: exact; } actions = { set_egress_port; @defaultonly drop; } const default_action = drop; } apply { l2_exact_table.apply(); } } //------------------------------------------------------------------------------ // EGRESS PIPELINE //------------------------------------------------------------------------------ control EgressPipeImpl (inout parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { action add_int_header(switch_id_t swid){ //increase int stack counter by one hdr.int_count.num_switches = hdr.int_count.num_switches + 1; hdr.int_headers.push_front(1); // This was not needed in older specs. Now by default pushed // invalid elements are hdr.int_headers[0].setValid(); hdr.int_headers[0].switch_id = (bit<13>)swid; hdr.int_headers[0].queue_depth = (bit<13>)standard_metadata.deq_qdepth; hdr.int_headers[0].output_port = (bit<6>)standard_metadata.egress_port; //update ip header length hdr.ipv4.ihl = hdr.ipv4.ihl + 1; hdr.ipv4.totalLen = hdr.ipv4.totalLen + 4; hdr.ipv4_option.optionLength = hdr.ipv4_option.optionLength + 4; } table int_table { key = { standard_metadata.ingress_port: exact; } actions = { add_int_header; NoAction; } default_action = NoAction; } apply { if (hdr.int_count.isValid()){ int_table.apply(); } } } control ComputeChecksumImpl(inout parsed_headers_t hdr, inout local_metadata_t local_metadata) { apply { update_checksum( hdr.ipv4.isValid(), { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.dscp, hdr.ipv4.ecn, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); } } control DeparserImpl(packet_out packet, in parsed_headers_t hdr) { apply { //parsed headers have to be added again into the packet. packet.emit(hdr.ethernet); packet.emit(hdr.ipv4); packet.emit(hdr.ipv4_option); packet.emit(hdr.int_count); packet.emit(hdr.int_headers); } } V1Switch( ParserImpl(), VerifyChecksumImpl(), IngressPipeImpl(), EgressPipeImpl(), ComputeChecksumImpl(), DeparserImpl() ) main; Loading
src/service/service/service_handlers/p4/p4_service_handler.py +48 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,48 @@ def create_rule_del(endpoint_a, endpoint_b): } ) def create_int_set(endpoint_a, id): return json_config_rule_set( 'table', { 'table-name': 'EgressPipeImpl.int_table', 'match-fields': [ { 'match-field': 'standard_metadata.ingress_port', 'match-value': endpoint_a } ], 'action-name': 'EgressPipeImpl.add_int_header', 'action-params': [ { 'action-param': 'swid', 'action-value': id } ] } ) def create_int_del(endpoint_a, id): return json_config_rule_delete( 'table', { 'table-name': 'EgressPipeImpl.int_table', 'match-fields': [ { 'match-field': 'standard_metadata.ingress_port', 'match-value': endpoint_a } ], 'action-name': 'EgressPipeImpl.add_int_header', 'action-params': [ { 'action-param': 'swid', 'action-value': id } ] } ) def find_names(uuid_a, uuid_b, device_endpoints): endpoint_a, endpoint_b = None, None for endpoint in device_endpoints: Loading Loading @@ -157,6 +199,9 @@ class P4ServiceHandler(_ServiceHandler): rule = create_rule_set(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) rule = create_int_set(endpoint_a, device.name[-1]) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) results.append(True) Loading Loading @@ -228,6 +273,9 @@ class P4ServiceHandler(_ServiceHandler): rule = create_rule_del(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) rule = create_int_del(endpoint_a, device.name[-1]) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) results.append(True) Loading
src/tests/hackfest3/new-probe/install-scapy.sh 0 → 100644 +7 −0 Original line number Diff line number Diff line #!/bin/bash sed -i 's/deb.debian.org/archive.debian.org/g' /etc/apt/sources.list sed -i 's|security.debian.org|archive.debian.org/debian-security/|g' /etc/apt/sources.list sed -i '/stretch-updates/d' /etc/apt/sources.list apt update apt install -y python-scapy
src/tests/hackfest3/new-probe/receive2.py 0 → 100644 +60 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 import sys import struct from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr from scapy.all import Packet, IPOption from scapy.all import PacketListField, ShortField, IntField, LongField, BitField, FieldListField, FieldLenField from scapy.all import IP, UDP, Raw from scapy.layers.inet import _IPOption_HDR def get_if(): ifs=get_if_list() iface=None for i in get_if_list(): if "eth0" in i: iface=i break if not iface: print("Cannot find eth0 interface") exit(1) return iface class SwitchTrace(Packet): fields_desc = [ BitField("timestamp", 0, 32)] def extract_padding(self, p): return "", p class IPOption_INT(IPOption): name = "INT" option = 31 fields_desc = [ _IPOption_HDR, FieldLenField("length", None, fmt="B", length_of="int_headers", adjust=lambda pkt,l:l*2+4), ShortField("count", 0), PacketListField("int_headers", [], SwitchTrace, count_from=lambda pkt:(pkt.count*1)) ] def handle_pkt(pkt): print("got a packet") pkt.show2() sys.stdout.flush() def main(): iface = 'server-eth0' print("sniffing on %s" % iface) sys.stdout.flush() sniff(filter="udp and port 4321", iface = iface, prn = lambda x: handle_pkt(x)) if __name__ == '__main__': main()
src/tests/hackfest3/p4/main.p4 +6 −8 Original line number Diff line number Diff line Loading @@ -35,8 +35,7 @@ typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; typedef bit<13> switch_id_t; typedef bit<13> queue_depth_t; typedef bit<6> output_port_t; typedef bit<32> queue_depth_t; header ethernet_t { macAddr_t dstAddr; Loading Loading @@ -72,9 +71,7 @@ header int_count_t { } header int_header_t { switch_id_t switch_id; queue_depth_t queue_depth; output_port_t output_port; } Loading Loading @@ -206,9 +203,7 @@ control EgressPipeImpl (inout parsed_headers_t hdr, // This was not needed in older specs. Now by default pushed // invalid elements are hdr.int_headers[0].setValid(); hdr.int_headers[0].switch_id = (bit<13>)swid; hdr.int_headers[0].queue_depth = (bit<13>)standard_metadata.deq_timedelta; hdr.int_headers[0].output_port = (bit<6>)standard_metadata.egress_port; hdr.int_headers[0].queue_depth = (bit<32>)standard_metadata.ingress_global_timestamp; //update ip header length hdr.ipv4.ihl = hdr.ipv4.ihl + 1; Loading @@ -217,11 +212,14 @@ control EgressPipeImpl (inout parsed_headers_t hdr, } table int_table { key = { standard_metadata.ingress_port: exact; } actions = { add_int_header; NoAction; } default_action = NoAction(); default_action = NoAction; } apply { Loading
src/tests/hackfest3/p4/qdepth.main.p4 0 → 100644 +281 −0 Original line number Diff line number Diff line /* * Copyright 2019-present Open Networking Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <core.p4> #include <v1model.p4> typedef bit<9> port_num_t; typedef bit<48> mac_addr_t; //------------------------------------------------------------------------------ // HEADER DEFINITIONS //------------------------------------------------------------------------------ #define MAX_INT_HEADERS 9 const bit<16> TYPE_IPV4 = 0x800; const bit<5> IPV4_OPTION_INT = 31; typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; typedef bit<13> switch_id_t; typedef bit<13> queue_depth_t; typedef bit<6> output_port_t; header ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } header ipv4_t { bit<4> version; bit<4> ihl; bit<6> dscp; bit<2> ecn; bit<16> totalLen; bit<16> identification; bit<3> flags; bit<13> fragOffset; bit<8> ttl; bit<8> protocol; bit<16> hdrChecksum; ip4Addr_t srcAddr; ip4Addr_t dstAddr; } header ipv4_option_t { bit<1> copyFlag; bit<2> optClass; bit<5> option; bit<8> optionLength; } header int_count_t { bit<16> num_switches; } header int_header_t { switch_id_t switch_id; queue_depth_t queue_depth; output_port_t output_port; } struct parser_metadata_t { bit<16> num_headers_remaining; } struct local_metadata_t { parser_metadata_t parser_metadata; } struct parsed_headers_t { ethernet_t ethernet; ipv4_t ipv4; ipv4_option_t ipv4_option; int_count_t int_count; int_header_t[MAX_INT_HEADERS] int_headers; } error { IPHeaderWithoutOptions } //------------------------------------------------------------------------------ // INGRESS PIPELINE //------------------------------------------------------------------------------ parser ParserImpl(packet_in packet, out parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { state start { packet.extract(hdr.ethernet); transition select(hdr.ethernet.etherType){ TYPE_IPV4: parse_ipv4; default: accept; } } state parse_ipv4 { packet.extract(hdr.ipv4); //Check if ihl is bigger than 5. Packets without ip options set ihl to 5. verify(hdr.ipv4.ihl >= 5, error.IPHeaderWithoutOptions); transition select(hdr.ipv4.ihl) { 5 : accept; default : parse_ipv4_option; } } state parse_ipv4_option { packet.extract(hdr.ipv4_option); transition select(hdr.ipv4_option.option){ IPV4_OPTION_INT: parse_int; default: accept; } } state parse_int { packet.extract(hdr.int_count); local_metadata.parser_metadata.num_headers_remaining = hdr.int_count.num_switches; transition select(local_metadata.parser_metadata.num_headers_remaining){ 0: accept; default: parse_int_headers; } } state parse_int_headers { packet.extract(hdr.int_headers.next); local_metadata.parser_metadata.num_headers_remaining = local_metadata.parser_metadata.num_headers_remaining -1 ; transition select(local_metadata.parser_metadata.num_headers_remaining){ 0: accept; default: parse_int_headers; } } } control VerifyChecksumImpl(inout parsed_headers_t hdr, inout local_metadata_t meta) { apply { /* EMPTY */ } } control IngressPipeImpl (inout parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { action drop() { mark_to_drop(standard_metadata); } action set_egress_port(port_num_t port) { standard_metadata.egress_spec = port; } // --- l2_exact_table ------------------ table l2_exact_table { key = { standard_metadata.ingress_port: exact; } actions = { set_egress_port; @defaultonly drop; } const default_action = drop; } apply { l2_exact_table.apply(); } } //------------------------------------------------------------------------------ // EGRESS PIPELINE //------------------------------------------------------------------------------ control EgressPipeImpl (inout parsed_headers_t hdr, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { action add_int_header(switch_id_t swid){ //increase int stack counter by one hdr.int_count.num_switches = hdr.int_count.num_switches + 1; hdr.int_headers.push_front(1); // This was not needed in older specs. Now by default pushed // invalid elements are hdr.int_headers[0].setValid(); hdr.int_headers[0].switch_id = (bit<13>)swid; hdr.int_headers[0].queue_depth = (bit<13>)standard_metadata.deq_qdepth; hdr.int_headers[0].output_port = (bit<6>)standard_metadata.egress_port; //update ip header length hdr.ipv4.ihl = hdr.ipv4.ihl + 1; hdr.ipv4.totalLen = hdr.ipv4.totalLen + 4; hdr.ipv4_option.optionLength = hdr.ipv4_option.optionLength + 4; } table int_table { key = { standard_metadata.ingress_port: exact; } actions = { add_int_header; NoAction; } default_action = NoAction; } apply { if (hdr.int_count.isValid()){ int_table.apply(); } } } control ComputeChecksumImpl(inout parsed_headers_t hdr, inout local_metadata_t local_metadata) { apply { update_checksum( hdr.ipv4.isValid(), { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.dscp, hdr.ipv4.ecn, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); } } control DeparserImpl(packet_out packet, in parsed_headers_t hdr) { apply { //parsed headers have to be added again into the packet. packet.emit(hdr.ethernet); packet.emit(hdr.ipv4); packet.emit(hdr.ipv4_option); packet.emit(hdr.int_count); packet.emit(hdr.int_headers); } } V1Switch( ParserImpl(), VerifyChecksumImpl(), IngressPipeImpl(), EgressPipeImpl(), ComputeChecksumImpl(), DeparserImpl() ) main;