From db12638055952e3573eee76c9bd9bd1f5045965d Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Tue, 2 Jan 2024 05:45:54 -0800 Subject: [PATCH 1/7] Fix actionparams type field in introspection.json --- backends/tc/introspection.cpp | 3 ++- .../p4tc_samples_outputs/default_action_example.json | 4 ++-- .../p4tc_samples_outputs/drop_packet_example.json | 2 +- testdata/p4tc_samples_outputs/matchtype.json | 8 ++++---- .../p4tc_samples_outputs/mix_matchtype_example.json | 8 ++++---- .../multiple_tables_example_01.json | 12 ++++++------ .../multiple_tables_example_02.json | 6 +++--- .../name_annotation_example.json | 4 ++-- .../p4tc_samples_outputs/noaction_example_01.json | 4 ++-- .../p4tc_samples_outputs/noaction_example_02.json | 2 +- .../p4tc_samples_outputs/send_to_port_example.json | 2 +- .../p4tc_samples_outputs/size_param_example.json | 4 ++-- testdata/p4tc_samples_outputs/test_ipv6_example.json | 2 +- 13 files changed, 31 insertions(+), 30 deletions(-) diff --git a/backends/tc/introspection.cpp b/backends/tc/introspection.cpp index 7db69d9dbc6..90c95c14d51 100644 --- a/backends/tc/introspection.cpp +++ b/backends/tc/introspection.cpp @@ -183,7 +183,8 @@ Util::JsonObject *IntrospectionGenerator::genActionInfo(struct ActionAttributes paramJson->emplace("name", param->name); switch (param->dataType) { case TC::BIT_TYPE: { - paramJson->emplace("type", "bit"); + auto paramtype = "bit" + Util::toString(param->bitwidth); + paramJson->emplace("type", paramtype); break; } case TC::DEV_TYPE: { diff --git a/testdata/p4tc_samples_outputs/default_action_example.json b/testdata/p4tc_samples_outputs/default_action_example.json index a5dfe5f0922..c3a84a31d63 100644 --- a/testdata/p4tc_samples_outputs/default_action_example.json +++ b/testdata/p4tc_samples_outputs/default_action_example.json @@ -35,7 +35,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -92,7 +92,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/drop_packet_example.json b/testdata/p4tc_samples_outputs/drop_packet_example.json index 7aa96cb1cb1..a5eeab7077b 100644 --- a/testdata/p4tc_samples_outputs/drop_packet_example.json +++ b/testdata/p4tc_samples_outputs/drop_packet_example.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/matchtype.json b/testdata/p4tc_samples_outputs/matchtype.json index d94e7f6e012..3d15bee551c 100644 --- a/testdata/p4tc_samples_outputs/matchtype.json +++ b/testdata/p4tc_samples_outputs/matchtype.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -128,7 +128,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -185,7 +185,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/mix_matchtype_example.json b/testdata/p4tc_samples_outputs/mix_matchtype_example.json index 42550549cd2..00241acde20 100644 --- a/testdata/p4tc_samples_outputs/mix_matchtype_example.json +++ b/testdata/p4tc_samples_outputs/mix_matchtype_example.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -135,7 +135,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -192,7 +192,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_01.json b/testdata/p4tc_samples_outputs/multiple_tables_example_01.json index d816c2b9578..a0991e2596e 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_01.json +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_01.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -142,7 +142,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -199,7 +199,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -324,7 +324,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -376,7 +376,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_02.json b/testdata/p4tc_samples_outputs/multiple_tables_example_02.json index e6700607404..8a55ffcd7ba 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_02.json +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_02.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -310,7 +310,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/name_annotation_example.json b/testdata/p4tc_samples_outputs/name_annotation_example.json index 057cd04c22c..c7e0de8fcd7 100644 --- a/testdata/p4tc_samples_outputs/name_annotation_example.json +++ b/testdata/p4tc_samples_outputs/name_annotation_example.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/noaction_example_01.json b/testdata/p4tc_samples_outputs/noaction_example_01.json index 6aedf438601..24eef3aa2c6 100644 --- a/testdata/p4tc_samples_outputs/noaction_example_01.json +++ b/testdata/p4tc_samples_outputs/noaction_example_01.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/noaction_example_02.json b/testdata/p4tc_samples_outputs/noaction_example_02.json index 649db8935e0..ccdd118d66f 100644 --- a/testdata/p4tc_samples_outputs/noaction_example_02.json +++ b/testdata/p4tc_samples_outputs/noaction_example_02.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/send_to_port_example.json b/testdata/p4tc_samples_outputs/send_to_port_example.json index 90fa54fd54d..cbb7ab45b7d 100644 --- a/testdata/p4tc_samples_outputs/send_to_port_example.json +++ b/testdata/p4tc_samples_outputs/send_to_port_example.json @@ -42,7 +42,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/size_param_example.json b/testdata/p4tc_samples_outputs/size_param_example.json index 57472c2d3aa..c71a89ce935 100644 --- a/testdata/p4tc_samples_outputs/size_param_example.json +++ b/testdata/p4tc_samples_outputs/size_param_example.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], @@ -85,7 +85,7 @@ { "id" : 1, "name" : "vport", - "type" : "bit", + "type" : "bit32", "bitwidth" : 32 } ], diff --git a/testdata/p4tc_samples_outputs/test_ipv6_example.json b/testdata/p4tc_samples_outputs/test_ipv6_example.json index a831ec986af..2b48f30708a 100644 --- a/testdata/p4tc_samples_outputs/test_ipv6_example.json +++ b/testdata/p4tc_samples_outputs/test_ipv6_example.json @@ -28,7 +28,7 @@ { "id" : 1, "name" : "addr6", - "type" : "bit", + "type" : "bit128", "bitwidth" : 128 } ], From c11158629f90e9205dec8a84d91af7e32aab3042 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Wed, 3 Jan 2024 20:38:36 -0800 Subject: [PATCH 2/7] Support const_entries --- backends/tc/backend.cpp | 40 ++ backends/tc/backend.h | 1 + backends/tc/ebpfCodeGen.cpp | 1 + backends/tc/tc.def | 16 + testdata/p4tc_samples/calculator.p4 | 239 ++++++++++++ testdata/p4tc_samples_outputs/calculator.json | 79 ++++ .../p4tc_samples_outputs/calculator.p4-stderr | 0 .../p4tc_samples_outputs/calculator.template | 42 +++ .../calculator_control_blocks.c | 355 ++++++++++++++++++ .../p4tc_samples_outputs/calculator_parser.c | 227 +++++++++++ .../p4tc_samples_outputs/calculator_parser.h | 39 ++ .../multiple_tables_example_01.template | 5 + .../multiple_tables_example_02.template | 5 + 13 files changed, 1049 insertions(+) create mode 100644 testdata/p4tc_samples/calculator.p4 create mode 100644 testdata/p4tc_samples_outputs/calculator.json create mode 100644 testdata/p4tc_samples_outputs/calculator.p4-stderr create mode 100755 testdata/p4tc_samples_outputs/calculator.template create mode 100644 testdata/p4tc_samples_outputs/calculator_control_blocks.c create mode 100644 testdata/p4tc_samples_outputs/calculator_parser.c create mode 100644 testdata/p4tc_samples_outputs/calculator_parser.h diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index a1afef187e2..4a9c87233d9 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -271,6 +271,45 @@ void ConvertToBackendIR::postorder(const IR::P4Action *action) { } } +void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *tabledef) { + // Check if there are const entries. + auto entriesList = t->getEntries(); + if (entriesList == nullptr) return; + auto keys = t->getKey(); + for (auto e : entriesList->entries) { + if (keys == nullptr) { + return; + } + auto keyset = e->getKeys(); + if (keyset->components.size() != keys->keyElements.size()) { + ::error("No of keys in const_entries should be same as no of keys in the table."); + return; + } + ordered_map keyList; + for (size_t itr = 0; itr < keyset->components.size(); itr++) { + auto keyElement = keys->keyElements.at(itr); + auto keyString = keyElement->expression->toString(); + auto annotations = keyElement->getAnnotations(); + if (annotations) { + if (auto anno = annotations->getSingle("name")) { + keyString = anno->expr.at(0)->to()->value; + } + } + auto keySetElement = keyset->components.at(itr); + // std::stringstream value; + // if(keySetElement->is()) { + // value << keySetElement->to()->value; + // } else if (keySetElement->is()) { + // value << keySetElement->to()->value ? 1 : 0; + // } else if (keySetElement->is()) { + // value << 0; + // } + keyList.emplace(keyString, keySetElement->toString()); + } + tabledef->addConstEntries(e->action->toString(), keyList); + } +} + void ConvertToBackendIR::updateDefaultMissAction(const IR::P4Table *t, IR::TCTable *tabledef) { auto defaultAction = t->getDefaultAction(); if (defaultAction == nullptr || !defaultAction->is()) return; @@ -450,6 +489,7 @@ void ConvertToBackendIR::postorder(const IR::P4Table *t) { updateDefaultHitAction(t, tableDefinition); updateDefaultMissAction(t, tableDefinition); updateMatchType(t, tableDefinition); + updateConstEntries(t, tableDefinition); tcPipeline->addTableDefinition(tableDefinition); } } diff --git a/backends/tc/backend.h b/backends/tc/backend.h index ae6ff95cac1..debf256f75b 100644 --- a/backends/tc/backend.h +++ b/backends/tc/backend.h @@ -73,6 +73,7 @@ class ConvertToBackendIR : public Inspector { bool isDuplicateOrNoAction(const IR::P4Action *action); void updateDefaultHitAction(const IR::P4Table *t, IR::TCTable *tdef); void updateDefaultMissAction(const IR::P4Table *t, IR::TCTable *tdef); + void updateConstEntries(const IR::P4Table *t, IR::TCTable *tdef); void updateMatchType(const IR::P4Table *t, IR::TCTable *tabledef); bool isPnaParserMeta(const IR::Member *mem); bool isPnaMainInputMeta(const IR::Member *mem); diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index ff3e384664d..94e17250d0c 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -182,6 +182,7 @@ void PNAArchTC::emitParser(EBPF::CodeBuilder *builder) const { emitPNAIncludes(builder); builder->newline(); emitInstances(builder); + // EBPF::EBPFHashAlgorithmTypeFactoryPSA::instance()->emitGlobals(builder); pipeline->name = "tc-parse"; pipeline->sectionName = "classifier/" + pipeline->name; pipeline->functionName = pipeline->name.replace("-", "_") + "_func"; diff --git a/backends/tc/tc.def b/backends/tc/tc.def index ad89cb25ed6..c6e0fb4893f 100644 --- a/backends/tc/tc.def +++ b/backends/tc/tc.def @@ -167,6 +167,7 @@ class TCTable { TCAction defaultMissAction; bool isDefaultMissConst; ordered_map actionList; + ordered_map> const_entries; void setKeySize(unsigned k) { keySize = k; } @@ -200,6 +201,9 @@ class TCTable { void addAction(TCAction action, unsigned flag) { actionList.emplace(action, flag); } + void addConstEntries(cstring action, ordered_map keys) { + const_entries.emplace(action, keys); + } cstring printMatchType(unsigned matchType) const { cstring matchTypeString = ""; switch(matchType) { @@ -288,6 +292,18 @@ class TCTable { } tcTable += " action " + defaultMissAction->getName(); } + if (const_entries.size() != 0) { + for (auto entry : const_entries) { + tcTable += "\n$TC p4template update table/" + pipelineName + + "/" + controlName + "/" + tableName + + " entry "; + for(auto k : entry.second) { + tcTable += k.first + " " + k.second; + } + tcTable += " action " + pipelineName + + "/" + controlName + "/" + entry.first; + } + } return tcTable; } dbprint { out << toString(); } diff --git a/testdata/p4tc_samples/calculator.p4 b/testdata/p4tc_samples/calculator.p4 new file mode 100644 index 00000000000..d5312da3c7f --- /dev/null +++ b/testdata/p4tc_samples/calculator.p4 @@ -0,0 +1,239 @@ +/* -*- P4_16 -*- */ + +/* + * P4 Calculator + * + * This program implements a simple protocol. It can be carried over Ethernet + * (Ethertype 0x1234). + * + * The Protocol header looks like this: + * + * 0 1 2 3 + * +----------------+----------------+----------------+---------------+ + * | P | 4 | Version | Op | + * +----------------+----------------+----------------+---------------+ + * | Operand A | + * +----------------+----------------+----------------+---------------+ + * | Operand B | + * +----------------+----------------+----------------+---------------+ + * | Result | + * +----------------+----------------+----------------+---------------+ + * + * P is an ASCII Letter 'P' (0x50) + * 4 is an ASCII Letter '4' (0x34) + * Version is currently 0.1 (0x01) + * Op is an operation to Perform: + * '+' (0x2b) Result = OperandA + OperandB + * '-' (0x2d) Result = OperandA - OperandB + * '&' (0x26) Result = OperandA & OperandB + * '|' (0x7c) Result = OperandA | OperandB + * '^' (0x5e) Result = OperandA ^ OperandB + * + * The device receives a packet, performs the requested operation, fills in the + * result and sends the packet back out of the same port it came in on, while + * swapping the source and destination addresses. + * + * If an unknown operation is specified or the header is not valid, the packet + * is dropped + */ + +#include +#include + + +/* + * Define the headers the program will recognize + */ + +/* + * Standard ethernet header + */ +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +/* + * This is a custom protocol header for the calculator. We'll use + * ethertype 0x1234 for is (see parser) + */ +const bit<16> P4CALC_ETYPE = 0x1234; +const bit<8> P4CALC_P = 0x50; // 'P' +const bit<8> P4CALC_4 = 0x34; // '4' +const bit<8> P4CALC_VER = 0x01; // v0.1 +const bit<8> P4CALC_PLUS = 0x2b; // '+' +const bit<8> P4CALC_MINUS = 0x2d; // '-' +const bit<8> P4CALC_AND = 0x26; // '&' +const bit<8> P4CALC_OR = 0x7c; // '|' +const bit<8> P4CALC_CARET = 0x5e; // '^' + +header p4calc_t { + bit<8> p; + bit<8> four; + bit<8> ver; + bit<8> op; + bit<32> operand_a; + bit<32> operand_b; + bit<32> res; +} + +/* + * All headers, used in the program needs to be assembed into a single struct. + * We only need to declare the type, but there is no need to instantiate it, + * because it is done "by the architecture", i.e. outside of P4 functions + */ +struct headers_t { + ethernet_t ethernet; + p4calc_t p4calc; +} + +/* + * All metadata, globally used in the program, also needs to be assembed + * into a single struct. As in the case of the headers, we only need to + * declare the type, but there is no need to instantiate it, + * because it is done "by the architecture", i.e. outside of P4 functions + */ + +struct metadata_t { + /* In our case it is empty */ +} + +/************************************************************************* + *********************** P A R S E R *********************************** + *************************************************************************/ +parser MainParserImpl( + packet_in pkt, + out headers_t hdr, + inout metadata_t meta, + in pna_main_parser_input_metadata_t istd) +{ + + state start { + pkt.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + P4CALC_ETYPE : check_p4calc; + default : accept; + } + } + + state check_p4calc { + transition select(pkt.lookahead().p, + pkt.lookahead().four, + pkt.lookahead().ver) { + (P4CALC_P, P4CALC_4, P4CALC_VER) : parse_p4calc; + default : accept; + } + } + + state parse_p4calc { + pkt.extract(hdr.p4calc); + transition accept; + } +} + + +/************************************************************************* + ********************** M A I N C O N T R O L ************************ + *************************************************************************/ +control MainControlImpl( + inout headers_t hdr, + inout metadata_t meta, + in pna_main_input_metadata_t istd, + inout pna_main_output_metadata_t ostd) +{ + + action send_back(bit<32> result) { + bit<48> tmp; + + /* Put the result back in */ + hdr.p4calc.res = result; + + /* Swap the MAC addresses */ + tmp = hdr.ethernet.dstAddr; + hdr.ethernet.dstAddr = hdr.ethernet.srcAddr; + hdr.ethernet.srcAddr = tmp; + /* Send the packet back to the port it came from */ + send_to_port(istd.input_port); + } + + action operation_add() { + send_back(hdr.p4calc.operand_a + hdr.p4calc.operand_b); + } + + action operation_sub() { + send_back(hdr.p4calc.operand_a - hdr.p4calc.operand_b); + } + + action operation_and() { + send_back(hdr.p4calc.operand_a & hdr.p4calc.operand_b); + } + + action operation_or() { + send_back(hdr.p4calc.operand_a | hdr.p4calc.operand_b); + } + + action operation_xor() { + send_back(hdr.p4calc.operand_a ^ hdr.p4calc.operand_b); + } + + action operation_drop() { + drop_packet(); + } + + table calculate { + key = { + hdr.p4calc.op : exact @name("op"); + } + actions = { + operation_add; + operation_sub; + operation_and; + operation_or; + operation_xor; + operation_drop; + } + const default_action = operation_drop(); + const entries = { + P4CALC_PLUS : operation_add(); + P4CALC_MINUS: operation_sub(); + P4CALC_AND : operation_and(); + P4CALC_OR : operation_or(); + P4CALC_CARET: operation_xor(); + } + } + + + apply { + if (hdr.p4calc.isValid()) { + calculate.apply(); + } else { + operation_drop(); + } + } +} + + +/************************************************************************* + *********************** D E P A R S E R ******************************* + *************************************************************************/ +control MainDeparserImpl( + packet_out pkt, + in headers_t hdr, + in metadata_t meta, + in pna_main_output_metadata_t ostd) +{ + apply { + pkt.emit(hdr.ethernet); + pkt.emit(hdr.p4calc); + } +} + +/************************************************************************* + ****************************** P N A ********************************** + *************************************************************************/ +PNA_NIC( + MainParserImpl(), + MainControlImpl(), + MainDeparserImpl() + ) main; \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/calculator.json b/testdata/p4tc_samples_outputs/calculator.json new file mode 100644 index 00000000000..b0a1e3ab115 --- /dev/null +++ b/testdata/p4tc_samples_outputs/calculator.json @@ -0,0 +1,79 @@ +{ + "schema_version" : "1.0.0", + "pipeline_name" : "calculator", + "id" : 1, + "tables" : [ + { + "name" : "MainControlImpl/calculate", + "id" : 1, + "tentries" : 2048, + "nummask" : 8, + "keysize" : 8, + "keyfields" : [ + { + "id" : 1, + "name" : "op", + "type" : "bit8", + "match_type" : "exact", + "bitwidth" : 8 + } + ], + "actions" : [ + { + "id" : 1, + "name" : "MainControlImpl/operation_add", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 2, + "name" : "MainControlImpl/operation_sub", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 3, + "name" : "MainControlImpl/operation_and", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 4, + "name" : "MainControlImpl/operation_or", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 5, + "name" : "MainControlImpl/operation_xor", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 6, + "name" : "MainControlImpl/operation_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/calculator.p4-stderr b/testdata/p4tc_samples_outputs/calculator.p4-stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4tc_samples_outputs/calculator.template b/testdata/p4tc_samples_outputs/calculator.template new file mode 100755 index 00000000000..91b48c0cadc --- /dev/null +++ b/testdata/p4tc_samples_outputs/calculator.template @@ -0,0 +1,42 @@ +#!/bin/bash -x + +set -e + +TC="tc" +$TC p4template create pipeline/calculator pipeid 1 numtables 1 + +$TC p4template create action/calculator/MainControlImpl/operation_add actid 1 +$TC p4template update action/calculator/MainControlImpl/operation_add state active + +$TC p4template create action/calculator/MainControlImpl/operation_sub actid 2 +$TC p4template update action/calculator/MainControlImpl/operation_sub state active + +$TC p4template create action/calculator/MainControlImpl/operation_and actid 3 +$TC p4template update action/calculator/MainControlImpl/operation_and state active + +$TC p4template create action/calculator/MainControlImpl/operation_or actid 4 +$TC p4template update action/calculator/MainControlImpl/operation_or state active + +$TC p4template create action/calculator/MainControlImpl/operation_xor actid 5 +$TC p4template update action/calculator/MainControlImpl/operation_xor state active + +$TC p4template create action/calculator/MainControlImpl/operation_drop actid 6 +$TC p4template update action/calculator/MainControlImpl/operation_drop state active + +$TC p4template create table/calculator/MainControlImpl/calculate \ + tblid 1 \ + type exact \ + keysz 8 nummasks 8 tentries 2048 \ + table_acts act name calculator/MainControlImpl/operation_add \ + act name calculator/MainControlImpl/operation_sub \ + act name calculator/MainControlImpl/operation_and \ + act name calculator/MainControlImpl/operation_or \ + act name calculator/MainControlImpl/operation_xor \ + act name calculator/MainControlImpl/operation_drop +$TC p4template update table/calculator/MainControlImpl/calculate default_miss_action permissions 0x1024 action calculator/MainControlImpl/operation_drop +$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x2b action calculator/MainControlImpl/operation_add +$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x2d action calculator/MainControlImpl/operation_sub +$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x26 action calculator/MainControlImpl/operation_and +$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x7c action calculator/MainControlImpl/operation_or +$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x5e action calculator/MainControlImpl/operation_xor +$TC p4template update pipeline/calculator state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/calculator_control_blocks.c b/testdata/p4tc_samples_outputs/calculator_control_blocks.c new file mode 100644 index 00000000000..035ccea9544 --- /dev/null +++ b/testdata/p4tc_samples_outputs/calculator_control_blocks.c @@ -0,0 +1,355 @@ + +#include "calculator_parser.h" +#include +#include +#include "pna.h" +struct internal_metadata { + __u16 pkt_ether_type; +} __attribute__((aligned(4))); + + +struct __attribute__((__packed__)) MainControlImpl_calculate_key { + u32 keysz; + u32 maskid; + u8 field0; /* hdr.p4calc.op */ +} __attribute__((aligned(4))); +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_ADD 1 +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_SUB 2 +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_AND 3 +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_OR 4 +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_XOR 5 +#define MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_DROP 6 +struct __attribute__((__packed__)) MainControlImpl_calculate_value { + unsigned int action; + union { + struct { + } _NoAction; + struct { + } MainControlImpl_operation_add; + struct { + } MainControlImpl_operation_sub; + struct { + } MainControlImpl_operation_and; + struct { + } MainControlImpl_operation_or; + struct { + } MainControlImpl_operation_xor; + struct { + } MainControlImpl_operation_drop; + } u; +}; + +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() + +SEC("xdp/xdp-ingress") +int xdp_func(struct xdp_md *skb) { + void *data_end = (void *)(long)skb->data_end; + struct ethhdr *eth = (struct ethhdr *)(long)skb->data; + if ((void *)((struct ethhdr *) eth + 1) > data_end) { + return XDP_ABORTED; + } + if (eth->h_proto == bpf_htons(0x0800) || eth->h_proto == bpf_htons(0x86DD)) { + return XDP_PASS; + } + + struct internal_metadata *meta; + int ret = bpf_xdp_adjust_meta(skb, -(int)sizeof(*meta)); + if (ret < 0) { + return XDP_ABORTED; + } + meta = (struct internal_metadata *)(unsigned long)skb->data_meta; + eth = (void *)(long)skb->data; + data_end = (void *)(long)skb->data_end; + if ((void *) ((struct internal_metadata *) meta + 1) > (void *)(long)skb->data) + return XDP_ABORTED; + if ((void *)((struct ethhdr *) eth + 1) > data_end) { + return XDP_ABORTED; + } + meta->pkt_ether_type = eth->h_proto; + eth->h_proto = bpf_htons(0x0800); + + return XDP_PASS; +} +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + 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 metadata_t *meta; + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); +{ + u8 hit; + u64 tmp_5 = 0; + { +if (/* hdr->p4calc.isValid() */ + hdr->p4calc.ebpf_valid) { +/* calculate_0.apply() */ + { + /* construct key */ + struct p4tc_table_entry_act_bpf_params__local params = { + .pipeid = 1, + .tblid = 1 + }; + struct MainControlImpl_calculate_key key = {}; + key.keysz = 8; + key.field0 = hdr->p4calc.op; + struct p4tc_table_entry_act_bpf *act_bpf; + /* value */ + struct MainControlImpl_calculate_value *value = NULL; + /* perform lookup */ + act_bpf = bpf_p4tc_tbl_read(skb, ¶ms, &key, sizeof(key)); + value = (struct MainControlImpl_calculate_value *)act_bpf; + if (value == NULL) { + /* miss; find default action */ + hit = 0; + } else { + hit = 1; + } + if (value != NULL) { + /* run action */ + switch (value->action) { + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_ADD: + { + hdr->p4calc.res = (hdr->p4calc.operand_a + hdr->p4calc.operand_b); + tmp_5 = hdr->ethernet.dstAddr; + hdr->ethernet.dstAddr = hdr->ethernet.srcAddr; + hdr->ethernet.srcAddr = tmp_5; + /* send_to_port(istd.input_port) */ + compiler_meta__->drop = false; + send_to_port(skb->ifindex); + } + break; + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_SUB: + { + hdr->p4calc.res = (hdr->p4calc.operand_a - hdr->p4calc.operand_b); + tmp_5 = hdr->ethernet.dstAddr; + hdr->ethernet.dstAddr = hdr->ethernet.srcAddr; + hdr->ethernet.srcAddr = tmp_5; + /* send_to_port(istd.input_port) */ + compiler_meta__->drop = false; + send_to_port(skb->ifindex); + } + break; + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_AND: + { + hdr->p4calc.res = (hdr->p4calc.operand_a & hdr->p4calc.operand_b); + tmp_5 = hdr->ethernet.dstAddr; + hdr->ethernet.dstAddr = hdr->ethernet.srcAddr; + hdr->ethernet.srcAddr = tmp_5; + /* send_to_port(istd.input_port) */ + compiler_meta__->drop = false; + send_to_port(skb->ifindex); + } + break; + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_OR: + { + hdr->p4calc.res = (hdr->p4calc.operand_a | hdr->p4calc.operand_b); + tmp_5 = hdr->ethernet.dstAddr; + hdr->ethernet.dstAddr = hdr->ethernet.srcAddr; + hdr->ethernet.srcAddr = tmp_5; + /* send_to_port(istd.input_port) */ + compiler_meta__->drop = false; + send_to_port(skb->ifindex); + } + break; + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_XOR: + { + hdr->p4calc.res = (hdr->p4calc.operand_a ^ hdr->p4calc.operand_b); + tmp_5 = hdr->ethernet.dstAddr; + hdr->ethernet.dstAddr = hdr->ethernet.srcAddr; + hdr->ethernet.srcAddr = tmp_5; + /* send_to_port(istd.input_port) */ + compiler_meta__->drop = false; + send_to_port(skb->ifindex); + } + break; + case MAINCONTROLIMPL_CALCULATE_ACT_MAINCONTROLIMPL_OPERATION_DROP: + { +/* drop_packet() */ + drop_packet(); + } + break; + default: + return TC_ACT_SHOT; + } + } else { + return TC_ACT_SHOT; +; + } + } +; } + + else { +/* operation_drop_1() */ +{ +/* drop_packet() */ + drop_packet(); + }; } + + } + } + { +{ +; + ; + } + + if (compiler_meta__->drop) { + return TC_ACT_SHOT; + } + int outHeaderLength = 0; + if (hdr->ethernet.ebpf_valid) { + outHeaderLength += 112; + } +; if (hdr->p4calc.ebpf_valid) { + outHeaderLength += 128; + } +; 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; + } + + hdr->ethernet.dstAddr = htonll(hdr->ethernet.dstAddr << 16); + 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; + + hdr->ethernet.srcAddr = htonll(hdr->ethernet.srcAddr << 16); + 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->p4calc.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 128)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->p4calc.p))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->p4calc.four))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->p4calc.ver))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->p4calc.op))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->p4calc.operand_a = htonl(hdr->p4calc.operand_a); + ebpf_byte = ((char*)(&hdr->p4calc.operand_a))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_a))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_a))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_a))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + hdr->p4calc.operand_b = htonl(hdr->p4calc.operand_b); + ebpf_byte = ((char*)(&hdr->p4calc.operand_b))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_b))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_b))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.operand_b))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + hdr->p4calc.res = htonl(hdr->p4calc.res); + ebpf_byte = ((char*)(&hdr->p4calc.res))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.res))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.res))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->p4calc.res))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + } +; + } + return -1; +} +SEC("classifier/tc-ingress") +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; + 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 headers_t *hdr; + int ret = -1; + ret = process(skb, (struct 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/calculator_parser.c b/testdata/p4tc_samples_outputs/calculator_parser.c new file mode 100644 index 00000000000..7e65e44e7c0 --- /dev/null +++ b/testdata/p4tc_samples_outputs/calculator_parser.c @@ -0,0 +1,227 @@ + +#include "calculator_parser.h" +#include +#include +#include "pna.h" + +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 int run_parser(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + unsigned ebpf_packetOffsetInBits = 0; + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + 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 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)); + + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); + { + struct p4calc_t tmp_0; + struct p4calc_t tmp_2; + struct p4calc_t tmp_4; + goto start; + check_p4calc: { + { + ebpf_packetOffsetInBits_save = ebpf_packetOffsetInBits; + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 128 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + tmp_0.p = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_0.four = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_0.ver = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_0.op = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_0.operand_a = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_0.operand_b = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_0.res = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_0.ebpf_valid = 1; + + ebpf_packetOffsetInBits = ebpf_packetOffsetInBits_save; + } + { + ebpf_packetOffsetInBits_save = ebpf_packetOffsetInBits; + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 128 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + tmp_2.p = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_2.four = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_2.ver = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_2.op = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_2.operand_a = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_2.operand_b = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_2.res = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_2.ebpf_valid = 1; + + ebpf_packetOffsetInBits = ebpf_packetOffsetInBits_save; + } + { + ebpf_packetOffsetInBits_save = ebpf_packetOffsetInBits; + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 128 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + tmp_4.p = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_4.four = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_4.ver = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_4.op = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + tmp_4.operand_a = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_4.operand_b = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_4.res = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + tmp_4.ebpf_valid = 1; + + ebpf_packetOffsetInBits = ebpf_packetOffsetInBits_save; + } + u32 select_0; + select_0 = (((((u32)(((u16)tmp_0.p << 8) | ((u16)tmp_2.four & 0xff)) << 8) & ((1 << 24) - 1)) | (((u32)tmp_4.ver & 0xff) & ((1 << 24) - 1))) & ((1 << 24) - 1)); + if (select_0 == 0x503401)goto parse_p4calc; + if ((select_0 & 0x0) == (0x0 & 0x0))goto accept; + else goto reject; + } + parse_p4calc: { +/* extract(hdr->p4calc) */ + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 128 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + hdr->p4calc.p = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->p4calc.four = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->p4calc.ver = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->p4calc.op = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->p4calc.operand_a = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->p4calc.operand_b = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->p4calc.res = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->p4calc.ebpf_valid = 1; + +; + goto accept; + } + start: { +/* extract(hdr->ethernet) */ + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 112 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + hdr->ethernet.dstAddr = (u64)((load_dword(pkt, BYTES(ebpf_packetOffsetInBits)) >> 16) & EBPF_MASK(u64, 48)); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.srcAddr = (u64)((load_dword(pkt, BYTES(ebpf_packetOffsetInBits)) >> 16) & EBPF_MASK(u64, 48)); + ebpf_packetOffsetInBits += 48; + + hdr->ethernet.etherType = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ethernet.ebpf_valid = 1; + +; + u16 select_1; + select_1 = hdr->ethernet.etherType; + if (select_1 == 0x1234)goto check_p4calc; + if ((select_1 & 0x0) == (0x0 & 0x0))goto accept; + else goto reject; + } + + reject: { + if (ebpf_errorCode == 0) { + return TC_ACT_SHOT; + } + goto accept; + } + + } + + accept: + hdrMd->ebpf_packetOffsetInBits = ebpf_packetOffsetInBits; + return -1; +} + +SEC("classifier/tc-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 headers_t *hdr; + int ret = -1; + ret = run_parser(skb, (struct 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/calculator_parser.h b/testdata/p4tc_samples_outputs/calculator_parser.h new file mode 100644 index 00000000000..92885802f1f --- /dev/null +++ b/testdata/p4tc_samples_outputs/calculator_parser.h @@ -0,0 +1,39 @@ +#include "ebpf_kernel.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 p4calc_t { + u8 p; /* bit<8> */ + u8 four; /* bit<8> */ + u8 ver; /* bit<8> */ + u8 op; /* bit<8> */ + u32 operand_a; /* bit<32> */ + u32 operand_b; /* bit<32> */ + u32 res; /* bit<32> */ + u8 ebpf_valid; +}; +struct headers_t { + struct ethernet_t ethernet; /* ethernet_t */ + struct p4calc_t p4calc; /* p4calc_t */ +}; +struct metadata_t { +}; +struct hdr_md { + struct headers_t cpumap_hdr; + struct metadata_t cpumap_usermeta; + unsigned ebpf_packetOffsetInBits; + __u8 __hook; +}; + diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template index ebb74f4ca5f..cbd2642dcb8 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template @@ -84,4 +84,9 @@ $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_o act name multiple_tables_example_01/MainControlImpl/sendtoport \ act name multiple_tables_example_01/MainControlImpl/drop $TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_01/MainControlImpl/drop +$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x1000hdr.tcp.srcPort 16w0x10hdr.ipv4.fragOffset 13w10hdr.ipv4.flags 3w1 action multiple_tables_example_01/MainControlImpl/tcp_syn_packet +$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x2000hdr.tcp.srcPort 16w0x20hdr.ipv4.fragOffset 13w20hdr.ipv4.flags 3w2 action multiple_tables_example_01/MainControlImpl/tcp_fin_or_rst_packet +$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x4000hdr.tcp.srcPort 16w0x40hdr.ipv4.fragOffset 13w40hdr.ipv4.flags 3w4 action multiple_tables_example_01/MainControlImpl/default_route_drop +$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x5000hdr.tcp.srcPort 16w0x50hdr.ipv4.fragOffset 13w50hdr.ipv4.flags 3w5 action multiple_tables_example_01/MainControlImpl/next_hop +$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x6000hdr.tcp.srcPort 16w0x60hdr.ipv4.fragOffset 13w60hdr.ipv4.flags 3w6 action multiple_tables_example_01/MainControlImpl/sendtoport $TC p4template update pipeline/multiple_tables_example_01 state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template index b54e9f06805..22f70044361 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template @@ -83,4 +83,9 @@ $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_o act name multiple_tables_example_02/MainControlImpl/sendtoport \ act name multiple_tables_example_02/MainControlImpl/drop $TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_02/MainControlImpl/drop +$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x1000hdr.tcp.srcPort 16w0x10hdr.ipv4.fragOffset 13w10hdr.ipv4.flags 3w1 action multiple_tables_example_02/MainControlImpl/tcp_syn_packet +$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x2000hdr.tcp.srcPort 16w0x20hdr.ipv4.fragOffset 13w20hdr.ipv4.flags 3w2 action multiple_tables_example_02/MainControlImpl/tcp_fin_or_rst_packet +$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x4000hdr.tcp.srcPort 16w0x40hdr.ipv4.fragOffset 13w40hdr.ipv4.flags 3w4 action multiple_tables_example_02/MainControlImpl/default_route_drop +$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x5000hdr.tcp.srcPort 16w0x50hdr.ipv4.fragOffset 13w50hdr.ipv4.flags 3w5 action multiple_tables_example_02/MainControlImpl/next_hop +$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x6000hdr.tcp.srcPort 16w0x60hdr.ipv4.fragOffset 13w60hdr.ipv4.flags 3w6 action multiple_tables_example_02/MainControlImpl/sendtoport $TC p4template update pipeline/multiple_tables_example_02 state ready \ No newline at end of file From 6dbf4678f6f26dcc9ba22ed79a2e591a411cfa66 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Thu, 11 Jan 2024 02:10:27 -0800 Subject: [PATCH 3/7] Update testcase --- backends/tc/backend.cpp | 8 ------- .../calculator_control_blocks.c | 23 +++++++++++-------- .../p4tc_samples_outputs/calculator_parser.c | 7 ++---- .../p4tc_samples_outputs/calculator_parser.h | 4 ++++ 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 4a9c87233d9..35597f3934c 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -296,14 +296,6 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t } } auto keySetElement = keyset->components.at(itr); - // std::stringstream value; - // if(keySetElement->is()) { - // value << keySetElement->to()->value; - // } else if (keySetElement->is()) { - // value << keySetElement->to()->value ? 1 : 0; - // } else if (keySetElement->is()) { - // value << 0; - // } keyList.emplace(keyString, keySetElement->toString()); } tabledef->addConstEntries(e->action->toString(), keyList); diff --git a/testdata/p4tc_samples_outputs/calculator_control_blocks.c b/testdata/p4tc_samples_outputs/calculator_control_blocks.c index 035ccea9544..657f2ab4cff 100644 --- a/testdata/p4tc_samples_outputs/calculator_control_blocks.c +++ b/testdata/p4tc_samples_outputs/calculator_control_blocks.c @@ -1,13 +1,8 @@ - #include "calculator_parser.h" -#include -#include -#include "pna.h" struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); - struct __attribute__((__packed__)) MainControlImpl_calculate_key { u32 keysz; u32 maskid; @@ -76,7 +71,7 @@ int xdp_func(struct xdp_md *skb) { static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) { struct hdr_md *hdrMd; - unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + unsigned ebpf_packetOffsetInBits_save = 0; ParserError_t ebpf_errorCode = NoError; void* pkt = ((void*)(long)skb->data); @@ -90,6 +85,7 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); if (!hdrMd) return TC_ACT_SHOT; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; hdr = &(hdrMd->cpumap_hdr); meta = &(hdrMd->cpumap_usermeta); { @@ -188,8 +184,8 @@ if (/* hdr->p4calc.isValid() */ return TC_ACT_SHOT; } } else { - return TC_ACT_SHOT; -; +/* drop_packet() */ + drop_packet(); } } ; } @@ -219,7 +215,16 @@ if (/* hdr->p4calc.isValid() */ ; if (hdr->p4calc.ebpf_valid) { outHeaderLength += 128; } -; pkt = ((void*)(long)skb->data); +; + int outHeaderOffset = BYTES(outHeaderLength) - BYTES(ebpf_packetOffsetInBits); + 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) { diff --git a/testdata/p4tc_samples_outputs/calculator_parser.c b/testdata/p4tc_samples_outputs/calculator_parser.c index 7e65e44e7c0..216e3157af5 100644 --- a/testdata/p4tc_samples_outputs/calculator_parser.c +++ b/testdata/p4tc_samples_outputs/calculator_parser.c @@ -1,8 +1,4 @@ - #include "calculator_parser.h" -#include -#include -#include "pna.h" REGISTER_START() REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2) @@ -12,7 +8,7 @@ REGISTER_END() static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) { struct hdr_md *hdrMd; - unsigned ebpf_packetOffsetInBits = 0; + unsigned ebpf_packetOffsetInBits_save = 0; ParserError_t ebpf_errorCode = NoError; void* pkt = ((void*)(long)skb->data); @@ -29,6 +25,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h return TC_ACT_SHOT; __builtin_memset(hdrMd, 0, sizeof(struct hdr_md)); + unsigned ebpf_packetOffsetInBits = 0; hdr = &(hdrMd->cpumap_hdr); meta = &(hdrMd->cpumap_usermeta); { diff --git a/testdata/p4tc_samples_outputs/calculator_parser.h b/testdata/p4tc_samples_outputs/calculator_parser.h index 92885802f1f..9adb56182d0 100644 --- a/testdata/p4tc_samples_outputs/calculator_parser.h +++ b/testdata/p4tc_samples_outputs/calculator_parser.h @@ -1,5 +1,8 @@ #include "ebpf_kernel.h" +#include +#include +#include "pna.h" #define EBPF_MASK(t, w) ((((t)(1)) << (w)) - (t)1) #define BYTES(w) ((w) / 8) @@ -30,6 +33,7 @@ struct headers_t { }; struct metadata_t { }; + struct hdr_md { struct headers_t cpumap_hdr; struct metadata_t cpumap_usermeta; From 4c0b344405822446e90525c2619a8c9df713c172 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Tue, 16 Jan 2024 23:58:28 -0800 Subject: [PATCH 4/7] Address new changes --- backends/tc/backend.cpp | 18 +++++++++++++++++- backends/tc/backend.h | 1 + backends/tc/tc.def | 7 ++++--- lib/stringify.h | 1 + .../p4tc_samples_outputs/calculator.template | 10 +++++----- .../multiple_tables_example_01.template | 10 +++++----- .../multiple_tables_example_02.template | 10 +++++----- 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 35597f3934c..075bf6c7a24 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -296,7 +296,23 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t } } auto keySetElement = keyset->components.at(itr); - keyList.emplace(keyString, keySetElement->toString()); + auto key = keySetElement->toString(); + if (keySetElement->is()) { + key = "default"; + } else if (keySetElement->is()) { + big_int kValue = keySetElement->to()->value; + int kBase = keySetElement->to()->base; + std::stringstream value; + std::deque buf; + do { + const int digit = static_cast(static_cast(kValue % kBase)); + kValue = kValue / kBase; + buf.push_front(Util::DigitToChar(digit)); + } while (kValue > 0); + for (auto ch : buf) value << ch; + key = value.str().c_str(); + } + keyList.emplace(keyString, key); } tabledef->addConstEntries(e->action->toString(), keyList); } diff --git a/backends/tc/backend.h b/backends/tc/backend.h index debf256f75b..5d28cf01d9c 100644 --- a/backends/tc/backend.h +++ b/backends/tc/backend.h @@ -26,6 +26,7 @@ and limitations under the License. #include "ir/ir.h" #include "lib/error.h" #include "lib/nullstream.h" +#include "lib/stringify.h" #include "options.h" #include "pnaProgramStructure.h" #include "tcAnnotations.h" diff --git a/backends/tc/tc.def b/backends/tc/tc.def index c6e0fb4893f..831c19c2a6b 100644 --- a/backends/tc/tc.def +++ b/backends/tc/tc.def @@ -294,14 +294,15 @@ class TCTable { } if (const_entries.size() != 0) { for (auto entry : const_entries) { - tcTable += "\n$TC p4template update table/" + pipelineName + tcTable += "\n$TC p4template create table/" + pipelineName + "/" + controlName + "/" + tableName - + " entry "; + + " entry"; for(auto k : entry.second) { - tcTable += k.first + " " + k.second; + tcTable += " " + k.first + " " + k.second; } tcTable += " action " + pipelineName + "/" + controlName + "/" + entry.first; + tcTable += " permissions 0x1024"; } } return tcTable; diff --git a/lib/stringify.h b/lib/stringify.h index 82c1e65c73b..04bff19611c 100644 --- a/lib/stringify.h +++ b/lib/stringify.h @@ -83,5 +83,6 @@ cstring toString(const void *value); cstring printf_format(const char *fmt_str, ...); // vprintf into a string cstring vprintf_format(const char *fmt_str, va_list ap); +char DigitToChar(int digit); } // namespace Util #endif /* LIB_STRINGIFY_H_ */ diff --git a/testdata/p4tc_samples_outputs/calculator.template b/testdata/p4tc_samples_outputs/calculator.template index 91b48c0cadc..b9ec986fffa 100755 --- a/testdata/p4tc_samples_outputs/calculator.template +++ b/testdata/p4tc_samples_outputs/calculator.template @@ -34,9 +34,9 @@ $TC p4template create table/calculator/MainControlImpl/calculate \ act name calculator/MainControlImpl/operation_xor \ act name calculator/MainControlImpl/operation_drop $TC p4template update table/calculator/MainControlImpl/calculate default_miss_action permissions 0x1024 action calculator/MainControlImpl/operation_drop -$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x2b action calculator/MainControlImpl/operation_add -$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x2d action calculator/MainControlImpl/operation_sub -$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x26 action calculator/MainControlImpl/operation_and -$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x7c action calculator/MainControlImpl/operation_or -$TC p4template update table/calculator/MainControlImpl/calculate entry op 8w0x5e action calculator/MainControlImpl/operation_xor +$TC p4template create table/calculator/MainControlImpl/calculate entry op 2b action calculator/MainControlImpl/operation_add permissions 0x1024 +$TC p4template create table/calculator/MainControlImpl/calculate entry op 2d action calculator/MainControlImpl/operation_sub permissions 0x1024 +$TC p4template create table/calculator/MainControlImpl/calculate entry op 26 action calculator/MainControlImpl/operation_and permissions 0x1024 +$TC p4template create table/calculator/MainControlImpl/calculate entry op 7c action calculator/MainControlImpl/operation_or permissions 0x1024 +$TC p4template create table/calculator/MainControlImpl/calculate entry op 5e action calculator/MainControlImpl/operation_xor permissions 0x1024 $TC p4template update pipeline/calculator state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template index cbd2642dcb8..745628f53ba 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template @@ -84,9 +84,9 @@ $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_o act name multiple_tables_example_01/MainControlImpl/sendtoport \ act name multiple_tables_example_01/MainControlImpl/drop $TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_01/MainControlImpl/drop -$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x1000hdr.tcp.srcPort 16w0x10hdr.ipv4.fragOffset 13w10hdr.ipv4.flags 3w1 action multiple_tables_example_01/MainControlImpl/tcp_syn_packet -$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x2000hdr.tcp.srcPort 16w0x20hdr.ipv4.fragOffset 13w20hdr.ipv4.flags 3w2 action multiple_tables_example_01/MainControlImpl/tcp_fin_or_rst_packet -$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x4000hdr.tcp.srcPort 16w0x40hdr.ipv4.fragOffset 13w40hdr.ipv4.flags 3w4 action multiple_tables_example_01/MainControlImpl/default_route_drop -$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x5000hdr.tcp.srcPort 16w0x50hdr.ipv4.fragOffset 13w50hdr.ipv4.flags 3w5 action multiple_tables_example_01/MainControlImpl/next_hop -$TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x6000hdr.tcp.srcPort 16w0x60hdr.ipv4.fragOffset 13w60hdr.ipv4.flags 3w6 action multiple_tables_example_01/MainControlImpl/sendtoport +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 1000 hdr.tcp.srcPort 10 hdr.ipv4.fragOffset 10 hdr.ipv4.flags 1 action multiple_tables_example_01/MainControlImpl/tcp_syn_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 2000 hdr.tcp.srcPort 20 hdr.ipv4.fragOffset 20 hdr.ipv4.flags 2 action multiple_tables_example_01/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 4000 hdr.tcp.srcPort 40 hdr.ipv4.fragOffset 40 hdr.ipv4.flags 4 action multiple_tables_example_01/MainControlImpl/default_route_drop permissions 0x1024 +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 5000 hdr.tcp.srcPort 50 hdr.ipv4.fragOffset 50 hdr.ipv4.flags 5 action multiple_tables_example_01/MainControlImpl/next_hop permissions 0x1024 +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 6000 hdr.tcp.srcPort 60 hdr.ipv4.fragOffset 60 hdr.ipv4.flags 6 action multiple_tables_example_01/MainControlImpl/sendtoport permissions 0x1024 $TC p4template update pipeline/multiple_tables_example_01 state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template index 22f70044361..253f44ec0c9 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template @@ -83,9 +83,9 @@ $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_o act name multiple_tables_example_02/MainControlImpl/sendtoport \ act name multiple_tables_example_02/MainControlImpl/drop $TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_02/MainControlImpl/drop -$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x1000hdr.tcp.srcPort 16w0x10hdr.ipv4.fragOffset 13w10hdr.ipv4.flags 3w1 action multiple_tables_example_02/MainControlImpl/tcp_syn_packet -$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x2000hdr.tcp.srcPort 16w0x20hdr.ipv4.fragOffset 13w20hdr.ipv4.flags 3w2 action multiple_tables_example_02/MainControlImpl/tcp_fin_or_rst_packet -$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x4000hdr.tcp.srcPort 16w0x40hdr.ipv4.fragOffset 13w40hdr.ipv4.flags 3w4 action multiple_tables_example_02/MainControlImpl/default_route_drop -$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x5000hdr.tcp.srcPort 16w0x50hdr.ipv4.fragOffset 13w50hdr.ipv4.flags 3w5 action multiple_tables_example_02/MainControlImpl/next_hop -$TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 32w0x6000hdr.tcp.srcPort 16w0x60hdr.ipv4.fragOffset 13w60hdr.ipv4.flags 3w6 action multiple_tables_example_02/MainControlImpl/sendtoport +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 1000 hdr.tcp.srcPort 10 hdr.ipv4.fragOffset 10 hdr.ipv4.flags 1 action multiple_tables_example_02/MainControlImpl/tcp_syn_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 2000 hdr.tcp.srcPort 20 hdr.ipv4.fragOffset 20 hdr.ipv4.flags 2 action multiple_tables_example_02/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 4000 hdr.tcp.srcPort 40 hdr.ipv4.fragOffset 40 hdr.ipv4.flags 4 action multiple_tables_example_02/MainControlImpl/default_route_drop permissions 0x1024 +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 5000 hdr.tcp.srcPort 50 hdr.ipv4.fragOffset 50 hdr.ipv4.flags 5 action multiple_tables_example_02/MainControlImpl/next_hop permissions 0x1024 +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 6000 hdr.tcp.srcPort 60 hdr.ipv4.fragOffset 60 hdr.ipv4.flags 6 action multiple_tables_example_02/MainControlImpl/sendtoport permissions 0x1024 $TC p4template update pipeline/multiple_tables_example_02 state ready \ No newline at end of file From 142a03e7bb9ed85541728d42815fb8505c759497 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Fri, 19 Jan 2024 03:00:27 -0800 Subject: [PATCH 5/7] Address comments --- backends/tc/backend.cpp | 10 ++++++++++ backends/tc/backend.h | 2 ++ backends/tc/ebpfCodeGen.cpp | 1 - 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 075bf6c7a24..a70a3dd7849 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -311,6 +311,16 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t } while (kValue > 0); for (auto ch : buf) value << ch; key = value.str().c_str(); + } else if (keySetElement->is()) { + auto left = keySetElement->to()->left; + auto right = keySetElement->to()->right; + auto operand = keySetElement->to()->getStringOp(); + key = left->toString() + operand + right->toString(); + } else if (keySetElement->is()) { + auto left = keySetElement->to()->left; + auto right = keySetElement->to()->right; + auto operand = keySetElement->to()->getStringOp(); + key = left->toString() + operand + right->toString(); } keyList.emplace(keyString, key); } diff --git a/backends/tc/backend.h b/backends/tc/backend.h index 5d28cf01d9c..a53935f0b53 100644 --- a/backends/tc/backend.h +++ b/backends/tc/backend.h @@ -17,6 +17,8 @@ and limitations under the License. #ifndef BACKENDS_TC_BACKEND_H_ #define BACKENDS_TC_BACKEND_H_ +#include + #include "backends/ebpf/psa/ebpfPsaGen.h" #include "ebpfCodeGen.h" #include "frontends/p4/evaluator/evaluator.h" diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 8e7ee99f5dd..62be4d1eb21 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -178,7 +178,6 @@ void PNAArchTC::emitParser(EBPF::CodeBuilder *builder) const { builder->newline(); builder->newline(); emitInstances(builder); - // EBPF::EBPFHashAlgorithmTypeFactoryPSA::instance()->emitGlobals(builder); pipeline->name = "tc-parse"; pipeline->sectionName = "classifier/" + pipeline->name; pipeline->functionName = pipeline->name.replace("-", "_") + "_func"; From 323ac8b4f20ad545a9ecfc86a8789d5439cbd3e6 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Mon, 29 Jan 2024 20:00:19 -0800 Subject: [PATCH 6/7] Addressed comments --- backends/tc/backend.cpp | 9 +- testdata/p4tc_samples/calculator.p4 | 2 +- .../p4tc_samples/const_entries_range_mask.p4 | 74 +++++++ .../const_entries_range_mask.json | 50 +++++ .../const_entries_range_mask.p4-stderr | 0 .../const_entries_range_mask.template | 23 +++ .../const_entries_range_mask_control_blocks.c | 180 ++++++++++++++++++ .../const_entries_range_mask_parser.c | 87 +++++++++ .../const_entries_range_mask_parser.h | 34 ++++ 9 files changed, 454 insertions(+), 5 deletions(-) create mode 100644 testdata/p4tc_samples/const_entries_range_mask.p4 create mode 100644 testdata/p4tc_samples_outputs/const_entries_range_mask.json create mode 100644 testdata/p4tc_samples_outputs/const_entries_range_mask.p4-stderr create mode 100755 testdata/p4tc_samples_outputs/const_entries_range_mask.template create mode 100644 testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c create mode 100644 testdata/p4tc_samples_outputs/const_entries_range_mask_parser.c create mode 100644 testdata/p4tc_samples_outputs/const_entries_range_mask_parser.h diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index a70a3dd7849..867fc989c2d 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -276,13 +276,14 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t auto entriesList = t->getEntries(); if (entriesList == nullptr) return; auto keys = t->getKey(); + if (keys == nullptr) { + return; + } for (auto e : entriesList->entries) { - if (keys == nullptr) { - return; - } auto keyset = e->getKeys(); if (keyset->components.size() != keys->keyElements.size()) { - ::error("No of keys in const_entries should be same as no of keys in the table."); + ::error(ErrorType::ERR_INVALID, + "No of keys in const_entries should be same as no of keys in the table."); return; } ordered_map keyList; diff --git a/testdata/p4tc_samples/calculator.p4 b/testdata/p4tc_samples/calculator.p4 index d5312da3c7f..343cb171083 100644 --- a/testdata/p4tc_samples/calculator.p4 +++ b/testdata/p4tc_samples/calculator.p4 @@ -219,7 +219,7 @@ control MainControlImpl( *************************************************************************/ control MainDeparserImpl( packet_out pkt, - in headers_t hdr, + inout headers_t hdr, in metadata_t meta, in pna_main_output_metadata_t ostd) { diff --git a/testdata/p4tc_samples/const_entries_range_mask.p4 b/testdata/p4tc_samples/const_entries_range_mask.p4 new file mode 100644 index 00000000000..64553d9fdd2 --- /dev/null +++ b/testdata/p4tc_samples/const_entries_range_mask.p4 @@ -0,0 +1,74 @@ +#include +#include + +header hdr { + bit<8> e; + bit<16> t; + bit<8> l; + bit<8> r; + bit<8> v; +} + +struct Header_t { + hdr h; +} +struct Meta_t {} + +parser MainParserImpl(packet_in b, out Header_t h, inout Meta_t m, in pna_main_parser_input_metadata_t istd) { + state start { + b.extract(h.h); + transition accept; + } +} + +control MainControlImpl(inout Header_t h, inout Meta_t m, + in pna_main_input_metadata_t istd, + inout pna_main_output_metadata_t ostd) { + + action a() { h.h.e = 0; } + action a_with_control_params(bit<16> x) { h.h.t = x; } + + table t_range { + + key = { + h.h.r : range; + } + + actions = { + a; + a_with_control_params; + } + + default_action = a; + + const entries = { + 1..8 : a_with_control_params(21); + 6..12: a_with_control_params(22); + 15 : a_with_control_params(24); + _ : a_with_control_params(23); + } + } + + apply { + t_range.apply(); + } +} + +/********************* D E P A R S E R ************************/ + +control MainDeparserImpl( + packet_out b, inout Header_t h, in Meta_t m, in pna_main_output_metadata_t ostd) +{ + apply {} +} + +/************ F I N A L P A C K A G E ******************************/ + + +// BEGIN:Package_Instantiation_Example +PNA_NIC( + MainParserImpl(), + MainControlImpl(), + MainDeparserImpl() + ) main; +// END:Package_Instantiation_Example diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask.json b/testdata/p4tc_samples_outputs/const_entries_range_mask.json new file mode 100644 index 00000000000..6ee18aa6c7a --- /dev/null +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask.json @@ -0,0 +1,50 @@ +{ + "schema_version" : "1.0.0", + "pipeline_name" : "const_entries_range_mask", + "id" : 1, + "tables" : [ + { + "name" : "MainControlImpl/t_range", + "id" : 1, + "tentries" : 2048, + "nummask" : 8, + "keysize" : 8, + "keyfields" : [ + { + "id" : 1, + "name" : "h.h.r", + "type" : "bit8", + "match_type" : "range", + "bitwidth" : 8 + } + ], + "actions" : [ + { + "id" : 1, + "name" : "MainControlImpl/a", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : true + }, + { + "id" : 2, + "name" : "MainControlImpl/a_with_control_params", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [ + { + "id" : 1, + "name" : "x", + "type" : "bit16", + "bitwidth" : 16 + } + ], + "default_hit_action" : false, + "default_miss_action" : false + } + ] + } + ] +} \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask.p4-stderr b/testdata/p4tc_samples_outputs/const_entries_range_mask.p4-stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask.template b/testdata/p4tc_samples_outputs/const_entries_range_mask.template new file mode 100755 index 00000000000..9e6f1cb2e4c --- /dev/null +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask.template @@ -0,0 +1,23 @@ +#!/bin/bash -x + +set -e + +TC="tc" +$TC p4template create pipeline/const_entries_range_mask pipeid 1 numtables 1 + +$TC p4template create action/const_entries_range_mask/MainControlImpl/a actid 1 +$TC p4template update action/const_entries_range_mask/MainControlImpl/a state active + +$TC p4template create action/const_entries_range_mask/MainControlImpl/a_with_control_params actid 2 \ + param x type bit16 +$TC p4template update action/const_entries_range_mask/MainControlImpl/a_with_control_params state active + +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range \ + tblid 1 \ + type ternary \ + keysz 8 nummasks 8 tentries 2048 \ + table_acts act name const_entries_range_mask/MainControlImpl/a \ + act name const_entries_range_mask/MainControlImpl/a_with_control_params +$TC p4template update table/const_entries_range_mask/MainControlImpl/t_range default_miss_action action const_entries_range_mask/MainControlImpl/a +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 8w1..8w8 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 +$TC p4template update pipeline/const_entries_range_mask state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c b/testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c new file mode 100644 index 00000000000..21e7fdd4c0e --- /dev/null +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c @@ -0,0 +1,180 @@ +#include "const_entries_range_mask_parser.h" +struct internal_metadata { + __u16 pkt_ether_type; +} __attribute__((aligned(4))); + +struct __attribute__((__packed__)) MainControlImpl_t_range_key { + u32 keysz; + u32 maskid; + u8 field0; /* h.h.r */ +} __attribute__((aligned(4))); +#define MAINCONTROLIMPL_T_RANGE_ACT_MAINCONTROLIMPL_A 1 +#define MAINCONTROLIMPL_T_RANGE_ACT_MAINCONTROLIMPL_A_WITH_CONTROL_PARAMS 2 +struct __attribute__((__packed__)) MainControlImpl_t_range_value { + unsigned int action; + union { + struct { + } _NoAction; + struct { + } MainControlImpl_a; + struct __attribute__((__packed__)) { + u16 x; + } MainControlImpl_a_with_control_params; + } u; +}; + +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() + +SEC("xdp/xdp-ingress") +int xdp_func(struct xdp_md *skb) { + void *data_end = (void *)(long)skb->data_end; + struct ethhdr *eth = (struct ethhdr *)(long)skb->data; + if ((void *)((struct ethhdr *) eth + 1) > data_end) { + return XDP_ABORTED; + } + if (eth->h_proto == bpf_htons(0x0800) || eth->h_proto == bpf_htons(0x86DD)) { + return XDP_PASS; + } + + struct internal_metadata *meta; + int ret = bpf_xdp_adjust_meta(skb, -(int)sizeof(*meta)); + if (ret < 0) { + return XDP_ABORTED; + } + meta = (struct internal_metadata *)(unsigned long)skb->data_meta; + eth = (void *)(long)skb->data; + data_end = (void *)(long)skb->data_end; + if ((void *) ((struct internal_metadata *) meta + 1) > (void *)(long)skb->data) + return XDP_ABORTED; + if ((void *)((struct ethhdr *) eth + 1) > data_end) { + return XDP_ABORTED; + } + meta->pkt_ether_type = eth->h_proto; + eth->h_proto = bpf_htons(0x0800); + + return XDP_PASS; +} +static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, 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); + 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 Meta_t *m; + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + h = &(hdrMd->cpumap_hdr); + m = &(hdrMd->cpumap_usermeta); +{ + u8 hit; + { +/* t_range_0.apply() */ + { + /* construct key */ + struct p4tc_table_entry_act_bpf_params__local params = { + .pipeid = 1, + .tblid = 1 + }; + struct MainControlImpl_t_range_key key = {}; + key.keysz = 8; + key.field0 = h->h.r; + struct p4tc_table_entry_act_bpf *act_bpf; + /* value */ + struct MainControlImpl_t_range_value *value = NULL; + /* perform lookup */ + act_bpf = bpf_p4tc_tbl_read(skb, ¶ms, &key, sizeof(key)); + value = (struct MainControlImpl_t_range_value *)act_bpf; + if (value == NULL) { + /* miss; find default action */ + hit = 0; + } else { + hit = 1; + } + if (value != NULL) { + /* run action */ + switch (value->action) { + case MAINCONTROLIMPL_T_RANGE_ACT_MAINCONTROLIMPL_A: + { + h->h.e = 0; + } + break; + case MAINCONTROLIMPL_T_RANGE_ACT_MAINCONTROLIMPL_A_WITH_CONTROL_PARAMS: + { + h->h.t = value->u.MainControlImpl_a_with_control_params.x; + } + break; + default: + return TC_ACT_SHOT; + } + } else { + h->h.e = 0; + } + } +; + } + } + { +{ + } + + if (compiler_meta__->drop) { + return TC_ACT_SHOT; + } + int outHeaderLength = 0; + + int outHeaderOffset = BYTES(outHeaderLength) - BYTES(ebpf_packetOffsetInBits); + 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; + + } + return -1; +} +SEC("classifier/tc-ingress") +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; + 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 Header_t *h; + int ret = -1; + ret = process(skb, (struct Header_t *) h, 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/const_entries_range_mask_parser.c b/testdata/p4tc_samples_outputs/const_entries_range_mask_parser.c new file mode 100644 index 00000000000..dcf14bb85aa --- /dev/null +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask_parser.c @@ -0,0 +1,87 @@ +#include "const_entries_range_mask_parser.h" + +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 int run_parser(struct __sk_buff *skb, struct Header_t *h, 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); + 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 Meta_t *m; + + 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; + h = &(hdrMd->cpumap_hdr); + m = &(hdrMd->cpumap_usermeta); + { + goto start; + start: { +/* extract(h->h) */ + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 48 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + h->h.e = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + h->h.t = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + h->h.l = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + h->h.r = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + h->h.v = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + h->h.ebpf_valid = 1; + +; + goto accept; + } + + reject: { + if (ebpf_errorCode == 0) { + return TC_ACT_SHOT; + } + goto accept; + } + + } + + accept: + hdrMd->ebpf_packetOffsetInBits = ebpf_packetOffsetInBits; + return -1; +} + +SEC("classifier/tc-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 Header_t *h; + int ret = -1; + ret = run_parser(skb, (struct Header_t *) h, compiler_meta__); + if (ret != -1) { + return ret; + } + return TC_ACT_PIPE; + } +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask_parser.h b/testdata/p4tc_samples_outputs/const_entries_range_mask_parser.h new file mode 100644 index 00000000000..a3e52c33622 --- /dev/null +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask_parser.h @@ -0,0 +1,34 @@ +#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 hdr { + u8 e; /* bit<8> */ + u16 t; /* bit<16> */ + u8 l; /* bit<8> */ + u8 r; /* bit<8> */ + u8 v; /* bit<8> */ + u8 ebpf_valid; +}; +struct Header_t { + struct hdr h; /* hdr */ +}; +struct Meta_t { +}; + +struct hdr_md { + struct Header_t cpumap_hdr; + struct Meta_t cpumap_usermeta; + unsigned ebpf_packetOffsetInBits; + __u8 __hook; +}; + From 5a8db7fe44338d58a3c1a29e4d5289fa55d4f0e3 Mon Sep 17 00:00:00 2001 From: "Jain, Komal" Date: Mon, 29 Jan 2024 21:50:53 -0800 Subject: [PATCH 7/7] Fix issue when all entries are not emitted in case of multiple entry with same action --- backends/tc/backend.cpp | 3 +- backends/tc/tc.def | 32 +++++++++++++------ .../p4tc_samples/const_entries_range_mask.p4 | 7 ++-- .../const_entries_range_mask.template | 4 +++ .../multiple_tables_example_01.template | 1 + .../multiple_tables_example_02.template | 1 + 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 867fc989c2d..17697e9e062 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -325,7 +325,8 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t } keyList.emplace(keyString, key); } - tabledef->addConstEntries(e->action->toString(), keyList); + IR::TCEntry *constEntry = new IR::TCEntry(e->action->toString(), keyList); + tabledef->addConstEntries(constEntry); } } diff --git a/backends/tc/tc.def b/backends/tc/tc.def index 831c19c2a6b..460f1368d99 100644 --- a/backends/tc/tc.def +++ b/backends/tc/tc.def @@ -151,6 +151,22 @@ class TCAction { dbprint { out << toString(); } } +class TCEntry { + cstring action; + ordered_map keys; + cstring getActionName() const { + return action; + } + toString { + std::string tcEntry = ""; + for(auto k : keys) { + tcEntry += " " + k.first + " " + k.second; + } + return tcEntry; + } + dbprint { out << toString(); } +} + class TCTable { unsigned tableID; cstring tableName; @@ -167,7 +183,8 @@ class TCTable { TCAction defaultMissAction; bool isDefaultMissConst; ordered_map actionList; - ordered_map> const_entries; + safe_vector const_entries; + void setKeySize(unsigned k) { keySize = k; } @@ -201,8 +218,8 @@ class TCTable { void addAction(TCAction action, unsigned flag) { actionList.emplace(action, flag); } - void addConstEntries(cstring action, ordered_map keys) { - const_entries.emplace(action, keys); + void addConstEntries(TCEntry entry) { + const_entries.push_back(entry); } cstring printMatchType(unsigned matchType) const { cstring matchTypeString = ""; @@ -295,13 +312,10 @@ class TCTable { if (const_entries.size() != 0) { for (auto entry : const_entries) { tcTable += "\n$TC p4template create table/" + pipelineName - + "/" + controlName + "/" + tableName - + " entry"; - for(auto k : entry.second) { - tcTable += " " + k.first + " " + k.second; - } + + "/" + controlName + "/" + tableName + + " entry" + entry->toString(); tcTable += " action " + pipelineName - + "/" + controlName + "/" + entry.first; + + "/" + controlName + "/" + entry->getActionName(); tcTable += " permissions 0x1024"; } } diff --git a/testdata/p4tc_samples/const_entries_range_mask.p4 b/testdata/p4tc_samples/const_entries_range_mask.p4 index 64553d9fdd2..2d9ba45eae1 100644 --- a/testdata/p4tc_samples/const_entries_range_mask.p4 +++ b/testdata/p4tc_samples/const_entries_range_mask.p4 @@ -42,10 +42,11 @@ control MainControlImpl(inout Header_t h, inout Meta_t m, default_action = a; const entries = { - 1..8 : a_with_control_params(21); - 6..12: a_with_control_params(22); + 1 : a_with_control_params(21); + 6: a_with_control_params(22); 15 : a_with_control_params(24); - _ : a_with_control_params(23); + 1..8 : a_with_control_params(23); + 1 &&& 2 : a_with_control_params(26); } } diff --git a/testdata/p4tc_samples_outputs/const_entries_range_mask.template b/testdata/p4tc_samples_outputs/const_entries_range_mask.template index 9e6f1cb2e4c..ed9e47ce535 100755 --- a/testdata/p4tc_samples_outputs/const_entries_range_mask.template +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask.template @@ -19,5 +19,9 @@ $TC p4template create table/const_entries_range_mask/MainControlImpl/t_range \ table_acts act name const_entries_range_mask/MainControlImpl/a \ act name const_entries_range_mask/MainControlImpl/a_with_control_params $TC p4template update table/const_entries_range_mask/MainControlImpl/t_range default_miss_action action const_entries_range_mask/MainControlImpl/a +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 1 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 6 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 15 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 $TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 8w1..8w8 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 +$TC p4template create table/const_entries_range_mask/MainControlImpl/t_range entry h.h.r 8w1&&&8w2 action const_entries_range_mask/MainControlImpl/a_with_control_params permissions 0x1024 $TC p4template update pipeline/const_entries_range_mask state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template index 745628f53ba..1ad95743ff4 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_01.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_01.template @@ -86,6 +86,7 @@ $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_o $TC p4template update table/multiple_tables_example_01/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_01/MainControlImpl/drop $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 1000 hdr.tcp.srcPort 10 hdr.ipv4.fragOffset 10 hdr.ipv4.flags 1 action multiple_tables_example_01/MainControlImpl/tcp_syn_packet permissions 0x1024 $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 2000 hdr.tcp.srcPort 20 hdr.ipv4.fragOffset 20 hdr.ipv4.flags 2 action multiple_tables_example_01/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 3000 hdr.tcp.srcPort 30 hdr.ipv4.fragOffset 30 hdr.ipv4.flags 3 action multiple_tables_example_01/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 4000 hdr.tcp.srcPort 40 hdr.ipv4.fragOffset 40 hdr.ipv4.flags 4 action multiple_tables_example_01/MainControlImpl/default_route_drop permissions 0x1024 $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 5000 hdr.tcp.srcPort 50 hdr.ipv4.fragOffset 50 hdr.ipv4.flags 5 action multiple_tables_example_01/MainControlImpl/next_hop permissions 0x1024 $TC p4template create table/multiple_tables_example_01/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 6000 hdr.tcp.srcPort 60 hdr.ipv4.fragOffset 60 hdr.ipv4.flags 6 action multiple_tables_example_01/MainControlImpl/sendtoport permissions 0x1024 diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template index 253f44ec0c9..33c7901ad61 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_02.template +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_02.template @@ -85,6 +85,7 @@ $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_o $TC p4template update table/multiple_tables_example_02/MainControlImpl/set_all_options default_miss_action permissions 0x1024 action multiple_tables_example_02/MainControlImpl/drop $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 1000 hdr.tcp.srcPort 10 hdr.ipv4.fragOffset 10 hdr.ipv4.flags 1 action multiple_tables_example_02/MainControlImpl/tcp_syn_packet permissions 0x1024 $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 2000 hdr.tcp.srcPort 20 hdr.ipv4.fragOffset 20 hdr.ipv4.flags 2 action multiple_tables_example_02/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 +$TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 3000 hdr.tcp.srcPort 30 hdr.ipv4.fragOffset 30 hdr.ipv4.flags 3 action multiple_tables_example_02/MainControlImpl/tcp_fin_or_rst_packet permissions 0x1024 $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 4000 hdr.tcp.srcPort 40 hdr.ipv4.fragOffset 40 hdr.ipv4.flags 4 action multiple_tables_example_02/MainControlImpl/default_route_drop permissions 0x1024 $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 5000 hdr.tcp.srcPort 50 hdr.ipv4.fragOffset 50 hdr.ipv4.flags 5 action multiple_tables_example_02/MainControlImpl/next_hop permissions 0x1024 $TC p4template create table/multiple_tables_example_02/MainControlImpl/set_all_options entry hdr.ipv4.srcAddr 6000 hdr.tcp.srcPort 60 hdr.ipv4.fragOffset 60 hdr.ipv4.flags 6 action multiple_tables_example_02/MainControlImpl/sendtoport permissions 0x1024