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

Fix missing declaration of custom externs in the generated eBPF/uBPF header file. #4644

Merged
merged 7 commits into from
May 8, 2024
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: 2 additions & 2 deletions backends/ebpf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ if(NOT APPLE)
set(FETCHCONTENT_QUIET OFF)
fetchcontent_declare(
bpfrepo
URL https://github.com/libbpf/libbpf/archive/refs/tags/v1.2.2.tar.gz
URL_HASH SHA256=32b0c41eabfbbe8e0c8aea784d7495387ff9171b5a338480a8fbaceb9da8d5e5
URL https://github.com/libbpf/libbpf/archive/refs/tags/v1.4.1.tar.gz
URL_HASH SHA256=cc01a3a05d25e5978c20be7656f14eb8b6fcb120bb1c7e8041e497814fc273cb
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/runtime/contrib/libbpf
USES_TERMINAL_DOWNLOAD TRUE
GIT_PROGRESS TRUE
Expand Down
31 changes: 31 additions & 0 deletions backends/ebpf/ebpfProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,24 @@ void EBPFProgram::emitTypes(CodeBuilder *builder) {
type->emit(builder);
builder->newline();
}
// TODO: This code is disabled until we fix stability issues in Ubuntu 20.04.
// For an unclear reason we can not use definitions and declarations for eBPF externs there.
// All externs need to be defined as static inline, which clashes with these definitions.
// Context: https://github.com/p4lang/p4c/pull/4644
// if (const auto *method = d->to<IR::Method>()) {
// if (!method->srcInfo.isValid()) {
// continue;
// }
// // Ignore methods originating from core.p4 and ubpf_model.p4 because they are already
// // defined.
// // TODO: Maybe we should still generate declarations for these methods?
// if (isLibraryMethod(method->controlPlaneName())) {
// continue;
// }
// EBPFMethodDeclaration methodInstance(method);
// methodInstance.emit(builder);
// builder->newline();
// }
}
}

Expand Down Expand Up @@ -332,4 +350,17 @@ void EBPFProgram::emitPipeline(CodeBuilder *builder) {
}
}

