diff --git a/backends/ebpf/codeGen.cpp b/backends/ebpf/codeGen.cpp index db05340e81..8dc1086123 100644 --- a/backends/ebpf/codeGen.cpp +++ b/backends/ebpf/codeGen.cpp @@ -61,12 +61,13 @@ bool CodeGenInspector::preorder(const IR::Declaration_Variable *decl) { return false; } +// We count on the optimizer to get rid of 64-bit arithmetic when it's unnecessary static cstring getMask(P4::TypeMap *typeMap, const IR::Node *node) { auto type = typeMap->getType(node, true); cstring mask = cstring::empty; if (auto tb = type->to()) { if (tb->size != 8 && tb->size != 16 && tb->size != 32 && tb->size != 64) - mask = " & ((1 << " + Util::toString(tb->size) + ") - 1)"; + mask = " & ((1ULL << " + Util::toString(tb->size) + ") - 1)"; } return mask; } diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 7390f72a4d..ac4bded08f 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -18,6 +18,12 @@ and limitations under the License. namespace P4::TC { +DeparserBodyTranslatorPNA::DeparserBodyTranslatorPNA(const IngressDeparserPNA *deparser) + : CodeGenInspector(deparser->program->refMap, deparser->program->typeMap), + DeparserBodyTranslatorPSA(deparser) { + setName("DeparserBodyTranslatorPNA"); +} + // =====================PNAEbpfGenerator============================= void PNAEbpfGenerator::emitPNAIncludes(EBPF::CodeBuilder *builder) const { builder->appendLine("#include "); @@ -49,10 +55,14 @@ void PNAEbpfGenerator::emitCommonPreamble(EBPF::CodeBuilder *builder) const { void PNAEbpfGenerator::emitInternalStructures(EBPF::CodeBuilder *builder) const { builder->appendLine("struct p4tc_filter_fields p4tc_filter_fields;"); builder->newline(); - builder->appendLine( + builder->append( "struct internal_metadata {\n" " __u16 pkt_ether_type;\n" - "} __attribute__((aligned(4)));"); + "} __attribute__((aligned(4)));\n\n" + "struct skb_aggregate {\n" + " struct p4tc_skb_meta_get get;\n" + " struct p4tc_skb_meta_set set;\n" + "};\n"); builder->newline(); } @@ -266,9 +276,10 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { parser->headerType->as().kind, parser->headerType->as().name, parser->headers->name, compilerGlobalMetadata); - + if (func_name == "process") builder->append(", struct skb_aggregate *sa"); builder->append(")"); builder->newline(); + builder->blockStart(); emitCPUMAPHeadersInitializers(builder); @@ -365,6 +376,27 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { builder->blockStart(); + builder->emitIndent(); + + if ((dynamic_cast(control))->touched_skb_metadata || + (dynamic_cast(deparser))->touched_skb_metadata) { + builder->append("struct skb_aggregate skbstuff = {\n"); + builder->newline(); + builder->increaseIndent(); + builder->emitIndent(); + builder->appendFormat( + ".get = { .bitmask = P4TC_SKB_META_GET_AT_INGRESS_BIT | " + "P4TC_SKB_META_GET_FROM_INGRESS_BIT },"); + builder->newline(); + builder->emitIndent(); + builder->appendFormat(".set = { },"); + builder->newline(); + builder->decreaseIndent(); + builder->append("};\n"); + } else { + builder->append("struct skb_aggregate skbstuff;\n"); + } + emitGlobalMetadataInitializer(builder); emitHeaderInstances(builder); @@ -376,7 +408,7 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) { builder->emitIndent(); builder->appendFormat("ret = %v(skb, ", func_name); - builder->appendFormat("(%v %v *) %v, %v);", + builder->appendFormat("(%v %v *) %v, %v, &skbstuff);", parser->headerType->as().kind, parser->headerType->as().name, parser->headers->name, compilerGlobalMetadata); @@ -446,14 +478,12 @@ void TCIngressPipelinePNA::emitGlobalMetadataInitializer(EBPF::CodeBuilder *buil compilerGlobalMetadata); builder->newline(); - // if Traffic Manager decided to pass packet to the kernel stack earlier, send it up immediately + // Make sure drop and recirculate start out false builder->emitIndent(); - builder->append("if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK;"); + builder->append("compiler_meta__->drop = false;"); builder->newline(); - - // Make sure drop starts out false builder->emitIndent(); - builder->append("compiler_meta__->drop = false;"); + builder->append("compiler_meta__->recirculate = false;"); builder->newline(); // workaround to make TC protocol-independent, DO NOT REMOVE @@ -482,24 +512,24 @@ void TCIngressPipelinePNA::emitGlobalMetadataInitializer(EBPF::CodeBuilder *buil void TCIngressPipelinePNA::emitTrafficManager(EBPF::CodeBuilder *builder) { builder->emitIndent(); - builder->appendFormat("if (!%v->drop && %v->egress_port == 0) ", compilerGlobalMetadata, + builder->appendFormat("if (!%v->drop && %v->recirculate) ", compilerGlobalMetadata, compilerGlobalMetadata); builder->blockStart(); - builder->target->emitTraceMessage(builder, "IngressTM: Sending packet up to the kernel stack"); - - // Since XDP helper re-writes EtherType for packets other than IPv4 (e.g., ARP) - // we cannot simply return TC_ACT_OK to pass the packet up to the kernel stack, - // because the kernel stack would receive a malformed packet (with invalid skb->protocol). - // The workaround is to send the packet back to the same interface. If we redirect, - // the packet will be re-written back to the original format. - // At the beginning of the pipeline we check if pass_to_kernel is true and, - // if so, the program returns TC_ACT_OK. builder->emitIndent(); - builder->appendLine("compiler_meta__->pass_to_kernel = true;"); + builder->appendFormat("%v->recirculated = true;", compilerGlobalMetadata); + builder->newline(); builder->emitIndent(); - builder->append("return bpf_redirect(skb->ifindex, BPF_F_INGRESS)"); - builder->endOfStatement(true); + builder->appendFormat("return TC_ACT_UNSPEC;"); + builder->newline(); builder->blockEnd(true); + builder->emitIndent(); + builder->appendFormat("if (!%v->drop && %v->egress_port == 0)", compilerGlobalMetadata, + compilerGlobalMetadata); + builder->newline(); + builder->increaseIndent(); + builder->emitIndent(); + builder->appendLine("return TC_ACT_OK;"); + builder->decreaseIndent(); cstring eg_port = absl::StrFormat("%v->egress_port", compilerGlobalMetadata); cstring cos = @@ -622,7 +652,7 @@ void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr, std::string sInt = value.substr(2).c_str(); unsigned int width = std::stoi(sInt); if (widthToExtract != width) { - ::P4::error("Width of the field doesnt match the annotation width. '%1%'", field); + ::P4::error("Width of the field doesn't match the annotation width. '%1%'", field); } noEndiannessConversion = true; } @@ -1218,7 +1248,51 @@ void IngressDeparserPNA::emit(EBPF::CodeBuilder *builder) { prepareBufferTranslator->substitute(this->headers, this->parserHeaders); controlBlock->container->body->apply(*prepareBufferTranslator); + builder->newline(); + builder->emitIndent(); + builder->appendFormat("__u16 saved_proto = 0"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bool have_saved_proto = false"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendLine("// bpf_skb_adjust_room works only when protocol is IPv4 or IPv6"); + builder->emitIndent(); + builder->appendLine("// 0x0800 = IPv4, 0x86dd = IPv6"); + builder->emitIndent(); + builder->append("if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) "); + builder->blockStart(); + builder->emitIndent(); + builder->appendFormat("saved_proto = skb->protocol"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("have_saved_proto = true"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800)"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set))"); + builder->endOfStatement(true); + builder->blockEnd(true); + builder->emitIndent(); + builder->endOfStatement(true); + emitBufferAdjusts(builder); + + builder->newline(); + builder->emitIndent(); + builder->append("if (have_saved_proto) "); + builder->blockStart(); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto)"); + builder->endOfStatement(true); + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set))"); + builder->endOfStatement(true); + builder->blockEnd(true); + builder->newline(); + builder->emitIndent(); builder->appendFormat("%v = %v;", program->packetStartVar, builder->target->dataOffset(program->model.CPacketName.toString())); @@ -1257,6 +1331,65 @@ void IngressDeparserPNA::emitDeclaration(EBPF::CodeBuilder *builder, const IR::D EBPFDeparser::emitDeclaration(builder, decl); } +static void gen_skb_call(EBPF::CodeBuilder *b, const P4::ExternMethod *m, + EBPF::CodeGenInspector *xlat) { + b->appendFormat("/* SKB metadata: call %s */", m->method->name.name.c_str()); + if (m->method->name.name == "get") { + if (!m->expr->arguments->empty()) { + ::P4::error("%1%: takes no arguments", m->method->name.name); + } + b->appendFormat("bpf_p4tc_skb_meta_get(skb,&sa->get,sizeof(sa->get))"); + } else if (m->method->name.name == "set") { + if (!m->expr->arguments->empty()) { + ::P4::error("%1%: takes no arguments", m->method->name.name); + } + b->appendFormat("bpf_p4tc_skb_meta_set(skb,&sa->set,sizeof(sa->set))"); + } +#define GETSET(n) \ + else if (m->method->name.name == ("get_" #n)) { \ + if (!m->expr->arguments->empty()) { \ + P4::error("%1%: takes no arguments", m->method->name.name); \ + } \ + b->append("bpf_p4tc_skb_get_" #n "(skb,&sa->get)"); \ + } \ + else if (m->method->name.name == ("set_" #n)) { \ + if (m->expr->arguments->size() != 1) { \ + P4::error("%1%: requires exactly one argument", m->method->name.name); \ + } \ + b->append("bpf_p4tc_skb_set_" #n "(skb,&sa->set,"); \ + xlat->visit(m->expr->arguments->at(0)->expression); \ + b->append(")"); \ + } + GETSET(tstamp) + GETSET(mark) + GETSET(tc_classid) + GETSET(tc_index) + GETSET(queue_mapping) + GETSET(protocol) + GETSET(tc_at_ingress) + GETSET(from_ingress) +#undef GETSET + else { + P4::error("Unsupported SKB metadata method call %1%", m->method->name.name); + } +} + +static bool is_skb_meta_func(const P4::cstring fname) { + return (fname == "skb_get_meta") || (fname == "skb_set_tstamp") || (fname == "skb_set_mark") || + (fname == "skb_set_queue_mapping") || (fname == "skb_set_protocol") || + (fname == "skb_set_tc_classid") || (fname == "skb_set_tc_index") || + (fname == "skb_set_meta"); +} + +void DeparserBodyTranslatorPNA::processFunction(const P4::ExternFunction *function) { + auto fname = function->expr->method->toString(); + + if (is_skb_meta_func(fname)) { + ::P4::error(ErrorType::ERR_UNEXPECTED, + "Unexpected call to extern function %s in the deparser", fname); + } +} + // =====================ConvertToEbpfPNA============================= const PNAEbpfGenerator *ConvertToEbpfPNA::build(const IR::ToplevelBlock *tlb) { /* @@ -1409,6 +1542,8 @@ bool ConvertToEBPFControlPNA::preorder(const IR::ControlBlock *ctrl) { ++it; control->outputStandardMetadata = *it; + control->touched_skb_metadata = false; + auto codegen = new ControlBodyTranslatorPNA(control, tcIR); codegen->substitute(control->headers, parserHeaders); @@ -1797,6 +1932,42 @@ void ControlBodyTranslatorPNA::processFunction(const P4::ExternFunction *functio "sizeof(key))"); return; } + + auto fname = function->expr->method->toString(); + + if (is_skb_meta_func(fname)) { + if (fname == "skb_get_meta") { + if (function->expr->arguments->size() != 0) { + ::P4::error("skb_get_meta takes no arguments"); + return; + } + builder->emitIndent(); + builder->append("bpf_p4tc_skb_meta_get(skb,&sa->get,sizeof(sa->get))"); + } else if ((fname == "skb_set_tstamp") || (fname == "skb_set_mark") || + (fname == "skb_set_tc_classid") || (fname == "skb_set_tc_index") || + (fname == "skb_set_queue_mapping") || (fname == "skb_set_protocol")) { + if (function->expr->arguments->size() != 1) { + ::P4::error("%1% takes exactly one argument", fname); + return; + } + builder->emitIndent(); + builder->appendFormat("bpf_p4tc_%s(skb,&sa->set,", fname.c_str()); + visit(function->expr->arguments->at(0)); + builder->append(")"); + } else if (fname == "skb_set_meta") { + if (function->expr->arguments->size() != 0) { + ::P4::error("skb_set_meta takes no arguments"); + return; + } + builder->emitIndent(); + builder->append("bpf_p4tc_skb_meta_set(skb,&sa->set,sizeof(sa->set))"); + } else { + BUG_CHECK(0, "impossible method name in %1%", &__func__[0]); + return; + } + (dynamic_cast(control))->touched_skb_metadata = true; + return; + } processCustomExternFunction(function, EBPF::EBPFTypeFactory::instance); } @@ -1971,6 +2142,14 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { builder->target->emitTraceMessage(builder, msgStr.c_str()); } +static void gen_skb_call_ctrl(const EBPFControlPNA *c, EBPF::CodeBuilder *b, + const P4::ExternMethod *m, ControlBodyTranslatorPNA *xlat) { + EBPF::CodeGenInspector *inspector = xlat; + + c->touched_skb_metadata = true; + gen_skb_call(b, m, inspector); +} + void ControlBodyTranslatorPNA::processMethod(const P4::ExternMethod *method) { auto decl = method->object; auto declType = method->originalExternType; @@ -2002,16 +2181,19 @@ void ControlBodyTranslatorPNA::processMethod(const P4::ExternMethod *method) { auto hash = pnaControl->getHash(name); hash->processMethod(builder, method->method->name.name, method->expr, this); return; + } else if (declType->name.name == "tc_skb_metadata") { + gen_skb_call_ctrl(pnaControl, builder, method, this); + return; } else { - ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: Unexpected method call", - method->expr); + ::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: [C] [%2%] Unexpected method call", + method->expr, declType->name.name); } } bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { if (auto methodCallExpr = a->right->to()) { - if (methodCallExpr->method->toString() == "is_net_port" || - methodCallExpr->method->toString() == "is_host_port") { + auto mname = methodCallExpr->method->toString(); + if (mname == "is_net_port" || mname == "is_host_port") { builder->emitIndent(); visit(a->left); builder->append(" = "); @@ -2023,6 +2205,17 @@ bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { assert(methodCallExpr->arguments->size() == 1); visit(methodCallExpr->arguments->at(0)); builder->append(");"); + } else if ((mname == "skb_get_tstamp") || (mname == "skb_get_mark") || + (mname == "skb_get_tc_classid") || (mname == "skb_get_tc_index") || + (mname == "skb_get_queue_mapping") || (mname == "skb_get_protocol") || + (mname == "skb_get_tc_at_ingress") || (mname == "skb_get_from_ingress")) { + if (methodCallExpr->arguments->size() != 0) { + ::P4::error("%1% takes no arguments", mname); + return (false); + } + visit(a->left); + builder->appendFormat(" = bpf_p4tc_%s(skb, &sa->get);", mname.c_str()); + return (false); } auto mi = P4::MethodInstance::resolve(methodCallExpr, control->program->refMap, control->program->typeMap); @@ -2055,6 +2248,8 @@ bool ControlBodyTranslatorPNA::preorder(const IR::AssignmentStatement *a) { auto pna_meter = dynamic_cast(meter); pna_meter->emitDirectMeterExecute(builder, ext, this, a->left); return false; + } else { + return (false); } } @@ -2114,9 +2309,9 @@ cstring ActionTranslationVisitorPNA::getParamName(const IR::PathExpression *expr void ActionTranslationVisitorPNA::processMethod(const P4::ExternMethod *method) { auto declType = method->originalExternType; auto decl = method->object; - BUG_CHECK(decl->is(), "Extern has not been declared: %1%", decl); - auto di = decl->to(); - auto instanceName = EBPF::EBPFObject::externalName(di); + BUG_CHECK(decl->is(), "Extern has not been declared [A]: %1% (is a %2%)", decl, + decl->node_type_name()); + auto instanceName = EBPF::EBPFObject::externalName(decl->to()); cstring name = EBPF::EBPFObject::externalName(decl); if (declType->name.name == "DirectCounter") { diff --git a/backends/tc/ebpfCodeGen.h b/backends/tc/ebpfCodeGen.h index 44b9462920..4c44b97532 100644 --- a/backends/tc/ebpfCodeGen.h +++ b/backends/tc/ebpfCodeGen.h @@ -185,11 +185,25 @@ class EBPFTablePNA : public EBPF::EBPFTablePSA { DECLARE_TYPEINFO(EBPFTablePNA, EBPF::EBPFTablePSA); }; +class IngressDeparserPNA; + +class DeparserBodyTranslatorPNA : public EBPF::DeparserBodyTranslatorPSA { + public: + explicit DeparserBodyTranslatorPNA(const IngressDeparserPNA *deparser); + + void processFunction(const P4::ExternFunction *function) override; +}; + class IngressDeparserPNA : public EBPF::EBPFDeparserPSA { public: + mutable bool touched_skb_metadata; + IngressDeparserPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control, const IR::Parameter *parserHeaders, const IR::Parameter *istd) - : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd) {} + : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd), + touched_skb_metadata(false) { + codeGen = new DeparserBodyTranslatorPNA(this); + } bool addExternDeclaration = false; bool build() override; @@ -282,9 +296,11 @@ class EBPFControlPNA : public EBPF::EBPFControlPSA { std::map pna_registers; std::map pna_hashes; + mutable bool touched_skb_metadata; + EBPFControlPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control, const IR::Parameter *parserHeaders) - : EBPF::EBPFControlPSA(program, control, parserHeaders) {} + : EBPF::EBPFControlPSA(program, control, parserHeaders), touched_skb_metadata(false) {} EBPFRegisterPNA *getRegister(cstring name) const { auto result = ::P4::get(pna_registers, name); diff --git a/backends/tc/runtime/pna.h b/backends/tc/runtime/pna.h index ae87f54526..42b0714b4a 100644 --- a/backends/tc/runtime/pna.h +++ b/backends/tc/runtime/pna.h @@ -75,6 +75,7 @@ struct pna_main_output_metadata_t { */ struct pna_global_metadata { bool recirculated; + bool recirculate; bool drop; // NOTE : no drop field in PNA metadata, so we keep drop state as internal metadata. PortId_t egress_port; enum MirrorType mirror_type; @@ -460,4 +461,152 @@ static inline u32 bpf_p4tc_extern_random(u32 min, u32 max) { return (min + bpf_get_prandom_u32()) % (max + 1); } + +#define BIT(x) (1 << x) + +#define P4TC_SKB_META_SET_TSTAMP BIT(0) +#define P4TC_SKB_META_SET_MARK BIT(1) +#define P4TC_SKB_META_SET_CLASSID BIT(2) +#define P4TC_SKB_META_SET_TC_INDEX BIT(3) +#define P4TC_SKB_META_SET_QMAP BIT(4) +#define P4TC_SKB_META_SET_PROTO BIT(5) + +struct p4tc_skb_meta_set { + __u64 tstamp; + __u32 mark; + __u16 tc_classid; + __u16 tc_index; + __u16 queue_mapping; + __be16 protocol; + __u32 bitmask; +}; + +static inline void +bpf_p4tc_skb_set_tstamp(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u64 tstamp) +{ + meta_set->tstamp = tstamp; + meta_set->bitmask |= P4TC_SKB_META_SET_TSTAMP; +} + +static inline void +bpf_p4tc_skb_set_mark(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u32 mark) +{ + meta_set->mark = mark; + meta_set->bitmask |= P4TC_SKB_META_SET_MARK; +} + +static inline void +bpf_p4tc_skb_set_tc_classid(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u32 tc_classid) +{ + meta_set->tc_classid = tc_classid; + meta_set->bitmask |= P4TC_SKB_META_SET_CLASSID; +} + +static inline void +bpf_p4tc_skb_set_tc_index(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __u16 tc_index) +{ + meta_set->tc_index = tc_index; + meta_set->bitmask |= P4TC_SKB_META_SET_TC_INDEX; +} + +static inline void +bpf_p4tc_skb_set_queue_mapping(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, + __u16 queue_mapping) +{ + meta_set->queue_mapping = queue_mapping; + meta_set->bitmask |= P4TC_SKB_META_SET_QMAP; +} + +static inline void +bpf_p4tc_skb_set_protocol(struct __sk_buff *skb, + struct p4tc_skb_meta_set *meta_set, __be16 protocol) +{ + meta_set->protocol = protocol; + meta_set->bitmask |= P4TC_SKB_META_SET_PROTO; +} + +int bpf_p4tc_skb_meta_set(struct __sk_buff *skb, + struct p4tc_skb_meta_set *skb_meta_set, + u32 skb_meta_set__sz) __ksym; + +#define P4TC_SKB_META_GET_AT_INGRESS_BIT BIT(0) +#define P4TC_SKB_META_GET_FROM_INGRESS_BIT BIT(1) + +struct p4tc_skb_meta_get { + u8 tc_at_ingress:1, + from_ingress:1; + u8 bitmask; +}; + +static inline __u64 +bpf_p4tc_skb_get_tstamp(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tstamp; +} + +static inline __u16 +bpf_p4tc_skb_get_tc_classid(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tc_classid; +} + +static inline __u16 +bpf_p4tc_skb_get_tc_index(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->tc_index; +} + +static inline __u16 +bpf_p4tc_skb_get_queue_mapping(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->queue_mapping; +} + +static inline __be16 +bpf_p4tc_skb_get_protocol(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->protocol; +} + +static inline int +bpf_p4tc_skb_get_tc_at_ingress(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + if (meta_get->bitmask & P4TC_SKB_META_GET_AT_INGRESS_BIT) + return meta_get->tc_at_ingress; + + return -1; +} + +static inline int +bpf_p4tc_skb_get_from_ingress(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + if (meta_get->bitmask & P4TC_SKB_META_GET_FROM_INGRESS_BIT) + return meta_get->from_ingress; + + return -1; +} + +static inline __u32 +bpf_p4tc_skb_get_mark(struct __sk_buff *skb, + struct p4tc_skb_meta_get *meta_get) +{ + return skb->mark; +} + +int bpf_p4tc_skb_meta_get(struct __sk_buff *skb, + struct p4tc_skb_meta_get *skb_meta_get, + u32 skb_meta_get__sz) __ksym; + #endif /* P4C_PNA_H */ diff --git a/p4include/tc/pna.p4 b/p4include/tc/pna.p4 index 9e2914cd95..51faa4bb9d 100644 --- a/p4include/tc/pna.p4 +++ b/p4include/tc/pna.p4 @@ -444,6 +444,23 @@ extern Counter { } // END:Counter_extern +extern void skb_get_meta(); +extern bit<64> skb_get_tstamp(); +extern bit<32> skb_get_mark(); +extern bit<16> skb_get_tc_classid(); +extern bit<16> skb_get_tc_index(); +extern bit<16> skb_get_queue_mapping(); +extern bit<16> skb_get_protocol(); +extern bit<1> skb_get_tc_at_ingress(); +extern bit<1> skb_get_from_ingress(); +extern void skb_set_tstamp(in bit<64> dummy); +extern void skb_set_mark(in bit<32> dummy); +extern void skb_set_tc_classid(in bit<16> dummy); +extern void skb_set_tc_index(in bit<16> dummy); +extern void skb_set_queue_mapping(in bit<16> dummy); +extern void skb_set_protocol(in bit<16> dummy); +extern void skb_set_meta(); + struct tc_ControlPath_Counter { @tc_key S index; @tc_data W pkts; @@ -610,6 +627,7 @@ struct pna_main_input_metadata_t { // common fields initialized for all packets that are input to main // parser, regardless of direction. bool recirculated; + bool recirculate; Timestamp_t timestamp; ParserError_t parser_error; ClassOfService_t class_of_service; diff --git a/testdata/p4tc_samples/skb_meta.p4 b/testdata/p4tc_samples/skb_meta.p4 new file mode 100644 index 0000000000..1e3cd4c4e1 --- /dev/null +++ b/testdata/p4tc_samples/skb_meta.p4 @@ -0,0 +1,142 @@ +#include +#include + +/****** G L O B A L I N G R E S S M E T A D A T A *********/ + +struct my_ingress_metadata_t { +} + +struct empty_metadata_t { +} + +/* -*- P4_16 -*- */ + +/* + * CONST VALUES FOR TYPES + */ +const bit<8> IP_PROTO_TCP = 0x06; +const bit<16> ETHERTYPE_IPV4 = 0x0800; + +/* + * Standard ethernet header + */ +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +header ipv4_t { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + bit<32> srcAddr; + bit<32> dstAddr; +} + +struct my_ingress_headers_t { + ethernet_t ethernet; + ipv4_t ipv4; +} + + /*********************** P A R S E R **************************/ +parser Ingress_Parser( + packet_in pkt, + out my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_parser_input_metadata_t istd) +{ + + state start { + transition parse_ethernet; + } + + state parse_ethernet { + pkt.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + ETHERTYPE_IPV4: parse_ipv4; + default: reject; + } + } + state parse_ipv4 { + pkt.extract(hdr.ipv4); + transition select(hdr.ipv4.protocol) { + IP_PROTO_TCP : accept; + default: reject; + } + } +} + +#define L3_TABLE_SIZE 2048 + +/***************** M A T C H - A C T I O N *********************/ + +control ingress( + inout my_ingress_headers_t hdr, + inout my_ingress_metadata_t meta, + in pna_main_input_metadata_t istd, + inout pna_main_output_metadata_t ostd +) +{ + action send_nh(@tc_type("dev") PortId_t port, @tc_type("macaddr") bit<48> srcMac, @tc_type("macaddr") bit<48> dstMac) { + + skb_get_meta(); + skb_set_tc_classid(skb_get_tc_classid() + 1); + skb_set_tc_index(skb_get_tc_index() + 1); + skb_set_meta(); + hdr.ethernet.srcAddr = (bit<48>)skb_get_tstamp() ^ srcMac; + hdr.ethernet.dstAddr = dstMac; + send_to_port(port); + } + + action drop() { + drop_packet(); + } + + table nh_table { + key = { + hdr.ipv4.dstAddr : exact @tc_type("ipv4") @name("dstAddr"); + } + actions = { + send_nh; + drop; + } + size = L3_TABLE_SIZE; + const default_action = drop; + } + + apply { + if (hdr.ipv4.isValid() && hdr.ipv4.protocol == IP_PROTO_TCP) { + nh_table.apply(); + } + } +} + + /********************* D E P A R S E R ************************/ + +control Ingress_Deparser( + packet_out pkt, + inout my_ingress_headers_t hdr, + in my_ingress_metadata_t meta, + in pna_main_output_metadata_t ostd) +{ + apply { + pkt.emit(hdr.ethernet); + pkt.emit(hdr.ipv4); + } +} + +/************ F I N A L P A C K A G E ******************************/ + +PNA_NIC( + Ingress_Parser(), + ingress(), + Ingress_Deparser() +) main; diff --git a/testdata/p4tc_samples_outputs/add_entry_1_example_control_blocks.c b/testdata/p4tc_samples_outputs/add_entry_1_example_control_blocks.c index 69860b00f7..6cbed581b2 100644 --- a/testdata/p4tc_samples_outputs/add_entry_1_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/add_entry_1_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -34,7 +39,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -153,6 +158,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -161,6 +178,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -291,9 +314,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -308,14 +332,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/add_entry_3_example_control_blocks.c b/testdata/p4tc_samples_outputs/add_entry_3_example_control_blocks.c index fb44998d93..7e9355909b 100644 --- a/testdata/p4tc_samples_outputs/add_entry_3_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/add_entry_3_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -34,7 +39,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -153,6 +158,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -161,6 +178,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -291,9 +314,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -308,14 +332,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/add_entry_example_control_blocks.c b/testdata/p4tc_samples_outputs/add_entry_example_control_blocks.c index 9e876665f2..b5c813ebe3 100644 --- a/testdata/p4tc_samples_outputs/add_entry_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/add_entry_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -53,7 +58,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -227,6 +232,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -235,6 +252,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -364,9 +387,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -381,14 +405,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/calculator_control_blocks.c b/testdata/p4tc_samples_outputs/calculator_control_blocks.c index 782ce63693..60547beff5 100644 --- a/testdata/p4tc_samples_outputs/calculator_control_blocks.c +++ b/testdata/p4tc_samples_outputs/calculator_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_calculate_key { u32 keysz; u32 maskid; @@ -40,7 +45,7 @@ struct __attribute__((__packed__)) MainControlImpl_calculate_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -191,6 +196,18 @@ if (/* hdr->p4calc.isValid() */ outHeaderLength += 128; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -199,6 +216,12 @@ if (/* hdr->p4calc.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -306,9 +329,10 @@ if (/* hdr->p4calc.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -323,14 +347,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; 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 index a9623807c5..0e4dad41d0 100644 --- a/testdata/p4tc_samples_outputs/calculator_parser.c +++ b/testdata/p4tc_samples_outputs/calculator_parser.c @@ -141,7 +141,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h 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)); + select_0 = (((((u32)(((u16)tmp_0.p << 8) | ((u16)tmp_2.four & 0xff)) << 8) & ((1ULL << 24) - 1)) | (((u32)tmp_4.ver & 0xff) & ((1ULL << 24) - 1))) & ((1ULL << 24) - 1)); if (select_0 == 0x503401)goto parse_p4calc; if ((select_0 & 0x0) == (0x0 & 0x0))goto accept; else goto reject; diff --git a/testdata/p4tc_samples_outputs/checksum_control_blocks.c b/testdata/p4tc_samples_outputs/checksum_control_blocks.c index 345bf2761c..75453be306 100644 --- a/testdata/p4tc_samples_outputs/checksum_control_blocks.c +++ b/testdata/p4tc_samples_outputs/checksum_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -125,6 +130,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -133,6 +150,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -262,9 +285,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -279,14 +303,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; 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 index 223fbb03d0..2db79d16a9 100644 --- a/testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c +++ b/testdata/p4tc_samples_outputs/const_entries_range_mask_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_t_range_key { u32 keysz; u32 maskid; @@ -29,7 +34,7 @@ struct __attribute__((__packed__)) MainControlImpl_t_range_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -110,6 +115,18 @@ static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, st } int outHeaderLength = 0; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -118,6 +135,12 @@ static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, st return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -127,9 +150,10 @@ static __always_inline int process(struct __sk_buff *skb, struct Header_t *h, st } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -144,14 +168,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct Header_t *h; int ret = -1; - ret = process(skb, (struct Header_t *) h, compiler_meta__); + ret = process(skb, (struct Header_t *) h, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/default_action_example_01_control_blocks.c b/testdata/p4tc_samples_outputs/default_action_example_01_control_blocks.c index d7701be5da..fa15e70ed4 100644 --- a/testdata/p4tc_samples_outputs/default_action_example_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/default_action_example_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -48,7 +53,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -181,6 +186,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -189,6 +206,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -320,9 +343,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -337,14 +361,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/default_action_example_control_blocks.c b/testdata/p4tc_samples_outputs/default_action_example_control_blocks.c index ccef7178c7..df79cd64e4 100644 --- a/testdata/p4tc_samples_outputs/default_action_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/default_action_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -201,6 +206,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -209,6 +226,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -340,9 +363,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -357,14 +381,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/default_action_with_param_01_control_blocks.c b/testdata/p4tc_samples_outputs/default_action_with_param_01_control_blocks.c index 58467d1d1d..2897a53987 100644 --- a/testdata/p4tc_samples_outputs/default_action_with_param_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/default_action_with_param_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -53,7 +58,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -201,6 +206,18 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -209,6 +226,12 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -340,9 +363,10 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -357,14 +381,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/default_action_with_param_control_blocks.c b/testdata/p4tc_samples_outputs/default_action_with_param_control_blocks.c index e197e40097..949201b7b8 100644 --- a/testdata/p4tc_samples_outputs/default_action_with_param_control_blocks.c +++ b/testdata/p4tc_samples_outputs/default_action_with_param_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -201,6 +206,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -209,6 +226,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -340,9 +363,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -357,14 +381,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/default_hit_const_example_control_blocks.c b/testdata/p4tc_samples_outputs/default_hit_const_example_control_blocks.c index e86861498d..b4f11a1fe7 100644 --- a/testdata/p4tc_samples_outputs/default_hit_const_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/default_hit_const_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_set_ct_options_key { u32 keysz; u32 maskid; @@ -35,7 +40,7 @@ struct __attribute__((__packed__)) MainControlImpl_set_ct_options_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -126,6 +131,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 112; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -134,6 +151,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -186,9 +209,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -203,14 +227,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/digest_01_control_blocks.c b/testdata/p4tc_samples_outputs/digest_01_control_blocks.c index 940cc86b8b..ba4a9e80e4 100644 --- a/testdata/p4tc_samples_outputs/digest_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/digest_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -146,6 +151,18 @@ if (meta->send_digest) { outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -154,6 +171,12 @@ if (meta->send_digest) { return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -283,9 +306,10 @@ if (meta->send_digest) { } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -300,14 +324,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/digest_control_blocks.c b/testdata/p4tc_samples_outputs/digest_control_blocks.c index 21bd433721..3047bfc234 100644 --- a/testdata/p4tc_samples_outputs/digest_control_blocks.c +++ b/testdata/p4tc_samples_outputs/digest_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -147,6 +152,18 @@ if (meta->send_digest) { outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -155,6 +172,12 @@ if (meta->send_digest) { return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -284,9 +307,10 @@ if (meta->send_digest) { } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -301,14 +325,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/digest_parser_meta_control_blocks.c b/testdata/p4tc_samples_outputs/digest_parser_meta_control_blocks.c index 87420dcad3..0a07f6218b 100644 --- a/testdata/p4tc_samples_outputs/digest_parser_meta_control_blocks.c +++ b/testdata/p4tc_samples_outputs/digest_parser_meta_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -142,6 +147,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ;; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -150,6 +167,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -279,9 +302,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -296,14 +320,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/direct_counter_example_control_blocks.c b/testdata/p4tc_samples_outputs/direct_counter_example_control_blocks.c index 81f840dfb8..c218f0a5d7 100644 --- a/testdata/p4tc_samples_outputs/direct_counter_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/direct_counter_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -134,6 +139,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -142,6 +159,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -273,9 +296,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -290,14 +314,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/direct_meter_color_control_blocks.c b/testdata/p4tc_samples_outputs/direct_meter_color_control_blocks.c index d795468e30..ca8ba0098d 100644 --- a/testdata/p4tc_samples_outputs/direct_meter_color_control_blocks.c +++ b/testdata/p4tc_samples_outputs/direct_meter_color_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -28,7 +33,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -136,6 +141,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -144,6 +161,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -275,9 +298,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -292,14 +316,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/direct_meter_control_blocks.c b/testdata/p4tc_samples_outputs/direct_meter_control_blocks.c index e4ea776af4..a3948999e3 100644 --- a/testdata/p4tc_samples_outputs/direct_meter_control_blocks.c +++ b/testdata/p4tc_samples_outputs/direct_meter_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -28,7 +33,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -130,6 +135,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -138,6 +155,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -269,9 +292,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -286,14 +310,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/drop_packet_example_control_blocks.c b/testdata/p4tc_samples_outputs/drop_packet_example_control_blocks.c index 5aa0fce713..891f46879a 100644 --- a/testdata/p4tc_samples_outputs/drop_packet_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/drop_packet_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_key { u32 keysz; u32 maskid; @@ -29,7 +34,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -124,6 +129,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -132,6 +149,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -263,9 +286,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -280,14 +304,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/global_action_example_01_control_blocks.c b/testdata/p4tc_samples_outputs/global_action_example_01_control_blocks.c index 9627bdb009..553c4224a1 100644 --- a/testdata/p4tc_samples_outputs/global_action_example_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/global_action_example_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table2_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -198,6 +203,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -206,6 +223,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -335,9 +358,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -352,14 +376,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/global_action_example_02_control_blocks.c b/testdata/p4tc_samples_outputs/global_action_example_02_control_blocks.c index 7cb9c3452e..85ec5ae5be 100644 --- a/testdata/p4tc_samples_outputs/global_action_example_02_control_blocks.c +++ b/testdata/p4tc_samples_outputs/global_action_example_02_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table2_key { u32 keysz; u32 maskid; @@ -56,7 +61,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -200,6 +205,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -208,6 +225,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -337,9 +360,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -354,14 +378,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/hash1_control_blocks.c b/testdata/p4tc_samples_outputs/hash1_control_blocks.c index c243f6d9ab..d33fc45293 100644 --- a/testdata/p4tc_samples_outputs/hash1_control_blocks.c +++ b/testdata/p4tc_samples_outputs/hash1_control_blocks.c @@ -5,8 +5,13 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) + +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -59,6 +64,18 @@ ingress_h_reg; outHeaderLength += 88; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -67,6 +84,12 @@ ingress_h_reg; return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -160,9 +183,10 @@ ingress_h_reg; } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -177,14 +201,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/hash_control_blocks.c b/testdata/p4tc_samples_outputs/hash_control_blocks.c index 9a924b31d5..94f46c9f9f 100644 --- a/testdata/p4tc_samples_outputs/hash_control_blocks.c +++ b/testdata/p4tc_samples_outputs/hash_control_blocks.c @@ -5,8 +5,13 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) + +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -59,6 +64,18 @@ ingress_h_reg ^ 0xFFFFFFFF; outHeaderLength += 104; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -67,6 +84,12 @@ ingress_h_reg ^ 0xFFFFFFFF; return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -164,9 +187,10 @@ ingress_h_reg ^ 0xFFFFFFFF; } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -181,14 +205,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/indirect_counter_01_example_control_blocks.c b/testdata/p4tc_samples_outputs/indirect_counter_01_example_control_blocks.c index 9ad5fd5c2e..0670ed1c4a 100644 --- a/testdata/p4tc_samples_outputs/indirect_counter_01_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/indirect_counter_01_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -34,7 +39,7 @@ struct ingress_global_counter_value { u64 packets; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -140,6 +145,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -148,6 +165,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -279,9 +302,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -296,14 +320,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c b/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c index 66f01311a3..0c5bc31c61 100644 --- a/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/internetchecksum_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_fwd_table_key { u32 keysz; u32 maskid; @@ -36,7 +41,7 @@ struct __attribute__((__packed__)) ingress_fwd_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -232,6 +237,18 @@ struct p4tc_ext_csum_params chk_csum = {}; outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -240,6 +257,12 @@ struct p4tc_ext_csum_params chk_csum = {}; return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -448,9 +471,10 @@ struct p4tc_ext_csum_params chk_csum = {}; } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -465,14 +489,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/ipip_control_blocks.c b/testdata/p4tc_samples_outputs/ipip_control_blocks.c index 9968083323..bbbb11d670 100644 --- a/testdata/p4tc_samples_outputs/ipip_control_blocks.c +++ b/testdata/p4tc_samples_outputs/ipip_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) Main_fwd_table_key { u32 keysz; u32 maskid; @@ -36,7 +41,7 @@ struct __attribute__((__packed__)) Main_fwd_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -166,6 +171,18 @@ if (/* hdr->outer.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -174,6 +191,12 @@ if (/* hdr->outer.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -386,9 +409,10 @@ if (/* hdr->outer.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -403,14 +427,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c b/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c index ffff2bafb1..b98c36a886 100644 --- a/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c +++ b/testdata/p4tc_samples_outputs/is_host_port_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -137,6 +142,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -145,6 +162,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -276,9 +299,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -293,14 +317,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c b/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c index 5b44f451af..91f2bfb8f3 100644 --- a/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c +++ b/testdata/p4tc_samples_outputs/is_net_port_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -137,6 +142,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -145,6 +162,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -276,9 +299,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -293,14 +317,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/matchtype_control_blocks.c b/testdata/p4tc_samples_outputs/matchtype_control_blocks.c index ab3253b2db..d5319ec9a1 100644 --- a/testdata/p4tc_samples_outputs/matchtype_control_blocks.c +++ b/testdata/p4tc_samples_outputs/matchtype_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -106,7 +111,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_4_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -349,6 +354,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -357,6 +374,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -488,9 +511,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -505,14 +529,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/meter_color_control_blocks.c b/testdata/p4tc_samples_outputs/meter_color_control_blocks.c index 3502797d78..5f5dea88b9 100644 --- a/testdata/p4tc_samples_outputs/meter_color_control_blocks.c +++ b/testdata/p4tc_samples_outputs/meter_color_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -28,7 +33,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -137,6 +142,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -145,6 +162,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -276,9 +299,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -293,14 +317,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/meter_control_blocks.c b/testdata/p4tc_samples_outputs/meter_control_blocks.c index c4a4779cbf..f242c579cc 100644 --- a/testdata/p4tc_samples_outputs/meter_control_blocks.c +++ b/testdata/p4tc_samples_outputs/meter_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -28,7 +33,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -135,6 +140,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -143,6 +160,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -274,9 +297,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -291,14 +315,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/mix_matchtype_example_control_blocks.c b/testdata/p4tc_samples_outputs/mix_matchtype_example_control_blocks.c index 8b0c6015ef..fd2088e276 100644 --- a/testdata/p4tc_samples_outputs/mix_matchtype_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/mix_matchtype_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -111,7 +116,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_4_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -355,6 +360,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -363,6 +380,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -494,9 +517,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -511,14 +535,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_01_control_blocks.c b/testdata/p4tc_samples_outputs/multiple_tables_example_01_control_blocks.c index 3209d563f6..39e0fc5f4b 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -191,7 +196,7 @@ struct __attribute__((__packed__)) MainControlImpl_set_ct_options_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -606,6 +611,18 @@ if (hdr->ipv4.protocol != 4 || (hdr->tcp.srcPort <= 3)) { outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -614,6 +631,12 @@ if (hdr->ipv4.protocol != 4 || (hdr->tcp.srcPort <= 3)) { return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -745,9 +768,10 @@ if (hdr->ipv4.protocol != 4 || (hdr->tcp.srcPort <= 3)) { } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -762,14 +786,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/multiple_tables_example_02_control_blocks.c b/testdata/p4tc_samples_outputs/multiple_tables_example_02_control_blocks.c index f14364a20c..ac6fee0a89 100644 --- a/testdata/p4tc_samples_outputs/multiple_tables_example_02_control_blocks.c +++ b/testdata/p4tc_samples_outputs/multiple_tables_example_02_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -188,7 +193,7 @@ struct __attribute__((__packed__)) MainControlImpl_set_ct_options_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -606,6 +611,18 @@ if (hdr->ipv4.protocol == 6 || ((hdr->ipv4.version > 1) && (hdr->ipv4.ihl <= 2)) outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -614,6 +631,12 @@ if (hdr->ipv4.protocol == 6 || ((hdr->ipv4.version > 1) && (hdr->ipv4.ihl <= 2)) return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -745,9 +768,10 @@ if (hdr->ipv4.protocol == 6 || ((hdr->ipv4.version > 1) && (hdr->ipv4.ihl <= 2)) } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -762,14 +786,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/name_annotation_example_control_blocks.c b/testdata/p4tc_samples_outputs/name_annotation_example_control_blocks.c index ec20ae1b6f..812f90fcde 100644 --- a/testdata/p4tc_samples_outputs/name_annotation_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/name_annotation_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -54,7 +59,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -199,6 +204,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -207,6 +224,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -338,9 +361,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -355,14 +379,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/no_table_example_control_blocks.c b/testdata/p4tc_samples_outputs/no_table_example_control_blocks.c index 1ed4181e43..0a660aa2c3 100644 --- a/testdata/p4tc_samples_outputs/no_table_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/no_table_example_control_blocks.c @@ -5,8 +5,13 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) + +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -57,6 +62,18 @@ if ((u32)skb->ifindex == 4) { outHeaderLength += 64; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -65,6 +82,12 @@ if ((u32)skb->ifindex == 4) { return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -230,9 +253,10 @@ if ((u32)skb->ifindex == 4) { } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -247,14 +271,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/noaction_example_01_control_blocks.c b/testdata/p4tc_samples_outputs/noaction_example_01_control_blocks.c index d2d7e226ce..b4f7560537 100644 --- a/testdata/p4tc_samples_outputs/noaction_example_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/noaction_example_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -54,7 +59,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -199,6 +204,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -207,6 +224,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -338,9 +361,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -355,14 +379,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/noaction_example_02_control_blocks.c b/testdata/p4tc_samples_outputs/noaction_example_02_control_blocks.c index e495411627..d2b3b7e6be 100644 --- a/testdata/p4tc_samples_outputs/noaction_example_02_control_blocks.c +++ b/testdata/p4tc_samples_outputs/noaction_example_02_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -45,7 +50,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -175,6 +180,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -183,6 +200,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -314,9 +337,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -331,14 +355,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/nummask_annotation_example_control_blocks.c b/testdata/p4tc_samples_outputs/nummask_annotation_example_control_blocks.c index 8371e7fcd8..7083be009d 100644 --- a/testdata/p4tc_samples_outputs/nummask_annotation_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/nummask_annotation_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_set_ct_options_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) MainControlImpl_set_ct_options_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -122,6 +127,18 @@ if (((u32)skb->ifindex == 2 && /* hdr->ipv4.isValid() */ outHeaderLength += 112; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -130,6 +147,12 @@ if (((u32)skb->ifindex == 2 && /* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -182,9 +205,10 @@ if (((u32)skb->ifindex == 2 && /* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -199,14 +223,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/send_to_port_example_control_blocks.c b/testdata/p4tc_samples_outputs/send_to_port_example_control_blocks.c index 7375df9042..d99ba81627 100644 --- a/testdata/p4tc_samples_outputs/send_to_port_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/send_to_port_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -154,6 +159,18 @@ ext_val = *ext_val_ptr; outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -162,6 +179,12 @@ ext_val = *ext_val_ptr; return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -293,9 +316,10 @@ ext_val = *ext_val_ptr; } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -310,14 +334,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/set_entry_timer_example_control_blocks.c b/testdata/p4tc_samples_outputs/set_entry_timer_example_control_blocks.c index 07eebe4dd1..df6f3416b9 100644 --- a/testdata/p4tc_samples_outputs/set_entry_timer_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/set_entry_timer_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -53,7 +58,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -209,6 +214,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -217,6 +234,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -348,9 +371,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -365,14 +389,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/simple_exact_example_control_blocks.c b/testdata/p4tc_samples_outputs/simple_exact_example_control_blocks.c index 5216d83472..f4cc947d34 100644 --- a/testdata/p4tc_samples_outputs/simple_exact_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/simple_exact_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -125,6 +130,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -133,6 +150,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -264,9 +287,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -281,14 +305,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/simple_extern_example_control_blocks.c b/testdata/p4tc_samples_outputs/simple_extern_example_control_blocks.c index 628bf01fe7..c46b97de1d 100644 --- a/testdata/p4tc_samples_outputs/simple_extern_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/simple_extern_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -35,7 +40,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -176,6 +181,18 @@ ext_val = *ext_val_ptr; outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -184,6 +201,12 @@ ext_val = *ext_val_ptr; return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -315,9 +338,10 @@ ext_val = *ext_val_ptr; } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -332,14 +356,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/simple_lpm_example_control_blocks.c b/testdata/p4tc_samples_outputs/simple_lpm_example_control_blocks.c index 606c218c12..01f93dca0d 100644 --- a/testdata/p4tc_samples_outputs/simple_lpm_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/simple_lpm_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -31,7 +36,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -125,6 +130,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -133,6 +150,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -262,9 +285,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -279,14 +303,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/simple_ternary_example_control_blocks.c b/testdata/p4tc_samples_outputs/simple_ternary_example_control_blocks.c index f8bf494757..ce7dfbd4f6 100644 --- a/testdata/p4tc_samples_outputs/simple_ternary_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/simple_ternary_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) ingress_nh_table_key { u32 keysz; u32 maskid; @@ -36,7 +41,7 @@ struct __attribute__((__packed__)) ingress_nh_table_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -131,6 +136,18 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -139,6 +156,12 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -268,9 +291,10 @@ static __always_inline int process(struct __sk_buff *skb, struct my_ingress_head } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -285,14 +309,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct my_ingress_headers_t *hdr; int ret = -1; - ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/size_param_example_control_blocks.c b/testdata/p4tc_samples_outputs/size_param_example_control_blocks.c index feba76ab74..22580bb3f9 100644 --- a/testdata/p4tc_samples_outputs/size_param_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/size_param_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -54,7 +59,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -199,6 +204,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -207,6 +224,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -338,9 +361,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -355,14 +379,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/skb_meta.json b/testdata/p4tc_samples_outputs/skb_meta.json new file mode 100644 index 0000000000..ddce3a92fe --- /dev/null +++ b/testdata/p4tc_samples_outputs/skb_meta.json @@ -0,0 +1,63 @@ +{ + "schema_version" : "1.0.0", + "pipeline_name" : "skb_meta", + "externs" : [], + "tables" : [ + { + "name" : "ingress/nh_table", + "id" : 1, + "tentries" : 2048, + "permissions" : "0x3da4", + "nummask" : 8, + "keysize" : 32, + "keyfields" : [ + { + "id" : 1, + "name" : "dstAddr", + "type" : "ipv4", + "match_type" : "exact", + "bitwidth" : 32 + } + ], + "actions" : [ + { + "id" : 1, + "name" : "ingress/send_nh", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [ + { + "id" : 1, + "name" : "port", + "type" : "dev", + "bitwidth" : 32 + }, + { + "id" : 2, + "name" : "srcMac", + "type" : "macaddr", + "bitwidth" : 48 + }, + { + "id" : 3, + "name" : "dstMac", + "type" : "macaddr", + "bitwidth" : 48 + } + ], + "default_hit_action" : false, + "default_miss_action" : false + }, + { + "id" : 2, + "name" : "ingress/drop", + "action_scope" : "TableAndDefault", + "annotations" : [], + "params" : [], + "default_hit_action" : false, + "default_miss_action" : true + } + ] + } + ] +} \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/skb_meta.template b/testdata/p4tc_samples_outputs/skb_meta.template new file mode 100755 index 0000000000..20739bec2a --- /dev/null +++ b/testdata/p4tc_samples_outputs/skb_meta.template @@ -0,0 +1,24 @@ +#!/bin/bash -x + +set -e + +: "${TC:="tc"}" +$TC p4template create pipeline/skb_meta numtables 1 + +$TC p4template create action/skb_meta/ingress/send_nh actid 1 \ + param port type dev \ + param srcMac type macaddr \ + param dstMac type macaddr +$TC p4template update action/skb_meta/ingress/send_nh state active + +$TC p4template create action/skb_meta/ingress/drop actid 2 +$TC p4template update action/skb_meta/ingress/drop state active + +$TC p4template create table/skb_meta/ingress/nh_table \ + tblid 1 \ + type exact \ + keysz 32 permissions 0x3da4 tentries 2048 nummasks 1 \ + table_acts act name skb_meta/ingress/send_nh \ + act name skb_meta/ingress/drop +$TC p4template update table/skb_meta/ingress/nh_table default_miss_action permissions 0x1024 action skb_meta/ingress/drop +$TC p4template update pipeline/skb_meta state ready \ No newline at end of file diff --git a/testdata/p4tc_samples_outputs/skb_meta_control_blocks.c b/testdata/p4tc_samples_outputs/skb_meta_control_blocks.c new file mode 100644 index 0000000000..78a7825932 --- /dev/null +++ b/testdata/p4tc_samples_outputs/skb_meta_control_blocks.c @@ -0,0 +1,343 @@ +#include "skb_meta_parser.h" +struct p4tc_filter_fields p4tc_filter_fields; + +struct internal_metadata { + __u16 pkt_ether_type; +} __attribute__((aligned(4))); + +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + +struct __attribute__((__packed__)) ingress_nh_table_key { + u32 keysz; + u32 maskid; + u32 field0; /* hdr.ipv4.dstAddr */ +} __attribute__((aligned(8))); +#define INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH 1 +#define INGRESS_NH_TABLE_ACT_INGRESS_DROP 2 +#define INGRESS_NH_TABLE_ACT_NOACTION 0 +struct __attribute__((__packed__)) ingress_nh_table_value { + unsigned int action; + u32 hit:1, + is_default_miss_act:1, + is_default_hit_act:1; + union { + struct { + } _NoAction; + struct __attribute__((__packed__)) { + u32 port; + u64 srcMac; + u64 dstMac; + } ingress_send_nh; + struct { + } ingress_drop; + } u; +}; + +static __always_inline int process(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits; + hdr_start = pkt + BYTES(ebpf_packetOffsetInBits); + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); +{ + u8 hit; + u16 tmp = 0; + u16 tmp_2 = 0; + u64 tmp_5 = 0; + { +if (/* hdr->ipv4.isValid() */ + hdr->ipv4.ebpf_valid && hdr->ipv4.protocol == 0x6) { +/* nh_table_0.apply() */ + { + /* construct key */ + struct p4tc_table_entry_act_bpf_params__local params = { + .pipeid = p4tc_filter_fields.pipeid, + .tblid = 1 + }; + struct ingress_nh_table_key key; + __builtin_memset(&key, 0, sizeof(key)); + key.keysz = 32; + key.field0 = bpf_htonl(hdr->ipv4.dstAddr); + struct p4tc_table_entry_act_bpf *act_bpf; + /* value */ + struct ingress_nh_table_value *value = NULL; + /* perform lookup */ + act_bpf = bpf_p4tc_tbl_read(skb, ¶ms, sizeof(params), &key, sizeof(key)); + value = (struct ingress_nh_table_value *)act_bpf; + if (value == NULL) { + /* miss; find default action */ + hit = 0; + } else { + hit = value->hit; + } + if (value != NULL) { + /* run action */ + switch (value->action) { + case INGRESS_NH_TABLE_ACT_INGRESS_SEND_NH: + { +/* skb_get_meta() */ + bpf_p4tc_skb_meta_get(skb,&sa->get,sizeof(sa->get)); + tmp = bpf_p4tc_skb_get_tc_classid(skb, &sa->get); + /* skb_set_tc_classid((tmp + 1)) */ + bpf_p4tc_skb_set_tc_classid(skb,&sa->set,(tmp + 1)); + tmp_2 = bpf_p4tc_skb_get_tc_index(skb, &sa->get); + /* skb_set_tc_index((tmp_2 + 1)) */ + bpf_p4tc_skb_set_tc_index(skb,&sa->set,(tmp_2 + 1)); + /* skb_set_meta() */ + bpf_p4tc_skb_meta_set(skb,&sa->set,sizeof(sa->set)); + tmp_5 = bpf_p4tc_skb_get_tstamp(skb, &sa->get); + hdr->ethernet.srcAddr = (((u64)tmp_5 ^ bpf_cpu_to_be64(value->u.ingress_send_nh.srcMac)) & ((1ULL << 48) - 1)); + hdr->ethernet.dstAddr = ntohll(value->u.ingress_send_nh.dstMac << 16); + /* send_to_port(value->u.ingress_send_nh.port) */ + compiler_meta__->drop = false; + send_to_port(value->u.ingress_send_nh.port); + } + break; + case INGRESS_NH_TABLE_ACT_INGRESS_DROP: + { +/* drop_packet() */ + drop_packet(); + } + break; + case INGRESS_NH_TABLE_ACT_NOACTION: + { + } + break; + } + } else { + } + } +; } + + } + } + { +{ +; + ; + } + + if (compiler_meta__->drop) { + return TC_ACT_SHOT; + } + int outHeaderLength = 0; + if (hdr->ethernet.ebpf_valid) { + outHeaderLength += 112; + } +; if (hdr->ipv4.ebpf_valid) { + outHeaderLength += 160; + } +; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); + if (outHeaderOffset != 0) { + int returnCode = 0; + returnCode = bpf_skb_adjust_room(skb, outHeaderOffset, 1, 0); + if (returnCode) { + return TC_ACT_SHOT; + } + } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + + 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->ipv4.ebpf_valid) { + if (ebpf_packetEnd < pkt + BYTES(ebpf_packetOffsetInBits + 160)) { + return TC_ACT_SHOT; + } + + ebpf_byte = ((char*)(&hdr->ipv4.version))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 4, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.ihl))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 4, 0, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 4; + + ebpf_byte = ((char*)(&hdr->ipv4.diffserv))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = bpf_htons(hdr->ipv4.totalLen); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.totalLen))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = bpf_htons(hdr->ipv4.identification); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.identification))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + ebpf_byte = ((char*)(&hdr->ipv4.flags))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 3, 5, (ebpf_byte >> 0)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = bpf_htons(hdr->ipv4.fragOffset << 3); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[0]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0, 5, 0, (ebpf_byte >> 3)); + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 0 + 1, 3, 5, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.fragOffset))[1]; + write_partial(pkt + BYTES(ebpf_packetOffsetInBits) + 1, 5, 0, (ebpf_byte >> 3)); + ebpf_packetOffsetInBits += 13; + + ebpf_byte = ((char*)(&hdr->ipv4.ttl))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + ebpf_byte = ((char*)(&hdr->ipv4.protocol))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = bpf_htons(hdr->ipv4.hdrChecksum); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.hdrChecksum))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = htonl(hdr->ipv4.srcAddr); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.srcAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = htonl(hdr->ipv4.dstAddr); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[0]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 0, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[1]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 1, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[2]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 2, (ebpf_byte)); + ebpf_byte = ((char*)(&hdr->ipv4.dstAddr))[3]; + write_byte(pkt, BYTES(ebpf_packetOffsetInBits) + 3, (ebpf_byte)); + ebpf_packetOffsetInBits += 32; + + } +; + } + return -1; +} +SEC("p4tc/main") +int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff = { + + .get = { .bitmask = P4TC_SKB_META_GET_AT_INGRESS_BIT | P4TC_SKB_META_GET_FROM_INGRESS_BIT }, + .set = { }, +}; + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + compiler_meta__->drop = false; + compiler_meta__->recirculate = false; + if (!compiler_meta__->recirculated) { + compiler_meta__->mark = 153; + struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; + if ((void *) ((struct internal_metadata *) md + 1) <= (void *)(long)skb->data) { + __u16 *ether_type = (__u16 *) ((void *) (long)skb->data + 12); + if ((void *) ((__u16 *) ether_type + 1) > (void *) (long) skb->data_end) { + return TC_ACT_SHOT; + } + *ether_type = md->pkt_ether_type; + } + } + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = process(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__, &skbstuff); + if (ret != -1) { + return ret; + } + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; + } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; + return bpf_redirect(compiler_meta__->egress_port, 0); +} +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/skb_meta_parser.c b/testdata/p4tc_samples_outputs/skb_meta_parser.c new file mode 100644 index 0000000000..feae2db4f8 --- /dev/null +++ b/testdata/p4tc_samples_outputs/skb_meta_parser.c @@ -0,0 +1,140 @@ +#include "skb_meta_parser.h" + +struct p4tc_filter_fields p4tc_filter_fields; + +static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_headers_t *hdr, struct pna_global_metadata *compiler_meta__) +{ + struct hdr_md *hdrMd; + + unsigned ebpf_packetOffsetInBits_save = 0; + ParserError_t ebpf_errorCode = NoError; + void* pkt = ((void*)(long)skb->data); + u8* hdr_start = pkt; + void* ebpf_packetEnd = ((void*)(long)skb->data_end); + u32 ebpf_zero = 0; + u32 ebpf_one = 1; + unsigned char ebpf_byte; + u32 pkt_len = skb->len; + + struct my_ingress_metadata_t *meta; + + hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero); + if (!hdrMd) + return TC_ACT_SHOT; + __builtin_memset(hdrMd, 0, sizeof(struct hdr_md)); + + unsigned ebpf_packetOffsetInBits = 0; + hdr = &(hdrMd->cpumap_hdr); + meta = &(hdrMd->cpumap_usermeta); + { + goto start; + parse_ipv4: { +/* extract(hdr->ipv4) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(160 + 0)) { + ebpf_errorCode = PacketTooShort; + goto reject; + } + + hdr->ipv4.version = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 4) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.ihl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u8, 4)); + ebpf_packetOffsetInBits += 4; + + hdr->ipv4.diffserv = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.totalLen = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.identification = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.flags = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)) >> 5) & EBPF_MASK(u8, 3)); + ebpf_packetOffsetInBits += 3; + + hdr->ipv4.fragOffset = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits))) & EBPF_MASK(u16, 13)); + ebpf_packetOffsetInBits += 13; + + hdr->ipv4.ttl = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.protocol = (u8)((load_byte(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 8; + + hdr->ipv4.hdrChecksum = (u16)((load_half(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 16; + + hdr->ipv4.srcAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + hdr->ipv4.dstAddr = (u32)((load_word(pkt, BYTES(ebpf_packetOffsetInBits)))); + ebpf_packetOffsetInBits += 32; + + + hdr->ipv4.ebpf_valid = 1; + hdr_start += BYTES(160); + +; + u8 select_0; + select_0 = hdr->ipv4.protocol; + if (select_0 == 0x6)goto accept; + if ((select_0 & 0x0) == (0x0 & 0x0))goto reject; + else goto reject; + } + start: { +/* extract(hdr->ethernet) */ + if ((u8*)ebpf_packetEnd < hdr_start + BYTES(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; + hdr_start += BYTES(112); + +; + u16 select_1; + select_1 = hdr->ethernet.etherType; + if (select_1 == 0x800)goto parse_ipv4; + if ((select_1 & 0x0) == (0x0 & 0x0))goto reject; + else goto reject; + } + + reject: { + if (ebpf_errorCode == 0) { + return TC_ACT_SHOT; + } + compiler_meta__->parser_error = ebpf_errorCode; + goto accept; + } + + } + + accept: + hdrMd->ebpf_packetOffsetInBits = ebpf_packetOffsetInBits; + return -1; +} + +SEC("p4tc/parse") +int tc_parse_func(struct __sk_buff *skb) { + struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; + struct hdr_md *hdrMd; + struct my_ingress_headers_t *hdr; + int ret = -1; + ret = run_parser(skb, (struct my_ingress_headers_t *) hdr, compiler_meta__); + if (ret != -1) { + return ret; + } + return TC_ACT_PIPE; + } +char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/skb_meta_parser.h b/testdata/p4tc_samples_outputs/skb_meta_parser.h new file mode 100644 index 0000000000..8869b895e0 --- /dev/null +++ b/testdata/p4tc_samples_outputs/skb_meta_parser.h @@ -0,0 +1,65 @@ +#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 my_ingress_metadata_t { +}; +struct empty_metadata_t { +}; +struct ethernet_t { + u64 dstAddr; /* bit<48> */ + u64 srcAddr; /* bit<48> */ + u16 etherType; /* bit<16> */ + u8 ebpf_valid; +}; +struct ipv4_t { + u8 version; /* bit<4> */ + u8 ihl; /* bit<4> */ + u8 diffserv; /* bit<8> */ + u16 totalLen; /* bit<16> */ + u16 identification; /* bit<16> */ + u8 flags; /* bit<3> */ + u16 fragOffset; /* bit<13> */ + u8 ttl; /* bit<8> */ + u8 protocol; /* bit<8> */ + u16 hdrChecksum; /* bit<16> */ + u32 srcAddr; /* bit<32> */ + u32 dstAddr; /* bit<32> */ + u8 ebpf_valid; +}; +struct my_ingress_headers_t { + struct ethernet_t ethernet; /* ethernet_t */ + struct ipv4_t ipv4; /* ipv4_t */ +}; + +struct hdr_md { + struct my_ingress_headers_t cpumap_hdr; + struct my_ingress_metadata_t cpumap_usermeta; + unsigned ebpf_packetOffsetInBits; + __u8 __hook; +}; + +struct p4tc_filter_fields { + __u32 pipeid; + __u32 handle; + __u32 classid; + __u32 chain; + __u32 blockid; + __be16 proto; + __u16 prio; +}; + +REGISTER_START() +REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2) +BPF_ANNOTATE_KV_PAIR(hdr_md_cpumap, u32, struct hdr_md) +REGISTER_END() + diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_01_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_01_control_blocks.c index d04b12b95e..e5917830cc 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_01_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_01_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -219,6 +224,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -227,6 +244,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -358,9 +381,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -375,14 +399,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_02_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_02_control_blocks.c index 6c58d986d3..f9f030850f 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_02_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_02_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -201,6 +206,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -209,6 +226,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -340,9 +363,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -357,14 +381,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_03_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_03_control_blocks.c index 13052c1671..37517dbd54 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_03_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_03_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -53,7 +58,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -201,6 +206,18 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -209,6 +226,12 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -340,9 +363,10 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -357,14 +381,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_04_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_04_control_blocks.c index 63e2fb8e6f..5839f4c8d7 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_04_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_04_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -213,6 +218,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -221,6 +238,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -352,9 +375,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -369,14 +393,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_05_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_05_control_blocks.c index b7cd71e6db..061b01e593 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_05_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_05_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -210,6 +215,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -218,6 +235,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -349,9 +372,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -366,14 +390,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_06_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_06_control_blocks.c index 26c759277f..0254808af0 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_06_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_06_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -55,7 +60,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -219,6 +224,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -227,6 +244,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -358,9 +381,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -375,14 +399,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_07_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_07_control_blocks.c index e2eb21769d..0539af21eb 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_07_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_07_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -58,7 +63,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -228,6 +233,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -236,6 +253,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -367,9 +390,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -384,14 +408,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_08_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_08_control_blocks.c index dc919a61bb..9bfbdd7ff7 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_08_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_08_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -58,7 +63,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -228,6 +233,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -236,6 +253,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -367,9 +390,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -384,14 +408,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_may_override_example_09_control_blocks.c b/testdata/p4tc_samples_outputs/tc_may_override_example_09_control_blocks.c index bd4cbe8cc8..4bd6a9602e 100644 --- a/testdata/p4tc_samples_outputs/tc_may_override_example_09_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_may_override_example_09_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -58,7 +63,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -219,6 +224,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -227,6 +244,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -358,9 +381,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -375,14 +399,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/tc_type_annotation_example_control_blocks.c b/testdata/p4tc_samples_outputs/tc_type_annotation_example_control_blocks.c index 0fd9258eb0..d0831c7917 100644 --- a/testdata/p4tc_samples_outputs/tc_type_annotation_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/tc_type_annotation_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key { u32 keysz; u32 maskid; @@ -46,7 +51,7 @@ struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_2_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -177,6 +182,18 @@ if (/* hdr->ipv4.isValid() */ outHeaderLength += 160; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -185,6 +202,12 @@ if (/* hdr->ipv4.isValid() */ return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -314,9 +337,10 @@ if (/* hdr->ipv4.isValid() */ } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -331,14 +355,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL"; diff --git a/testdata/p4tc_samples_outputs/test_ipv6_example_control_blocks.c b/testdata/p4tc_samples_outputs/test_ipv6_example_control_blocks.c index 561e55eeb6..3657aa7c4d 100644 --- a/testdata/p4tc_samples_outputs/test_ipv6_example_control_blocks.c +++ b/testdata/p4tc_samples_outputs/test_ipv6_example_control_blocks.c @@ -5,6 +5,11 @@ struct internal_metadata { __u16 pkt_ether_type; } __attribute__((aligned(4))); +struct skb_aggregate { + struct p4tc_skb_meta_get get; + struct p4tc_skb_meta_set set; +}; + struct __attribute__((__packed__)) MainControlImpl_tbl_default_key { u32 keysz; u32 maskid; @@ -26,7 +31,7 @@ struct __attribute__((__packed__)) MainControlImpl_tbl_default_value { } u; }; -static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__) +static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__, struct skb_aggregate *sa) { struct hdr_md *hdrMd; @@ -111,6 +116,18 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, outHeaderLength += 320; } ; + __u16 saved_proto = 0; + bool have_saved_proto = false; + // bpf_skb_adjust_room works only when protocol is IPv4 or IPv6 + // 0x0800 = IPv4, 0x86dd = IPv6 + if ((skb->protocol != 0x0800) && (skb->protocol != 0x86dd)) { + saved_proto = skb->protocol; + have_saved_proto = true; + bpf_p4tc_skb_set_protocol(skb, &sa->set, 0x0800); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + ; + int outHeaderOffset = BYTES(outHeaderLength) - (hdr_start - (u8*)pkt); if (outHeaderOffset != 0) { int returnCode = 0; @@ -119,6 +136,12 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, return TC_ACT_SHOT; } } + + if (have_saved_proto) { + bpf_p4tc_skb_set_protocol(skb, &sa->set, saved_proto); + bpf_p4tc_skb_meta_set(skb, &sa->set, sizeof(sa->set)); + } + pkt = ((void*)(long)skb->data); ebpf_packetEnd = ((void*)(long)skb->data_end); ebpf_packetOffsetInBits = 0; @@ -278,9 +301,10 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, } SEC("p4tc/main") int tc_ingress_func(struct __sk_buff *skb) { + struct skb_aggregate skbstuff; struct pna_global_metadata *compiler_meta__ = (struct pna_global_metadata *) skb->cb; - if (compiler_meta__->pass_to_kernel == true) return TC_ACT_OK; compiler_meta__->drop = false; + compiler_meta__->recirculate = false; if (!compiler_meta__->recirculated) { compiler_meta__->mark = 153; struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta; @@ -295,14 +319,16 @@ int tc_ingress_func(struct __sk_buff *skb) { struct hdr_md *hdrMd; struct headers_t *hdr; int ret = -1; - ret = process(skb, (struct headers_t *) hdr, compiler_meta__); + ret = process(skb, (struct headers_t *) hdr, compiler_meta__, &skbstuff); 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); + if (!compiler_meta__->drop && compiler_meta__->recirculate) { + compiler_meta__->recirculated = true; + return TC_ACT_UNSPEC; } + if (!compiler_meta__->drop && compiler_meta__->egress_port == 0) + return TC_ACT_OK; return bpf_redirect(compiler_meta__->egress_port, 0); } char _license[] SEC("license") = "GPL";