Skip to content

Commit

Permalink
Support of Digest extern in P4TC
Browse files Browse the repository at this point in the history
  • Loading branch information
komaljai committed Jul 31, 2024
1 parent 9d4e3c1 commit 64f40b4
Show file tree
Hide file tree
Showing 24 changed files with 1,918 additions and 23 deletions.
8 changes: 4 additions & 4 deletions backends/ebpf/psa/externs/ebpfPsaDigest.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ class EBPFDigestPSA : public EBPFObject {
private:
cstring instanceName;
const EBPFProgram *program;
EBPFType *valueType;
cstring valueTypeName;
const IR::Declaration_Instance *declaration;
/// arbitrary value for max queue size
/// TODO: make it configurable
int maxDigestQueueSize = 128;

public:
EBPFType *valueType;
EBPFDigestPSA(const EBPFProgram *program, const IR::Declaration_Instance *di);

void emitTypes(CodeBuilder *builder);
void emitInstance(CodeBuilder *builder) const;
void processMethod(CodeBuilder *builder, cstring method, const IR::MethodCallExpression *expr,
DeparserBodyTranslatorPSA *visitor);

void emitPushElement(CodeBuilder *builder, const IR::Expression *elem,
Inspector *codegen) const;
void emitPushElement(CodeBuilder *builder, cstring elem) const;
virtual void emitPushElement(CodeBuilder *builder, const IR::Expression *elem,
Inspector *codegen) const;
virtual void emitPushElement(CodeBuilder *builder, cstring elem) const;
};

} // namespace EBPF
Expand Down
39 changes: 30 additions & 9 deletions backends/tc/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,8 @@ safe_vector<const IR::TCKey *> ConvertToBackendIR::processExternConstructor(
} else {
/* If a parameter is not annoated by tc_init or tc_numel then it is emitted as
constructor parameters.*/
IR::TCKey *key = new IR::TCKey(0, parameter->type->width_bits(),
cstring ptype = "bit"_cs + std::to_string(parameter->type->width_bits());
IR::TCKey *key = new IR::TCKey(0, parameter->type->width_bits(), ptype,
parameter->toString(), "param"_cs, false);
keys.push_back(key);
if (exp->is<IR::Constant>()) {
Expand Down Expand Up @@ -910,8 +911,9 @@ safe_vector<const IR::TCKey *> ConvertToBackendIR::processCounterControlPathKeys
auto temp_keys = HandleTypeNameStructField(field, extn, decl, kId, annoName);
keys.insert(keys.end(), temp_keys.begin(), temp_keys.end());
} else {
IR::TCKey *key =
new IR::TCKey(kId++, field->type->width_bits(), field->toString(), annoName, true);
cstring ptype = "bit"_cs + std::to_string(field->type->width_bits());
IR::TCKey *key = new IR::TCKey(kId++, field->type->width_bits(), ptype,
field->toString(), annoName, true);
keys.push_back(key);
}
}
Expand Down Expand Up @@ -942,8 +944,9 @@ safe_vector<const IR::TCKey *> ConvertToBackendIR::processExternControlPath(
auto temp_keys = HandleTypeNameStructField(field, extn, decl, kId, annoName);
keys.insert(keys.end(), temp_keys.begin(), temp_keys.end());
} else {
IR::TCKey *key = new IR::TCKey(kId++, field->type->width_bits(), field->toString(),
annoName, true);
cstring ptype = "bit"_cs + std::to_string(field->type->width_bits());
IR::TCKey *key = new IR::TCKey(kId++, field->type->width_bits(), ptype,
field->toString(), annoName, true);
keys.push_back(key);
}
}
Expand All @@ -965,13 +968,27 @@ safe_vector<const IR::TCKey *> ConvertToBackendIR::HandleTypeNameStructField(
/* If 'T' is of Type_Struct, extract all fields of structure*/
if (auto param_struct = param_val->to<IR::Type_Struct>()) {
for (auto f : param_struct->fields) {
IR::TCKey *key =
new IR::TCKey(kId++, f->type->width_bits(), f->toString(), annoName, true);
cstring ptype = "bit"_cs + std::to_string(f->type->width_bits());
if (auto anno = f->getAnnotations()->getSingle(ParseTCAnnotations::tcType)) {
auto expr = anno->expr[0];
if (auto typeLiteral = expr->to<IR::StringLiteral>()) {
ptype = typeLiteral->value;
}
}
IR::TCKey *key = new IR::TCKey(kId++, f->type->width_bits(), ptype,
f->toString(), annoName, true);
keys.push_back(key);
}
} else {
IR::TCKey *key = new IR::TCKey(kId++, param_val->width_bits(), field->toString(),
annoName, true);
cstring ptype = "bit"_cs + std::to_string(param_val->width_bits());
if (auto anno = field->getAnnotations()->getSingle(ParseTCAnnotations::tcType)) {
auto expr = anno->expr[0];
if (auto typeLiteral = expr->to<IR::StringLiteral>()) {
ptype = typeLiteral->value;
}
}
IR::TCKey *key = new IR::TCKey(kId++, param_val->width_bits(), ptype,
field->toString(), annoName, true);
keys.push_back(key);
}
break;
Expand Down Expand Up @@ -1025,6 +1042,10 @@ void ConvertToBackendIR::postorder(const IR::Declaration_Instance *decl) {
eb->externId = "0x1A000000"_cs;
} else if (eName == "Counter") {
eb->externId = "0x19000000"_cs;
} else if (eName == "Digest") {
eb->externId = "0x05000000"_cs;
instance->is_num_elements = true;
instance->num_elements = 0;
} else {
externCount += 1;
std::stringstream value;
Expand Down
8 changes: 4 additions & 4 deletions backends/tc/ebpfCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ void PNAEbpfGenerator::emitP4TCActionParam(EBPF::CodeBuilder *builder) const {

void PNAEbpfGenerator::emitPipelineInstances(EBPF::CodeBuilder *builder) const {
pipeline->parser->emitValueSetInstances(builder);
pipeline->deparser->emitDigestInstances(builder);

builder->target->emitTableDecl(builder, "hdr_md_cpumap"_cs, EBPF::TablePerCPUArray, "u32"_cs,
"struct hdr_md"_cs, 2);
Expand Down Expand Up @@ -1185,7 +1184,7 @@ void IngressDeparserPNA::emitPreDeparser(EBPF::CodeBuilder *builder) {

void IngressDeparserPNA::emit(EBPF::CodeBuilder *builder) {
codeGen->setBuilder(builder);

emitExternDefinition(builder);
for (auto a : controlBlock->container->controlLocals) {
if (a->is<IR::Declaration_Variable>()) {
auto vd = a->to<IR::Declaration_Variable>();
Expand Down Expand Up @@ -1324,7 +1323,7 @@ bool ConvertToEbpfPipelineTC::preorder(const IR::PackageBlock *block) {
CHECK_NULL(pipeline->control);

auto deparser_converter = new ConvertToEBPFDeparserPNA(
pipeline, pipeline->parser->headers, pipeline->control->outputStandardMetadata);
pipeline, pipeline->parser->headers, pipeline->control->outputStandardMetadata, tcIR);
deparserBlock->apply(*deparser_converter);
pipeline->deparser = deparser_converter->getEBPFDeparser();
CHECK_NULL(pipeline->deparser);
Expand Down Expand Up @@ -1516,8 +1515,9 @@ bool ConvertToEBPFDeparserPNA::preorder(const IR::Declaration_Instance *di) {
auto baseType = typeSpec->baseType;
auto typeName = baseType->to<IR::Type_Name>()->path->name.name;
if (typeName == "Digest") {
deparser->addExternDeclaration = true;
cstring instance = EBPF::EBPFObject::externalName(di);
auto digest = new EBPF::EBPFDigestPSA(program, di);
auto digest = new EBPFDigestPNA(program, di, typeName, tcIR);
deparser->digests.emplace(instance, digest);
}
}
Expand Down
16 changes: 14 additions & 2 deletions backends/tc/ebpfCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,18 @@ class IngressDeparserPNA : public EBPF::EBPFDeparserPSA {
const IR::Parameter *parserHeaders, const IR::Parameter *istd)
: EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd) {}

bool addExternDeclaration = false;
bool build() override;
void emit(EBPF::CodeBuilder *builder) override;
void emitPreDeparser(EBPF::CodeBuilder *builder) override;
void emitDeclaration(EBPF::CodeBuilder *builder, const IR::Declaration *decl) override;

void emitExternDefinition(EBPF::CodeBuilder *builder) {
if (addExternDeclaration) {
builder->emitIndent();
builder->appendLine("struct p4tc_ext_bpf_params ext_params = {};");
}
}
DECLARE_TYPEINFO(IngressDeparserPNA, EBPF::EBPFDeparserPSA);
};

Expand Down Expand Up @@ -329,12 +336,17 @@ class ConvertToEBPFDeparserPNA : public Inspector {
EBPF::EBPFProgram *program;
const IR::Parameter *parserHeaders;
const IR::Parameter *istd;
const ConvertToBackendIR *tcIR;
TC::IngressDeparserPNA *deparser;

public:
ConvertToEBPFDeparserPNA(EBPF::EBPFProgram *program, const IR::Parameter *parserHeaders,
const IR::Parameter *istd)
: program(program), parserHeaders(parserHeaders), istd(istd), deparser(nullptr) {}
const IR::Parameter *istd, const ConvertToBackendIR *tcIR)
: program(program),
parserHeaders(parserHeaders),
istd(istd),
tcIR(tcIR),
deparser(nullptr) {}

bool preorder(const IR::ControlBlock *) override;
bool preorder(const IR::Declaration_Instance *) override;
Expand Down
2 changes: 1 addition & 1 deletion backends/tc/introspection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void IntrospectionGenerator::collectExternInfo() {
keyField->id = control_field->keyID;
keyField->name = control_field->keyName;
keyField->attribute = control_field->keyAttribute;
keyField->type = "bit" + Util::toString(control_field->bitwidth);
keyField->type = control_field->type;
keyField->bitwidth = control_field->bitwidth;
externInstanceInfo->keyFields.push_back(keyField);
}
Expand Down
8 changes: 8 additions & 0 deletions backends/tc/runtime/pna.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ extern int xdp_p4tc_extern_md_write(struct xdp_md *xdp_ctx,
struct p4tc_ext_bpf_val *val,
const u32 val__sz) __ksym;

int bpf_p4tc_extern_digest_pack(struct __sk_buff *skb,
struct p4tc_ext_bpf_params *params,
const u32 params__sz) __ksym;

int xdp_p4tc_extern_digest_pack(struct xdp_md *xdp_ctx,
struct p4tc_ext_bpf_params *params,
const u32 params__sz) __ksym;

/* Timestamp PNA extern */
static inline u64 bpf_p4tc_extern_timestamp() {
return bpf_ktime_get_ns();
Expand Down
6 changes: 4 additions & 2 deletions backends/tc/tc.def
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,16 @@ class TCTable {
class TCKey {
unsigned keyID;
unsigned bitwidth;
cstring type;
cstring keyName;
cstring keyAttribute;
bool emitID;
bool emitValue;
unsigned value;
TCKey(unsigned id, unsigned width, cstring name, cstring attr, bool isID) {
TCKey(unsigned id, unsigned width, cstring ptype, cstring name, cstring attr, bool isID) {
keyID = id;
bitwidth = width;
type = ptype;
keyName = name;
keyAttribute = attr;
emitID = isID;
Expand All @@ -446,7 +448,7 @@ class TCKey {
emitValue = true;
}
toString {
std::string tckeyInstance = " " + keyAttribute + " " + keyName + " ptype bit" + Util::toString(bitwidth);
std::string tckeyInstance = " " + keyAttribute + " " + keyName + " ptype " + type;
if (emitID) {
tckeyInstance += " id " + Util::toString(keyID);
}
Expand Down
45 changes: 45 additions & 0 deletions backends/tc/tcExterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,49 @@ cstring InternetChecksumAlgorithmPNA::getConvertByteOrderFunction(unsigned width
return emit;
}

void EBPFDigestPNA::emitInitializer(EBPF::CodeBuilder *builder) const {
builder->newline();
builder->emitIndent();
builder->appendLine("__builtin_memset(&ext_params, 0, sizeof(struct p4tc_ext_bpf_params));");
builder->emitIndent();
builder->appendLine("ext_params.pipe_id = p4tc_filter_fields.pipeid;");
builder->emitIndent();
auto extId = tcIR->getExternId(externName);
BUG_CHECK(!extId.isNullOrEmpty(), "Extern ID not found");
builder->appendFormat("ext_params.ext_id = %s;", extId);
builder->newline();
builder->emitIndent();
auto instId = tcIR->getExternInstanceId(externName, instanceName);
BUG_CHECK(instId != 0, "Extern instance ID not found");
builder->appendFormat("ext_params.inst_id = %d;", instId);
builder->newline();
}

void EBPFDigestPNA::emitPushElement(EBPF::CodeBuilder *builder, const IR::Expression *elem,
Inspector *codegen) const {
emitInitializer(builder);
builder->newline();
builder->emitIndent();
builder->append("__builtin_memcpy(ext_params.in_params, &");
codegen->visit(elem);
builder->append(", sizeof(");
this->valueType->declare(builder, cstring::empty, false);
builder->append("));");
builder->newline();
builder->emitIndent();
builder->append("bpf_p4tc_extern_digest_pack(skb, &ext_params, sizeof(ext_params))");
}

void EBPFDigestPNA::emitPushElement(EBPF::CodeBuilder *builder, cstring elem) const {
emitInitializer(builder);
builder->newline();
builder->emitIndent();
builder->appendFormat("__builtin_memcpy(ext_params.in_params, &%s, sizeof(", elem);
this->valueType->declare(builder, cstring::empty, false);
builder->append("));");
builder->newline();
builder->emitIndent();
builder->append("bpf_p4tc_extern_digest_pack(skb, &ext_params, sizeof(ext_params));");
}

} // namespace TC
19 changes: 19 additions & 0 deletions backends/tc/tcExterns.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,25 @@ class EBPFInternetChecksumPNA : public EBPFChecksumPNA {
const IR::MethodCallExpression *expr, Visitor *visitor) override;
};

class EBPFDigestPNA : public EBPF::EBPFDigestPSA {
const ConvertToBackendIR *tcIR;
cstring externName;
cstring instanceName;

public:
EBPFDigestPNA(const EBPF::EBPFProgram *program, const IR::Declaration_Instance *di,
cstring externName, const ConvertToBackendIR *tcIR)
: EBPF::EBPFDigestPSA(program, di) {
this->tcIR = tcIR;
this->externName = externName;
this->instanceName = di->toString();
}
void emitInitializer(EBPF::CodeBuilder *builder) const;
void emitPushElement(EBPF::CodeBuilder *builder, const IR::Expression *elem,
Inspector *codegen) const;
void emitPushElement(EBPF::CodeBuilder *builder, cstring elem) const;
};

} // namespace TC

#endif /* BACKENDS_TC_TCEXTERNS_H_ */
7 changes: 6 additions & 1 deletion p4include/tc/pna.p4
Original file line number Diff line number Diff line change
Expand Up @@ -554,10 +554,15 @@ extern ActionSelector {
// BEGIN:Digest_extern
extern Digest<T> {
Digest(); /// define a digest stream to the control plane
void pack(in T data); /// emit data into the stream
@tc_md_exec void pack(in T data); /// emit data into the stream
}
// END:Digest_extern

struct tc_ControlPath_Digest<T> {
@tc_key bit<32> index;
@tc_data T data;
}

enum PNA_Source_t {
FROM_HOST,
FROM_NET
Expand Down
Loading

0 comments on commit 64f40b4

Please sign in to comment.