Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support default action in P4TC #4308

Merged
merged 6 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 59 additions & 35 deletions backends/tc/ebpfCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ namespace TC {

// =====================PNAEbpfGenerator=============================
void PNAEbpfGenerator::emitPNAIncludes(EBPF::CodeBuilder *builder) const {
builder->newline();
cstring headerFile = getProgramName() + "_parser.h";
builder->appendFormat("#include \"%s\"", headerFile);
builder->newline();
builder->appendLine("#include <stdbool.h>");
builder->appendLine("#include <linux/if_ether.h>");
builder->appendLine("#include \"pna.h\"");
Expand Down Expand Up @@ -67,9 +63,6 @@ void PNAEbpfGenerator::emitInternalStructures(EBPF::CodeBuilder *builder) const

/* Generate headers and structs in p4 prog */
void PNAEbpfGenerator::emitTypes(EBPF::CodeBuilder *builder) const {
PNAErrorCodesGen errorGen(builder);
pipeline->program->apply(errorGen);

pipeline->parser->emitTypes(builder);
pipeline->control->emitTableTypes(builder);
pipeline->deparser->emitTypes(builder);
Expand Down Expand Up @@ -129,10 +122,11 @@ void PNAArchTC::emit(EBPF::CodeBuilder *builder) const {
xdp->emitGeneratedComment(builder);

/*
* 2. Includes.
* 2. Include header file.
*/
emitPNAIncludes(builder);

cstring headerFile = getProgramName() + "_parser.h";
builder->appendFormat("#include \"%s\"", headerFile);
builder->newline();
/*
* 3. Headers, structs
*/
Expand Down Expand Up @@ -179,7 +173,9 @@ void PNAArchTC::emitParser(EBPF::CodeBuilder *builder) const {
* 4. TC Pipeline program for parser.
*/
xdp->emitGeneratedComment(builder);
emitPNAIncludes(builder);
cstring headerFile = getProgramName() + "_parser.h";
builder->appendFormat("#include \"%s\"", headerFile);
builder->newline();
builder->newline();
emitInstances(builder);
pipeline->name = "tc-parse";
Expand All @@ -192,10 +188,13 @@ void PNAArchTC::emitParser(EBPF::CodeBuilder *builder) const {
void PNAArchTC::emitHeader(EBPF::CodeBuilder *builder) const {
xdp->emitGeneratedComment(builder);
builder->target->emitIncludes(builder);
emitPNAIncludes(builder);
emitPreamble(builder);
for (auto type : ebpfTypes) {
type->emit(builder);
}
PNAErrorCodesGen errorGen(builder);
pipeline->program->apply(errorGen);
emitGlobalHeadersMetadata(builder);
}

Expand Down Expand Up @@ -229,6 +228,9 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) {
if (name == "tc-parse") {
builder->newline();
emitCPUMAPInitializers(builder);
builder->newline();
builder->emitIndent();
builder->appendFormat("unsigned %s = 0;", offsetVar.c_str());
} else {
emitCPUMAPLookup(builder);
builder->emitIndent();
Expand All @@ -237,6 +239,9 @@ void TCIngressPipelinePNA::emit(EBPF::CodeBuilder *builder) {
builder->emitIndent();
builder->emitIndent();
builder->appendFormat("return %s;", dropReturnCode());
builder->newline();
builder->emitIndent();
builder->appendFormat("unsigned %s = hdrMd->%s;", offsetVar.c_str(), offsetVar.c_str());
}
builder->newline();
emitHeadersFromCPUMAP(builder);
Expand Down Expand Up @@ -445,12 +450,6 @@ void TCIngressPipelinePNA::emitTrafficManager(EBPF::CodeBuilder *builder) {
}

void TCIngressPipelinePNA::emitLocalVariables(EBPF::CodeBuilder *builder) {
builder->emitIndent();
if (name == "tc-parse") {
builder->appendFormat("unsigned %s = 0;", offsetVar.c_str());
} else if (name == "tc-ingress") {
builder->appendFormat("unsigned %s = hdrMd->%s;", offsetVar.c_str(), offsetVar.c_str());
}
builder->newline();
builder->emitIndent();
builder->appendFormat("unsigned %s_save = 0;", offsetVar.c_str());
Expand Down Expand Up @@ -807,6 +806,9 @@ void EBPFTablePNA::emitActionArguments(EBPF::CodeBuilder *builder, const IR::P4A

void EBPFTablePNA::emitAction(EBPF::CodeBuilder *builder, cstring valueName,
cstring actionRunVariable) {
builder->blockStart();
builder->emitIndent();
builder->appendLine("/* run action */");
builder->emitIndent();
builder->appendFormat("switch (%s->action) ", valueName.c_str());
builder->blockStart();
Expand Down Expand Up @@ -871,6 +873,16 @@ void EBPFTablePNA::emitAction(EBPF::CodeBuilder *builder, cstring valueName,
builder->appendFormat("%s = %s->action", actionRunVariable.c_str(), valueName.c_str());
builder->endOfStatement(true);
}

builder->blockEnd(false);
builder->appendFormat(" else ");
if (dropOnNoMatchingEntryFound()) {
builder->target->emitTraceMessage(builder, "Control: Entry not found, aborting");
emitDefaultAction(builder, valueName);
} else {
builder->target->emitTraceMessage(builder,
"Control: Entry not found, executing implicit NoAction");
}
}

void EBPFTablePNA::emitInitializer(EBPF::CodeBuilder *builder) {
Expand All @@ -893,6 +905,35 @@ void EBPFTablePNA::emitDefaultActionStruct(EBPF::CodeBuilder *builder) {
}
}

void EBPFTablePNA::emitDefaultAction(EBPF::CodeBuilder *builder, cstring valueName) {
const IR::P4Table *t = table->container;
const IR::Expression *default_action = t->getDefaultAction();
bool visitDefaultAction = false;
if (default_action) {
if (auto mc = default_action->to<IR::MethodCallExpression>()) {
default_action = mc->method;
}
auto path = default_action->to<IR::PathExpression>();
BUG_CHECK(path, "Default action path %s cannot be found", default_action);
komaljai marked this conversation as resolved.
Show resolved Hide resolved
if (auto defaultActionDecl =
program->refMap->getDeclaration(path->path)->to<IR::P4Action>()) {
if (defaultActionDecl->name.originalName != "NoAction") {
visitDefaultAction = true;
auto visitor = createActionTranslationVisitor(valueName, program);
visitor->setBuilder(builder);
visitor->copySubstitutions(codeGen);
visitor->copyPointerVariables(codeGen);
defaultActionDecl->apply(*visitor);
builder->newline();
}
}
}
if (visitDefaultAction == false) {
builder->blockStart();
builder->blockEnd(true);
}
}

void EBPFTablePNA::emitValueActionIDNames(EBPF::CodeBuilder *builder) {
// create type definition for action
builder->emitIndent();
Expand Down Expand Up @@ -962,6 +1003,7 @@ void IngressDeparserPNA::emit(EBPF::CodeBuilder *builder) {
prepareBufferTranslator->substitute(this->headers, this->parserHeaders);
controlBlock->container->body->apply(*prepareBufferTranslator);

emitBufferAdjusts(builder);
builder->emitIndent();
builder->appendFormat("%s = %s;", program->packetStartVar,
builder->target->dataOffset(program->model.CPacketName.str()));
Expand Down Expand Up @@ -1479,26 +1521,8 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) {

builder->emitIndent();
builder->appendFormat("if (%s != NULL) ", valueName.c_str());
builder->blockStart();
builder->emitIndent();
builder->appendLine("/* run action */");
table->emitAction(builder, valueName, actionVariableName);
toDereference.clear();

builder->blockEnd(false);
builder->appendFormat(" else ");
builder->blockStart();
if (table->dropOnNoMatchingEntryFound()) {
builder->target->emitTraceMessage(builder, "Control: Entry not found, aborting");
builder->emitIndent();
builder->appendFormat("return %s", builder->target->abortReturnCode().c_str());
builder->endOfStatement(true);
} else {
builder->target->emitTraceMessage(builder,
"Control: Entry not found, executing implicit NoAction");
}
builder->endOfStatement(true);
builder->blockEnd(true);
builder->blockEnd(true);

msgStr = Util::printf_format("Control: %s applied", method->object->getName().name);
Expand Down
1 change: 1 addition & 0 deletions backends/tc/ebpfCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class EBPFTablePNA : public EBPF::EBPFTablePSA {
void emitAction(EBPF::CodeBuilder *builder, cstring valueName,
cstring actionRunVariable) override;
void emitValueActionIDNames(EBPF::CodeBuilder *builder) override;
void emitDefaultAction(EBPF::CodeBuilder *builder, cstring valueName);
cstring p4ActionToActionIDName(const IR::P4Action *action) const;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@

#include "default_action_example_parser.h"
#include <stdbool.h>
#include <linux/if_ether.h>
#include "pna.h"
struct internal_metadata {
__u16 pkt_ether_type;
} __attribute__((aligned(4)));


struct __attribute__((__packed__)) MainControlImpl_ipv4_tbl_1_key {
u32 keysz;
u32 maskid;
Expand Down Expand Up @@ -87,7 +82,7 @@ int xdp_func(struct xdp_md *skb) {
static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__)
{
struct hdr_md *hdrMd;
unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits;

unsigned ebpf_packetOffsetInBits_save = 0;
ParserError_t ebpf_errorCode = NoError;
void* pkt = ((void*)(long)skb->data);
Expand All @@ -101,6 +96,7 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr,
hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero);
if (!hdrMd)
return TC_ACT_SHOT;
unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits;
hdr = &(hdrMd->cpumap_hdr);
user_meta = &(hdrMd->cpumap_usermeta);
{
Expand Down Expand Up @@ -151,8 +147,8 @@ if (/* hdr->ipv4.isValid() */
return TC_ACT_SHOT;
}
} else {
return TC_ACT_SHOT;
;
/* drop_packet() */
drop_packet();
komaljai marked this conversation as resolved.
Show resolved Hide resolved
}
}
;
Expand Down Expand Up @@ -200,8 +196,8 @@ if (/* hdr->ipv4.isValid() */
return TC_ACT_SHOT;
}
} else {
return TC_ACT_SHOT;
;
/* drop_packet() */
drop_packet();
}
}
;
Expand All @@ -224,7 +220,16 @@ if (/* hdr->ipv4.isValid() */
; if (hdr->ipv4.ebpf_valid) {
outHeaderLength += 160;
}
; pkt = ((void*)(long)skb->data);
;
int outHeaderOffset = BYTES(outHeaderLength) - BYTES(ebpf_packetOffsetInBits);
komaljai marked this conversation as resolved.
Show resolved Hide resolved
if (outHeaderOffset != 0) {
int returnCode = 0;
returnCode = bpf_skb_adjust_room(skb, outHeaderOffset, 1, 0);
if (returnCode) {
return TC_ACT_SHOT;
}
}
pkt = ((void*)(long)skb->data);
ebpf_packetEnd = ((void*)(long)skb->data_end);
ebpf_packetOffsetInBits = 0;
if (hdr->ethernet.ebpf_valid) {
Expand Down
7 changes: 2 additions & 5 deletions testdata/p4tc_samples_outputs/default_action_example_parser.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@

#include "default_action_example_parser.h"
#include <stdbool.h>
#include <linux/if_ether.h>
#include "pna.h"

REGISTER_START()
REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2)
Expand All @@ -12,7 +8,7 @@ REGISTER_END()
static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__)
{
struct hdr_md *hdrMd;
unsigned ebpf_packetOffsetInBits = 0;

unsigned ebpf_packetOffsetInBits_save = 0;
ParserError_t ebpf_errorCode = NoError;
void* pkt = ((void*)(long)skb->data);
Expand All @@ -29,6 +25,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
return TC_ACT_SHOT;
__builtin_memset(hdrMd, 0, sizeof(struct hdr_md));

unsigned ebpf_packetOffsetInBits = 0;
hdr = &(hdrMd->cpumap_hdr);
user_meta = &(hdrMd->cpumap_usermeta);
{
Expand Down
4 changes: 4 additions & 0 deletions testdata/p4tc_samples_outputs/default_action_example_parser.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "ebpf_kernel.h"

#include <stdbool.h>
#include <linux/if_ether.h>
#include "pna.h"

#define EBPF_MASK(t, w) ((((t)(1)) << (w)) - (t)1)
#define BYTES(w) ((w) / 8)
Expand Down Expand Up @@ -35,6 +38,7 @@ struct headers_t {
struct ethernet_t ethernet; /* ethernet_t */
struct ipv4_t ipv4; /* ipv4_t */
};

struct hdr_md {
struct headers_t cpumap_hdr;
struct main_metadata_t cpumap_usermeta;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@

#include "default_hit_const_example_parser.h"
#include <stdbool.h>
#include <linux/if_ether.h>
#include "pna.h"
struct internal_metadata {
__u16 pkt_ether_type;
} __attribute__((aligned(4)));


struct __attribute__((__packed__)) MainControlImpl_set_ct_options_key {
u32 keysz;
u32 maskid;
Expand Down Expand Up @@ -72,7 +67,7 @@ int xdp_func(struct xdp_md *skb) {
static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__)
{
struct hdr_md *hdrMd;
unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits;

unsigned ebpf_packetOffsetInBits_save = 0;
ParserError_t ebpf_errorCode = NoError;
void* pkt = ((void*)(long)skb->data);
Expand All @@ -86,6 +81,7 @@ static __always_inline int process(struct __sk_buff *skb, struct headers_t *hdr,
hdrMd = BPF_MAP_LOOKUP_ELEM(hdr_md_cpumap, &ebpf_zero);
if (!hdrMd)
return TC_ACT_SHOT;
unsigned ebpf_packetOffsetInBits = hdrMd->ebpf_packetOffsetInBits;
hdr = &(hdrMd->cpumap_hdr);
meta = &(hdrMd->cpumap_usermeta);
{
Expand Down Expand Up @@ -135,8 +131,6 @@ if (/* hdr->ipv4.isValid() */
return TC_ACT_SHOT;
}
} else {
return TC_ACT_SHOT;
;
}
}
; }
Expand All @@ -155,7 +149,16 @@ if (/* hdr->ipv4.isValid() */
if (hdr->eth.ebpf_valid) {
outHeaderLength += 112;
}
; pkt = ((void*)(long)skb->data);
;
int outHeaderOffset = BYTES(outHeaderLength) - BYTES(ebpf_packetOffsetInBits);
if (outHeaderOffset != 0) {
int returnCode = 0;
returnCode = bpf_skb_adjust_room(skb, outHeaderOffset, 1, 0);
if (returnCode) {
return TC_ACT_SHOT;
}
}
pkt = ((void*)(long)skb->data);
ebpf_packetEnd = ((void*)(long)skb->data_end);
ebpf_packetOffsetInBits = 0;
if (hdr->eth.ebpf_valid) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@

#include "default_hit_const_example_parser.h"
#include <stdbool.h>
#include <linux/if_ether.h>
#include "pna.h"

REGISTER_START()
REGISTER_TABLE(hdr_md_cpumap, BPF_MAP_TYPE_PERCPU_ARRAY, u32, struct hdr_md, 2)
Expand All @@ -12,7 +8,7 @@ REGISTER_END()
static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *hdr, struct pna_global_metadata *compiler_meta__)
{
struct hdr_md *hdrMd;
unsigned ebpf_packetOffsetInBits = 0;

unsigned ebpf_packetOffsetInBits_save = 0;
ParserError_t ebpf_errorCode = NoError;
void* pkt = ((void*)(long)skb->data);
Expand All @@ -29,6 +25,7 @@ static __always_inline int run_parser(struct __sk_buff *skb, struct headers_t *h
return TC_ACT_SHOT;
__builtin_memset(hdrMd, 0, sizeof(struct hdr_md));

unsigned ebpf_packetOffsetInBits = 0;
hdr = &(hdrMd->cpumap_hdr);
meta = &(hdrMd->cpumap_usermeta);
{
Expand Down
Loading
Loading