From b622b488bfa92235cb53aff6cad0d9f315ef136d Mon Sep 17 00:00:00 2001 From: "Komal, Jain" Date: Sun, 18 Aug 2024 10:22:53 +0530 Subject: [PATCH] Support of is_net_port and is_host_port externs. Signed-off-by: Komal Jain --- backends/tc/ebpfCodeGen.cpp | 16 +- backends/tc/ebpfCodeGen.h | 1 - backends/tc/runtime/pna.h | 21 ++ testdata/p4tc_samples/internetchecksum_01.p4 | 4 +- testdata/p4tc_samples/is_host_port.p4 | 128 ++++++++ testdata/p4tc_samples/is_net_port.p4 | 128 ++++++++ .../internetchecksum_01.json | 2 +- .../internetchecksum_01.template | 6 +- .../internetchecksum_01_control_blocks.c | 14 +- .../p4tc_samples_outputs/is_host_port.json | 63 ++++ .../is_host_port.p4-stderr | 0 .../is_host_port.template | 24 ++ .../is_host_port_control_blocks.c | 306 ++++++++++++++++++ .../is_host_port_parser.c | 136 ++++++++ .../is_host_port_parser.h | 157 +++++++++ .../p4tc_samples_outputs/is_net_port.json | 63 ++++ .../is_net_port.p4-stderr | 0 .../p4tc_samples_outputs/is_net_port.template | 24 ++ .../is_net_port_control_blocks.c | 306 ++++++++++++++++++ .../is_net_port_errors.p4-stderr | 14 + .../p4tc_samples_outputs/is_net_port_parser.c | 136 ++++++++ .../p4tc_samples_outputs/is_net_port_parser.h | 157 +++++++++ 22 files changed, 1691 insertions(+), 15 deletions(-) create mode 100644 testdata/p4tc_samples/is_host_port.p4 create mode 100644 testdata/p4tc_samples/is_net_port.p4 create mode 100644 testdata/p4tc_samples_outputs/is_host_port.json create mode 100644 testdata/p4tc_samples_outputs/is_host_port.p4-stderr create mode 100755 testdata/p4tc_samples_outputs/is_host_port.template create mode 100644 testdata/p4tc_samples_outputs/is_host_port_control_blocks.c create mode 100644 testdata/p4tc_samples_outputs/is_host_port_parser.c create mode 100644 testdata/p4tc_samples_outputs/is_host_port_parser.h create mode 100644 testdata/p4tc_samples_outputs/is_net_port.json create mode 100644 testdata/p4tc_samples_outputs/is_net_port.p4-stderr create mode 100755 testdata/p4tc_samples_outputs/is_net_port.template create mode 100644 testdata/p4tc_samples_outputs/is_net_port_control_blocks.c create mode 100644 testdata/p4tc_samples_outputs/is_net_port_errors.p4-stderr create mode 100644 testdata/p4tc_samples_outputs/is_net_port_parser.c create mode 100644 testdata/p4tc_samples_outputs/is_net_port_parser.h diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 2fdcd83bacc..f25aa4cd9a6 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -1992,6 +1992,21 @@ void ControlBodyTranslatorPNA::processMethod(const P4::ExternMethod *method) { bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { if (auto methodCallExpr = a->right->to()) { + if (methodCallExpr->method->toString() == "is_net_port" || + methodCallExpr->method->toString() == "is_host_port") { + builder->emitIndent(); + visit(a->left); + builder->append(" = "); + if (methodCallExpr->method->toString() == "is_net_port") { + builder->append("bpf_p4tc_is_net_port(skb, "); + } else { + builder->append("bpf_p4tc_is_host_port(skb, "); + } + if (methodCallExpr->arguments->size() == 1) { + visit(methodCallExpr->arguments->at(0)); + builder->append(");"); + } + } auto mi = P4::MethodInstance::resolve(methodCallExpr, control->program->refMap, control->program->typeMap); auto ext = mi->to(); @@ -1999,7 +2014,6 @@ bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { if (ext == nullptr) { return false; } - if (ext->originalExternType->name.name == "Register" && ext->method->type->name == "read") { cstring name = EBPF::EBPFObject::externalName(ext->object); auto reg = pnaControl->getRegister(name); diff --git a/backends/tc/ebpfCodeGen.h b/backends/tc/ebpfCodeGen.h index f244604d94c..3ad38c9d4d1 100644 --- a/backends/tc/ebpfCodeGen.h +++ b/backends/tc/ebpfCodeGen.h @@ -366,7 +366,6 @@ class ControlBodyTranslatorPNA : public EBPF::ControlBodyTranslator { const EBPF::EBPFTablePSA *table); void processFunction(const P4::ExternFunction *function) override; void processApply(const P4::ApplyMethod *method) override; - bool checkPnaPortMem(const IR::Member *m); virtual cstring getParamName(const IR::PathExpression *); bool preorder(const IR::AssignmentStatement *a) override; void processMethod(const P4::ExternMethod *method) override; diff --git a/backends/tc/runtime/pna.h b/backends/tc/runtime/pna.h index 627900b3742..d5f47efe50f 100644 --- a/backends/tc/runtime/pna.h +++ b/backends/tc/runtime/pna.h @@ -353,6 +353,27 @@ bpf_p4tc_ext_hash_base_16bit_complement(const void *data, const u32 data__sz, return (base + (hash % max)); } +/* DPDK doesn't implement this yet */ +/* Equivalent to PNA is_net_port */ +extern bool +bpf_p4tc_is_net_port(struct __sk_buff *skb_ctx, const u32 ifindex) __ksym; + +/* DPDK doesn't implement this yet */ +/* Equivalent to PNA is_host_port */ +extern bool +bpf_p4tc_is_host_port(struct __sk_buff *skb_ctx, const u32 ifindex) __ksym; + +/* DPDK doesn't implement this yet */ +/* Equivalent to PNA is_net_port */ +extern bool +xdp_p4tc_is_net_port(struct xdp_md *xdp_ctx, const u32 ifindex) __ksym; + +/* DPDK doesn't implement this yet */ +/* Equivalent to PNA is_host_port */ +extern bool +xdp_p4tc_is_host_port(struct xdp_md *xdp_ctx, const u32 ifindex) __ksym; + + /* per extern specifics start */ /* in this case it is PNA so we have these helpers like below diff --git a/testdata/p4tc_samples/internetchecksum_01.p4 b/testdata/p4tc_samples/internetchecksum_01.p4 index 907dc5a1232..62d0767755c 100644 --- a/testdata/p4tc_samples/internetchecksum_01.p4 +++ b/testdata/p4tc_samples/internetchecksum_01.p4 @@ -139,7 +139,7 @@ control ingress( inout pna_main_output_metadata_t ostd ) { - action set_ipip_internet_checksum(@tc_type("ipv4") bit<32> src, @tc_type("ipv4") bit<32> dst, @tc_type("dev") PortId_t port) { + action set_ipip_csum(@tc_type("ipv4") bit<32> src, @tc_type("ipv4") bit<32> dst, @tc_type("dev") PortId_t port) { meta.src = src; meta.dst = dst; meta.push = true; @@ -160,7 +160,7 @@ control ingress( istd.input_port : exact @tc_type("dev") @name("port"); } actions = { - set_ipip_internet_checksum; + set_ipip_csum; set_nh; drop; } diff --git a/testdata/p4tc_samples/is_host_port.p4 b/testdata/p4tc_samples/is_host_port.p4 new file mode 100644 index 00000000000..8b35f1a70f1 --- /dev/null +++ b/testdata/p4tc_samples/is_host_port.p4 @@ -0,0 +1,128 @@ +/* -*- P4_16 -*- */ + +#include +#include + +#define PORT_TABLE_SIZE 262144 + +/* + * Standard ethernet header + */ +header ethernet_t { + @tc_type ("macaddr") bit<48> dstAddr; + @tc_type ("macaddr") bit<48> srcAddr; + bit<16> etherType; +} + +header ipv4_t { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + bit<32> srcAddr; + bit<32> dstAddr; +} + +struct my_ingress_headers_t { + ethernet_t ethernet; + ipv4_t ipv4; +} + +/****** G L O B A L I N G R E S S M E T A D A T A *********/ + +struct my_ingress_metadata_t { +} + +struct empty_metadata_t { +} + +/*********************** P A R S E R **************************/ + +parser Ingress_Parser( + packet_in pkt, + out my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_parser_input_metadata_t istd) +{ + const bit<16> ETHERTYPE_IPV4 = 0x0800; + + state start { + transition parse_ethernet; + } + state parse_ethernet { + pkt.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + ETHERTYPE_IPV4 : parse_ipv4; + default : reject; + } + } + state parse_ipv4 { + pkt.extract(hdr.ipv4); + transition accept; + } +} + +/***************** M A T C H - A C T I O N *********************/ + +control ingress( + inout my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_input_metadata_t istd, + inout pna_main_output_metadata_t ostd +) +{ + action send_nh(@tc_type("dev") PortId_t port_id, @tc_type("macaddr") bit<48> dmac, @tc_type("macaddr") bit<48> smac) { + hdr.ethernet.srcAddr = smac; + hdr.ethernet.dstAddr = dmac; + send_to_port(port_id); + } + action drop() { + drop_packet(); + } + + table nh_table { + key = { + hdr.ipv4.srcAddr : exact @tc_type ("ipv4"); + } + actions = { + send_nh; + drop; + } + size = PORT_TABLE_SIZE; + const default_action = drop; + } + + apply { + if (hdr.ipv4.isValid() && is_host_port(istd.input_port)) { + nh_table.apply(); + } + } +} + +/********************* D E P A R S E R ************************/ + +control Ingress_Deparser( + packet_out pkt, + inout my_ingress_headers_t hdr, + in my_ingress_metadata_t meta, + in pna_main_output_metadata_t ostd) +{ + apply { + pkt.emit(hdr.ethernet); + pkt.emit(hdr.ipv4); + } +} + +/************ F I N A L P A C K A G E ******************************/ + +PNA_NIC( + Ingress_Parser(), + ingress(), + Ingress_Deparser() +) main; diff --git a/testdata/p4tc_samples/is_net_port.p4 b/testdata/p4tc_samples/is_net_port.p4 new file mode 100644 index 00000000000..a6433267467 --- /dev/null +++ b/testdata/p4tc_samples/is_net_port.p4 @@ -0,0 +1,128 @@ +/* -*- P4_16 -*- */ + +#include +#include + +#define PORT_TABLE_SIZE 262144 + +/* + * Standard ethernet header + */ +header ethernet_t { + @tc_type ("macaddr") bit<48> dstAddr; + @tc_type ("macaddr") bit<48> srcAddr; + bit<16> etherType; +} + +header ipv4_t { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + bit<32> srcAddr; + bit<32> dstAddr; +} + +struct my_ingress_headers_t { + ethernet_t ethernet; + ipv4_t ipv4; +} + +/****** G L O B A L I N G R E S S M E T A D A T A *********/ + +struct my_ingress_metadata_t { +} + +struct empty_metadata_t { +} + +/*********************** P A R S E R **************************/ + +parser Ingress_Parser( + packet_in pkt, + out my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_parser_input_metadata_t istd) +{ + const bit<16> ETHERTYPE_IPV4 = 0x0800; + + state start { + transition parse_ethernet; + } + state parse_ethernet { + pkt.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + ETHERTYPE_IPV4 : parse_ipv4; + default : reject; + } + } + state parse_ipv4 { + pkt.extract(hdr.ipv4); + transition accept; + } +} + +/***************** M A T C H - A C T I O N *********************/ + +control ingress( + inout my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_input_metadata_t istd, + inout pna_main_output_metadata_t ostd +) +{ + action send_nh(@tc_type("dev") PortId_t port_id, @tc_type("macaddr") bit<48> dmac, @tc_type("macaddr") bit<48> smac) { + hdr.ethernet.srcAddr = smac; + hdr.ethernet.dstAddr = dmac; + send_to_port(port_id); + } + action drop() { + drop_packet(); + } + + table nh_table { + key = { + hdr.ipv4.srcAddr : exact @tc_type ("ipv4"); + } + actions = { + send_nh; + drop; + } + size = PORT_TABLE_SIZE; + const default_action = drop; + } + + apply { + if (hdr.ipv4.isValid() && is_net_port(istd.input_port)) { + nh_table.apply(); + } + } +} + +/********************* D E P A R S E R ************************/ + +control Ingress_Deparser( + packet_out pkt, + inout my_ingress_headers_t hdr, + in my_ingress_metadata_t meta, + in pna_main_output_metadata_t ostd) +{ + apply { + pkt.emit(hdr.ethernet); + pkt.emit(hdr.ipv4); + } +} + +/************ F I N A L P A C K A G E ******************************/ + +PNA_NIC( + Ingress_Parser(), + ingress(), + Ingress_Deparser() +) main; diff --git a/testdata/p4tc_samples_outputs/internetchecksum_01.json b/testdata/p4tc_samples_outputs/internetchecksum_01.json index 9f426a986aa..69bc7177b05 100644 --- a/testdata/p4tc_samples_outputs/internetchecksum_01.json +++ b/testdata/p4tc_samples_outputs/internetchecksum_01.json @@ -22,7 +22,7 @@ "actions" : [ { "id" : 1, - "name" : "ingress/set_ipip_internet_checksum", + "name" : "ingress/set_ipip_csum", "action_scope" : "TableAndDefault", "annotations" : [], "params" : [ diff --git a/testdata/p4tc_samples_outputs/internetchecksum_01.template b/testdata/p4tc_samples_outputs/internetchecksum_01.template index 3fec551d379..f630e936e0e 100755 --- a/testdata/p4tc_samples_outputs/internetchecksum_01.template +++ b/testdata/p4tc_samples_outputs/internetchecksum_01.template @@ -5,11 +5,11 @@ set -e TC="tc" $TC p4template create pipeline/internetchecksum_01 numtables 1 -$TC p4template create action/internetchecksum_01/ingress/set_ipip_internet_checksum actid 1 \ +$TC p4template create action/internetchecksum_01/ingress/set_ipip_csum actid 1 \ param src type ipv4 \ param dst type ipv4 \ param port type dev -$TC p4template update action/internetchecksum_01/ingress/set_ipip_internet_checksum state active +$TC p4template update action/internetchecksum_01/ingress/set_ipip_csum state active $TC p4template create action/internetchecksum_01/ingress/set_nh actid 2 \ param dmac type macaddr \ @@ -23,7 +23,7 @@ $TC p4template create table/internetchecksum_01/ingress/fwd_table \ tblid 1 \ type exact \ keysz 32 nummasks 8 permissions 0x3da4 tentries 1024 \ - table_acts act name internetchecksum_01/ingress/set_ipip_internet_checksum \ + table_acts act name internetchecksum_01/ingress/set_ipip_csum \ act name internetchecksum_01/ingress/set_nh \ act name internetchecksum_01/ingress/drop $TC p4template update table/internetchecksum_01/ingress/fwd_table default_miss_action action internetchecksum_01/ingress/drop diff --git a/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c b/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c index a5d3fb5a389..66f01311a3e 100644 --- a/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c @@ -10,7 +10,7 @@ struct __attribute__((__packed__)) ingress_fwd_table_key { u32 maskid; u32 field0; /* istd.input_port */ } __attribute__((aligned(8))); -#define INGRESS_FWD_TABLE_ACT_INGRESS_SET_IPIP_INTERNET_CHECKSUM 1 +#define INGRESS_FWD_TABLE_ACT_INGRESS_SET_IPIP_CSUM 1 #define INGRESS_FWD_TABLE_ACT_INGRESS_SET_NH 2 #define INGRESS_FWD_TABLE_ACT_INGRESS_DROP 3 #define INGRESS_FWD_TABLE_ACT_NOACTION 0 @@ -26,7 +26,7 @@ struct __attribute__((__packed__)) ingress_fwd_table_value { u32 src; u32 dst; u32 port; - } ingress_set_ipip_internet_checksum; + } ingress_set_ipip_csum; struct __attribute__((__packed__)) { u64 dmac; u32 port; @@ -89,14 +89,14 @@ if (/* hdr->outer.isValid() */ if (value != NULL) { /* run action */ switch (value->action) { - case INGRESS_FWD_TABLE_ACT_INGRESS_SET_IPIP_INTERNET_CHECKSUM: + case INGRESS_FWD_TABLE_ACT_INGRESS_SET_IPIP_CSUM: { - meta->src = bpf_ntohl(value->u.ingress_set_ipip_internet_checksum.src); - meta->dst = bpf_ntohl(value->u.ingress_set_ipip_internet_checksum.dst); + meta->src = bpf_ntohl(value->u.ingress_set_ipip_csum.src); + meta->dst = bpf_ntohl(value->u.ingress_set_ipip_csum.dst); meta->push = true; - /* send_to_port(value->u.ingress_set_ipip_internet_checksum.port) */ + /* send_to_port(value->u.ingress_set_ipip_csum.port) */ compiler_meta__->drop = false; - send_to_port(value->u.ingress_set_ipip_internet_checksum.port); + send_to_port(value->u.ingress_set_ipip_csum.port); } break; case INGRESS_FWD_TABLE_ACT_INGRESS_SET_NH: diff --git a/testdata/p4tc_samples_outputs/is_host_port.json b/testdata/p4tc_samples_outputs/is_host_port.json new file mode 100644 index 00000000000..c98a64c72e9 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_host_port.json @@ -0,0 +1,63 @@ +{ + "schema_version" : "1.0.0", + "pipeline_name" : "is_host_port", + "externs" : [], + "tables" : [ + { + "name" : "ingress/nh_table", + "id" : 1, + "tentries" : 262144, + "permissions" : "0x3da4", + "nummask" : 8, + "keysize" : 32, + "keyfields" : [ + { + "id" : 1, + "name" : "hdr.ipv4.srcAddr", + "type" : "ipv4", + "match_type" : "exact", + "bitwidth" : 32 + } + ], + "actions" : [ + { + "id" : 1, + "name" : "ingress/send_nh", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [ + { + "id" : 1, + "name" : "port_id", + "type" : "dev", + "bitwidth" : 32 + }, + { + "id" : 2, + "name" : "dmac", + "type" : "macaddr", + "bitwidth" : 48 + }, + { + "id" : 3, + "name" : "smac", + "type" : "macaddr", + "bitwidth" : 48 + } + ], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 2, + "name" : "ingress/drop", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : true + } + ] + } + ] +} \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/is_host_port.p4-stderr b/testdata/p4tc_samples_outputs/is_host_port.p4-stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4tc_samples_outputs/is_host_port.template b/testdata/p4tc_samples_outputs/is_host_port.template new file mode 100755 index 00000000000..e5746803458 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_host_port.template @@ -0,0 +1,24 @@ +#!/bin/bash -x + +set -e + +TC="tc" +$TC p4template create pipeline/is_host_port numtables 1 + +$TC p4template create action/is_host_port/ingress/send_nh actid 1 \ + param port_id type dev \ + param dmac type macaddr \ + param smac type macaddr +$TC p4template update action/is_host_port/ingress/send_nh state active + +$TC p4template create action/is_host_port/ingress/drop actid 2 +$TC p4template update action/is_host_port/ingress/drop state active + +$TC p4template create table/is_host_port/ingress/nh_table \ + tblid 1 \ + type exact \ + keysz 32 nummasks 8 permissions 0x3da4 tentries 262144 \ + table_acts act name is_host_port/ingress/send_nh \ + act name is_host_port/ingress/drop +$TC p4template update table/is_host_port/ingress/nh_table default_miss_action permissions 0x1024 action is_host_port/ingress/drop +$TC p4template update pipeline/is_host_port state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c b/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c new file mode 100644 index 00000000000..ffff2bafb1a --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c @@ -0,0 +1,306 @@ +#include "is_host_port_parser.h" +struct p4tc_filter_fields p4tc_filter_fields; + +struct internal_metadata { + __u16 pkt_ether_type; +} __attribute__((aligned(4))); + +struct __attribute__((__packed__)) ingress_nh_table_key { + u32 keysz; + u32 maskid; + u32 field0; /* hdr.ipv4.srcAddr */ +} __attribute__((aligned(8))); +#define INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH 1 +#define INGRESS_NH_TABLE_ACT_INGRESS_DROP 2 +#define INGRESS_NH_TABLE_ACT_NOACTION 0 +struct __attribute__((__packed__)) ingress_nh_table_value { + unsigned int action; + u32 hit:1, + is_default_miss_act:1, + is_default_hit_act:1; + union { + struct { + } _NoAction; + struct __attribute__((__packed__)) { + u32 port_id; + u64 dmac; + u64 smac; + } ingress_send_nh; + struct { + } ingress_drop; + } u; +}; + +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + hdr_start = pkt + BYTES(ebpf_packetOffsetInBits); + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); +{ + u8 hit; + u8 tmp; + u8 tmp_0; + { +if (/* hdr->ipv4.isValid() */ + hdr->ipv4.ebpf_valid) { + tmp_0 = bpf_p4tc_is_host_port(skb, skb->ifindex); + tmp = tmp_0; + } + else { + tmp = false; } + + if (tmp) { +/* nh_table_0.apply() */ + { + /* construct key */ + struct p4tc_table_entry_act_bpf_params__local params = { + .pipeid = p4tc_filter_fields.pipeid, + .tblid = 1 + }; + struct ingress_nh_table_key key; + __builtin_memset(&key, 0, sizeof(key)); + key.keysz = 32; + key.field0 = bpf_htonl(hdr->ipv4.srcAddr); + struct p4tc_table_entry_act_bpf *act_bpf; + /* value */ + struct ingress_nh_table_value *value = NULL; + /* perform lookup */ + act_bpf = bpf_p4tc_tbl_read(skb, ¶ms, sizeof(params), &key, sizeof(key)); + value = (struct ingress_nh_table_value *)act_bpf; + if (value == NULL) { + /* miss; find default action */ + hit = 0; + } else { + hit = value->hit; + } + if (value != NULL) { + /* run action */ + switch (value->action) { + case INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH: + { + hdr->ethernet.srcAddr = value->u.ingress_send_nh.smac; + hdr->ethernet.dstAddr = value->u.ingress_send_nh.dmac; + /* send_to_port(value->u.ingress_send_nh.port_id) */ + compiler_meta__->drop = false; + send_to_port(value->u.ingress_send_nh.port_id); + } + break; + case INGRESS_NH_TABLE_ACT_INGRESS_DROP: + { +/* drop_packet() */ + drop_packet(); + } + break; + case INGRESS_NH_TABLE_ACT_NOACTION: + { + } + break; + } + } else { + } + } +; } + + } + } + { +{ +; + ; + } + + if (compiler_meta__->drop) { + return TC_ACT_SHOT; + } + int outHeaderLength = 0; + if (hdr->ethernet.ebpf_valid) { + outHeaderLength += 112; + } +; if (hdr->ipv4.ebpf_valid) { + outHeaderLength += 160; + } +; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); + if (outHeaderOffset != 0) { + int returnCode = 0; + returnCode = bpf_skb_adjust_room(skb, outHeaderOffset, 1, 0); + if (returnCode) { + return TC_ACT_SHOT; + } + } + pkt = ((void*)(long)skb->data); + ebpf_packetEnd = ((void*)(long)skb->data_end); + ebpf_packetOffsetInBits = 0; + if (hdr->ethernet.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 112)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[4]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 4, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[5]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 5, (ebpf_byte)); + ebpf_packetOffsetInBits += 48; + + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[4]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 4, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[5]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 5, (ebpf_byte)); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.etherType = bpf_htons(hdr->ethernet.etherType); + ebpf_byte = ((char*)(&hdr->ethernet.etherType))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.etherType))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + } +; if (hdr->ipv4.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 160)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->ipv4.version))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 4, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.ihl))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 0, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.diffserv))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = bpf_htons(hdr->ipv4.totalLen); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = bpf_htons(hdr->ipv4.identification); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + ebpf_byte = ((char*)(&hdr->ipv4.flags))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 3, 5, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = bpf_htons(hdr->ipv4.fragOffset << 3); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 5, 0, (ebpf_byte >> 3)); + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0 + 1, 3, 5, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[1]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 1, 5, 0, (ebpf_byte >> 3)); + ebpf_packetOffsetInBits += 13; + + ebpf_byte = ((char*)(&hdr->ipv4.ttl))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->ipv4.protocol))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = bpf_htons(hdr->ipv4.hdrChecksum); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = htonl(hdr->ipv4.srcAddr); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = htonl(hdr->ipv4.dstAddr); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + } +; + } + return -1; +} +SEC("p4tc/main") +int tc_ingress_func(struct __sk_buff *skb) { + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; + compiler_meta__->drop = false; + if (!compiler_meta__->recirculated) { + compiler_meta__->mark = 153; + struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; + if ((void *) ((struct internal_metadata *) md + 1) <= (void *)(long)skb->data) { + __u16 *ether_type = (__u16 *) ((void *) (long)skb->data + 12); + if ((void *) ((__u16 *) ether_type + 1) > (void *) (long) skb->data_end) { + return TC_ACT_SHOT; + } + *ether_type = md->pkt_ether_type; + } + } + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + if (ret != -1) { + return ret; + } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) { + compiler_meta__->pass_to_kernel = true; + return bpf_redirect(skb->ifindex, BPF_F_INGRESS); + } + return bpf_redirect(compiler_meta__->egress_port, 0); +} +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_host_port_parser.c b/testdata/p4tc_samples_outputs/is_host_port_parser.c new file mode 100644 index 00000000000..ba6639f2e07 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_host_port_parser.c @@ -0,0 +1,136 @@ +#include "is_host_port_parser.h" + +struct p4tc_filter_fields p4tc_filter_fields; + +static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + __builtin_memset(hdrMd, 0, sizeof(struct hdr_md)); + + unsigned ebpf_packetOffsetInBits = 0; + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); + { + goto start; + parse_ipv4: { +/* extract(hdr->ipv4) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(160 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + hdr->ipv4.version = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 4) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.ihl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.diffserv = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.flags = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 5) & EBPF_MASK(u8, 3)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u16, 13)); + ebpf_packetOffsetInBits += 13; + + hdr->ipv4.ttl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.protocol = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + + hdr->ipv4.ebpf_valid = 1; + hdr_start += BYTES(160); + +; + goto accept; + } + start: { +/* extract(hdr->ethernet) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(112 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + __builtin_memcpy(&hdr->ethernet.dstAddr, pkt + BYTES(ebpf_packetOffsetInBits), 6); + ebpf_packetOffsetInBits += 48; + + __builtin_memcpy(&hdr->ethernet.srcAddr, pkt + BYTES(ebpf_packetOffsetInBits), 6); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.etherType = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + + hdr->ethernet.ebpf_valid = 1; + hdr_start += BYTES(112); + +; + u16 select_0; + select_0 = hdr->ethernet.etherType; + if (select_0 == 0x800)goto parse_ipv4; + if ((select_0 & 0x0) == (0x0 & 0x0))goto reject; + else goto reject; + } + + reject: { + if (ebpf_errorCode == 0) { + return TC_ACT_SHOT; + } + compiler_meta__->parser_error = ebpf_errorCode; + goto accept; + } + + } + + accept: + hdrMd->ebpf_packetOffsetInBits = ebpf_packetOffsetInBits; + return -1; +} + +SEC("p4tc/parse") +int tc_parse_func(struct __sk_buff *skb) { + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = run_parser(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + if (ret != -1) { + return ret; + } + return TC_ACT_PIPE; + } +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_host_port_parser.h b/testdata/p4tc_samples_outputs/is_host_port_parser.h new file mode 100644 index 00000000000..7c722359cc5 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_host_port_parser.h @@ -0,0 +1,157 @@ +#include "ebpf_kernel.h" + +#include +#include +#include "pna.h" + +#define EBPF_MASK(t, w) ((((t)(1)) << (w)) - (t)1) +#define BYTES(w) ((w) / 8) +#define write_partial(a, w, s, v) do { *((u8*)a) = ((*((u8*)a)) & ~(EBPF_MASK(u8, w) << s)) | (v << s) ; } while (0) +#define write_byte(base, offset, v) do { *(u8*)((base) + (offset)) = (v); } while (0) +#define bpf_trace_message(fmt, ...) + + +struct ethernet_t { + u64 dstAddr; /* bit<48> */ + u64 srcAddr; /* bit<48> */ + u16 etherType; /* bit<16> */ + u8 ebpf_valid; +}; +struct ipv4_t { + u8 version; /* bit<4> */ + u8 ihl; /* bit<4> */ + u8 diffserv; /* bit<8> */ + u16 totalLen; /* bit<16> */ + u16 identification; /* bit<16> */ + u8 flags; /* bit<3> */ + u16 fragOffset; /* bit<13> */ + u8 ttl; /* bit<8> */ + u8 protocol; /* bit<8> */ + u16 hdrChecksum; /* bit<16> */ + u32 srcAddr; /* bit<32> */ + u32 dstAddr; /* bit<32> */ + u8 ebpf_valid; +}; +struct my_ingress_headers_t { + struct ethernet_t ethernet; /* ethernet_t */ + struct ipv4_t ipv4; /* ipv4_t */ +}; +struct my_ingress_metadata_t { +}; +struct empty_metadata_t { +}; + +struct hdr_md { + struct my_ingress_headers_t cpumap_hdr; + struct my_ingress_metadata_t cpumap_usermeta; + unsigned ebpf_packetOffsetInBits; + __u8 __hook; +}; + +struct p4tc_filter_fields { + __u32 pipeid; + __u32 handle; + __u32 classid; + __u32 chain; + __u32 blockid; + __be16 proto; + __u16 prio; +}; + +REGISTER_START() +REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2) +BPF_ANNOTATE_KV_PAIR(hdr_md_cpumap, u32, struct hdr_md) +REGISTER_END() + +static __always_inline +void crc16_update(u16 * reg, const u8 * data, u16 data_size, const u16 poly) { + if (data_size <= 8) + data += data_size - 1; + #pragma clang loop unroll(full) + for (u16 i = 0; i < data_size; i++) { + bpf_trace_message("CRC16: data byte: %x\n", *data); + *reg ^= *data; + for (u8 bit = 0; bit < 8; bit++) { + *reg = (*reg) & 1 ? ((*reg) >> 1) ^ poly : (*reg) >> 1; + } + if (data_size <= 8) + data--; + else + data++; + } +} +static __always_inline u16 crc16_finalize(u16 reg) { + return reg; +} +static __always_inline +void crc32_update(u32 * reg, const u8 * data, u16 data_size, const u32 poly) { + u32* current = (u32*) data; + u32 index = 0; + u32 lookup_key = 0; + u32 lookup_value = 0; + u32 lookup_value1 = 0; + u32 lookup_value2 = 0; + u32 lookup_value3 = 0; + u32 lookup_value4 = 0; + u32 lookup_value5 = 0; + u32 lookup_value6 = 0; + u32 lookup_value7 = 0; + u32 lookup_value8 = 0; + u16 tmp = 0; + if (crc32_table != NULL) { + for (u16 i = data_size; i >= 8; i -= 8) { + /* Vars one and two will have swapped byte order if data_size == 8 */ + if (data_size == 8) current = (u32 *)(data + 4); + bpf_trace_message("CRC32: data dword: %x\n", *current); + u32 one = (data_size == 8 ? __builtin_bswap32(*current--) : *current++) ^ *reg; + bpf_trace_message("CRC32: data dword: %x\n", *current); + u32 two = (data_size == 8 ? __builtin_bswap32(*current--) : *current++); + lookup_key = (one & 0x000000FF); + lookup_value8 = crc32_table[(u16)(1792 + (u8)lookup_key)]; + lookup_key = (one >> 8) & 0x000000FF; + lookup_value7 = crc32_table[(u16)(1536 + (u8)lookup_key)]; + lookup_key = (one >> 16) & 0x000000FF; + lookup_value6 = crc32_table[(u16)(1280 + (u8)lookup_key)]; + lookup_key = one >> 24; + lookup_value5 = crc32_table[(u16)(1024 + (u8)(lookup_key))]; + lookup_key = (two & 0x000000FF); + lookup_value4 = crc32_table[(u16)(768 + (u8)lookup_key)]; + lookup_key = (two >> 8) & 0x000000FF; + lookup_value3 = crc32_table[(u16)(512 + (u8)lookup_key)]; + lookup_key = (two >> 16) & 0x000000FF; + lookup_value2 = crc32_table[(u16)(256 + (u8)lookup_key)]; + lookup_key = two >> 24; + lookup_value1 = crc32_table[(u8)(lookup_key)]; + *reg = lookup_value8 ^ lookup_value7 ^ lookup_value6 ^ lookup_value5 ^ + lookup_value4 ^ lookup_value3 ^ lookup_value2 ^ lookup_value1; + tmp += 8; + } + volatile int std_algo_lookup_key = 0; + if (data_size < 8) { + unsigned char *currentChar = (unsigned char *) current; + currentChar += data_size - 1; + for (u16 i = tmp; i < data_size; i++) { + bpf_trace_message("CRC32: data byte: %x\n", *currentChar); + std_algo_lookup_key = (u32)(((*reg) & 0xFF) ^ *currentChar--); + if (std_algo_lookup_key >= 0) { + lookup_value = crc32_table[(u8)(std_algo_lookup_key & 255)]; + } + *reg = ((*reg) >> 8) ^ lookup_value; + } + } else { + /* Consume data not processed by slice-by-8 algorithm above, these data are in network byte order */ + unsigned char *currentChar = (unsigned char *) current; + for (u16 i = tmp; i < data_size; i++) { + bpf_trace_message("CRC32: data byte: %x\n", *currentChar); + std_algo_lookup_key = (u32)(((*reg) & 0xFF) ^ *currentChar++); + if (std_algo_lookup_key >= 0) { + lookup_value = crc32_table[(u8)(std_algo_lookup_key & 255)]; + } + *reg = ((*reg) >> 8) ^ lookup_value; + } + } + } +} +static __always_inline u32 crc32_finalize(u32 reg) { + return reg ^ 0xFFFFFFFF; +} diff --git a/testdata/p4tc_samples_outputs/is_net_port.json b/testdata/p4tc_samples_outputs/is_net_port.json new file mode 100644 index 00000000000..76328b932c3 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port.json @@ -0,0 +1,63 @@ +{ + "schema_version" : "1.0.0", + "pipeline_name" : "is_net_port", + "externs" : [], + "tables" : [ + { + "name" : "ingress/nh_table", + "id" : 1, + "tentries" : 262144, + "permissions" : "0x3da4", + "nummask" : 8, + "keysize" : 32, + "keyfields" : [ + { + "id" : 1, + "name" : "hdr.ipv4.srcAddr", + "type" : "ipv4", + "match_type" : "exact", + "bitwidth" : 32 + } + ], + "actions" : [ + { + "id" : 1, + "name" : "ingress/send_nh", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [ + { + "id" : 1, + "name" : "port_id", + "type" : "dev", + "bitwidth" : 32 + }, + { + "id" : 2, + "name" : "dmac", + "type" : "macaddr", + "bitwidth" : 48 + }, + { + "id" : 3, + "name" : "smac", + "type" : "macaddr", + "bitwidth" : 48 + } + ], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 2, + "name" : "ingress/drop", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : true + } + ] + } + ] +} \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/is_net_port.p4-stderr b/testdata/p4tc_samples_outputs/is_net_port.p4-stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4tc_samples_outputs/is_net_port.template b/testdata/p4tc_samples_outputs/is_net_port.template new file mode 100755 index 00000000000..8ad1f63de94 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port.template @@ -0,0 +1,24 @@ +#!/bin/bash -x + +set -e + +TC="tc" +$TC p4template create pipeline/is_net_port numtables 1 + +$TC p4template create action/is_net_port/ingress/send_nh actid 1 \ + param port_id type dev \ + param dmac type macaddr \ + param smac type macaddr +$TC p4template update action/is_net_port/ingress/send_nh state active + +$TC p4template create action/is_net_port/ingress/drop actid 2 +$TC p4template update action/is_net_port/ingress/drop state active + +$TC p4template create table/is_net_port/ingress/nh_table \ + tblid 1 \ + type exact \ + keysz 32 nummasks 8 permissions 0x3da4 tentries 262144 \ + table_acts act name is_net_port/ingress/send_nh \ + act name is_net_port/ingress/drop +$TC p4template update table/is_net_port/ingress/nh_table default_miss_action permissions 0x1024 action is_net_port/ingress/drop +$TC p4template update pipeline/is_net_port state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c b/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c new file mode 100644 index 00000000000..5b44f451af2 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c @@ -0,0 +1,306 @@ +#include "is_net_port_parser.h" +struct p4tc_filter_fields p4tc_filter_fields; + +struct internal_metadata { + __u16 pkt_ether_type; +} __attribute__((aligned(4))); + +struct __attribute__((__packed__)) ingress_nh_table_key { + u32 keysz; + u32 maskid; + u32 field0; /* hdr.ipv4.srcAddr */ +} __attribute__((aligned(8))); +#define INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH 1 +#define INGRESS_NH_TABLE_ACT_INGRESS_DROP 2 +#define INGRESS_NH_TABLE_ACT_NOACTION 0 +struct __attribute__((__packed__)) ingress_nh_table_value { + unsigned int action; + u32 hit:1, + is_default_miss_act:1, + is_default_hit_act:1; + union { + struct { + } _NoAction; + struct __attribute__((__packed__)) { + u32 port_id; + u64 dmac; + u64 smac; + } ingress_send_nh; + struct { + } ingress_drop; + } u; +}; + +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + hdr_start = pkt + BYTES(ebpf_packetOffsetInBits); + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); +{ + u8 hit; + u8 tmp; + u8 tmp_0; + { +if (/* hdr->ipv4.isValid() */ + hdr->ipv4.ebpf_valid) { + tmp_0 = bpf_p4tc_is_net_port(skb, skb->ifindex); + tmp = tmp_0; + } + else { + tmp = false; } + + if (tmp) { +/* nh_table_0.apply() */ + { + /* construct key */ + struct p4tc_table_entry_act_bpf_params__local params = { + .pipeid = p4tc_filter_fields.pipeid, + .tblid = 1 + }; + struct ingress_nh_table_key key; + __builtin_memset(&key, 0, sizeof(key)); + key.keysz = 32; + key.field0 = bpf_htonl(hdr->ipv4.srcAddr); + struct p4tc_table_entry_act_bpf *act_bpf; + /* value */ + struct ingress_nh_table_value *value = NULL; + /* perform lookup */ + act_bpf = bpf_p4tc_tbl_read(skb, ¶ms, sizeof(params), &key, sizeof(key)); + value = (struct ingress_nh_table_value *)act_bpf; + if (value == NULL) { + /* miss; find default action */ + hit = 0; + } else { + hit = value->hit; + } + if (value != NULL) { + /* run action */ + switch (value->action) { + case INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH: + { + hdr->ethernet.srcAddr = value->u.ingress_send_nh.smac; + hdr->ethernet.dstAddr = value->u.ingress_send_nh.dmac; + /* send_to_port(value->u.ingress_send_nh.port_id) */ + compiler_meta__->drop = false; + send_to_port(value->u.ingress_send_nh.port_id); + } + break; + case INGRESS_NH_TABLE_ACT_INGRESS_DROP: + { +/* drop_packet() */ + drop_packet(); + } + break; + case INGRESS_NH_TABLE_ACT_NOACTION: + { + } + break; + } + } else { + } + } +; } + + } + } + { +{ +; + ; + } + + if (compiler_meta__->drop) { + return TC_ACT_SHOT; + } + int outHeaderLength = 0; + if (hdr->ethernet.ebpf_valid) { + outHeaderLength += 112; + } +; if (hdr->ipv4.ebpf_valid) { + outHeaderLength += 160; + } +; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); + if (outHeaderOffset != 0) { + int returnCode = 0; + returnCode = bpf_skb_adjust_room(skb, outHeaderOffset, 1, 0); + if (returnCode) { + return TC_ACT_SHOT; + } + } + pkt = ((void*)(long)skb->data); + ebpf_packetEnd = ((void*)(long)skb->data_end); + ebpf_packetOffsetInBits = 0; + if (hdr->ethernet.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 112)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[4]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 4, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.dstAddr))[5]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 5, (ebpf_byte)); + ebpf_packetOffsetInBits += 48; + + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[4]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 4, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.srcAddr))[5]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 5, (ebpf_byte)); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.etherType = bpf_htons(hdr->ethernet.etherType); + ebpf_byte = ((char*)(&hdr->ethernet.etherType))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ethernet.etherType))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + } +; if (hdr->ipv4.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 160)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->ipv4.version))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 4, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.ihl))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 0, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.diffserv))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = bpf_htons(hdr->ipv4.totalLen); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = bpf_htons(hdr->ipv4.identification); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + ebpf_byte = ((char*)(&hdr->ipv4.flags))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 3, 5, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = bpf_htons(hdr->ipv4.fragOffset << 3); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 5, 0, (ebpf_byte >> 3)); + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0 + 1, 3, 5, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[1]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 1, 5, 0, (ebpf_byte >> 3)); + ebpf_packetOffsetInBits += 13; + + ebpf_byte = ((char*)(&hdr->ipv4.ttl))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->ipv4.protocol))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = bpf_htons(hdr->ipv4.hdrChecksum); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = htonl(hdr->ipv4.srcAddr); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = htonl(hdr->ipv4.dstAddr); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + } +; + } + return -1; +} +SEC("p4tc/main") +int tc_ingress_func(struct __sk_buff *skb) { + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; + compiler_meta__->drop = false; + if (!compiler_meta__->recirculated) { + compiler_meta__->mark = 153; + struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; + if ((void *) ((struct internal_metadata *) md + 1) <= (void *)(long)skb->data) { + __u16 *ether_type = (__u16 *) ((void *) (long)skb->data + 12); + if ((void *) ((__u16 *) ether_type + 1) > (void *) (long) skb->data_end) { + return TC_ACT_SHOT; + } + *ether_type = md->pkt_ether_type; + } + } + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + if (ret != -1) { + return ret; + } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) { + compiler_meta__->pass_to_kernel = true; + return bpf_redirect(skb->ifindex, BPF_F_INGRESS); + } + return bpf_redirect(compiler_meta__->egress_port, 0); +} +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_net_port_errors.p4-stderr b/testdata/p4tc_samples_outputs/is_net_port_errors.p4-stderr new file mode 100644 index 00000000000..146a4f0893e --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port_errors.p4-stderr @@ -0,0 +1,14 @@ +[--Werror=type-error] error: 'is_net_port(istd.input_port, hdr.ipv4.srcAddr)' + if (hdr.ipv4.isValid() && is_net_port(istd.input_port, hdr.ipv4.srcAddr)) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ---- Actual error: + /home/komaljai/is_net/p4c/build/p4include/tc/pna.p4(589): is_net_port: 2 arguments supplied while 1 are expected + extern bool is_net_port (in PortId_t p); + ^^^^^^^^^^^ + ---- Originating from: + /home/komaljai/is_net/p4c/build/p4include/tc/pna.p4(589): Function type 'is_net_port' does not match invocation type '' + extern bool is_net_port (in PortId_t p); + ^^^^^^^^^^^ + p4tc_samples/is_net_port_errors.p4(102) + if (hdr.ipv4.isValid() && is_net_port(istd.input_port, hdr.ipv4.srcAddr)) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/testdata/p4tc_samples_outputs/is_net_port_parser.c b/testdata/p4tc_samples_outputs/is_net_port_parser.c new file mode 100644 index 00000000000..cb4fde57aa4 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port_parser.c @@ -0,0 +1,136 @@ +#include "is_net_port_parser.h" + +struct p4tc_filter_fields p4tc_filter_fields; + +static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + __builtin_memset(hdrMd, 0, sizeof(struct hdr_md)); + + unsigned ebpf_packetOffsetInBits = 0; + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); + { + goto start; + parse_ipv4: { +/* extract(hdr->ipv4) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(160 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + hdr->ipv4.version = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 4) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.ihl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.diffserv = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.flags = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 5) & EBPF_MASK(u8, 3)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u16, 13)); + ebpf_packetOffsetInBits += 13; + + hdr->ipv4.ttl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.protocol = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + + hdr->ipv4.ebpf_valid = 1; + hdr_start += BYTES(160); + +; + goto accept; + } + start: { +/* extract(hdr->ethernet) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(112 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + __builtin_memcpy(&hdr->ethernet.dstAddr, pkt + BYTES(ebpf_packetOffsetInBits), 6); + ebpf_packetOffsetInBits += 48; + + __builtin_memcpy(&hdr->ethernet.srcAddr, pkt + BYTES(ebpf_packetOffsetInBits), 6); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.etherType = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + + hdr->ethernet.ebpf_valid = 1; + hdr_start += BYTES(112); + +; + u16 select_0; + select_0 = hdr->ethernet.etherType; + if (select_0 == 0x800)goto parse_ipv4; + if ((select_0 & 0x0) == (0x0 & 0x0))goto reject; + else goto reject; + } + + reject: { + if (ebpf_errorCode == 0) { + return TC_ACT_SHOT; + } + compiler_meta__->parser_error = ebpf_errorCode; + goto accept; + } + + } + + accept: + hdrMd->ebpf_packetOffsetInBits = ebpf_packetOffsetInBits; + return -1; +} + +SEC("p4tc/parse") +int tc_parse_func(struct __sk_buff *skb) { + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = run_parser(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + if (ret != -1) { + return ret; + } + return TC_ACT_PIPE; + } +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_net_port_parser.h b/testdata/p4tc_samples_outputs/is_net_port_parser.h new file mode 100644 index 00000000000..7c722359cc5 --- /dev/null +++ b/testdata/p4tc_samples_outputs/is_net_port_parser.h @@ -0,0 +1,157 @@ +#include "ebpf_kernel.h" + +#include +#include +#include "pna.h" + +#define EBPF_MASK(t, w) ((((t)(1)) << (w)) - (t)1) +#define BYTES(w) ((w) / 8) +#define write_partial(a, w, s, v) do { *((u8*)a) = ((*((u8*)a)) & ~(EBPF_MASK(u8, w) << s)) | (v << s) ; } while (0) +#define write_byte(base, offset, v) do { *(u8*)((base) + (offset)) = (v); } while (0) +#define bpf_trace_message(fmt, ...) + + +struct ethernet_t { + u64 dstAddr; /* bit<48> */ + u64 srcAddr; /* bit<48> */ + u16 etherType; /* bit<16> */ + u8 ebpf_valid; +}; +struct ipv4_t { + u8 version; /* bit<4> */ + u8 ihl; /* bit<4> */ + u8 diffserv; /* bit<8> */ + u16 totalLen; /* bit<16> */ + u16 identification; /* bit<16> */ + u8 flags; /* bit<3> */ + u16 fragOffset; /* bit<13> */ + u8 ttl; /* bit<8> */ + u8 protocol; /* bit<8> */ + u16 hdrChecksum; /* bit<16> */ + u32 srcAddr; /* bit<32> */ + u32 dstAddr; /* bit<32> */ + u8 ebpf_valid; +}; +struct my_ingress_headers_t { + struct ethernet_t ethernet; /* ethernet_t */ + struct ipv4_t ipv4; /* ipv4_t */ +}; +struct my_ingress_metadata_t { +}; +struct empty_metadata_t { +}; + +struct hdr_md { + struct my_ingress_headers_t cpumap_hdr; + struct my_ingress_metadata_t cpumap_usermeta; + unsigned ebpf_packetOffsetInBits; + __u8 __hook; +}; + +struct p4tc_filter_fields { + __u32 pipeid; + __u32 handle; + __u32 classid; + __u32 chain; + __u32 blockid; + __be16 proto; + __u16 prio; +}; + +REGISTER_START() +REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2) +BPF_ANNOTATE_KV_PAIR(hdr_md_cpumap, u32, struct hdr_md) +REGISTER_END() + +static __always_inline +void crc16_update(u16 * reg, const u8 * data, u16 data_size, const u16 poly) { + if (data_size <= 8) + data += data_size - 1; + #pragma clang loop unroll(full) + for (u16 i = 0; i < data_size; i++) { + bpf_trace_message("CRC16: data byte: %x\n", *data); + *reg ^= *data; + for (u8 bit = 0; bit < 8; bit++) { + *reg = (*reg) & 1 ? ((*reg) >> 1) ^ poly : (*reg) >> 1; + } + if (data_size <= 8) + data--; + else + data++; + } +} +static __always_inline u16 crc16_finalize(u16 reg) { + return reg; +} +static __always_inline +void crc32_update(u32 * reg, const u8 * data, u16 data_size, const u32 poly) { + u32* current = (u32*) data; + u32 index = 0; + u32 lookup_key = 0; + u32 lookup_value = 0; + u32 lookup_value1 = 0; + u32 lookup_value2 = 0; + u32 lookup_value3 = 0; + u32 lookup_value4 = 0; + u32 lookup_value5 = 0; + u32 lookup_value6 = 0; + u32 lookup_value7 = 0; + u32 lookup_value8 = 0; + u16 tmp = 0; + if (crc32_table != NULL) { + for (u16 i = data_size; i >= 8; i -= 8) { + /* Vars one and two will have swapped byte order if data_size == 8 */ + if (data_size == 8) current = (u32 *)(data + 4); + bpf_trace_message("CRC32: data dword: %x\n", *current); + u32 one = (data_size == 8 ? __builtin_bswap32(*current--) : *current++) ^ *reg; + bpf_trace_message("CRC32: data dword: %x\n", *current); + u32 two = (data_size == 8 ? __builtin_bswap32(*current--) : *current++); + lookup_key = (one & 0x000000FF); + lookup_value8 = crc32_table[(u16)(1792 + (u8)lookup_key)]; + lookup_key = (one >> 8) & 0x000000FF; + lookup_value7 = crc32_table[(u16)(1536 + (u8)lookup_key)]; + lookup_key = (one >> 16) & 0x000000FF; + lookup_value6 = crc32_table[(u16)(1280 + (u8)lookup_key)]; + lookup_key = one >> 24; + lookup_value5 = crc32_table[(u16)(1024 + (u8)(lookup_key))]; + lookup_key = (two & 0x000000FF); + lookup_value4 = crc32_table[(u16)(768 + (u8)lookup_key)]; + lookup_key = (two >> 8) & 0x000000FF; + lookup_value3 = crc32_table[(u16)(512 + (u8)lookup_key)]; + lookup_key = (two >> 16) & 0x000000FF; + lookup_value2 = crc32_table[(u16)(256 + (u8)lookup_key)]; + lookup_key = two >> 24; + lookup_value1 = crc32_table[(u8)(lookup_key)]; + *reg = lookup_value8 ^ lookup_value7 ^ lookup_value6 ^ lookup_value5 ^ + lookup_value4 ^ lookup_value3 ^ lookup_value2 ^ lookup_value1; + tmp += 8; + } + volatile int std_algo_lookup_key = 0; + if (data_size < 8) { + unsigned char *currentChar = (unsigned char *) current; + currentChar += data_size - 1; + for (u16 i = tmp; i < data_size; i++) { + bpf_trace_message("CRC32: data byte: %x\n", *currentChar); + std_algo_lookup_key = (u32)(((*reg) & 0xFF) ^ *currentChar--); + if (std_algo_lookup_key >= 0) { + lookup_value = crc32_table[(u8)(std_algo_lookup_key & 255)]; + } + *reg = ((*reg) >> 8) ^ lookup_value; + } + } else { + /* Consume data not processed by slice-by-8 algorithm above, these data are in network byte order */ + unsigned char *currentChar = (unsigned char *) current; + for (u16 i = tmp; i < data_size; i++) { + bpf_trace_message("CRC32: data byte: %x\n", *currentChar); + std_algo_lookup_key = (u32)(((*reg) & 0xFF) ^ *currentChar++); + if (std_algo_lookup_key >= 0) { + lookup_value = crc32_table[(u8)(std_algo_lookup_key & 255)]; + } + *reg = ((*reg) >> 8) ^ lookup_value; + } + } + } +} +static __always_inline u32 crc32_finalize(u32 reg) { + return reg ^ 0xFFFFFFFF; +}