Skip to content

Commit 37f885c

Browse files
mbudiu-vmwChris Dodd
mbudiu-vmw
authored and
Chris Dodd
committed
Fix for issue 249; ebpf improvements
1 parent b3f26cd commit 37f885c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1106
-557
lines changed

backends/bmv2/Makefile.am

-3
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ p4c_bm2_ss_UNIFIED = \
2323
backends/bmv2/bmv2.cpp \
2424
backends/bmv2/analyzer.cpp \
2525
backends/bmv2/jsonconverter.cpp \
26-
backends/bmv2/inlining.cpp \
2726
backends/bmv2/midend.cpp \
2827
backends/bmv2/lower.cpp
2928

3029
noinst_HEADERS += \
3130
backends/bmv2/analyzer.h \
32-
backends/bmv2/inlining.h \
3331
backends/bmv2/jsonconverter.h \
3432
backends/bmv2/lower.h \
3533
backends/bmv2/midend.h
@@ -50,4 +48,3 @@ bmv2tests.mk: $(GENTESTS) $(srcdir)/%reldir%/Makefile.am \
5048
$(srcdir)/testdata/p4_14_samples/switch_*/switch.p4 \
5149
$(srcdir)/testdata/p4_16_samples $(srcdir)/testdata/p4_14_samples
5250
@$(GENTESTS) $(srcdir) bmv2 $(srcdir)/backends/bmv2/run-bmv2-test.py $^ >$@
53-

backends/bmv2/analyzer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ class DiscoverStructure : public Inspector {
293293
};
294294
} // namespace
295295

296-
void ProgramParts::analyze(IR::ToplevelBlock* toplevel) {
296+
void ProgramParts::analyze(const IR::ToplevelBlock* toplevel) {
297297
DiscoverStructure disc(this);
298298
toplevel->getProgram()->apply(disc);
299299
}

backends/bmv2/analyzer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class ProgramParts {
185185
std::vector<const IR::Declaration_Variable*> variables;
186186

187187
ProgramParts() {}
188-
void analyze(IR::ToplevelBlock* toplevel);
188+
void analyze(const IR::ToplevelBlock* toplevel);
189189
};
190190

191191
} // namespace BMV2

backends/bmv2/jsonconverter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,7 @@ void JsonConverter::addMetaInformation() {
18391839
}
18401840