bool EBPFProgram::isLibraryMethod(cstring methodName) {
static std::set<cstring> DEFAULT_METHODS = {"static_assert", "verify"};
if (DEFAULT_METHODS.find(methodName) != DEFAULT_METHODS.end() && options.target != "xdp") {
return true;
}

static std::set<cstring> XDP_METHODS = {
"ebpf_ipv4_checksum", "csum_replace2", "csum_replace4",
"BPF_PERF_EVENT_OUTPUT", "BPF_KTIME_GET_NS",
};
return XDP_METHODS.find(methodName) != XDP_METHODS.end();
}

} // namespace EBPF
5 changes: 5 additions & 0 deletions backends/ebpf/ebpfProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ class EBPFProgram : public EBPFObject {
virtual void emitLocalVariables(CodeBuilder *builder);
virtual void emitPipeline(CodeBuilder *builder);

/// Checks whether a method name is considered to be part of the standard library, e.g., defined
/// in core.p4 or ebpf_model.p4.
/// TODO: Should we also distinguish overloaded methods?
virtual bool isLibraryMethod(cstring methodName);

public:
virtual void emitCommonPreamble(CodeBuilder *builder);
virtual void emitGeneratedComment(CodeBuilder *builder);
Expand Down
56 changes: 55 additions & 1 deletion backends/ebpf/ebpfType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ EBPFType *EBPFTypeFactory::create(const IR::Type *type) {
auto canon = typeMap->getTypeType(type, true);
result = create(canon);
result = new EBPFTypeName(tn, result);
} else if (auto te = type->to<IR::Type_Enum>()) {
} else if (const auto *te = type->to<IR::Type_Enum>()) {
result = new EBPFEnumType(te);
} else if (auto te = type->to<IR::Type_Error>()) {
result = new EBPFErrorType(te);
} else if (auto ts = type->to<IR::Type_Stack>()) {
auto et = create(ts->elementType);
if (et == nullptr) return nullptr;
Expand Down Expand Up @@ -325,4 +327,56 @@ void EBPFEnumType::emit(EBPF::CodeBuilder *builder) {
builder->blockEnd(true);
}

////////////////////////////////////////////////////////////////

void EBPFErrorType::declare(EBPF::CodeBuilder *builder, cstring id, bool asPointer) {
builder->append("enum ");
builder->append(getType()->name);
if (asPointer) builder->append("*");
builder->append(" ");
builder->append(id);
}

void EBPFErrorType::declareInit(CodeBuilder *builder, cstring id, bool asPointer) {
declare(builder, id, asPointer);
}

void EBPFErrorType::emit(EBPF::CodeBuilder *builder) {
builder->append("enum ");
auto et = getType();
builder->append(et->name);
builder->blockStart();
for (auto m : et->members) {
builder->append(m->name);
builder->appendLine(",");
}
builder->blockEnd(true);
}

////////////////////////////////////////////////////////////////

EBPFMethodDeclaration::EBPFMethodDeclaration(const IR::Method *method) : method_(method) {}

void EBPFMethodDeclaration::emit(CodeBuilder *builder) {
auto *returnType = EBPFTypeFactory::instance->create(method_->type->returnType);
builder->append("extern ");
returnType->emit(builder);
builder->append(" ");
builder->append(method_->name);
builder->append("(");
for (const auto *parameter : method_->getParameters()->parameters) {
if (parameter->direction == IR::Direction::None ||
parameter->direction == IR::Direction::In) {
builder->append("const ");
}
auto *type = EBPFTypeFactory::instance->create(parameter->type);
type->declare(builder, parameter->name, false);
if (parameter != method_->getParameters()->parameters.back()) {
builder->append(", ");
}
}
builder->append(");");
builder->newline();
}

} // namespace EBPF
29 changes: 29 additions & 0 deletions backends/ebpf/ebpfType.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,35 @@ class EBPFEnumType : public EBPFType, public EBPF::IHasWidth {
DECLARE_TYPEINFO(EBPFEnumType, EBPFType, IHasWidth);
};

class EBPFErrorType : public EBPFType, public EBPF::IHasWidth {
public:
explicit EBPFErrorType(const IR::Type_Error *type) : EBPFType(type) {}
void emit(CodeBuilder *builder) override;
void declare(CodeBuilder *builder, cstring id, bool asPointer) override;
void declareInit(CodeBuilder *builder, cstring id, bool asPointer) override;
void emitInitializer(CodeBuilder *builder) override { builder->append("0"); }
unsigned widthInBits() const override { return 32; }
unsigned implementationWidthInBits() const override { return 32; }
const IR::Type_Error *getType() const { return type->to<IR::Type_Error>(); }

DECLARE_TYPEINFO(EBPFErrorType, EBPFType, IHasWidth);
};

/// Methods are function signatures.
class EBPFMethodDeclaration : public EBPFObject {
private:
/// The underlying P4 method of this declaration.
const IR::Method *method_;

public:
explicit EBPFMethodDeclaration(const IR::Method *method);

/// Emit the signature declaration of this method in C-style form.
void emit(CodeBuilder *builder);

DECLARE_TYPEINFO(EBPFMethodDeclaration, EBPFObject);
};

} // namespace EBPF

#endif /* BACKENDS_EBPF_EBPFTYPE_H_ */
4 changes: 3 additions & 1 deletion backends/ebpf/runtime/runtime.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ BPFOBJ=
BPFNAME=$(basename $(BPFOBJ))
BPFDIR=$(dir $(BPFOBJ))
override INCLUDES+= -I$(dir $(BPFOBJ))
# This can be any file with the extension ".c"
EXTERNOBJ=

# Arguments for the P4 Compiler
P4INCLUDE=-I./p4include
Expand All @@ -31,7 +33,7 @@ SOURCE_BASE= $(ROOT_DIR)ebpf_runtime.c $(ROOT_DIR)pcap_util.c
SOURCE_BASE+= $(ROOT_DIR)ebpf_runtime_$(TARGET).c
# Add the generated file and externs to the base sources
override SOURCES+= $(SOURCE_BASE)
SRC_PROCESSED= $(notdir $(SOURCES))
SRC_PROCESSED= $(notdir $(SOURCES)) $(EXTERNOBJ)
OBJECTS = $(SRC_PROCESSED:%.c=$(BUILDDIR)/%.o)
DEPS = $(OBJECTS:%.o=%.d)

