Skip to content

Commit

Permalink
P4TC - Add permission annotations to tables (#4610)
Browse files Browse the repository at this point in the history
* Implementation to add permisson annotation 'tc_acl' to P4Tables.

* Update testcases and Fix cpplint issue

* Addressed comments

* Addressed comments

* Change Default Permission
  • Loading branch information
komaljai authored Apr 17, 2024
1 parent 8f0d531 commit 5848a28
Show file tree
Hide file tree
Showing 88 changed files with 1,132 additions and 97 deletions.
126 changes: 117 additions & 9 deletions backends/tc/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,110 @@ void ConvertToBackendIR::updateDefaultHitAction(const IR::P4Table *t, IR::TCTabl
}
}

void ConvertToBackendIR::updateAddOnMissTable(const IR::P4Table *t) {
auto tblname = t->name.originalName;
for (auto table : tcPipeline->tableDefs) {
if (table->tableName == tblname) {
add_on_miss_tables.push_back(t);
auto tableDefinition = ((IR::TCTable *)table);
tableDefinition->setTableAddOnMiss();
tableDefinition->setTablePermission(HandleTableAccessPermission(t));
}
}
}

unsigned ConvertToBackendIR::GetAccessNumericValue(cstring access) {
unsigned value = 0;
for (auto s : access) {
unsigned mask = 0;
switch (s) {
case 'C':
mask = 1 << 6;
break;
case 'R':
mask = 1 << 5;
break;
case 'U':
mask = 1 << 4;
break;
case 'D':
mask = 1 << 3;
break;
case 'X':
mask = 1 << 2;
break;
case 'P':
mask = 1 << 1;
break;
case 'S':
mask = 1;
break;
default:
::error(ErrorType::ERR_INVALID,
"tc_acl annotation cannot have '%1%' in access permisson", s);
}
value |= mask;
}
return value;
}

cstring ConvertToBackendIR::HandleTableAccessPermission(const IR::P4Table *t) {
bool IsTableAddOnMiss = false;
cstring control_path, data_path;
for (auto table : add_on_miss_tables) {
if (table->name.originalName == t->name.originalName) {
IsTableAddOnMiss = true;
}
}
auto find = tablePermissions.find(t->name.originalName);
if (find != tablePermissions.end()) {
auto paths = tablePermissions[t->name.originalName];
control_path = paths->first;
data_path = paths->second;
}
// Default access value of Control_path and Data_Path
if (control_path.isNullOrEmpty()) {
control_path = IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_CONTROL_PATH_ACCESS
: DEFAULT_TABLE_CONTROL_PATH_ACCESS;
}
if (data_path.isNullOrEmpty()) {
data_path = IsTableAddOnMiss ? DEFAULT_ADD_ON_MISS_TABLE_DATA_PATH_ACCESS
: DEFAULT_TABLE_DATA_PATH_ACCESS;
}

if (IsTableAddOnMiss) {
auto access = data_path.find('C');
if (!access) {
::warning(
ErrorType::WARN_INVALID,
"Add on miss table '%1%' should have 'create' access permissons for data path.",
t->name.originalName);
}
}
auto access_cp = GetAccessNumericValue(control_path);
auto access_dp = GetAccessNumericValue(data_path);
auto access_permisson = (access_cp << 7) | access_dp;
std::stringstream value;
value << "0x" << std::hex << access_permisson;
return value.str().c_str();
}

std::pair<cstring, cstring> *ConvertToBackendIR::GetAnnotatedAccessPath(
const IR::Annotation *anno) {
cstring control_path, data_path;
if (anno) {
auto expr = anno->expr[0];
if (auto typeLiteral = expr->to<IR::StringLiteral>()) {
auto permisson_str = typeLiteral->value;
auto char_pos = permisson_str.find(":");
control_path = permisson_str.before(char_pos);
data_path = permisson_str.substr(char_pos - permisson_str.begin() + 1);
}
}
auto paths = new std::pair<cstring, cstring>(control_path, data_path);
return paths;
}

