From 5149bf6e191d111dda9dff738985df8f34e6c4af Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Thu, 19 Dec 2024 08:02:28 +0000 Subject: [PATCH] 1. Change function names to be more readable 2. Move non-template function implementations to p4meta.cpp --- dash-pipeline/SAI/src/dashsai.cpp | 44 +-- dash-pipeline/SAI/src/p4meta.cpp | 361 ++++++++++++++++++ dash-pipeline/SAI/src/p4meta.h | 355 ++++------------- .../SAI/templates/impls/sai_api_group.cpp.j2 | 77 ++-- 4 files changed, 504 insertions(+), 333 deletions(-) create mode 100644 dash-pipeline/SAI/src/p4meta.cpp diff --git a/dash-pipeline/SAI/src/dashsai.cpp b/dash-pipeline/SAI/src/dashsai.cpp index 352ad8501..e61a1914d 100644 --- a/dash-pipeline/SAI/src/dashsai.cpp +++ b/dash-pipeline/SAI/src/dashsai.cpp @@ -1061,13 +1061,13 @@ sai_status_t DashSai::set( pi_p4_id_t action_id = action->action_id(); auto meta_param = meta_table.get_meta_action_param(action_id, attr->id); if (meta_param) { - auto pair_param = get_action_param(meta_param, matchActionEntry); + auto pair_param = get_action_param_pair_from_p4_table_entry(meta_param, matchActionEntry); if (pair_param.second) { - set_ipaddr_family(attr->value, pair_param.second); + set_attr_ipaddr_family_to_p4(attr->value, pair_param.second); } assert(pair_param.first); - set_value(meta_param->field, meta_param->bitwidth, attr->value, pair_param.first); + set_attr_value_to_p4(meta_param->field, meta_param->bitwidth, attr->value, pair_param.first); auto ret = mutateTableEntry(matchActionEntry, p4::v1::Update_Type_MODIFY); return ret == grpc::StatusCode::OK ? SAI_STATUS_SUCCESS : SAI_STATUS_FAILURE; @@ -1079,18 +1079,18 @@ sai_status_t DashSai::set( std::shared_ptr new_entry = std::make_shared(); new_entry->CopyFrom(*matchActionEntry); - auto pair_key = get_key(meta_key, new_entry); + auto pair_key = get_match_pair_from_p4_table_entry(meta_key, new_entry); if (pair_key.second) { - set_ipaddr_family(attr->value, pair_key.second->mutable_exact()); + set_attr_ipaddr_family_to_p4(attr->value, pair_key.second->mutable_exact()); } assert(pair_key.first); - if (meta_key->match_type == "ternary" && has_suffix(meta_key->name, "_MASK")) { - set_mask(meta_key->field, meta_key->bitwidth, attr->value, + if (meta_key->match_type == "ternary" && string_has_suffix(meta_key->name, "_MASK")) { + set_attr_value_mask_to_p4_ternary(meta_key->field, meta_key->bitwidth, attr->value, pair_key.first->mutable_ternary()); } else { - set_key_value(*meta_key, attr->value, pair_key.first); + set_attr_value_to_p4_match(*meta_key, attr->value, pair_key.first); } removeFromTable(objectId); @@ -1118,13 +1118,13 @@ sai_status_t DashSai::set( pi_p4_id_t action_id = action->action_id(); auto meta_param = meta_table.get_meta_action_param(action_id, attr->id); if (meta_param) { - auto pair_param = get_action_param(meta_param, matchActionEntry); + auto pair_param = get_action_param_pair_from_p4_table_entry(meta_param, matchActionEntry); if (pair_param.second) { - set_ipaddr_family(attr->value, pair_param.second); + set_attr_ipaddr_family_to_p4(attr->value, pair_param.second); } assert(pair_param.first); - set_value(meta_param->field, meta_param->bitwidth, attr->value, pair_param.first); + set_attr_value_to_p4(meta_param->field, meta_param->bitwidth, attr->value, pair_param.first); auto ret = mutateTableEntry(matchActionEntry, p4::v1::Update_Type_MODIFY); return ret == grpc::StatusCode::OK ? SAI_STATUS_SUCCESS : SAI_STATUS_FAILURE; @@ -1153,28 +1153,28 @@ sai_status_t DashSai::get( for (uint32_t i = 0; i < attr_count; i++) { if (auto meta_param = meta_table.get_meta_action_param(action_id, attr_list[i].id)) { // attr in table action params - auto pair_param = get_action_param(meta_param, matchActionEntry); + auto pair_param = get_action_param_pair_from_p4_table_entry(meta_param, matchActionEntry); if (pair_param.second) { - get_ipaddr_family(pair_param.second, attr_list[i].value); + get_attr_ipaddr_family_from_p4(pair_param.second, attr_list[i].value); } assert(pair_param.first); - get_value(meta_param->field, meta_param->bitwidth, pair_param.first, attr_list[i].value); + get_attr_value_from_p4(meta_param->field, meta_param->bitwidth, pair_param.first, attr_list[i].value); } else if (auto meta_key = meta_table.get_meta_key(attr_list[i].id)) { // attr in table keys - auto pair_key = get_key(meta_key, matchActionEntry); + auto pair_key = get_match_pair_from_p4_table_entry(meta_key, matchActionEntry); if (pair_key.second) { - get_ipaddr_family(pair_key.second->mutable_exact(), attr_list[i].value); + get_attr_ipaddr_family_from_p4(pair_key.second->mutable_exact(), attr_list[i].value); } assert(pair_key.first); - if (meta_key->match_type == "ternary" && has_suffix(meta_key->name, "_MASK")) { - get_mask(meta_key->field, meta_key->bitwidth, + if (meta_key->match_type == "ternary" && string_has_suffix(meta_key->name, "_MASK")) { + get_attr_value_mask_from_p4_ternary(meta_key->field, meta_key->bitwidth, pair_key.first->mutable_ternary(), attr_list[i].value); } else { - get_key_value(*meta_key, pair_key.first, attr_list[i].value); + get_attr_value_from_p4_match(*meta_key, pair_key.first, attr_list[i].value); } } else { @@ -1204,13 +1204,13 @@ sai_status_t DashSai::get( for (uint32_t i = 0; i < attr_count; i++) { if (auto meta_param = meta_table.get_meta_action_param(action_id, attr_list[i].id)) { // attr in table action params - auto pair_param = get_action_param(meta_param, matchActionEntry); + auto pair_param = get_action_param_pair_from_p4_table_entry(meta_param, matchActionEntry); if (pair_param.second) { - get_ipaddr_family(pair_param.second, attr_list[i].value); + get_attr_ipaddr_family_from_p4(pair_param.second, attr_list[i].value); } assert(pair_param.first); - get_value(meta_param->field, meta_param->bitwidth, pair_param.first, attr_list[i].value); + get_attr_value_from_p4(meta_param->field, meta_param->bitwidth, pair_param.first, attr_list[i].value); } else { DASH_LOG_ERROR("failed to get value for attr %d", attr_list[i].id); diff --git a/dash-pipeline/SAI/src/p4meta.cpp b/dash-pipeline/SAI/src/p4meta.cpp new file mode 100644 index 000000000..7c9b068e3 --- /dev/null +++ b/dash-pipeline/SAI/src/p4meta.cpp @@ -0,0 +1,361 @@ +extern "C" { +#include "saimetadata.h" +} + +#include "utils.h" +#include "p4meta.h" + +using namespace dash; +using namespace dash::utils; + +namespace dash +{ + const P4MetaKey* P4MetaTable::get_meta_key( + _In_ sai_attr_id_t attr_id) const + { + for (auto i=0u; isecond.params; + for (auto i=0u; ifirst; + } + + auto itr = extra_fields.find("ACTION"); + assert(itr != extra_fields.end()); + + for (uint32_t i = 0; i < attr_count; i++) { + if (attr_list[i].id == itr->second) { + uint32_t action_enum_id = attr_list[i].value.u32; + for (auto &action: actions) { + if (action.second.enum_id == action_enum_id) { + return action.first; + } + } + break; + } + } + + return 0; // invalid p4 action id + } + + // + // helper functions, set/get attr to/from p4 match|action + // + + void set_attr_value_to_p4( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const sai_attribute_value_t &value, + _Inout_ p4::v1::FieldMatch_LPM *mf_lpm) + { + assert (field == "ipPrefix"); + return ipPrefixSetVal(value, mf_lpm, bitwidth); + } + + void get_attr_value_from_p4( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const p4::v1::FieldMatch_LPM *mf_lpm, + _Out_ sai_attribute_value_t &value) + { + assert (field == "ipPrefix"); + const char *v = mf_lpm->value().c_str(); + auto prefix_len = mf_lpm->prefix_len(); + + if (value.ipprefix.addr_family == SAI_IP_ADDR_FAMILY_IPV4) { + uint32_t val = *(const uint32_t*)v; + prefix_len -= 96; + assert (prefix_len <= 32); + value.ipprefix.addr.ip4 = val; + value.ipprefix.mask.ip4 = 0xffffffff << (32 - prefix_len); + } + else { + assert (prefix_len <= 128); + uint8_t netmask[16] = { 0 }; + int i; + + for (i = 0; i < prefix_len/8; i++) + netmask[i] = 0xff; + if (prefix_len % 8 != 0) + netmask[i] = (uint8_t)(0xff << (8 - prefix_len%8)); + memcpy(value.ipprefix.mask.ip6, netmask, 16); + } + } + + + void set_attr_value_mask_to_p4_ternary( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const sai_attribute_value_t &value, + _Inout_ p4::v1::FieldMatch_Ternary *mf_ternary) + { + if (field == "ipaddr") + return ipaddrSetMask(value, mf_ternary, bitwidth); + if (field == "u32") + return u32SetMask(value, mf_ternary, bitwidth); + if (field == "u64") + return u64SetMask(value, mf_ternary, bitwidth); + + assert(0); + } + + void get_attr_value_mask_from_p4_ternary( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const p4::v1::FieldMatch_Ternary *mf_ternary, + _Out_ sai_attribute_value_t &value) + + { + const char *v = mf_ternary->mask().c_str(); + + if (field == "ipaddr") { + if (value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) { + uint32_t val = *(const uint32_t*)v; + value.ipaddr.addr.ip4 = val; + } + else { + memcpy(value.ipaddr.addr.ip6, v, 16); + } + } + else if (field == "u32") { + uint32_t val = *(const uint32_t*)v; + value.u32 = ntohl(val) >> (32 - bitwidth); + } + else if (field == "u64") { + uint64_t val = *(const uint64_t*)v; + if (*reinterpret_cast("\0\x01") == 0) { // Little Endian + value.u64 = be64toh(val) >> (64 - bitwidth); + } + else { + value.u64 = val & ((1ul<mutable_exact(); + set_attr_value_to_p4(key.field, key.bitwidth, value, mf_exact); + } + else if (key.match_type == "lpm") { + auto mf_lpm = mf->mutable_lpm(); + if (getPrefixLength(value) == 0) + { + // https://github.com/p4lang/PI/blob/24e0a3c08c964e36d235973556b90e0ae922b894/proto/frontend/src/device_mgr.cpp#L2242-L2246 + DASH_LOG_WARN("Invalid reprsentation of 'don't care' LPM match, omit match field instead of using a prefix length of 0"); + return; + } + set_attr_value_to_p4(key.field, key.bitwidth, value, mf_lpm); + } + else if (key.match_type == "ternary") { + auto mf_ternary = mf->mutable_ternary(); + set_attr_value_to_p4(key.field, key.bitwidth, value, mf_ternary); + } + else if (key.match_type == "optional") { + auto mf_optional = mf->mutable_optional(); + set_attr_value_to_p4(key.field, key.bitwidth, value, mf_optional); + } + else if (key.match_type == "list") { + // BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. + // Hence, here we only take the first item from the list and program it as optional match. + auto mf_optional = mf->mutable_optional(); + if (key.field == "ipprefixlist") { + sai_attribute_value_t val; + val.ipaddr.addr_family = value.ipprefixlist.list[0].addr_family; + val.ipaddr.addr = value.ipprefixlist.list[0].addr; + set_attr_value_to_p4("ipaddr", key.bitwidth, val, mf_optional); + } + else { + set_attr_value_to_p4(key.field, key.bitwidth, value, mf_optional); + } + } + else if (key.match_type == "range_list") { + // BMv2 doesn't support "range_list" match type, and we are using "optional" match in v1model as our implementation. + // Hence, here we only take the first item from the list and program the range start as optional match. + auto mf_optional = mf->mutable_optional(); + // FIXME only u16rangelist in sai_attribute_value_t + u16SetVal(value.u16rangelist.list[0].min, mf_optional, key.bitwidth); + } + else { + assert(0); + } + } + + void get_attr_value_from_p4_match( + _In_ const P4MetaKey &key, + _In_ p4::v1::FieldMatch *mf, + _Out_ sai_attribute_value_t &value) + { + if (key.match_type == "exact") { + auto mf_exact = mf->mutable_exact(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_exact, value); + } + else if (key.match_type == "lpm") { + auto mf_lpm = mf->mutable_lpm(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_lpm, value); + } + else if (key.match_type == "ternary") { + auto mf_ternary = mf->mutable_ternary(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_ternary, value); + } + else if (key.match_type == "optional") { + auto mf_optional = mf->mutable_optional(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_optional, value); + } + else if (key.match_type == "list") { + auto mf_optional = mf->mutable_optional(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_optional, value); + } + else if (key.match_type == "range_list") { + auto mf_optional = mf->mutable_optional(); + get_attr_value_from_p4(key.field, key.bitwidth, mf_optional, value); + } + else { + assert(0); + } + } + + void set_attr_to_p4_match( + _In_ const P4MetaKey *meta_key, + _In_ const sai_attribute_t *attr, + _Inout_ std::shared_ptr matchActionEntry) + { + if (meta_key->ip_is_v6_field_id) { + auto mf = matchActionEntry->add_match(); + mf->set_field_id(meta_key->ip_is_v6_field_id); + set_attr_ipaddr_family_to_p4(attr->value, mf->mutable_exact()); + } + + auto mf = matchActionEntry->add_match(); + mf->set_field_id(meta_key->id); + if (meta_key->match_type == "ternary" && string_has_suffix(meta_key->name, "_MASK")) { + set_attr_value_mask_to_p4_ternary(meta_key->field, meta_key->bitwidth, attr->value, + mf->mutable_ternary()); + } + else { + set_attr_value_to_p4_match(*meta_key, attr->value, mf); + } + } + + void set_attr_to_p4_action( + _In_ const P4MetaActionParam *meta_param, + _In_ const sai_attribute_t *attr, + _Out_ p4::v1::Action *action) + { + if (meta_param->ip_is_v6_field_id) { + auto param = action->add_params(); + param->set_param_id(meta_param->ip_is_v6_field_id); + set_attr_ipaddr_family_to_p4(attr->value, param); + } + + auto param = action->add_params(); + param->set_param_id(meta_param->id); + set_attr_value_to_p4(meta_param->field, meta_param->bitwidth, attr->value, param); + } + + std::pair get_match_pair_from_p4_table_entry( + _In_ const P4MetaKey *meta_key, + _In_ std::shared_ptr matchActionEntry) + { + std::pair pair_key = {nullptr, nullptr}; + + for (int i = 0; i < matchActionEntry->match_size(); i++) { + auto mf = matchActionEntry->mutable_match(i); + if (mf->field_id() == meta_key->id) { + pair_key.first = mf; + } + else if (mf->field_id() == meta_key->ip_is_v6_field_id) { + pair_key.second = mf; + } + } + + return pair_key; + } + + std::pair get_action_param_pair_from_p4_table_entry( + _In_ const P4MetaActionParam *meta_param, + _In_ std::shared_ptr matchActionEntry) + { + auto action = matchActionEntry->mutable_action()->mutable_action(); + std::pair pair_param = {nullptr, nullptr}; + + for (int i = 0; i < action->params_size(); i++) { + auto param = action->mutable_params(i); + if (param->param_id() == meta_param->id) { + pair_param.first = param; + } + else if (param->param_id() == meta_param->ip_is_v6_field_id) { + pair_param.second = param; + } + } + + return pair_param; + } + + bool string_has_suffix(const std::string &str, const std::string &suffix) + { + if (str.length() < suffix.length()) + return false; + + return !str.compare(str.length() - suffix.length(), suffix.length(), suffix); + } +} + diff --git a/dash-pipeline/SAI/src/p4meta.h b/dash-pipeline/SAI/src/p4meta.h index 40e0692c6..219aab202 100644 --- a/dash-pipeline/SAI/src/p4meta.h +++ b/dash-pipeline/SAI/src/p4meta.h @@ -5,10 +5,6 @@ #include #include -extern "C" { -#include "saimetadata.h" -} - #include "utils.h" using namespace dash::utils; @@ -27,7 +23,6 @@ namespace dash struct P4MetaActionParam { sai_attr_id_t attr_id; - std::string name; uint32_t id; std::string field; uint32_t bitwidth; @@ -35,8 +30,7 @@ namespace dash }; struct P4MetaAction { - std::string name; - uint32_t id; + uint32_t enum_id; std::vector params; }; @@ -44,114 +38,78 @@ namespace dash uint32_t id; std::vector keys; std::map actions; + std::map extra_fields; P4MetaTable( uint32_t table_id, std::initializer_list init_keys, - std::initializer_list::value_type> init_actions - ) : id(table_id), keys(init_keys), actions(init_actions) + std::initializer_list::value_type> init_actions, + std::initializer_list::value_type> extras + ) : id(table_id), keys(init_keys), actions(init_actions), extra_fields(extras) {} const P4MetaKey* get_meta_key( - _In_ sai_attr_id_t attr_id) const - { - for (auto i=0u; isecond.params; - for (auto i=0u; i + template static inline - void set_value( + void set_attr_value_to_p4( _In_ const std::string &field, _In_ uint32_t bitwidth, - _In_ const V &value, - _Inout_ T *t) + _In_ const sai_attribute_value_t &value, + _Inout_ T *p4_key_or_param) { if (field == "booldata") - return booldataSetVal(value, t, bitwidth); + return booldataSetVal(value, p4_key_or_param, bitwidth); if (field == "u8") - return u8SetVal(value, t, bitwidth); + return u8SetVal(value, p4_key_or_param, bitwidth); if (field == "u16") - return u16SetVal(value, t, bitwidth); + return u16SetVal(value, p4_key_or_param, bitwidth); if (field == "u32") - return u32SetVal(value, t, bitwidth); + return u32SetVal(value, p4_key_or_param, bitwidth); if (field == "u64") - return u64SetVal(value, t, bitwidth); + return u64SetVal(value, p4_key_or_param, bitwidth); if (field == "ipaddr") - return ipaddrSetVal(value, t, bitwidth); + return ipaddrSetVal(value, p4_key_or_param, bitwidth); if (field == "mac") - return macSetVal(value, t, bitwidth); + return macSetVal(value, p4_key_or_param, bitwidth); if (field == "u8list") - return u8listSetVal(value, t, bitwidth); + return u8listSetVal(value, p4_key_or_param, bitwidth); assert(0); } - template - static inline - void set_value( + void set_attr_value_to_p4( _In_ const std::string &field, _In_ uint32_t bitwidth, - _In_ const V &value, - _Inout_ p4::v1::FieldMatch_LPM *t) - { - assert (field == "ipPrefix"); - return ipPrefixSetVal(value, t, bitwidth); - } + _In_ const sai_attribute_value_t &value, + _Inout_ p4::v1::FieldMatch_LPM *mf_lpm); template static inline - void get_value( + void get_attr_value_from_p4( _In_ const std::string &field, _In_ uint32_t bitwidth, - _In_ const T *t, + _In_ const T *p4_key_or_param, _Out_ sai_attribute_value_t &value) { - const char *v = t->value().c_str(); + const char *v = p4_key_or_param->value().c_str(); if (field == "booldata") { value.booldata = *(const bool*)v; @@ -189,192 +147,23 @@ namespace dash memcpy(value.mac, v, 6); } else if (field == "u8list") { - memcpy(value.u8list.list, v, t->value().size()); + memcpy(value.u8list.list, v, p4_key_or_param->value().size()); } else { assert(0); } } - static inline - void get_value( + void get_attr_value_from_p4( _In_ const std::string &field, _In_ uint32_t bitwidth, - _In_ const p4::v1::FieldMatch_LPM *t, - _Out_ sai_attribute_value_t &value) - { - assert (field == "ipPrefix"); - const char *v = t->value().c_str(); - auto prefix_len = t->prefix_len(); - - if (value.ipprefix.addr_family == SAI_IP_ADDR_FAMILY_IPV4) { - uint32_t val = *(const uint32_t*)v; - prefix_len -= 96; - assert (prefix_len <= 32); - value.ipprefix.addr.ip4 = val; - value.ipprefix.mask.ip4 = 0xffffffff << (32 - prefix_len); - } - else { - assert (prefix_len <= 128); - uint8_t netmask[16] = { 0 }; - int i; - - for (i = 0; i < prefix_len/8; i++) - netmask[i] = 0xff; - if (prefix_len % 8 != 0) - netmask[i] = (uint8_t)(0xff << (8 - prefix_len%8)); - memcpy(value.ipprefix.mask.ip6, netmask, 16); - } - } - - template - static inline - void set_mask( - _In_ const std::string &field, - _In_ uint32_t bitwidth, - _In_ const V &value, - _Inout_ p4::v1::FieldMatch_Ternary *t) - { - if (field == "ipaddr") - return ipaddrSetMask(value, t, bitwidth); - if (field == "u32") - return u32SetMask(value, t, bitwidth); - if (field == "u64") - return u64SetMask(value, t, bitwidth); - - assert(0); - } - - static inline - void get_mask( - _In_ const std::string &field, - _In_ uint32_t bitwidth, - _In_ const p4::v1::FieldMatch_Ternary *t, - _Out_ sai_attribute_value_t &value) - - { - const char *v = t->mask().c_str(); - - if (field == "ipaddr") { - if (value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) { - uint32_t val = *(const uint32_t*)v; - value.ipaddr.addr.ip4 = val; - } - else { - memcpy(value.ipaddr.addr.ip6, v, 16); - } - } - else if (field == "u32") { - uint32_t val = *(const uint32_t*)v; - value.u32 = ntohl(val) >> (32 - bitwidth); - } - else if (field == "u64") { - uint64_t val = *(const uint64_t*)v; - if (*reinterpret_cast("\0\x01") == 0) { // Little Endian - value.u64 = be64toh(val) >> (64 - bitwidth); - } - else { - value.u64 = val & ((1ul<mutable_exact(); - set_value(key.field, key.bitwidth, value, mf_exact); - } - else if (key.match_type == "lpm") { - auto mf_lpm = mf->mutable_lpm(); - if (getPrefixLength(value) == 0) - { - // https://github.com/p4lang/PI/blob/24e0a3c08c964e36d235973556b90e0ae922b894/proto/frontend/src/device_mgr.cpp#L2242-L2246 - DASH_LOG_WARN("Invalid reprsentation of 'don't care' LPM match, omit match field instead of using a prefix length of 0"); - return; - } - set_value(key.field, key.bitwidth, value, mf_lpm); - } - else if (key.match_type == "ternary") { - auto mf_ternary = mf->mutable_ternary(); - set_value(key.field, key.bitwidth, value, mf_ternary); - } - else if (key.match_type == "optional") { - auto mf_optional = mf->mutable_optional(); - set_value(key.field, key.bitwidth, value, mf_optional); - } - else if (key.match_type == "list") { - // BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. - // Hence, here we only take the first item from the list and program it as optional match. - auto mf_optional = mf->mutable_optional(); - if (key.field == "ipprefixlist") { - sai_attribute_value_t val; - val.ipaddr.addr_family = value.ipprefixlist.list[0].addr_family; - val.ipaddr.addr = value.ipprefixlist.list[0].addr; - set_value("ipaddr", key.bitwidth, val, mf_optional); - } - else { - set_value(key.field, key.bitwidth, value, mf_optional); - } - } - else if (key.match_type == "range_list") { - // BMv2 doesn't support "range_list" match type, and we are using "optional" match in v1model as our implementation. - // Hence, here we only take the first item from the list and program the range start as optional match. - auto mf_optional = mf->mutable_optional(); - // FIXME only u16rangelist in sai_attribute_value_t - u16SetVal(value.u16rangelist.list[0].min, mf_optional, key.bitwidth); - } - else { - assert(0); - } - } - - static inline - void get_key_value( - _In_ const P4MetaKey &key, - _In_ p4::v1::FieldMatch *mf, - _Out_ sai_attribute_value_t &value) - { - if (key.match_type == "exact") { - auto mf_exact = mf->mutable_exact(); - get_value(key.field, key.bitwidth, mf_exact, value); - } - else if (key.match_type == "lpm") { - auto mf_lpm = mf->mutable_lpm(); - get_value(key.field, key.bitwidth, mf_lpm, value); - } - else if (key.match_type == "ternary") { - auto mf_ternary = mf->mutable_ternary(); - get_value(key.field, key.bitwidth, mf_ternary, value); - } - else if (key.match_type == "optional") { - auto mf_optional = mf->mutable_optional(); - get_value(key.field, key.bitwidth, mf_optional, value); - } - else if (key.match_type == "list") { - auto mf_optional = mf->mutable_optional(); - get_value(key.field, key.bitwidth, mf_optional, value); - } - else if (key.match_type == "range_list") { - auto mf_optional = mf->mutable_optional(); - get_value(key.field, key.bitwidth, mf_optional, value); - } - else { - assert(0); - } - } + _In_ const p4::v1::FieldMatch_LPM *mf_lpm, + _Out_ sai_attribute_value_t &value); // set/get only for value.ipaddr.addr_family template static inline - void set_ipaddr_family( + void set_attr_ipaddr_family_to_p4( _In_ const sai_attribute_value_t &value, _Out_ T *t) { @@ -383,7 +172,7 @@ namespace dash template static inline - void get_ipaddr_family( + void get_attr_ipaddr_family_from_p4( _In_ const T *t, _Out_ sai_attribute_value_t &value) { @@ -395,45 +184,45 @@ namespace dash value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; } + void set_attr_value_mask_to_p4_ternary( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const sai_attribute_value_t &value, + _Inout_ p4::v1::FieldMatch_Ternary *mf_ternary); - static inline - std::pair get_key( - _In_ const P4MetaKey *meta_key, - _In_ std::shared_ptr matchActionEntry) - { - std::pair pair_key = {nullptr, nullptr}; + void get_attr_value_mask_from_p4_ternary( + _In_ const std::string &field, + _In_ uint32_t bitwidth, + _In_ const p4::v1::FieldMatch_Ternary *mf_ternary, + _Out_ sai_attribute_value_t &value); - for (int i = 0; i < matchActionEntry->match_size(); i++) { - auto mf = matchActionEntry->mutable_match(i); - if (mf->field_id() == meta_key->id) { - pair_key.first = mf; - } - else if (mf->field_id() == meta_key->ip_is_v6_field_id) { - pair_key.second = mf; - } - } + void set_attr_value_to_p4_match( + _In_ const P4MetaKey &key, + _In_ const sai_attribute_value_t &value, + _Inout_ p4::v1::FieldMatch *mf); - return pair_key; - } + void get_attr_value_from_p4_match( + _In_ const P4MetaKey &key, + _In_ p4::v1::FieldMatch *mf, + _Out_ sai_attribute_value_t &value); - static inline - std::pair get_action_param( + void set_attr_to_p4_match( + _In_ const P4MetaKey *meta_key, + _In_ const sai_attribute_t *attr, + _Inout_ std::shared_ptr matchActionEntry); + + void set_attr_to_p4_action( _In_ const P4MetaActionParam *meta_param, - _In_ std::shared_ptr matchActionEntry) - { - auto action = matchActionEntry->mutable_action()->mutable_action(); - std::pair pair_param = {nullptr, nullptr}; + _In_ const sai_attribute_t *attr, + _Out_ p4::v1::Action *action); - for (int i = 0; i < action->params_size(); i++) { - auto param = action->mutable_params(i); - if (param->param_id() == meta_param->id) { - pair_param.first = param; - } - else if (param->param_id() == meta_param->ip_is_v6_field_id) { - pair_param.second = param; - } - } + std::pair get_match_pair_from_p4_table_entry( + _In_ const P4MetaKey *meta_key, + _In_ std::shared_ptr matchActionEntry); - return pair_param; - } + std::pair get_action_param_pair_from_p4_table_entry( + _In_ const P4MetaActionParam *meta_param, + _In_ std::shared_ptr matchActionEntry); + + bool string_has_suffix(const std::string &str, const std::string &suffix); } diff --git a/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 b/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 index d1c7bb74e..8308ecc49 100644 --- a/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 +++ b/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 @@ -12,54 +12,60 @@ using namespace dash::utils; {% set table = api.p4_meta.tables[0] -%} {% set meta_table = api.name ~ '_meta_table' -%} static dash::P4MetaTable {{meta_table}} ( - {{table.id}}, + {{table.id}}, // p4 table id { // meta table keys {% for key in table['keys'] %} - {% if not key.is_object_key %} { - {% if api.is_object %} + {% if api.is_object and not key.is_object_key %} SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}, - {% else %} - SAI_{{ api.name | upper }}_ATTR_END, - {% endif%} - "{{key.name}}", - {{key.id}}, - "{{key.match_type}}", - "{{key.field}}", - {{key.bitwidth}}, - {{key.ip_is_v6_field_id}} + {% else %} + ~0u, // key is not ATTR + {% endif%} + {% if key.is_object_key %} + "{{key.name}}_OBJECT_KEY", // p4 match name + {% else %} + "{{key.name}}", // p4 match name + {% endif%} + {{key.id}}, // p4 match field id + "{{key.match_type}}", // p4 match type + "{{key.field}}", // field + {{key.bitwidth}}, // bitwidth + {{key.ip_is_v6_field_id}} // ip_is_v6_field_id }, {% if api.is_object and key.match_type == 'ternary'%} { // extra added for set_mask of ternary key SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}_MASK, - "{{key.name}}_MASK", - {{key.id}}, - "{{key.match_type}}", - "{{key.field}}", - {{key.bitwidth}}, - {{key.ip_is_v6_field_id}} + "{{key.name}}_MASK", // p4 match name + {{key.id}}, // p4 match field id + "{{key.match_type}}", // p4 match type + "{{key.field}}", // field + {{key.bitwidth}}, // bitwidth + {{key.ip_is_v6_field_id}} // ip_is_v6_field_id }, {% endif%} - {% endif%} {% endfor %} }, { // meta table actions {% for name, action in table.actions.items() %} { - {{action.id}}, + {{action.id}}, // p4 action id { - "{{name}}", - {{action.id}}, + {% if api.is_object and table.actions|length == 1 %} + ~0u, // Have no ATTR ACTION value for oid API with 1 action + {% elif api_group.api_type == "underlay" %} + ~0u, // Have no ATTR ACTION value for underlay api type + {% else %} + {{name}}, // attr action enum id + {% endif %} { {% for param_name, param in action.attr_params.items() %} {% if param.skipattr != 'true' %} { - {{param_name}}, - "{{param_name}}", - {{param.id}}, - "{{param.field}}", - {{param.bitwidth}}, - {{param.ip_is_v6_field_id}} + {{param_name}}, // attr id + {{param.id}}, // p4 action param id + "{{param.field}}", // field + {{param.bitwidth}}, // bitwidth + {{param.ip_is_v6_field_id}} // ip_is_v6_field_id }, {% endif%} {% endfor %} @@ -68,6 +74,21 @@ static dash::P4MetaTable {{meta_table}} ( }, }, {% endfor %} + }, + { // extra fields for SAI object attributes + {% if api_group.api_type != "underlay" %} + {% for attr in api.attributes %} + {% if attr.name.endswith("ATTR_ACTION") %} + {"ACTION", {{attr.name}}}, + {% elif attr.name.endswith("ATTR_PRIORITY") %} + {"PRIORITY", {{attr.name}}}, + {% elif attr.name.endswith("ATTR_COUNTER_ID") %} + {"COUNTER_ID", {{attr.name}}}, + {% elif attr.name.endswith("ATTR_IP_ADDR_FAMILY") %} + {"IP_ADDR_FAMILY", {{attr.name}}}, + {% endif%} + {% endfor %} + {% endif%} } );