Expand Down
14 changes: 14 additions & 0 deletions backends/ubpf/ubpfProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ void UBPFProgram::emitTypes(EBPF::CodeBuilder *builder) {
type->emit(builder);
builder->newline();
}
if (const auto *method = d->to<IR::Method>()) {
if (!method->srcInfo.isValid()) {
continue;
}
// Ignore methods originating from core.p4 and ubpf_model.p4 because they are already
// defined.
// TODO: Maybe we should still generate declarations for these methods?
if (isLibraryMethod(method->controlPlaneName())) {
continue;
}
EBPF::EBPFMethodDeclaration methodInstance(method);
methodInstance.emit(builder);
builder->newline();
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions backends/ubpf/ubpfProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ class UBPFProgram : public EBPF::EBPFProgram {
void emitMetadataInstance(EBPF::CodeBuilder *builder) const;
void emitLocalVariables(EBPF::CodeBuilder *builder) override;
void emitPipeline(EBPF::CodeBuilder *builder) override;

bool isLibraryMethod(cstring methodName) override {
static std::set<cstring> DEFAULT_METHODS = {
"mark_to_drop", "mark_to_pass", "ubpf_time_get_ns", "truncate",
"hash", "csum_replace2", "csum_replace4",
};
return DEFAULT_METHODS.find(methodName) != DEFAULT_METHODS.end() ||
EBPFProgram::isLibraryMethod(methodName);
}
};

} // namespace UBPF
Expand Down
18 changes: 18 additions & 0 deletions backends/ubpf/ubpfType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ EBPF::EBPFType *UBPFTypeFactory::create(const IR::Type *type) {
result = new EBPF::EBPFTypeName(tn, result);
} else if (auto te = type->to<IR::Type_Enum>()) {
result = new UBPFEnumType(te);
} else if (auto te = type->to<IR::Type_Error>()) {
result = new UBPFErrorType(te);
} else if (auto ts = type->to<IR::Type_Stack>()) {
auto et = create(ts->elementType);
if (et == nullptr) return nullptr;
Expand Down Expand Up @@ -155,6 +157,7 @@ void UBPFStructType::declare(EBPF::CodeBuilder *builder, cstring id, bool asPoin
void UBPFStructType::declareInit(EBPF::CodeBuilder *builder, cstring id, bool asPointer) {
declare(builder, id, asPointer);
}

//////////////////////////////////////////////////////////

void UBPFEnumType::emit(EBPF::CodeBuilder *builder) {
Expand All @@ -172,6 +175,21 @@ void UBPFEnumType::emit(EBPF::CodeBuilder *builder) {

//////////////////////////////////////////////////////////

void UBPFErrorType::emit(EBPF::CodeBuilder *builder) {
builder->append("enum ");
auto et = getType();
builder->append(et->name);
builder->blockStart();
for (auto m : et->members) {
builder->append(m->name);
builder->appendLine(",");
}
builder->blockEnd(false);
builder->endOfStatement(true);
}

//////////////////////////////////////////////////////////

UBPFListType::UBPFListType(const IR::Type_List *lst) : EBPFType(lst) {
kind = "struct";
width = 0;
Expand Down
23 changes: 23 additions & 0 deletions backends/ubpf/ubpfType.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ class UBPFScalarType : public EBPF::EBPFScalarType {
DECLARE_TYPEINFO(UBPFScalarType, EBPF::EBPFScalarType);
};

class UBPFExternType : public EBPF::EBPFScalarType {
public:
explicit UBPFExternType(const IR::Type_Bits *bits) : EBPF::EBPFScalarType(bits) {}

void emit(EBPF::CodeBuilder *builder) override;

cstring getAsString();

void declare(EBPF::CodeBuilder *builder, cstring id, bool asPointer) override;
void declareInit(EBPF::CodeBuilder *builder, cstring id, bool asPointer) override;

DECLARE_TYPEINFO(UBPFExternType, EBPF::EBPFScalarType);
};

class UBPFStructType : public EBPF::EBPFStructType {
public:
explicit UBPFStructType(const IR::Type_StructLike *strct) : EBPF::EBPFStructType(strct) {}
Expand All @@ -77,6 +91,15 @@ class UBPFEnumType : public EBPF::EBPFEnumType {
DECLARE_TYPEINFO(UBPFEnumType, EBPF::EBPFEnumType);
};

class UBPFErrorType : public EBPF::EBPFErrorType {
public:
explicit UBPFErrorType(const IR::Type_Error *strct) : EBPF::EBPFErrorType(strct) {}

void emit(EBPF::CodeBuilder *builder) override;

DECLARE_TYPEINFO(UBPFErrorType, EBPF::EBPFErrorType);
};

class UBPFListType : public EBPF::EBPFType, public EBPF::IHasWidth {
class UBPFListElement : public ICastable {
public:
Expand Down
Loading