18411841
void JsonConverter::convert(P4::ReferenceMap* refMap, P4::TypeMap* typeMap,
1842-
IR::ToplevelBlock* toplevelBlock,
1842+
const IR::ToplevelBlock* toplevelBlock,
18431843
P4::ConvertEnums::EnumMapping* enumMap) {
18441844
this->toplevelBlock = toplevelBlock;
18451845
this->refMap = refMap;

backends/bmv2/jsonconverter.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class JsonConverter final {
6161
P4::TypeMap* typeMap;
6262
ProgramParts structure;
6363
cstring scalarsName; // name of struct in JSON holding all scalars
64-
IR::ToplevelBlock* toplevelBlock;
64+
const IR::ToplevelBlock* toplevelBlock;
6565
ExpressionConverter* conv;
6666
DirectMeterMap meterMap;
6767
const IR::Parameter* headerParameter;
@@ -154,7 +154,7 @@ class JsonConverter final {
154154

155155
public:
156156
explicit JsonConverter(const CompilerOptions& options);
157-
void convert(P4::ReferenceMap* refMap, P4::TypeMap* typeMap, IR::ToplevelBlock *toplevel,
157+
void convert(P4::ReferenceMap* refMap, P4::TypeMap* typeMap, const IR::ToplevelBlock *toplevel,
158158
P4::ConvertEnums::EnumMapping* enumMap);
159159
void serialize(std::ostream& out) const
160160
{ toplevel.serialize(out); }

backends/bmv2/lower.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,36 @@ const IR::Node* LowerExpressions::postorder(IR::Concat* expression) {
125125
return result;
126126
}
127127

128+
/////////////////////////////////////////////////////////////
129+
130+
const IR::Node* FixupChecksum::preorder(IR::P4Control* control) {
131+
if (control->name != *updateBlockName)
132+
return control;
133+
// Convert
134+
// tmp = e;
135+
// f = tmp;
136+
// into
137+
// f = e;
138+
auto instrs = control->body->components;
139+
if (instrs->size() != 2)
140+
return control;
141+
if (!instrs->at(0)->is<IR::AssignmentStatement>() || !instrs->at(1)->is<IR::AssignmentStatement>())
142+
return control;
143+
auto ass0 = instrs->at(0)->to<IR::AssignmentStatement>();
144+
auto ass1 = instrs->at(1)->to<IR::AssignmentStatement>();
145+
if (!ass0->left->is<IR::PathExpression>() || !ass1->right->is<IR::PathExpression>())
146+
return control;
147+
auto pe0 = ass0->left->to<IR::PathExpression>();
148+
auto pe1 = ass1->right->to<IR::PathExpression>();
149+
if (pe0->path->name != pe1->path->name ||
150+
pe0->path->absolute != pe1->path->absolute)
151+
return control;
152+
auto ass = new IR::AssignmentStatement(ass1->srcInfo, ass1->left, ass0->right);
153+
auto vec = new IR::IndexedVector<IR::StatOrDecl>();
154+
vec->push_back(ass);
155+
auto block = new IR::BlockStatement(control->body->srcInfo, control->body->annotations, vec);
156+
control->body = block;
157+
return control;
158+
}
159+
128160
} // namespace BMV2

backends/bmv2/lower.h

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ limitations under the License.
1919

2020
#include "ir/ir.h"
2121
#include "frontends/p4/typeMap.h"
22+
#include "frontends/common/resolveReferences/resolveReferences.h"
2223

2324
namespace BMV2 {
2425

@@ -45,6 +46,19 @@ class LowerExpressions : public Transform {
4546
{ prune(); return table; } // don't simplify expressions in table
4647
};
4748

49+
// TODO: FIXME
50+
// This pass is a hack to work around current BMv2 limitations:
51+
// checksum computations must be expressed in a restricted way, since
52+
// the JSON code generator uses simple pattern-matching.
53+
class FixupChecksum : public Transform {
54+
const cstring* updateBlockName;
55+
public:
56+
explicit FixupChecksum(const cstring* updateBlockName) :
57+
updateBlockName(updateBlockName)
58+
{ setName("FixupChecksum"); }
59+
const IR::Node* preorder(IR::P4Control* control) override;
60+
};
61+
4862
} // namespace BMV2
4963

5064
#endif /* _BACKENDS_BMV2_LOWER_H_ */

backends/bmv2/midend.cpp

+42-24
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ limitations under the License.
1616

1717
#include "midend.h"
1818
#include "lower.h"
19+
#if 0
1920
#include "inlining.h"
21+
#endif
2022
#include "frontends/common/constantFolding.h"
2123
#include "frontends/common/resolveReferences/resolveReferences.h"
2224
#include "frontends/p4/evaluator/evaluator.h"
@@ -84,11 +86,26 @@ class EnumOn32Bits : public P4::ChooseEnumRepresentation {
8486
{ return 32; }
8587
};
8688

89+
class SkipControls : public P4::ActionSynthesisPolicy {
90+
const std::set<cstring> *skip;
91+
92+
public:
93+
SkipControls(const std::set<cstring> *skip) : skip(skip) { CHECK_NULL(skip); }
94+
bool convert(const IR::P4Control* control) const {
95+
if (skip->find(control->name) != skip->end())
96+
return false;
97+
return true;
98+
}
99+
};
87100

88-
void MidEnd::setup_for_P4_16(CompilerOptions&) {
89-
// we may come through this path even if the program is actually a P4 v1.0 program
101+
MidEnd::MidEnd(CompilerOptions& options) {
102+
bool isv1 = options.isv1();
103+
setName("MidEnd");
104+
refMap.setIsV1(isv1); // must be done BEFORE creating passes
90105
auto evaluator = new P4::EvaluatorPass(&refMap, &typeMap);
91106
auto convertEnums = new P4::ConvertEnums(&refMap, &typeMap, new EnumOn32Bits());
107+
auto v1controls = new std::set<cstring>();
108+
92109
addPasses({
93110
convertEnums,
94111
new VisitFunctor([this, convertEnums]() { enumMap = convertEnums->getEnumMapping(); }),
@@ -97,11 +114,29 @@ void MidEnd::setup_for_P4_16(CompilerOptions&) {
97114
new P4::RemoveAllUnusedDeclarations(&refMap),
98115
new P4::ClearTypeMap(&typeMap),
99116
evaluator,
100-
new VisitFunctor([evaluator](const IR::Node *root) -> const IR::Node * {
117+
new VisitFunctor([this,v1controls,evaluator](const IR::Node *root) -> const IR::Node* {
101118
auto toplevel = evaluator->getToplevelBlock();
102-
if (toplevel->getMain() == nullptr)
119+
auto main = toplevel->getMain();
120+
if (main == nullptr)
103121
// nothing further to do
104122
return nullptr;
123+
// We save the names of some control blocks for special processing later
124+
if (main->getConstructorParameters()->size() != 6)
125+
::error("%1%: Expected 6 arguments for main package", main);
126+
auto verify = main->getParameterValue(P4V1::V1Model::instance.sw.verify.name);
127+
auto update = main->getParameterValue(P4V1::V1Model::instance.sw.update.name);
128+
auto deparser = main->getParameterValue(P4V1::V1Model::instance.sw.deparser.name);
129+
if (verify == nullptr || update == nullptr || deparser == nullptr ||
130+
!verify->is<IR::ControlBlock>() || !update->is<IR::ControlBlock>() ||
131+
!deparser->is<IR::ControlBlock>()) {
132+
::error("%1%: main package does not match the expected model %2%",
133+
main, P4V1::V1Model::instance.file.toString());
134+
return nullptr;
135+
}
136+
updateControlBlockName = update->to<IR::ControlBlock>()->container->name;
137+
v1controls->emplace(verify->to<IR::ControlBlock>()->container->name);
138+
v1controls->emplace(updateControlBlockName);
139+
v1controls->emplace(deparser->to<IR::ControlBlock>()->container->name);
105140
return root; }),
106141
new P4::Inline(&refMap, &typeMap, evaluator),
107142
new P4::InlineActions(&refMap, &typeMap),
@@ -130,33 +165,16 @@ void MidEnd::setup_for_P4_16(CompilerOptions&) {
130165
"meters", "size", "support_timeout" }),
131166
new P4::SimplifyControlFlow(&refMap, &typeMap),
132167
new P4::CompileTimeOperations(),
133-
new P4::SynthesizeActions(&refMap, &typeMap),
168+
new P4::SynthesizeActions(&refMap, &typeMap, new SkipControls(v1controls)),
134169
new P4::MoveActionsToTables(&refMap, &typeMap),
135-
});
136-
}
137-
138-
139-
MidEnd::MidEnd(CompilerOptions& options) {
140-
bool isv1 = options.isv1();
141-
setName("MidEnd");
142-
refMap.setIsV1(isv1); // must be done BEFORE creating passes
143-
#if 0
144-
if (isv1)
145-
// TODO: This path should be eventually deprecated
146-
setup_for_P4_14(options);
147-
else
148-
#endif
149-
setup_for_P4_16(options);
150-
151-
// BMv2-specific passes
152-
auto evaluator = new P4::EvaluatorPass(&refMap, &typeMap);
153-
addPasses({
170+
// Proper back-end
154171
new P4::TypeChecking(&refMap, &typeMap),
155172
new P4::SimplifyControlFlow(&refMap, &typeMap),
156173
new P4::RemoveLeftSlices(&refMap, &typeMap),
157174
new P4::TypeChecking(&refMap, &typeMap),
158175
new LowerExpressions(&typeMap),
159176
new P4::ConstantFolding(&refMap, &typeMap, false),
177+
new FixupChecksum(&updateControlBlockName),
160178
evaluator,
161179
new VisitFunctor([this, evaluator]() { toplevel = evaluator->getToplevelBlock(); })
162180
});

backends/bmv2/midend.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,21 @@ namespace BMV2 {
2929
class MidEnd : public PassManager {
3030
#if 0
3131
void setup_for_P4_14(CompilerOptions& options);
32-
#endif
3332
void setup_for_P4_16(CompilerOptions& options);
33+
#endif
3434
P4::InlineWorkList controlsToInline;
3535
P4::ActionsInlineList actionsToInline;
36+
cstring updateControlBlockName;
3637

3738
public:
3839
// These will be accurate when the mid-end completes evaluation
39-
P4::ReferenceMap refMap;
40-
P4::TypeMap typeMap;
41-
IR::ToplevelBlock *toplevel = nullptr; // Should this be const?
40+
P4::ReferenceMap refMap;
41+
P4::TypeMap typeMap;
42+
const IR::ToplevelBlock *toplevel = nullptr;
4243
P4::ConvertEnums::EnumMapping enumMap;
4344

4445
explicit MidEnd(CompilerOptions& options);
45-
IR::ToplevelBlock* process(const IR::P4Program *&program) {
46+
const IR::ToplevelBlock* process(const IR::P4Program *&program) {
4647
program = program->apply(*this);
4748
return toplevel; }
4849
};

backends/ebpf/Makefile.am

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ p4c_ebpf_LDADD = libfrontend.la libp4ctoolkit.a
2121
p4c_ebpf_UNIFIED = \
2222
backends/ebpf/p4c-ebpf.cpp \
2323
backends/ebpf/ebpfBackend.cpp \
24-
backends/ebpf/ebpfObject.cpp \
24+
backends/ebpf/ebpfProgram.cpp \
2525
backends/ebpf/ebpfTable.cpp \
2626
backends/ebpf/ebpfControl.cpp \
2727
backends/ebpf/ebpfParser.cpp \
@@ -37,6 +37,7 @@ noinst_HEADERS += \
3737
backends/ebpf/ebpfControl.h \
3838
backends/ebpf/ebpfModel.h \
3939
backends/ebpf/ebpfObject.h \
40+
backends/ebpf/ebpfProgram.h \
4041
backends/ebpf/ebpfOptions.h \
4142
backends/ebpf/ebpfParser.h \
4243
backends/ebpf/ebpfTable.h \

backends/ebpf/ebpfBackend.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ limitations under the License.
2121
#include "ebpfBackend.h"
2222
#include "target.h"
2323
#include "ebpfType.h"
24+
#include "ebpfProgram.h"
2425

2526
namespace EBPF {
2627

0 commit comments

Comments
 (0)