Skip to content

Commit

Permalink
Fix missing declaration of custom externs in the generated eBPF/uBPF …
Browse files Browse the repository at this point in the history
…header file. (#4644)

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

* Add library functions instead of checking for file names.

* Do not use static for extern definition if we generate a declaration.

* Use extern objects for the eBPF test framework.

* Try an inline declaration to fix Ubuntu 20.04 problems?

* Use a different libbpf version?

* Revert to old techniques for eBPF code.
  • Loading branch information
fruffy authored May 8, 2024
1 parent 7c3a9d2 commit f26cd96
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 4 deletions.
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

0 comments on commit f26cd96

Please sign in to comment.