Skip to content

Commit

Permalink
Add support for parser errors in tc backend (#4443)
Browse files Browse the repository at this point in the history
* Try to handle pna_main_input_metadata_t fields better

* Add support for parser errors in tc backend

---------

Co-authored-by: Mouse <mouse@mojatatu.com>
  • Loading branch information
vbnogueira and mouse-mt authored Feb 26, 2024
1 parent 0b6a29e commit bbc74eb
Show file tree
Hide file tree
Showing 34 changed files with 79 additions and 31 deletions.
60 changes: 39 additions & 21 deletions backends/tc/ebpfCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,24 @@ void EBPFPnaParser::emit(EBPF::CodeBuilder *builder) {
builder->blockEnd(true);
}

void EBPFPnaParser::emitRejectState(EBPF::CodeBuilder *builder) {
builder->emitIndent();
builder->appendFormat("if (%s == 0) ", program->errorVar.c_str());
builder->blockStart();
builder->target->emitTraceMessage(
builder, "Parser: Explicit transition to reject state, dropping packet..");
builder->emitIndent();
builder->appendFormat("return %s", builder->target->abortReturnCode().c_str());
builder->endOfStatement(true);
builder->blockEnd(true);
builder->emitIndent();
builder->appendFormat("compiler_meta__->parser_error = %s", program->errorVar.c_str());
builder->endOfStatement(true);
builder->emitIndent();
builder->appendFormat("goto %s", IR::ParserState::accept.c_str());
builder->endOfStatement(true);
}

// This code is similar to compileExtractField function in PsaStateTranslationVisitor.
// Handled TC "macaddr" annotation.
void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr,
Expand Down Expand Up @@ -1306,6 +1324,26 @@ ControlBodyTranslatorPNA::ControlBodyTranslatorPNA(const EBPF::EBPFControlPSA *c
EBPF::ControlBodyTranslator(control),
tcIR(tcIR) {}

bool ControlBodyTranslatorPNA::preorder(const IR::Member *m) {
if ((m->expr != nullptr) && (m->expr->type != nullptr)) {
if (auto st = m->expr->type->to<IR::Type_Struct>()) {
if (st->name == "pna_main_input_metadata_t") {
if (m->member.name == "input_port") {
builder->append("skb->ifindex");
return false;
} else if (m->member.name == "parser_error") {
builder->append("compiler_meta__->parser_error");
return false;
} else {
::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
"%1%: this metadata field is not supported", m);
}
}
}
}
return CodeGenInspector::preorder(m);
}

ControlBodyTranslatorPNA::ControlBodyTranslatorPNA(const EBPF::EBPFControlPSA *control,
const ConvertToBackendIR *tcIR,
const EBPF::EBPFTablePSA *table)
Expand All @@ -1318,17 +1356,6 @@ cstring ControlBodyTranslatorPNA::getParamName(const IR::PathExpression *expr) {
return expr->path->name.name;
}

bool ControlBodyTranslatorPNA::checkPnaPortMem(const IR::Member *m) {
if (m->expr != nullptr && m->expr->type != nullptr) {
if (auto str_type = m->expr->type->to<IR::Type_Struct>()) {
if (str_type->name == "pna_main_input_metadata_t" && m->member.name == "input_port") {
return true;
}
}
}
return false;
}

void ControlBodyTranslatorPNA::processFunction(const P4::ExternFunction *function) {
if (function->expr->method->toString() == "send_to_port" ||
function->expr->method->toString() == "drop_packet") {
Expand All @@ -1343,12 +1370,7 @@ void ControlBodyTranslatorPNA::processFunction(const P4::ExternFunction *functio
for (auto a : *function->expr->arguments) {
if (!first) builder->append(", ");
first = false;
if (a->expression->is<IR::Member>() &&
checkPnaPortMem(a->expression->to<IR::Member>())) {
builder->append("skb->ifindex");
} else {
visit(a);
}
visit(a);
}
builder->append(")");
return;
Expand Down Expand Up @@ -1465,16 +1487,12 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) {
}
}

auto mem = c->expression->to<IR::Member>();
builder->emitIndent();
if (memcpy) {
builder->appendFormat("__builtin_memcpy(&(%s.%s[0]), &(", keyname.c_str(),
fieldName.c_str());
table->codeGen->visit(c->expression);
builder->appendFormat("[0]), %d)", scalar->bytesRequired());
} else if (mem && checkPnaPortMem(mem)) {
builder->appendFormat("%s.%s = ", keyname.c_str(), fieldName.c_str());
builder->append("skb->ifindex");
} else {
builder->appendFormat("%s.%s = ", keyname.c_str(), fieldName.c_str());
if (isLPMKeyBigEndian) builder->appendFormat("%s(", swap.c_str());
Expand Down
2 changes: 2 additions & 0 deletions backends/tc/ebpfCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class EBPFPnaParser : public EBPF::EBPFPsaParser {
EBPFPnaParser(const EBPF::EBPFProgram *program, const IR::ParserBlock *block,
const P4::TypeMap *typeMap);
void emit(EBPF::CodeBuilder *builder) override;
void emitRejectState(EBPF::CodeBuilder *) override;

DECLARE_TYPEINFO(EBPFPnaParser, EBPF::EBPFPsaParser);
};
Expand Down Expand Up @@ -316,6 +317,7 @@ class ControlBodyTranslatorPNA : public EBPF::ControlBodyTranslator {
virtual cstring getParamName(const IR::PathExpression *);
bool preorder(const IR::AssignmentStatement *a) override;
void processMethod(const P4::ExternMethod *method) override;
bool preorder(const IR::Member *) override;
};

// Similar to class ActionTranslationVisitorPSA in backends/ebpf/psa/ebpfPsaControl.h
Expand Down
1 change: 1 addition & 0 deletions backends/tc/runtime/pna.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct pna_global_metadata {
PortId_t egress_port;
enum MirrorType mirror_type;
MirrorSlotId_t mirror_slot_id;
ParserError_t parser_error;
MirrorSessionId_t mirror_session_id;
__u8 mark;
bool pass_to_kernel; // internal metadata, forces sending packet up to kernel stack
Expand Down
10 changes: 5 additions & 5 deletions testdata/p4tc_samples_outputs/calculator_control_blocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ if (/* hdr->p4calc.isValid() */
tmp_5 = hdr->ethernet.dstAddr;
hdr->ethernet.dstAddr = hdr->ethernet.srcAddr;
hdr->ethernet.srcAddr = tmp_5;
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand All @@ -103,7 +103,7 @@ if (/* hdr->p4calc.isValid() */
tmp_5 = hdr->ethernet.dstAddr;
hdr->ethernet.dstAddr = hdr->ethernet.srcAddr;
hdr->ethernet.srcAddr = tmp_5;
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand All @@ -114,7 +114,7 @@ if (/* hdr->p4calc.isValid() */
tmp_5 = hdr->ethernet.dstAddr;
hdr->ethernet.dstAddr = hdr->ethernet.srcAddr;
hdr->ethernet.srcAddr = tmp_5;
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand All @@ -125,7 +125,7 @@ if (/* hdr->p4calc.isValid() */
tmp_5 = hdr->ethernet.dstAddr;
hdr->ethernet.dstAddr = hdr->ethernet.srcAddr;
hdr->ethernet.srcAddr = tmp_5;
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand All @@ -136,7 +136,7 @@ if (/* hdr->p4calc.isValid() */
tmp_5 = hdr->ethernet.dstAddr;
hdr->ethernet.dstAddr = hdr->ethernet.srcAddr;
hdr->ethernet.srcAddr = tmp_5;
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/calculator_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/checksum_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ ck_0_state; goto accept;
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct Header_t *h,
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/drop_packet_example_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/hash1_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/ipip_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/matchtype_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ if (hdr->ipv4.protocol == 6 || ((hdr->ipv4.version > 1) && (hdr->ipv4.ihl <= 2))
switch (value->action) {
case MAINCONTROLIMPL_IPV4_TBL_3_ACT_MAINCONTROLIMPL_SENDTOPORT:
{
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand Down Expand Up @@ -377,7 +377,7 @@ if (hdr->ipv4.protocol == 6 || ((hdr->ipv4.version > 1) && (hdr->ipv4.ihl <= 2))
switch (value->action) {
case MAINCONTROLIMPL_IPV4_TBL_4_ACT_MAINCONTROLIMPL_SENDTOPORT:
{
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand Down Expand Up @@ -539,7 +539,7 @@ if (hdr->ipv4.protocol != 6) {
break;
case MAINCONTROLIMPL_SET_ALL_OPTIONS_ACT_MAINCONTROLIMPL_SENDTOPORT:
{
/* send_to_port(istd.input_port) */
/* send_to_port(skb->ifindex) */
compiler_meta__->drop = false;
send_to_port(skb->ifindex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr,
{
u8 hit;
{
if ((u32)istd.input_port == 4) {
if ((u32)skb->ifindex == 4) {
hdr->udp.src_port = (hdr->udp.src_port + 1); }

}
Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/no_table_example_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/noaction_example_01_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/noaction_example_02_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr,
{
u8 hit;
{
if (((u32)istd.input_port == 2 && /* hdr->ipv4.isValid() */
if (((u32)skb->ifindex == 2 && /* hdr->ipv4.isValid() */
hdr->ipv4.ebpf_valid) && /* hdr->tcp.isValid() */
hdr->tcp.ebpf_valid) {
/* set_ct_options_0.apply() */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
1 change: 1 addition & 0 deletions testdata/p4tc_samples_outputs/simple_lpm_example_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct my_ingress_h
if (ebpf_errorCode == 0) {
return TC_ACT_SHOT;
}
compiler_meta__->parser_error = ebpf_errorCode;
goto accept;
}

Expand Down
Loading

0 comments on commit bbc74eb

Please sign in to comment.