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

Add support for Register extern to PSA/eBPF backend #3202

Merged
merged 8 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could give an error for other methods

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