void ConvertToBackendIR::postorder(const IR::P4Table *t) {
if (t != nullptr) {
tableCount++;
Expand Down Expand Up @@ -551,17 +655,21 @@ void ConvertToBackendIR::postorder(const IR::P4Table *t) {
tableKeysizeList.emplace(tId, keySize);
auto annoList = t->getAnnotations()->annotations;
for (auto anno : annoList) {
if (anno->name != ParseTCAnnotations::numMask) continue;
auto expr = anno->expr[0];
if (auto val = expr->to<IR::Constant>()) {
tableDefinition->setNumMask(val->asUint64());
} else {
::error(ErrorType::ERR_INVALID,
"nummask annotation cannot have '%1%' as value. Only integer "
"constants are allowed",
expr);
if (anno->name == ParseTCAnnotations::tc_acl) {
tablePermissions.emplace(t->name.originalName, GetAnnotatedAccessPath(anno));
} else if (anno->name == ParseTCAnnotations::numMask) {
auto expr = anno->expr[0];
if (auto val = expr->to<IR::Constant>()) {
tableDefinition->setNumMask(val->asUint64());
} else {
::error(ErrorType::ERR_INVALID,
"nummask annotation cannot have '%1%' as value. Only integer "
"constants are allowed",
expr);
}
}
}
tableDefinition->setTablePermission(HandleTableAccessPermission(t));
auto actionlist = t->getActionList();
for (auto action : actionlist->actionList) {
for (auto actionDef : tcPipeline->actionDefs) {
Expand Down
13 changes: 6 additions & 7 deletions backends/tc/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class ConvertToBackendIR : public Inspector {
ordered_map<unsigned, cstring> tableIDList;
ordered_map<unsigned, cstring> actionIDList;
ordered_map<unsigned, unsigned> tableKeysizeList;
safe_vector<const IR::P4Table *> add_on_miss_tables;
ordered_map<cstring, std::pair<cstring, cstring> *> tablePermissions;

public:
ConvertToBackendIR(const IR::ToplevelBlock *tlb, IR::TCPipeline *pipe, P4::ReferenceMap *refMap,
Expand Down Expand Up @@ -89,13 +91,10 @@ class ConvertToBackendIR : public Inspector {
unsigned getActionId(cstring actionName) const;
unsigned getTableKeysize(unsigned tableId) const;
cstring externalName(const IR::IDeclaration *declaration) const;
void updateAddOnMissTable(cstring tblname) const {
for (auto table : tcPipeline->tableDefs) {
if (table->tableName == tblname) {
((IR::TCTable *)table)->setTableAddOnMiss();
}
}
}
cstring HandleTableAccessPermission(const IR::P4Table *t);
std::pair<cstring, cstring> *GetAnnotatedAccessPath(const IR::Annotation *anno);
unsigned GetAccessNumericValue(cstring access);
void updateAddOnMissTable(const IR::P4Table *t);
};

class Extern {
Expand Down
3 changes: 1 addition & 2 deletions backends/tc/ebpfCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,6 @@ void ControlBodyTranslatorPNA::ValidateAddOnMissMissAction(const IR::P4Action *a
act);
}
const IR::P4Table *t = table->table->container;
cstring tblname = t->name.originalName;
const IR::Expression *defaultAction = t->getDefaultAction();
CHECK_NULL(defaultAction);
auto defaultActionName = table->getActionNameExpression(defaultAction);
Expand All @@ -1548,7 +1547,7 @@ void ControlBodyTranslatorPNA::ValidateAddOnMissMissAction(const IR::P4Action *a
"add_entry extern can only be used in an action"
" of a table with property add_on_miss equals to true.");
}
tcIR->updateAddOnMissTable(tblname);
((ConvertToBackendIR *)tcIR)->updateAddOnMissTable(t);
}

void ControlBodyTranslatorPNA::processFunction(const P4::ExternFunction *function) {
Expand Down
2 changes: 2 additions & 0 deletions backends/tc/introspection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void IntrospectionGenerator::collectTableInfo() {
tableInfo->id = table->tableID;
tableInfo->name = table->controlName + "/" + table->tableName;
tableInfo->tentries = table->tableEntriesCount;
tableInfo->permissions = table->permissions;
tableInfo->numMask = table->numMask;
if (table->keySize != 0) {
tableInfo->keysize = table->keySize;
Expand Down Expand Up @@ -240,6 +241,7 @@ Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *t
tableJson->emplace("name", tbl->name);
tableJson->emplace("id", tbl->id);
tableJson->emplace("tentries", tbl->tentries);
tableJson->emplace("permissions", tbl->permissions);
tableJson->emplace("nummask", tbl->numMask);
if (tbl->keysize != 0) {
tableJson->emplace("keysize", tbl->keysize);
Expand Down
2 changes: 2 additions & 0 deletions backends/tc/introspection.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct ActionAttributes {

struct TableAttributes {
cstring name;
cstring permissions;
unsigned int id;
unsigned int tentries;
unsigned int numMask;
Expand All @@ -106,6 +107,7 @@ struct TableAttributes {
safe_vector<struct ActionAttributes *> actions;
TableAttributes() {
name = nullptr;
permissions = nullptr;
id = 0;
tentries = 0;
numMask = 0;
Expand Down
12 changes: 7 additions & 5 deletions backends/tc/tc.def
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class TCTable {
cstring tableName;
cstring controlName;
cstring pipelineName;
cstring permissions;
unsigned keySize;
unsigned tableEntriesCount;
unsigned numMask;
Expand All @@ -244,6 +245,9 @@ class TCTable {
ordered_map<TCAction, unsigned> actionList;
safe_vector<TCEntry> const_entries;

void setTablePermission(cstring p) {
permissions = p;
}
void setKeySize(unsigned k) {
keySize = k;
}
Expand Down Expand Up @@ -326,12 +330,10 @@ class TCTable {
tcTable += "\n\ttype " + printMatchType(matchType) + " \\";
tcTable += "\n\tkeysz " + Util::toString(keySize);
tcTable += " nummasks " + Util::toString(numMask);
tcTable += " permissions " + Util::toString(permissions);
tcTable += " tentries " + Util::toString(tableEntriesCount);
if (isTableAddOnMiss) {
tcTable += " permissions 0x3DE6";
if(timerProfiles > defaultTimerProfiles) {
tcTable += " num_timer_profiles " + Util::toString(timerProfiles);
}
if (isTableAddOnMiss && timerProfiles > defaultTimerProfiles) {
tcTable += " num_timer_profiles " + Util::toString(timerProfiles);
}

if (!actionList.empty()) {
Expand Down
1 change: 1 addition & 0 deletions backends/tc/tcAnnotations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ const cstring ParseTCAnnotations::defaultHitConst = "default_hit_const";
const cstring ParseTCAnnotations::tcType = "tc_type";
const cstring ParseTCAnnotations::numMask = "nummask";
const cstring ParseTCAnnotations::tcMayOverride = "tc_may_override";
const cstring ParseTCAnnotations::tc_acl = "tc_acl";

} // namespace TC
3 changes: 2 additions & 1 deletion backends/tc/tcAnnotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ class ParseTCAnnotations : public P4::ParseAnnotations {
static const cstring tcType;
static const cstring numMask;
static const cstring tcMayOverride;
static const cstring tc_acl;
ParseTCAnnotations()
: P4::ParseAnnotations(
"TC", true,
{PARSE_EMPTY(defaultHit), PARSE_EMPTY(defaultHitConst),
PARSE_CONSTANT_OR_STRING_LITERAL(tcType), PARSE_CONSTANT_OR_STRING_LITERAL(numMask),
PARSE_EMPTY(tcMayOverride)}) {}
PARSE_EMPTY(tcMayOverride), PARSE_CONSTANT_OR_STRING_LITERAL(tc_acl)}) {}
};

} // namespace TC
Expand Down
6 changes: 6 additions & 0 deletions backends/tc/tc_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ inline constexpr auto DEFAULT_METADATA_ID = 1;
inline constexpr auto BITWIDTH = 32;
inline constexpr auto DEFAULT_TIMER_PROFILES = 4;

// Default Access Permissons
inline constexpr auto DEFAULT_TABLE_CONTROL_PATH_ACCESS = "CRUDPS";
inline constexpr auto DEFAULT_TABLE_DATA_PATH_ACCESS = "RX";
inline constexpr auto DEFAULT_ADD_ON_MISS_TABLE_CONTROL_PATH_ACCESS = "CRUDPS";
inline constexpr auto DEFAULT_ADD_ON_MISS_TABLE_DATA_PATH_ACCESS = "CRXP";

// Supported data types.
inline constexpr auto BIT_TYPE = 0;
inline constexpr auto DEV_TYPE = 1;
Expand Down
2 changes: 1 addition & 1 deletion testdata/p4tc_samples/add_entry_1_example.p4
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ control MainControlImpl(
drop_packet();
}

table ipv4_tbl_1 {
@tc_acl("CRUS:CRXP") table ipv4_tbl_1 {
key = {
hdr.ipv4.dstAddr : exact @tc_type ("ipv4");
istd.input_port : exact;
Expand Down
Loading

0 comments on commit 5848a28

Please sign in to comment.