Skip to content

Commit

Permalink
Add support for Register extern to PSA/eBPF backend (#3202)
Browse files Browse the repository at this point in the history
* Add support for Register extern to PSA/eBPF backend

Co-authored-by: Mateusz Kossakowski <[email protected]>
Co-authored-by: Jan Palimąka <[email protected]>
  • Loading branch information
3 people authored Apr 14, 2022
1 parent 1794c3b commit 5ab6998
Show file tree
Hide file tree
Showing 17 changed files with 1,326 additions and 6 deletions.
4 changes: 3 additions & 1 deletion backends/ebpf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ set (P4C_EBPF_SRCS
psa/externs/ebpfPsaCounter.cpp
psa/externs/ebpfPsaChecksum.cpp
psa/externs/ebpfPsaHashAlgorithm.cpp
psa/externs/ebpfPsaTableImplementation.cpp)
psa/externs/ebpfPsaTableImplementation.cpp
psa/externs/ebpfPsaRegister.cpp)

set (P4C_EBPF_HDRS
codeGen.h
Expand Down Expand Up @@ -79,6 +80,7 @@ set (P4C_EBPF_HDRS
psa/externs/ebpfPsaChecksum.h
psa/externs/ebpfPsaHashAlgorithm.h
psa/externs/ebpfPsaTableImplementation.h
psa/externs/ebpfPsaRegister.h
)

add_cpplint_files(${CMAKE_CURRENT_SOURCE_DIR} "${P4C_EBPF_SRCS};${P4C_EBPF_HDRS}")
Expand Down
21 changes: 21 additions & 0 deletions backends/ebpf/ebpfControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,27 @@ void EBPFControl::emitDeclaration(CodeBuilder* builder, const IR::Declaration* d
bool isPointer = codeGen->isPointerVariable(decl->name.name);
etype->declareInit(builder, vd->name, isPointer);
builder->endOfStatement(true);

if (!isPointer) {
if (auto type = etype->to<EBPFTypeName>()) {
if (type->canonicalTypeIs<EBPFStructType>()) {
// A struct type might be used as a lookup key.
// When a data structure is aligned and is not packed,
// the compiler might generate offsets between fields.
// The BPF verifier may reject using such structures with
// uninitialized offsets as lookup keys.
// Therefore, this piece of code zero-initialize structures
// that might be used as keys.
builder->emitIndent();
builder->appendFormat("__builtin_memset((void *) &%s, 0, sizeof(",
vd->name.name);
etype->declare(builder, cstring::empty, false);
builder->append("))");
builder->endOfStatement(true);
}
}
}

BUG_CHECK(vd->initializer == nullptr,
"%1%: declarations with initializers not supported", decl);
return;
Expand Down
7 changes: 4 additions & 3 deletions backends/ebpf/ebpfTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ namespace EBPF {

bool ActionTranslationVisitor::preorder(const IR::PathExpression* expression) {
if (isActionParameter(expression)) {
cstring paramStr = getActionParamStr(expression);
builder->append(paramStr.c_str());
cstring paramInstanceName = getParamInstanceName(expression);
builder->append(paramInstanceName.c_str());
return false;
}
visit(expression->path);
Expand All @@ -41,7 +41,8 @@ bool ActionTranslationVisitor::isActionParameter(const IR::PathExpression *expre
return false;
}

cstring ActionTranslationVisitor::getActionParamStr(const IR::Expression *expression) const {
cstring ActionTranslationVisitor::getParamInstanceName(
const IR::Expression *expression) const {
cstring actionName = EBPFObject::externalName(action);
auto paramStr = Util::printf_format("%s->u.%s.%s",
valueName, actionName,
Expand Down
2 changes: 1 addition & 1 deletion backends/ebpf/ebpfTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ActionTranslationVisitor : public virtual CodeGenInspector {
bool preorder(const IR::PathExpression* expression);

bool preorder(const IR::P4Action* act);
virtual cstring getActionParamStr(const IR::Expression *expression) const;
virtual cstring getParamInstanceName(const IR::Expression *expression) const;
bool isActionParameter(const IR::PathExpression *expression) const;
}; // ActionTranslationVisitor

Expand Down
3 changes: 3 additions & 0 deletions backends/ebpf/ebpfType.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ class EBPFTypeName : public EBPFType, public IHasWidth {
unsigned widthInBits() override;
unsigned implementationWidthInBits() override;
void declareArray(CodeBuilder* builder, cstring id, unsigned size) override;

template<typename T> bool canonicalTypeIs() const
{ return dynamic_cast<const T*>(this->canonical) != nullptr; }
};

// Also represents headers and unions
Expand Down
63 changes: 62 additions & 1 deletion backends/ebpf/psa/ebpfPsaControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@ ControlBodyTranslatorPSA::ControlBodyTranslatorPSA(const EBPFControlPSA* control
CodeGenInspector(control->program->refMap, control->program->typeMap),
ControlBodyTranslator(control) {}

bool ControlBodyTranslatorPSA::preorder(const IR::AssignmentStatement* a) {
if (auto methodCallExpr = a->right->to<IR::MethodCallExpression>()) {
auto mi = P4::MethodInstance::resolve(methodCallExpr,
control->program->refMap,
control->program->typeMap);
auto ext = mi->to<P4::ExternMethod>();
if (ext == nullptr) {
return false;
}

if (ext->originalExternType->name.name == "Register" &&
ext->method->type->name == "read") {
cstring name = EBPFObject::externalName(ext->object);
auto reg = control->to<EBPFControlPSA>()->getRegister(name);
reg->emitRegisterRead(builder, ext, this, a->left);
return false;
}
}

return CodeGenInspector::preorder(a);
}

void ControlBodyTranslatorPSA::processMethod(const P4::ExternMethod* method) {
auto decl = method->object;
auto declType = method->originalExternType;
Expand All @@ -32,9 +54,48 @@ void ControlBodyTranslatorPSA::processMethod(const P4::ExternMethod* method) {
auto counterMap = control->getCounter(name);
counterMap->to<EBPFCounterPSA>()->emitMethodInvocation(builder, method, this);
return;
} else if (declType->name.name == "Register") {
auto reg = control->to<EBPFControlPSA>()->getRegister(name);
if (method->method->type->name == "write") {
reg->emitRegisterWrite(builder, method, this);
} else if (method->method->type->name == "read") {
::warning(ErrorType::WARN_UNUSED, "This Register(%1%) read value is not used!", name);
reg->emitRegisterRead(builder, method, this, nullptr);
}
return;
} else {
::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET,
"%1%: Unexpected method call", method->expr);
}
}

cstring ControlBodyTranslatorPSA::getParamName(const IR::PathExpression *expr) {
return expr->path->name.name;
}

void EBPFControlPSA::emitTableTypes(CodeBuilder *builder) {
EBPFControl::emitTableTypes(builder);

for (auto it : registers)
it.second->emitTypes(builder);
}

ControlBodyTranslator::processMethod(method);
void EBPFControlPSA::emitTableInstances(CodeBuilder* builder) {
for (auto it : tables)
it.second->emitInstance(builder);
for (auto it : counters)
it.second->emitInstance(builder);
for (auto it : registers)
it.second->emitInstance(builder);
}

void EBPFControlPSA::emitTableInitializers(CodeBuilder* builder) {
for (auto it : tables) {
it.second->emitInitializer(builder);
}
for (auto it : registers) {
it.second->emitInitializer(builder);
}
}

}
18 changes: 18 additions & 0 deletions backends/ebpf/psa/ebpfPsaControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.

#include "ebpfPsaTable.h"
#include "backends/ebpf/ebpfControl.h"
#include "backends/ebpf/psa/externs/ebpfPsaRegister.h"

namespace EBPF {

Expand All @@ -28,7 +29,11 @@ class ControlBodyTranslatorPSA : public ControlBodyTranslator {
public:
explicit ControlBodyTranslatorPSA(const EBPFControlPSA* control);

bool preorder(const IR::AssignmentStatement* a) override;

void processMethod(const P4::ExternMethod* method) override;

virtual cstring getParamName(const IR::PathExpression *);
};

class ActionTranslationVisitorPSA : public ActionTranslationVisitor,
Expand All @@ -44,6 +49,8 @@ class ActionTranslationVisitorPSA : public ActionTranslationVisitor,
bool isActionParameter(const IR::Expression *expression) const;

void processMethod(const P4::ExternMethod* method) override;
cstring getParamInstanceName(const IR::Expression *expression) const override;
cstring getParamName(const IR::PathExpression *) override;
};

class EBPFControlPSA : public EBPFControl {
Expand All @@ -55,9 +62,20 @@ class EBPFControlPSA : public EBPFControl {
const IR::Parameter* inputStandardMetadata;
const IR::Parameter* outputStandardMetadata;

std::map<cstring, EBPFRegisterPSA*> registers;

EBPFControlPSA(const EBPFProgram* program, const IR::ControlBlock* control,
const IR::Parameter* parserHeaders) :
EBPFControl(program, control, parserHeaders) {}

void emitTableTypes(CodeBuilder* builder) override;
void emitTableInstances(CodeBuilder* builder) override;
void emitTableInitializers(CodeBuilder* builder) override;

EBPFRegisterPSA* getRegister(cstring name) const {
auto result = ::get(registers, name);
BUG_CHECK(result != nullptr, "No register named %1%", name);
return result; }
};

} // namespace EBPF
Expand Down
3 changes: 3 additions & 0 deletions backends/ebpf/psa/ebpfPsaGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ bool ConvertToEBPFControlPSA::preorder(const IR::ExternBlock* instance) {
} else if (typeName == "Counter") {
auto ctr = new EBPFCounterPSA(program, di, name, control->codeGen);
control->counters.emplace(name, ctr);
} else if (typeName == "Register") {
auto reg = new EBPFRegisterPSA(program, name, di, control->codeGen);
control->registers.emplace(name, reg);
} else if (typeName == "DirectCounter") {
// instance will be created by table
return false;
Expand Down
16 changes: 16 additions & 0 deletions backends/ebpf/psa/ebpfPsaTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,22 @@ void ActionTranslationVisitorPSA::processMethod(const P4::ExternMethod* method)
}
}

cstring ActionTranslationVisitorPSA::getParamInstanceName(
const IR::Expression *expression) const {
if (auto cast = expression->to<IR::Cast>())
expression = cast->expr;

return ActionTranslationVisitor::getParamInstanceName(expression);
}

cstring ActionTranslationVisitorPSA::getParamName(const IR::PathExpression *expr) {
if (isActionParameter(expr)) {
return getParamInstanceName(expr);
}

return ControlBodyTranslatorPSA::getParamName(expr);
}

// =====================EBPFTablePSA=============================
EBPFTablePSA::EBPFTablePSA(const EBPFProgram* program, const IR::TableBlock* table,
CodeGenInspector* codeGen) :
Expand Down
Loading

0 comments on commit 5ab6998

Please sign in to comment.