From e20762a05f2430da540b30d91ddba0c6189144b9 Mon Sep 17 00:00:00 2001 From: Sosutha Sethuramapandian Date: Mon, 16 Sep 2024 22:26:42 -0700 Subject: [PATCH] Support for 128 bit bitwise operation * Added movh statement definition * Added support for 128 bitwise operation * Updated testcase and output --- backends/dpdk/dbprint-dpdk.cpp | 4 + backends/dpdk/dpdk.def | 14 ++ backends/dpdk/dpdkArch.h | 13 ++ backends/dpdk/dpdkHelpers.cpp | 148 +++++++++++++++++- backends/dpdk/dpdkHelpers.h | 7 +- backends/dpdk/dpdkProgram.cpp | 11 +- backends/dpdk/dpdkProgramStructure.h | 7 + backends/dpdk/spec.cpp | 9 ++ testdata/p4_16_samples/pna-ipv6-actions.p4 | 15 ++ .../pna-ipv6-actions-first.p4 | 12 ++ .../pna-ipv6-actions-frontend.p4 | 12 ++ .../pna-ipv6-actions-midend.p4 | 22 ++- .../p4_16_samples_outputs/pna-ipv6-actions.p4 | 12 ++ .../pna-ipv6-actions.p4-error | 2 +- .../pna-ipv6-actions.p4-stderr | 2 +- .../pna-ipv6-actions.p4.bfrt.json | 21 +++ .../pna-ipv6-actions.p4.spec | 59 +++++++ .../psa-dpdk-128bitCast.p4.spec | 42 ++++- 18 files changed, 396 insertions(+), 16 deletions(-) diff --git a/backends/dpdk/dbprint-dpdk.cpp b/backends/dpdk/dbprint-dpdk.cpp index 50b9e5e80bc..3fe933a7270 100644 --- a/backends/dpdk/dbprint-dpdk.cpp +++ b/backends/dpdk/dbprint-dpdk.cpp @@ -70,4 +70,8 @@ void IR::DpdkMovStatement::dbprint(std::ostream &out) const { out << "mov " << dst << " " << src << std::endl; } +void IR::DpdkMovhStatement::dbprint(std::ostream &out) const { + out << "movh " << dst << " " << src << std::endl; +} + } // namespace P4 diff --git a/backends/dpdk/dpdk.def b/backends/dpdk/dpdk.def index 511c2bcd8f8..fd9dd896b49 100644 --- a/backends/dpdk/dpdk.def +++ b/backends/dpdk/dpdk.def @@ -18,6 +18,13 @@ class DpdkHeaderType : Type_Header, IDPDKNode { #nodbprint } +class DpdkHeaderInstance : IDPDKNode { + Declaration_Variable name; + Type_Header headerType; + std::ostream& toSpec(std::ostream& out) const override; +#nodbprint +} + class DpdkStructType : Type_Struct, IDPDKNode { std::ostream& toSpec(std::ostream& out) const override; #nodbprint @@ -99,6 +106,7 @@ class DpdkLearner { class DpdkAsmProgram { inline IndexedVector headerType; inline IndexedVector structType; + inline IndexedVector headerInstance; inline IndexedVector externDeclarations; inline IndexedVector actions; inline IndexedVector tables; @@ -304,6 +312,12 @@ class DpdkMovStatement : DpdkUnaryStatement { #noconstructor } +class DpdkMovhStatement : DpdkUnaryStatement { + DpdkMovhStatement(Expression dst, Expression src) : + DpdkUnaryStatement("movh"_cs, dst, src) { } +#noconstructor +} + abstract DpdkBinaryStatement : DpdkAssignmentStatement { Expression src1; Expression src2; diff --git a/backends/dpdk/dpdkArch.h b/backends/dpdk/dpdkArch.h index 7a826712e4f..0f2239fb4dd 100644 --- a/backends/dpdk/dpdkArch.h +++ b/backends/dpdk/dpdkArch.h @@ -1101,10 +1101,23 @@ class ValidateOperandSize : public Inspector { } void postorder(const IR::Operation_Binary *binop) override { + if (binop->is() || binop->is() || binop->is()) + if (checkIf128bitOp(binop->left, binop->right)) return; isValidOperandSize(binop->left); isValidOperandSize(binop->right); } + bool checkIf128bitOp(const IR::Expression *src1Op, const IR::Expression *src2Op) { + if (auto src1Type = src1Op->type->to()) { + if (src1Type->width_bits() == 128) { + if (auto src2Type = src2Op->type->to()) { + if (src2Type->width_bits() == 128) return true; + } + } + } + return false; + } + // Reject all operations except typecast if the operand size is beyond the supported limit void postorder(const IR::Operation_Unary *unop) override { if (unop->is()) return; diff --git a/backends/dpdk/dpdkHelpers.cpp b/backends/dpdk/dpdkHelpers.cpp index 79d2475a2d0..7cc373141a5 100644 --- a/backends/dpdk/dpdkHelpers.cpp +++ b/backends/dpdk/dpdkHelpers.cpp @@ -212,11 +212,20 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) { } else if (right->is() || right->is()) { process_logical_operation(left, r); } else if (right->is()) { - add_instr(new IR::DpdkOrStatement(left, src1Op, src2Op)); + if (checkIf128bitOp(left, src1Op, src2Op)) + add128bitInstr(src1Op, src2Op, "or"); + else + add_instr(new IR::DpdkOrStatement(left, src1Op, src2Op)); } else if (right->is()) { - add_instr(new IR::DpdkAndStatement(left, src1Op, src2Op)); + if (checkIf128bitOp(left, src1Op, src2Op)) + add128bitInstr(src1Op, src2Op, "and"); + else + add_instr(new IR::DpdkAndStatement(left, src1Op, src2Op)); } else if (right->is()) { - add_instr(new IR::DpdkXorStatement(left, src1Op, src2Op)); + if (checkIf128bitOp(left, src1Op, src2Op)) + add128bitInstr(src1Op, src2Op, "xor"); + else + add_instr(new IR::DpdkXorStatement(left, src1Op, src2Op)); } else if (right->is()) { add_instr(new IR::DpdkMovStatement(a->left, a->right)); } else { @@ -1460,4 +1469,137 @@ bool ConvertStatementToDpdk::preorder(const IR::SwitchStatement *s) { return false; } +bool ConvertStatementToDpdk::checkIf128bitOp(const IR::Expression *left, + const IR::Expression *src1Op, + const IR::Expression *src2Op) { + if (auto t = left->type->to()) { + auto leftWidth = t->width_bits(); + if (leftWidth == 128) { + if (auto src1Type = src1Op->type->to()) { + if (src1Type->width_bits() == 128) { + if (auto src2Type = src2Op->type->to()) { + if (src2Type->width_bits() == 128) return true; + } + } + } + } + } + return false; +} + +void ConvertStatementToDpdk::add128bitInstr(const IR::Expression *src1Op, + const IR::Expression *src2Op, const char *op) { + // check bool variable to check and create sandbox struct + // sandbox tmp variable creation + if (!createTmpVar) { + createTmpVar = true; + createTmpVarForSandbox(); + } + if (!createSandboxHeaderType) { + createSandboxHeaderType = true; + createSandboxHeader(); + } + const IR::Type_Header *Type_Header = nullptr; + const IR::Type_Header *Type_Tmp = nullptr; + for (auto header : structure->header_types) { + if (strcmp(header.first, "sandbox_header_t") == 0) { + Type_Header = header.second; + } else if (strcmp(header.first, "tmp128_t") == 0) { + Type_Tmp = header.second; + } + } + if (Type_Header == nullptr || Type_Tmp == nullptr) { + BUG("Header type not found"); + } + auto src1OpHeaderName = src1Op->toString(); + if (src1Op->is()) { + src1OpHeaderName = src1Op->to()->member.name; + } + auto tmpVarOpName = src1OpHeaderName + "_tmp"; + src1OpHeaderName = src1OpHeaderName + "_128"; + auto src1OpHeader = new IR::Declaration_Variable(src1OpHeaderName, Type_Header); + auto tmpVarOp = new IR::Declaration_Variable(tmpVarOpName, Type_Tmp); + auto src1OpHeaderInstance = new IR::DpdkHeaderInstance(src1OpHeader, Type_Header); + auto tmpVarOpInstance = new IR::DpdkHeaderInstance(tmpVarOp, Type_Tmp); + structure->addHeaderInstances(src1OpHeaderInstance); + structure->addHeaderInstances(tmpVarOpInstance); + auto src1OpUpper = + new IR::Member(new IR::PathExpression("h." + src1OpHeader->name), IR::ID("upper_half")); + auto src1OpLower = + new IR::Member(new IR::PathExpression("h." + src1OpHeader->name), IR::ID("lower_half")); + auto tmp = new IR::Member(new IR::PathExpression("h." + tmpVarOp->name), IR::ID("inter")); + if (src2Op->is()) { + add_instr(new IR::DpdkMovhStatement(src1OpUpper, src1Op)); + add_instr(new IR::DpdkMovStatement(src1OpLower, src1Op)); + add_instr(new IR::DpdkMovStatement(tmp, src1OpLower)); + if (strcmp(op, "xor") == 0) { + add_instr(new IR::DpdkXorStatement(tmp, tmp, src2Op)); + } else if (strcmp(op, "or") == 0) { + add_instr(new IR::DpdkOrStatement(tmp, tmp, src2Op)); + } else if (strcmp(op, "and") == 0) { + add_instr(new IR::DpdkAndStatement(tmp, tmp, src2Op)); + } + add_instr(new IR::DpdkMovStatement(src1Op, tmp)); + add_instr(new IR::DpdkMovStatement(tmp, src1OpUpper)); + if (strcmp(op, "xor") == 0) { + add_instr(new IR::DpdkXorStatement(tmp, tmp, src2Op)); + } else if (strcmp(op, "or") == 0) { + add_instr(new IR::DpdkOrStatement(tmp, tmp, src2Op)); + } else if (strcmp(op, "and") == 0) { + add_instr(new IR::DpdkAndStatement(tmp, tmp, src2Op)); + } + add_instr(new IR::DpdkMovhStatement(src1Op, tmp)); + } else { + auto src2OpHeaderName = src2Op->toString(); + if (src2Op->is()) { + src2OpHeaderName = src2Op->to()->member.name; + } + src2OpHeaderName = src2OpHeaderName + "_128"; + auto src2OpHeader = new IR::Declaration_Variable(src2OpHeaderName, Type_Header); + auto src2OpHeaderInstance = new IR::DpdkHeaderInstance(src2OpHeader, Type_Header); + structure->addHeaderInstances(src2OpHeaderInstance); + auto src2OpUpper = + new IR::Member(new IR::PathExpression("h." + src2OpHeader->name), IR::ID("upper_half")); + auto src2OpLower = + new IR::Member(new IR::PathExpression("h." + src2OpHeader->name), IR::ID("lower_half")); + add_instr(new IR::DpdkMovhStatement(src1OpUpper, src1Op)); + add_instr(new IR::DpdkMovStatement(src1OpLower, src1Op)); + add_instr(new IR::DpdkMovhStatement(src2OpUpper, src2Op)); + add_instr(new IR::DpdkMovStatement(src2OpLower, src2Op)); + add_instr(new IR::DpdkMovStatement(tmp, src1OpLower)); + if (strcmp(op, "xor") == 0) { + add_instr(new IR::DpdkXorStatement(tmp, tmp, src2OpLower)); + } else if (strcmp(op, "or") == 0) { + add_instr(new IR::DpdkOrStatement(tmp, tmp, src2OpLower)); + } else if (strcmp(op, "and") == 0) { + add_instr(new IR::DpdkAndStatement(tmp, tmp, src2OpLower)); + } + add_instr(new IR::DpdkMovStatement(src1Op, tmp)); + add_instr(new IR::DpdkMovStatement(tmp, src1OpUpper)); + if (strcmp(op, "xor") == 0) { + add_instr(new IR::DpdkXorStatement(tmp, tmp, src2OpUpper)); + } else if (strcmp(op, "or") == 0) { + add_instr(new IR::DpdkOrStatement(tmp, tmp, src2OpUpper)); + } else if (strcmp(op, "and") == 0) { + add_instr(new IR::DpdkAndStatement(tmp, tmp, src2OpUpper)); + } + add_instr(new IR::DpdkMovhStatement(src1Op, tmp)); + } +} + +void ConvertStatementToDpdk::createSandboxHeader() { + auto fields = new IR::IndexedVector; + fields->push_back(new IR::StructField("upper_half", IR::Type_Bits::get(64))); + fields->push_back(new IR::StructField("lower_half", IR::Type_Bits::get(64))); + const IR::Type_Header *headerStruct = new IR::Type_Header(IR::ID("sandbox_header_t"), *fields); + structure->header_types.emplace(cstring("sandbox_header_t"), headerStruct); +} + +void ConvertStatementToDpdk::createTmpVarForSandbox() { + auto fields = new IR::IndexedVector; + fields->push_back(new IR::StructField("tmp", IR::Type_Bits::get(64))); + const IR::Type_Header *headerStruct = new IR::Type_Header(IR::ID("tmp128_t"), *fields); + structure->header_types.emplace(cstring("tmp128_t"), headerStruct); +} + } // namespace P4::DPDK diff --git a/backends/dpdk/dpdkHelpers.h b/backends/dpdk/dpdkHelpers.h index 91d1cafdf1e..8bd882e490a 100644 --- a/backends/dpdk/dpdkHelpers.h +++ b/backends/dpdk/dpdkHelpers.h @@ -150,6 +150,8 @@ class ConvertStatementToDpdk : public Inspector { const IR::P4Parser *parser = nullptr; const IR::Node *parent = nullptr; IR::Type_Struct *metadataStruct = nullptr; + bool createSandboxHeaderType = false; + bool createTmpVar = false; private: void processHashParams(const IR::Argument *field, IR::Vector &components); @@ -157,6 +159,8 @@ class ConvertStatementToDpdk : public Inspector { void updateMdStrAndGenInstr(const IR::Argument *field, IR::Vector &components); cstring getHdrMdStrName(const IR::Member *mem); bool checkIfConsecutiveHdrMdfields(const IR::Argument *field); + void createSandboxHeader(); + void createTmpVarForSandbox(); public: ConvertStatementToDpdk(P4::ReferenceMap *refmap, P4::TypeMap *typemap, @@ -185,8 +189,9 @@ class ConvertStatementToDpdk : public Inspector { void set_parser(const IR::P4Parser *p) { parser = p; } void set_parent(const IR::Node *p) { parent = p; } bool handleConstSwitch(const IR::SwitchStatement *a); + bool checkIf128bitOp(const IR::Expression *, const IR::Expression *, const IR::Expression *); + void add128bitInstr(const IR::Expression *src1Op, const IR::Expression *src2Op, const char *op); }; - /// Only simplify complex expression in ingress/egress. class ProcessControls : public P4::RemoveComplexExpressionsPolicy { const std::set *process; diff --git a/backends/dpdk/dpdkProgram.cpp b/backends/dpdk/dpdkProgram.cpp index 3896a35f4e8..a9eb18878d4 100644 --- a/backends/dpdk/dpdkProgram.cpp +++ b/backends/dpdk/dpdkProgram.cpp @@ -238,8 +238,15 @@ const IR::DpdkAsmProgram *ConvertToDpdkProgram::create(IR::P4Program *prog) { learners.append(egress_converter->getLearners()); } - return new IR::DpdkAsmProgram(headerType, structType, dpdkExternDecls, actions, tables, - selectors, learners, statements, structure->get_globals()); + IR::IndexedVector headerInstances; + + for (auto it : structure->header_instances) { + headerInstances.push_back(it.second); + } + + return new IR::DpdkAsmProgram(headerType, structType, headerInstances, dpdkExternDecls, actions, + tables, selectors, learners, statements, + structure->get_globals()); } const IR::Node *ConvertToDpdkProgram::preorder(IR::P4Program *prog) { diff --git a/backends/dpdk/dpdkProgramStructure.h b/backends/dpdk/dpdkProgramStructure.h index 85fbedfb008..cada579d022 100644 --- a/backends/dpdk/dpdkProgramStructure.h +++ b/backends/dpdk/dpdkProgramStructure.h @@ -36,6 +36,7 @@ struct DpdkProgramStructure { ordered_map learner_action_table; ordered_map table_type_map; ordered_map direct_resource_map; + ordered_map header_instances; IR::IndexedVector variables; @@ -70,6 +71,12 @@ struct DpdkProgramStructure { void push_variable(const IR::DpdkDeclaration *d) { variables.push_back(d); } IR::IndexedVector &get_globals() { return variables; } + void addHeaderInstances(const IR::DpdkHeaderInstance *d) { + if (header_instances.find(d->name->toString()) == header_instances.end()) { + header_instances.emplace(d->name->toString(), d); + } + } + bool hasVisited(const IR::Type_StructLike *st) { if (auto h = st->to()) return header_types.count(h->getName()); diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index 60510233515..60083e567c4 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -36,6 +36,10 @@ std::ostream &IR::DpdkAsmProgram::toSpec(std::ostream &out) const { add_comment(out, s->name.toString()); s->toSpec(out) << std::endl; } + for (auto hi : headerInstance) { + add_comment(out, hi->name->toString()); + hi->toSpec(out) << std::endl; + } for (auto s : externDeclarations) { add_comment(out, s->name.toString()); s->toSpec(out); @@ -213,6 +217,11 @@ std::ostream &IR::DpdkHeaderType::toSpec(std::ostream &out) const { return out; } +std::ostream &IR::DpdkHeaderInstance::toSpec(std::ostream &out) const { + out << "header " << name->toString() << " instanceof " << headerType->toString(); + return out; +} + std::ostream &IR::DpdkStructType::toSpec(std::ostream &out) const { if (getAnnotations()->getSingle("__packet_data__"_cs)) { for (auto it = fields.begin(); it != fields.end(); ++it) { diff --git a/testdata/p4_16_samples/pna-ipv6-actions.p4 b/testdata/p4_16_samples/pna-ipv6-actions.p4 index 9f802bd6420..dad445c1166 100644 --- a/testdata/p4_16_samples/pna-ipv6-actions.p4 +++ b/testdata/p4_16_samples/pna-ipv6-actions.p4 @@ -117,6 +117,18 @@ control MainControlImpl( tmp1 = (bit<32>)headers.ipv6.srcAddr; } + action ipv6_addr_or() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr | headers.ipv6.srcAddr; + } + + action ipv6_addr_and() { + headers.ipv6.dstAddr = tmp & headers.ipv6.srcAddr; + } + + action ipv6_addr_xor() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr ^ tmp; + } + action ipv6_swap_addr() { headers.ipv6.dstAddr = headers.ipv6.srcAddr; headers.ipv6.srcAddr = tmp; @@ -156,6 +168,9 @@ control MainControlImpl( ipv6_modify_dstAddr; ipv6_swap_addr; set_flowlabel; + ipv6_addr_or; + ipv6_addr_xor; + ipv6_addr_and; set_traffic_class_flow_label; set_ipv6_version; set_next_hdr; diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions-first.p4 b/testdata/p4_16_samples_outputs/pna-ipv6-actions-first.p4 index 670e1b9b4be..c4d9240b85e 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions-first.p4 +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions-first.p4 @@ -91,6 +91,15 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in headers.ipv6.dstAddr = (bit<128>)dstAddr; tmp1 = (bit<32>)headers.ipv6.srcAddr; } + action ipv6_addr_or() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr | headers.ipv6.srcAddr; + } + action ipv6_addr_and() { + headers.ipv6.dstAddr = tmp & headers.ipv6.srcAddr; + } + action ipv6_addr_xor() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr ^ tmp; + } action ipv6_swap_addr() { headers.ipv6.dstAddr = headers.ipv6.srcAddr; headers.ipv6.srcAddr = tmp; @@ -123,6 +132,9 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in ipv6_modify_dstAddr(); ipv6_swap_addr(); set_flowlabel(); + ipv6_addr_or(); + ipv6_addr_xor(); + ipv6_addr_and(); set_traffic_class_flow_label(); set_ipv6_version(); set_next_hdr(); diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions-frontend.p4 b/testdata/p4_16_samples_outputs/pna-ipv6-actions-frontend.p4 index eca6c6ba8e8..03558fe971c 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions-frontend.p4 +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions-frontend.p4 @@ -92,6 +92,15 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in @name("MainControlImpl.ipv6_modify_dstAddr") action ipv6_modify_dstAddr(@name("dstAddr") bit<32> dstAddr_1) { headers.ipv6.dstAddr = (bit<128>)dstAddr_1; } + @name("MainControlImpl.ipv6_addr_or") action ipv6_addr_or() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr | headers.ipv6.srcAddr; + } + @name("MainControlImpl.ipv6_addr_and") action ipv6_addr_and() { + headers.ipv6.dstAddr = tmp_0 & headers.ipv6.srcAddr; + } + @name("MainControlImpl.ipv6_addr_xor") action ipv6_addr_xor() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr ^ tmp_0; + } @name("MainControlImpl.ipv6_swap_addr") action ipv6_swap_addr() { headers.ipv6.dstAddr = headers.ipv6.srcAddr; headers.ipv6.srcAddr = tmp_0; @@ -121,6 +130,9 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in ipv6_modify_dstAddr(); ipv6_swap_addr(); set_flowlabel(); + ipv6_addr_or(); + ipv6_addr_xor(); + ipv6_addr_and(); set_traffic_class_flow_label(); set_ipv6_version(); set_next_hdr(); diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions-midend.p4 b/testdata/p4_16_samples_outputs/pna-ipv6-actions-midend.p4 index 1f7c2c7451b..95153a9a3a1 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions-midend.p4 +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions-midend.p4 @@ -90,6 +90,15 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in @name("MainControlImpl.ipv6_modify_dstAddr") action ipv6_modify_dstAddr(@name("dstAddr") bit<32> dstAddr_1) { headers.ipv6.dstAddr = (bit<128>)dstAddr_1; } + @name("MainControlImpl.ipv6_addr_or") action ipv6_addr_or() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr | headers.ipv6.srcAddr; + } + @name("MainControlImpl.ipv6_addr_and") action ipv6_addr_and() { + headers.ipv6.dstAddr = tmp_0 & headers.ipv6.srcAddr; + } + @name("MainControlImpl.ipv6_addr_xor") action ipv6_addr_xor() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr ^ tmp_0; + } @name("MainControlImpl.ipv6_swap_addr") action ipv6_swap_addr() { headers.ipv6.dstAddr = headers.ipv6.srcAddr; headers.ipv6.srcAddr = tmp_0; @@ -119,6 +128,9 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in ipv6_modify_dstAddr(); ipv6_swap_addr(); set_flowlabel(); + ipv6_addr_or(); + ipv6_addr_xor(); + ipv6_addr_and(); set_traffic_class_flow_label(); set_ipv6_version(); set_next_hdr(); @@ -144,20 +156,20 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in } control MainDeparserImpl(packet_out packet, in headers_t headers, in main_metadata_t user_meta, in pna_main_output_metadata_t ostd) { - @hidden action pnaipv6actions180() { + @hidden action pnaipv6actions195() { packet.emit(headers.ethernet); packet.emit(headers.mpls); packet.emit(headers.ipv6); packet.emit(headers.ipv4); } - @hidden table tbl_pnaipv6actions180 { + @hidden table tbl_pnaipv6actions195 { actions = { - pnaipv6actions180(); + pnaipv6actions195(); } - const default_action = pnaipv6actions180(); + const default_action = pnaipv6actions195(); } apply { - tbl_pnaipv6actions180.apply(); + tbl_pnaipv6actions195.apply(); } } diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4 b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4 index 782d6b2869c..9277293d3c2 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4 +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4 @@ -91,6 +91,15 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in headers.ipv6.dstAddr = (bit<128>)dstAddr; tmp1 = (bit<32>)headers.ipv6.srcAddr; } + action ipv6_addr_or() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr | headers.ipv6.srcAddr; + } + action ipv6_addr_and() { + headers.ipv6.dstAddr = tmp & headers.ipv6.srcAddr; + } + action ipv6_addr_xor() { + headers.ipv6.dstAddr = headers.ipv6.dstAddr ^ tmp; + } action ipv6_swap_addr() { headers.ipv6.dstAddr = headers.ipv6.srcAddr; headers.ipv6.srcAddr = tmp; @@ -123,6 +132,9 @@ control MainControlImpl(inout headers_t headers, inout main_metadata_t meta, in ipv6_modify_dstAddr; ipv6_swap_addr; set_flowlabel; + ipv6_addr_or; + ipv6_addr_xor; + ipv6_addr_and; set_traffic_class_flow_label; set_ipv6_version; set_next_hdr; diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-error b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-error index 96915c1b3ee..df91fcdc902 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-error +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-error @@ -1,3 +1,3 @@ -pna-ipv6-actions.p4(136): [--Wwarn=uninitialized_use] warning: tmp1 may be uninitialized +pna-ipv6-actions.p4(148): [--Wwarn=uninitialized_use] warning: tmp1 may be uninitialized headers.ipv6.srcAddr = (bit<128>)tmp1; ^^^^ diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-stderr b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-stderr index 96915c1b3ee..df91fcdc902 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-stderr +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4-stderr @@ -1,3 +1,3 @@ -pna-ipv6-actions.p4(136): [--Wwarn=uninitialized_use] warning: tmp1 may be uninitialized +pna-ipv6-actions.p4(148): [--Wwarn=uninitialized_use] warning: tmp1 may be uninitialized headers.ipv6.srcAddr = (bit<128>)tmp1; ^^^^ diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.bfrt.json b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.bfrt.json index 03ee286a952..015e9b50a0c 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.bfrt.json +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.bfrt.json @@ -71,6 +71,27 @@ } ] }, + { + "id" : 23072859, + "name" : "MainControlImpl.ipv6_addr_or", + "action_scope" : "TableAndDefault", + "annotations" : [], + "data" : [] + }, + { + "id" : 26319412, + "name" : "MainControlImpl.ipv6_addr_xor", + "action_scope" : "TableAndDefault", + "annotations" : [], + "data" : [] + }, + { + "id" : 22390528, + "name" : "MainControlImpl.ipv6_addr_and", + "action_scope" : "TableAndDefault", + "annotations" : [], + "data" : [] + }, { "id" : 31572308, "name" : "MainControlImpl.set_traffic_class_flow_label", diff --git a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.spec b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.spec index 6203c1aebc1..329d9539223 100644 --- a/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-ipv6-actions.p4.spec @@ -38,6 +38,15 @@ struct dpdk_pseudo_header_t { bit<64> pseudo_1 } +struct tmp128_t { + bit<64> tmp +} + +struct sandbox_header_t { + bit<64> upper_half + bit<64> lower_half +} + struct ipv6_modify_dstAddr_arg_t { bit<32> dstAddr } @@ -87,6 +96,10 @@ struct main_metadata_t { } metadata instanceof main_metadata_t +header dstAddr_128 instanceof header sandbox_header_t +header dstAddr_tmp instanceof header tmp128_t +header srcAddr_128 instanceof header sandbox_header_t +header MainControlT_tmp_13_128 instanceof header sandbox_header_t regarray direction size 0x100 initval 0 action NoAction args none { return @@ -103,6 +116,49 @@ action ipv6_modify_dstAddr args instanceof ipv6_modify_dstAddr_arg_t { return } +action ipv6_addr_or args none { + movh h.dstAddr_128.upper_half h.ipv6.dstAddr + mov h.dstAddr_128.lower_half h.ipv6.dstAddr + movh h.srcAddr_128.upper_half h.ipv6.srcAddr + mov h.srcAddr_128.lower_half h.ipv6.srcAddr + mov h.dstAddr_tmp.inter h.dstAddr_128.lower_half + or h.dstAddr_tmp.inter h.srcAddr_128.lower_half + mov h.ipv6.dstAddr h.dstAddr_tmp.inter + mov h.dstAddr_tmp.inter h.dstAddr_128.upper_half + or h.dstAddr_tmp.inter h.srcAddr_128.upper_half + movh h.ipv6.dstAddr h.dstAddr_tmp.inter + return +} + +action ipv6_addr_and args none { + mov h.ipv6.dstAddr m.MainControlT_tmp_13 + movh h.dstAddr_128.upper_half h.ipv6.dstAddr + mov h.dstAddr_128.lower_half h.ipv6.dstAddr + movh h.srcAddr_128.upper_half h.ipv6.srcAddr + mov h.srcAddr_128.lower_half h.ipv6.srcAddr + mov h.dstAddr_tmp.inter h.dstAddr_128.lower_half + and h.dstAddr_tmp.inter h.srcAddr_128.lower_half + mov h.ipv6.dstAddr h.dstAddr_tmp.inter + mov h.dstAddr_tmp.inter h.dstAddr_128.upper_half + and h.dstAddr_tmp.inter h.srcAddr_128.upper_half + movh h.ipv6.dstAddr h.dstAddr_tmp.inter + return +} + +action ipv6_addr_xor args none { + movh h.dstAddr_128.upper_half h.ipv6.dstAddr + mov h.dstAddr_128.lower_half h.ipv6.dstAddr + movh h.MainControlT_tmp_13_128.upper_half m.MainControlT_tmp_13 + mov h.MainControlT_tmp_13_128.lower_half m.MainControlT_tmp_13 + mov h.dstAddr_tmp.inter h.dstAddr_128.lower_half + xor h.dstAddr_tmp.inter h.MainControlT_tmp_13_128.lower_half + mov h.ipv6.dstAddr h.dstAddr_tmp.inter + mov h.dstAddr_tmp.inter h.dstAddr_128.upper_half + xor h.dstAddr_tmp.inter h.MainControlT_tmp_13_128.upper_half + movh h.ipv6.dstAddr h.dstAddr_tmp.inter + return +} + action ipv6_swap_addr args none { mov h.ipv6.dstAddr h.ipv6.srcAddr mov h.ipv6.srcAddr m.MainControlT_tmp_13 @@ -169,6 +225,9 @@ table filter_tbl { ipv6_modify_dstAddr ipv6_swap_addr set_flowlabel + ipv6_addr_or + ipv6_addr_xor + ipv6_addr_and set_traffic_class_flow_label set_ipv6_version set_next_hdr diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec index 42699369936..e419a8540d7 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec @@ -9,6 +9,15 @@ struct dpdk_pseudo_header_t { bit<64> pseudo } +struct tmp128_t { + bit<64> tmp +} + +struct sandbox_header_t { + bit<64> upper_half + bit<64> lower_half +} + struct psa_ingress_output_metadata_t { bit<8> class_of_service bit<8> clone @@ -44,17 +53,44 @@ struct user_meta_data_t { } metadata instanceof user_meta_data_t +header Ingress_tmp_128 instanceof header sandbox_header_t +header Ingress_tmp_tmp instanceof header tmp128_t +header Ingress_tmp_0_128 instanceof header sandbox_header_t +header Ingress_tmp_0_tmp instanceof header tmp128_t +header Ingress_tmp_1_128 instanceof header sandbox_header_t +header Ingress_tmp_1_tmp instanceof header tmp128_t action NoAction args none { return } action macswp args none { mov m.Ingress_tmp m.Ingress_flg - and m.Ingress_tmp 0xFFFFFFFFFFFFFFFF + movh h.Ingress_tmp_128.upper_half m.Ingress_tmp + mov h.Ingress_tmp_128.lower_half m.Ingress_tmp + mov h.Ingress_tmp_tmp.inter h.Ingress_tmp_128.lower_half + and h.Ingress_tmp_tmp.inter 0xFFFFFFFFFFFFFFFF + mov m.Ingress_tmp h.Ingress_tmp_tmp.inter + mov h.Ingress_tmp_tmp.inter h.Ingress_tmp_128.upper_half + and h.Ingress_tmp_tmp.inter 0xFFFFFFFFFFFFFFFF + movh m.Ingress_tmp h.Ingress_tmp_tmp.inter mov m.Ingress_tmp_0 m.Ingress_tmp - and m.Ingress_tmp_0 0xFFFFFFFFFFFFFFFF + movh h.Ingress_tmp_0_128.upper_half m.Ingress_tmp_0 + mov h.Ingress_tmp_0_128.lower_half m.Ingress_tmp_0 + mov h.Ingress_tmp_0_tmp.inter h.Ingress_tmp_0_128.lower_half + and h.Ingress_tmp_0_tmp.inter 0xFFFFFFFFFFFFFFFF + mov m.Ingress_tmp_0 h.Ingress_tmp_0_tmp.inter + mov h.Ingress_tmp_0_tmp.inter h.Ingress_tmp_0_128.upper_half + and h.Ingress_tmp_0_tmp.inter 0xFFFFFFFFFFFFFFFF + movh m.Ingress_tmp_0 h.Ingress_tmp_0_tmp.inter mov m.Ingress_tmp_1 m.Ingress_tmp_0 - and m.Ingress_tmp_1 0xFFFFFFFFFFFFFFFF + movh h.Ingress_tmp_1_128.upper_half m.Ingress_tmp_1 + mov h.Ingress_tmp_1_128.lower_half m.Ingress_tmp_1 + mov h.Ingress_tmp_1_tmp.inter h.Ingress_tmp_1_128.lower_half + and h.Ingress_tmp_1_tmp.inter 0xFFFFFFFFFFFFFFFF + mov m.Ingress_tmp_1 h.Ingress_tmp_1_tmp.inter + mov h.Ingress_tmp_1_tmp.inter h.Ingress_tmp_1_128.upper_half + and h.Ingress_tmp_1_tmp.inter 0xFFFFFFFFFFFFFFFF + movh m.Ingress_tmp_1 h.Ingress_tmp_1_tmp.inter mov h.dpdk_pseudo_header.pseudo m.Ingress_tmp_1 jmpneq LABEL_END h.dpdk_pseudo_header.pseudo 0x2 mov m.local_metadata_addr h.ethernet.dst_addr