From 57488dcb6a0fafb861099acb35660f11e24e669a Mon Sep 17 00:00:00 2001 From: kcudnik Date: Tue, 8 Aug 2023 18:12:32 +0200 Subject: [PATCH 01/11] [SAI] Improve code quality in utils --- dash-pipeline/SAI/templates/utils.cpp.j2 | 69 ++++- dash-pipeline/SAI/templates/utils.h.j2 | 357 ++++++++++++++--------- 2 files changed, 275 insertions(+), 151 deletions(-) diff --git a/dash-pipeline/SAI/templates/utils.cpp.j2 b/dash-pipeline/SAI/templates/utils.cpp.j2 index 962b9b8b7..c2738e519 100644 --- a/dash-pipeline/SAI/templates/utils.cpp.j2 +++ b/dash-pipeline/SAI/templates/utils.cpp.j2 @@ -12,39 +12,57 @@ std::unique_ptr stub; void correctIpPrefix(void *ip, const void *mask, size_t length) { + DASH_LOG_ENTER(); + auto _ip = reinterpret_cast(ip); auto _mask = reinterpret_cast(mask); + for (size_t i = 0; i < length; i++) { _ip[i] = _ip[i] & _mask[i]; } } -int leadingNonZeroBits(const uint32_t ipv4) { - auto firstSetBit = __builtin_ffs(ipv4); - if (0==firstSetBit) { +int leadingNonZeroBits(const uint32_t ipv4) +{ + DASH_LOG_ENTER(); + + auto firstSetBit = __builtin_ffs(ipv4); + + if (0==firstSetBit) + { return 0; } - return 33 - firstSetBit; + + return 33 - firstSetBit; } -int leadingNonZeroBits(const sai_ip6_t ipv6) { +int leadingNonZeroBits(const sai_ip6_t& ipv6) +{ + DASH_LOG_ENTER(); + int trailingZeros = 0; - for (int i = 0; i < 16; i+=4) { + + for (int i = 0; i < 16; i+=4) + { auto num = static_cast(ipv6[i]) + - (static_cast(ipv6[i+1]) << 8) + - (static_cast(ipv6[i+2]) << 16) + - (static_cast(ipv6[i+3]) << 24); - auto firstSetBit = leadingNonZeroBits(num); - if (firstSetBit > 0) { + (static_cast(ipv6[i+1]) << 8) + + (static_cast(ipv6[i+2]) << 16) + + (static_cast(ipv6[i+3]) << 24); + + auto firstSetBit = leadingNonZeroBits(num); + + if (firstSetBit > 0) + { return 129-trailingZeros-firstSetBit; } + trailingZeros += 32; } + return 0; } - static int GetDeviceId() { DASH_LOG_ENTER(); @@ -52,17 +70,27 @@ static int GetDeviceId() return deviceId; } -std::string updateTypeStr(p4::v1::Update_Type updateType) { +std::string updateTypeStr(p4::v1::Update_Type updateType) +{ + DASH_LOG_ENTER(); + const google::protobuf::EnumDescriptor *descriptor = p4::v1::Update_Type_descriptor(); + return descriptor->FindValueByNumber(updateType)->name(); } -const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) { - for (uint32_t i = 0; i < attr_count; i++) { - if (attr_list[i].id == id) { +const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + + for (uint32_t i = 0; i < attr_count; i++) + { + if (attr_list[i].id == id) + { return &attr_list[i]; } } + return nullptr; } @@ -71,14 +99,21 @@ grpc::StatusCode MutateTableEntry(std::shared_ptr entry, p4: DASH_LOG_ENTER(); p4::v1::WriteRequest request; + request.set_device_id(GetDeviceId()); + auto update = request.add_updates(); + update->set_type(updateType); + auto entity = update->mutable_entity(); + entity->set_allocated_table_entry(entry.get()); p4::v1::WriteResponse rep; + grpc::ClientContext context; + grpc::Status status = stub->Write(&context, request, &rep); if (status.ok()) @@ -93,6 +128,7 @@ grpc::StatusCode MutateTableEntry(std::shared_ptr entry, p4: //MILIND?? What is this? reference release? memory release? entity->release_table_entry(); + return status.error_code(); } @@ -122,6 +158,7 @@ bool InsertInTable(std::shared_ptr entry, sai_object_type_t // TODO to be removed and merged #define DASH_OBJECT_SHFT 48 #define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype< #include -template -void booldataSetVal(const sai_attribute_value_t &value, T &t, int bits = 8){ + template +void booldataSetVal(const sai_attribute_value_t &value, T &t, int bits = 8) +{ assert(bits <= 8); + t->set_value(const_cast(&value.booldata), 1); } -template -void booldataSetVal(const bool &value, T &t, int bits = 8){ + template +void booldataSetVal(const bool &value, T &t, int bits = 8) +{ assert(bits <= 8); + t->set_value(const_cast(&value), 1); } -template -void u8SetVal(const sai_attribute_value_t &value, T &t, int bits = 8){ + template +void u8SetVal(const sai_attribute_value_t &value, T &t, int bits = 8) +{ assert(bits <= 8); + t->set_value(const_cast(&value.u8), 1); } -template -void u8SetVal(const sai_uint8_t &value, T &t, int bits = 8){ + template +void u8SetVal(const sai_uint8_t &value, T &t, int bits = 8) +{ assert(bits <= 8); + t->set_value(const_cast(&value), 1); } -template -void u16SetVal(const sai_attribute_value_t &value, T &t, int bits = 16){ + template +void u16SetVal(const sai_attribute_value_t &value, T &t, int bits = 16) +{ assert(bits <= 16); + uint16_t val = value.u16; + val = htons(val); - t->set_value(&val, 2);} -template -void u16SetVal(const sai_uint16_t &value, T &t, int bits = 16){ + t->set_value(&val, 2); +} + + template +void u16SetVal(const sai_uint16_t &value, T &t, int bits = 16) +{ assert(bits <= 16); + uint16_t val = value; + val = htons(val); + t->set_value(&val, 2); } -template -void u32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32){ + template +void u32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) +{ assert(bits <= 32); + uint32_t val = value.u32; + val = htonl(val); val = val >> (32 - bits); + int bytes = (bits + 7) / 8; + t->set_value(&val, bytes); } -template -void s32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32){ + template +void s32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) +{ assert(bits <= 32); + uint32_t val = value.u32; + val = htonl(val); val = val >> (32 - bits); + int bytes = (bits + 7) / 8; + t->set_value(&val, bytes); } -template -void u32SetVal(const sai_uint32_t &value, T &t, int bits = 32){ + template +void u32SetVal(const sai_uint32_t &value, T &t, int bits = 32) +{ assert(bits <= 32); + uint32_t val = value; + val = htonl(val); val = val >> (32 - bits); + int bytes = (bits + 7) / 8; + t->set_value(&val, bytes); } -template -void u64SetVal(const sai_attribute_value_t &value, T &t, int bits = 64){ + template +void u64SetVal(const sai_uint64_t &value, T &t, int bits = 64) +{ assert(bits <= 64); - uint64_t val = value.u64; - if (*reinterpret_cast("\0\x01") == 0) { // Little Endian - const uint32_t high_part = htonl(static_cast(val >> 32)); - const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); - val = (static_cast(low_part) << 32) | high_part; - val = val >> (64-bits); - } - int bytes = (bits + 7) / 8; - t->set_value(&val, bytes);} -template -void u64SetVal(const sai_uint64_t &value, T &t, int bits = 64) { - assert(bits <= 64); uint64_t val = value; - if (*reinterpret_cast("\0\x01") == 0) { // Little Endian + + if (*reinterpret_cast("\0\x01") == 0) // Little Endian + { const uint32_t high_part = htonl(static_cast(val >> 32)); const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); + val = (static_cast(low_part) << 32) | high_part; - val = val >> (64-bits); + val = val >> (64 - bits); } + int bytes = (bits + 7) / 8; + t->set_value(&val, bytes); } -template -void ipaddrSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u64SetVal(const sai_attribute_value_t &value, T &t, int bits = 64) +{ + u64SetVal(value.u64, t, bits); +} + + template +void ipaddrSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ ipaddrSetVal(value.ipaddr, t); } -template -void ipaddrSetVal(const sai_ip_address_t &value, T &t, int bits = -1){ - switch(value.addr_family) { - case SAI_IP_ADDR_FAMILY_IPV4: { - uint32_t val = value.addr.ip4; - t->set_value(&val, 4); - } - break; - case SAI_IP_ADDR_FAMILY_IPV6: { - t->set_value(const_cast(&value.addr.ip6[0]), 16); - } - break; - default: assert(0 && "unrecognzed value.ipaddr.addr_family"); + template +void ipaddrSetVal(const sai_ip_address_t &value, T &t, int bits = -1) +{ + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t val = value.addr.ip4; + + t->set_value(&val, 4); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + t->set_value(const_cast(&value.addr.ip6[0]), 16); + } + break; + + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); } } -template -void ipaddrSetMask(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void ipaddrSetMask(const sai_attribute_value_t &value, T &t, int bits = -1) +{ ipaddrSetMask(value.ipaddr, t); } -template -void ipaddrSetMask(const sai_ip_address_t &value, T &t, int bits = -1){ - switch(value.addr_family) { - case SAI_IP_ADDR_FAMILY_IPV4: { - uint32_t mask = value.addr.ip4; - t->set_mask(&mask, 4); - } - break; - case SAI_IP_ADDR_FAMILY_IPV6: { - t->set_mask(const_cast(&value.addr.ip6[0]), 16); - } - break; - default: assert(0 && "unrecognzed value.ipaddr.addr_family"); + template +void ipaddrSetMask(const sai_ip_address_t &value, T &t, int bits = -1) +{ + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t mask = value.addr.ip4; + + t->set_mask(&mask, 4); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + t->set_mask(const_cast(&value.addr.ip6[0]), 16); + } + break; + + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); } } -template -void macSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void macSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ t->set_value(const_cast(&value.mac[0]), 6); } -template -void macSetVal(const sai_mac_t &value, T &t, int bits = -1){ + template +void macSetVal(const sai_mac_t &value, T &t, int bits = -1) +{ t->set_value(const_cast(&value[0]), 6); } @@ -180,137 +232,172 @@ void correctIpPrefix(void *ip, const void *mask, size_t length); int leadingNonZeroBits(const uint32_t ipv4); -int leadingNonZeroBits(const sai_ip6_t ipv6); +int leadingNonZeroBits(const sai_ip6_t& ipv6); -template -void ipPrefixSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void ipPrefixSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ ipPrefixSetVal(value.ipprefix, t); } -template -void ipPrefixSetVal(const sai_ip_prefix_t &value, T &t, int bits = -1){ - switch(value.addr_family) { - case SAI_IP_ADDR_FAMILY_IPV4: { - uint32_t val = value.addr.ip4; - correctIpPrefix(&val, &value.mask.ip4, 4); - t->set_value(&val, 4); - val = htonl(value.mask.ip4); - // LPM entry match field prefix length calculation needs to be fixed to accomodate 128 bit size. - // So the 96 is added to the prefix length. - t->set_prefix_len(leadingNonZeroBits(val)+96); - } - break; - case SAI_IP_ADDR_FAMILY_IPV6: { - uint8_t ip[16]; - std::copy(const_cast(&value.addr.ip6[0]), const_cast(&value.addr.ip6[0])+16, ip); - correctIpPrefix(ip, value.mask.ip6, 16); - t->set_value(ip, 16); - t->set_prefix_len(leadingNonZeroBits(value.mask.ip6)); - } - break; - default: assert(0 && "unrecognzed value.ipaddr.addr_family"); + template +void ipPrefixSetVal(const sai_ip_prefix_t &value, T &t, int bits = -1) +{ + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t val = value.addr.ip4; + + correctIpPrefix(&val, &value.mask.ip4, 4); + + t->set_value(&val, 4); + + val = htonl(value.mask.ip4); + + // LPM entry match field prefix length calculation needs to be fixed to accomodate 128 bit size. + // So the 96 is added to the prefix length. + t->set_prefix_len(leadingNonZeroBits(val) + 96); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + uint8_t ip[16]; + + std::copy(const_cast(&value.addr.ip6[0]), const_cast(&value.addr.ip6[0]) + 16, ip); + + correctIpPrefix(ip, value.mask.ip6, 16); + + t->set_value(ip, 16); + t->set_prefix_len(leadingNonZeroBits(value.mask.ip6)); + } + break; + + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); } } -template -void u8listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u8listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u16listVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u16listVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u32listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u32listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u64listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u64listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void ipaddrlistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void ipaddrlistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u8rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u8rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u16rangelistVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u16rangelistVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u32rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u32rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void u64rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void u64rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -template -void ipaddrrangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){ + template +void ipaddrrangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) +{ assert (0 && "NYI"); } -const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list); - -template -void u32SetMask(const sai_attribute_value_t &value, T &t, int bits = 32){ + template +void u32SetMask(const sai_attribute_value_t &value, T &t, int bits = 32) +{ assert(bits <= 32); + uint32_t val = value.u32; + val = htonl(val); val = val >> (32 - bits); + int bytes = (bits + 7) / 8; + t->set_mask(&val, bytes); } -template -void u32SetMask(const sai_uint32_t &value, T &t, int bits = 32){ + template +void u32SetMask(const sai_uint32_t &value, T &t, int bits = 32) +{ assert(bits <= 32); + uint32_t val = value; + val = htonl(val); val = val >> (32 - bits); + int bytes = (bits + 7) / 8; + t->set_mask(&val, bytes); } -template -void u64SetMask(const sai_attribute_value_t &value, T &t, int bits = 64){ + template +void u64SetMask(const sai_uint64_t &value, T &t, int bits = 64) +{ assert(bits <= 64); - uint64_t val = value.u64; - if (*reinterpret_cast("\0\x01") == 0) { // Little Endian - const uint32_t high_part = htonl(static_cast(val >> 32)); - const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); - val = (static_cast(low_part) << 32) | high_part; - val = val >> (64-bits); - } - int bytes = (bits + 7) / 8; - t->set_value(&val, bytes);} -template -void u64SetMask(const sai_uint64_t &value, T &t, int bits = 64) { - assert(bits <= 64); uint64_t val = value; - if (*reinterpret_cast("\0\x01") == 0) { // Little Endian + + if (*reinterpret_cast("\0\x01") == 0) // Little Endian + { const uint32_t high_part = htonl(static_cast(val >> 32)); const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); + val = (static_cast(low_part) << 32) | high_part; val = val >> (64-bits); } + int bytes = (bits + 7) / 8; + t->set_mask(&val, bytes); } + template +void u64SetMask(const sai_attribute_value_t &value, T &t, int bits = 64) +{ + u64SetMask(value.u64, t, bits); +} + +const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list); + grpc::StatusCode MutateTableEntry(std::shared_ptr, p4::v1::Update_Type updateType); sai_object_id_t NextObjectId(sai_object_type_t objectType); From 69fbd6e8f0153ad4b14b37bd047b5b90f73cfeeb Mon Sep 17 00:00:00 2001 From: kcudnik Date: Tue, 8 Aug 2023 18:49:55 +0200 Subject: [PATCH 02/11] [SAI] Move utils to it's own namespace dash::utils To prevent leak symbols to other modules --- dash-pipeline/SAI/templates/saiapi.cpp.j2 | 2 + dash-pipeline/SAI/templates/utils.cpp.j2 | 18 +- dash-pipeline/SAI/templates/utils.h.j2 | 562 +++++++++++----------- 3 files changed, 295 insertions(+), 287 deletions(-) diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index b4dae1376..4e815bc47 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -1,5 +1,7 @@ #include "utils.h" +using namespace dash::utils; + {% set registered_group = [] %} {% for table in tables %} {% if table.name in registered_group %}{% continue %}{% endif %} diff --git a/dash-pipeline/SAI/templates/utils.cpp.j2 b/dash-pipeline/SAI/templates/utils.cpp.j2 index c2738e519..4a80b64f0 100644 --- a/dash-pipeline/SAI/templates/utils.cpp.j2 +++ b/dash-pipeline/SAI/templates/utils.cpp.j2 @@ -10,7 +10,7 @@ static std::atomic nextId; std::unique_ptr stub; -void correctIpPrefix(void *ip, const void *mask, size_t length) +void dash::utils::correctIpPrefix(void *ip, const void *mask, size_t length) { DASH_LOG_ENTER(); @@ -23,7 +23,7 @@ void correctIpPrefix(void *ip, const void *mask, size_t length) } } -int leadingNonZeroBits(const uint32_t ipv4) +int dash::utils::leadingNonZeroBits(const uint32_t ipv4) { DASH_LOG_ENTER(); @@ -37,7 +37,7 @@ int leadingNonZeroBits(const uint32_t ipv4) return 33 - firstSetBit; } -int leadingNonZeroBits(const sai_ip6_t& ipv6) +int dash::utils::leadingNonZeroBits(const sai_ip6_t& ipv6) { DASH_LOG_ENTER(); @@ -70,7 +70,7 @@ static int GetDeviceId() return deviceId; } -std::string updateTypeStr(p4::v1::Update_Type updateType) +static std::string updateTypeStr(p4::v1::Update_Type updateType) { DASH_LOG_ENTER(); @@ -79,7 +79,7 @@ std::string updateTypeStr(p4::v1::Update_Type updateType) return descriptor->FindValueByNumber(updateType)->name(); } -const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) +const sai_attribute_t* dash::utils::getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) { DASH_LOG_ENTER(); @@ -94,7 +94,7 @@ const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const return nullptr; } -grpc::StatusCode MutateTableEntry(std::shared_ptr entry, p4::v1::Update_Type updateType) +grpc::StatusCode dash::utils::MutateTableEntry(std::shared_ptr entry, p4::v1::Update_Type updateType) { DASH_LOG_ENTER(); @@ -132,7 +132,7 @@ grpc::StatusCode MutateTableEntry(std::shared_ptr entry, p4: return status.error_code(); } -bool InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId) +bool dash::utils::InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId) { DASH_LOG_ENTER(); @@ -159,14 +159,14 @@ bool InsertInTable(std::shared_ptr entry, sai_object_type_t #define DASH_OBJECT_SHFT 48 #define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype< #include - template -void booldataSetVal(const sai_attribute_value_t &value, T &t, int bits = 8) +namespace dash { - assert(bits <= 8); - - t->set_value(const_cast(&value.booldata), 1); -} - - template -void booldataSetVal(const bool &value, T &t, int bits = 8) -{ - assert(bits <= 8); + namespace utils + { + template + void booldataSetVal(const sai_attribute_value_t &value, T &t, int bits = 8) + { + assert(bits <= 8); - t->set_value(const_cast(&value), 1); -} + t->set_value(const_cast(&value.booldata), 1); + } - template -void u8SetVal(const sai_attribute_value_t &value, T &t, int bits = 8) -{ - assert(bits <= 8); + template + void booldataSetVal(const bool &value, T &t, int bits = 8) + { + assert(bits <= 8); - t->set_value(const_cast(&value.u8), 1); -} + t->set_value(const_cast(&value), 1); + } - template -void u8SetVal(const sai_uint8_t &value, T &t, int bits = 8) -{ - assert(bits <= 8); + template + void u8SetVal(const sai_attribute_value_t &value, T &t, int bits = 8) + { + assert(bits <= 8); - t->set_value(const_cast(&value), 1); -} + t->set_value(const_cast(&value.u8), 1); + } - template -void u16SetVal(const sai_attribute_value_t &value, T &t, int bits = 16) -{ - assert(bits <= 16); + template + void u8SetVal(const sai_uint8_t &value, T &t, int bits = 8) + { + assert(bits <= 8); - uint16_t val = value.u16; + t->set_value(const_cast(&value), 1); + } - val = htons(val); + template + void u16SetVal(const sai_attribute_value_t &value, T &t, int bits = 16) + { + assert(bits <= 16); - t->set_value(&val, 2); -} + uint16_t val = value.u16; - template -void u16SetVal(const sai_uint16_t &value, T &t, int bits = 16) -{ - assert(bits <= 16); + val = htons(val); - uint16_t val = value; + t->set_value(&val, 2); + } - val = htons(val); + template + void u16SetVal(const sai_uint16_t &value, T &t, int bits = 16) + { + assert(bits <= 16); - t->set_value(&val, 2); -} + uint16_t val = value; - template -void u32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) -{ - assert(bits <= 32); + val = htons(val); - uint32_t val = value.u32; + t->set_value(&val, 2); + } - val = htonl(val); - val = val >> (32 - bits); + template + void u32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) + { + assert(bits <= 32); - int bytes = (bits + 7) / 8; + uint32_t val = value.u32; - t->set_value(&val, bytes); -} + val = htonl(val); + val = val >> (32 - bits); - template -void s32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) -{ - assert(bits <= 32); + int bytes = (bits + 7) / 8; - uint32_t val = value.u32; + t->set_value(&val, bytes); + } - val = htonl(val); - val = val >> (32 - bits); + template + void s32SetVal(const sai_attribute_value_t &value, T &t, int bits = 32) + { + assert(bits <= 32); - int bytes = (bits + 7) / 8; + uint32_t val = value.u32; - t->set_value(&val, bytes); -} + val = htonl(val); + val = val >> (32 - bits); - template -void u32SetVal(const sai_uint32_t &value, T &t, int bits = 32) -{ - assert(bits <= 32); + int bytes = (bits + 7) / 8; - uint32_t val = value; + t->set_value(&val, bytes); + } - val = htonl(val); - val = val >> (32 - bits); + template + void u32SetVal(const sai_uint32_t &value, T &t, int bits = 32) + { + assert(bits <= 32); - int bytes = (bits + 7) / 8; + uint32_t val = value; - t->set_value(&val, bytes); -} + val = htonl(val); + val = val >> (32 - bits); - template -void u64SetVal(const sai_uint64_t &value, T &t, int bits = 64) -{ - assert(bits <= 64); + int bytes = (bits + 7) / 8; - uint64_t val = value; + t->set_value(&val, bytes); + } - if (*reinterpret_cast("\0\x01") == 0) // Little Endian - { - const uint32_t high_part = htonl(static_cast(val >> 32)); - const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); + template + void u64SetVal(const sai_uint64_t &value, T &t, int bits = 64) + { + assert(bits <= 64); - val = (static_cast(low_part) << 32) | high_part; - val = val >> (64 - bits); - } + uint64_t val = value; - int bytes = (bits + 7) / 8; + if (*reinterpret_cast("\0\x01") == 0) // Little Endian + { + const uint32_t high_part = htonl(static_cast(val >> 32)); + const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); - t->set_value(&val, bytes); -} + val = (static_cast(low_part) << 32) | high_part; + val = val >> (64 - bits); + } - template -void u64SetVal(const sai_attribute_value_t &value, T &t, int bits = 64) -{ - u64SetVal(value.u64, t, bits); -} + int bytes = (bits + 7) / 8; - template -void ipaddrSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - ipaddrSetVal(value.ipaddr, t); -} + t->set_value(&val, bytes); + } - template -void ipaddrSetVal(const sai_ip_address_t &value, T &t, int bits = -1) -{ - switch(value.addr_family) - { - case SAI_IP_ADDR_FAMILY_IPV4: + template + void u64SetVal(const sai_attribute_value_t &value, T &t, int bits = 64) { - uint32_t val = value.addr.ip4; - - t->set_value(&val, 4); + u64SetVal(value.u64, t, bits); } - break; - case SAI_IP_ADDR_FAMILY_IPV6: + template + void ipaddrSetVal(const sai_ip_address_t &value, T &t, int bits = -1) { - t->set_value(const_cast(&value.addr.ip6[0]), 16); + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t val = value.addr.ip4; + + t->set_value(&val, 4); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + t->set_value(const_cast(&value.addr.ip6[0]), 16); + } + break; + + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); + } } - break; - default: - assert(0 && "unrecognzed value.ipaddr.addr_family"); - } -} + template + void ipaddrSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + ipaddrSetVal(value.ipaddr, t); + } - template -void ipaddrSetMask(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - ipaddrSetMask(value.ipaddr, t); -} + template + void ipaddrSetMask(const sai_ip_address_t &value, T &t, int bits = -1) + { + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t mask = value.addr.ip4; + + t->set_mask(&mask, 4); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + t->set_mask(const_cast(&value.addr.ip6[0]), 16); + } + break; + + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); + } + } - template -void ipaddrSetMask(const sai_ip_address_t &value, T &t, int bits = -1) -{ - switch(value.addr_family) - { - case SAI_IP_ADDR_FAMILY_IPV4: + template + void ipaddrSetMask(const sai_attribute_value_t &value, T &t, int bits = -1) { - uint32_t mask = value.addr.ip4; + ipaddrSetMask(value.ipaddr, t); + } - t->set_mask(&mask, 4); + template + void macSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + t->set_value(const_cast(&value.mac[0]), 6); } - break; - case SAI_IP_ADDR_FAMILY_IPV6: + template + void macSetVal(const sai_mac_t &value, T &t, int bits = -1) { - t->set_mask(const_cast(&value.addr.ip6[0]), 16); + t->set_value(const_cast(&value[0]), 6); } - break; - default: - assert(0 && "unrecognzed value.ipaddr.addr_family"); - } -} + void correctIpPrefix(void *ip, const void *mask, size_t length); - template -void macSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - t->set_value(const_cast(&value.mac[0]), 6); -} + int leadingNonZeroBits(const uint32_t ipv4); - template -void macSetVal(const sai_mac_t &value, T &t, int bits = -1) -{ - t->set_value(const_cast(&value[0]), 6); -} + int leadingNonZeroBits(const sai_ip6_t& ipv6); + + template + void ipPrefixSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + ipPrefixSetVal(value.ipprefix, t); + } -void correctIpPrefix(void *ip, const void *mask, size_t length); + template + void ipPrefixSetVal(const sai_ip_prefix_t &value, T &t, int bits = -1) + { + switch(value.addr_family) + { + case SAI_IP_ADDR_FAMILY_IPV4: + { + uint32_t val = value.addr.ip4; -int leadingNonZeroBits(const uint32_t ipv4); + correctIpPrefix(&val, &value.mask.ip4, 4); -int leadingNonZeroBits(const sai_ip6_t& ipv6); + t->set_value(&val, 4); - template -void ipPrefixSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - ipPrefixSetVal(value.ipprefix, t); -} + val = htonl(value.mask.ip4); - template -void ipPrefixSetVal(const sai_ip_prefix_t &value, T &t, int bits = -1) -{ - switch(value.addr_family) - { - case SAI_IP_ADDR_FAMILY_IPV4: - { - uint32_t val = value.addr.ip4; + // LPM entry match field prefix length calculation needs to be fixed to accomodate 128 bit size. + // So the 96 is added to the prefix length. + t->set_prefix_len(leadingNonZeroBits(val) + 96); + } + break; + + case SAI_IP_ADDR_FAMILY_IPV6: + { + uint8_t ip[16]; - correctIpPrefix(&val, &value.mask.ip4, 4); + std::copy(const_cast(&value.addr.ip6[0]), const_cast(&value.addr.ip6[0]) + 16, ip); - t->set_value(&val, 4); + correctIpPrefix(ip, value.mask.ip6, 16); - val = htonl(value.mask.ip4); + t->set_value(ip, 16); + t->set_prefix_len(leadingNonZeroBits(value.mask.ip6)); + } + break; - // LPM entry match field prefix length calculation needs to be fixed to accomodate 128 bit size. - // So the 96 is added to the prefix length. - t->set_prefix_len(leadingNonZeroBits(val) + 96); + default: + assert(0 && "unrecognzed value.ipaddr.addr_family"); + } } - break; - case SAI_IP_ADDR_FAMILY_IPV6: + template + void u8listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) { - uint8_t ip[16]; - - std::copy(const_cast(&value.addr.ip6[0]), const_cast(&value.addr.ip6[0]) + 16, ip); + assert (0 && "NYI"); + } - correctIpPrefix(ip, value.mask.ip6, 16); + template + void u16listVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - t->set_value(ip, 16); - t->set_prefix_len(leadingNonZeroBits(value.mask.ip6)); + template + void u32listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); } - break; - default: - assert(0 && "unrecognzed value.ipaddr.addr_family"); - } -} + template + void u64listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u8listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void ipaddrlistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u16listVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void u8rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u32listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void u16rangelistVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u64listSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void u32rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void ipaddrlistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void u64rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u8rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void ipaddrrangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) + { + assert (0 && "NYI"); + } - template -void u16rangelistVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + template + void u32SetMask(const sai_attribute_value_t &value, T &t, int bits = 32) + { + assert(bits <= 32); - template -void u32rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + uint32_t val = value.u32; - template -void u64rangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + val = htonl(val); + val = val >> (32 - bits); - template -void ipaddrrangelistSetVal(const sai_attribute_value_t &value, T &t, int bits = -1) -{ - assert (0 && "NYI"); -} + int bytes = (bits + 7) / 8; - template -void u32SetMask(const sai_attribute_value_t &value, T &t, int bits = 32) -{ - assert(bits <= 32); + t->set_mask(&val, bytes); + } - uint32_t val = value.u32; + template + void u32SetMask(const sai_uint32_t &value, T &t, int bits = 32) + { + assert(bits <= 32); - val = htonl(val); - val = val >> (32 - bits); + uint32_t val = value; - int bytes = (bits + 7) / 8; + val = htonl(val); + val = val >> (32 - bits); - t->set_mask(&val, bytes); -} + int bytes = (bits + 7) / 8; - template -void u32SetMask(const sai_uint32_t &value, T &t, int bits = 32) -{ - assert(bits <= 32); - - uint32_t val = value; - - val = htonl(val); - val = val >> (32 - bits); - - int bytes = (bits + 7) / 8; - - t->set_mask(&val, bytes); -} + t->set_mask(&val, bytes); + } - template -void u64SetMask(const sai_uint64_t &value, T &t, int bits = 64) -{ - assert(bits <= 64); + template + void u64SetMask(const sai_uint64_t &value, T &t, int bits = 64) + { + assert(bits <= 64); - uint64_t val = value; + uint64_t val = value; - if (*reinterpret_cast("\0\x01") == 0) // Little Endian - { - const uint32_t high_part = htonl(static_cast(val >> 32)); - const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); + if (*reinterpret_cast("\0\x01") == 0) // Little Endian + { + const uint32_t high_part = htonl(static_cast(val >> 32)); + const uint32_t low_part = htonl(static_cast(val & 0xFFFFFFFFLL)); - val = (static_cast(low_part) << 32) | high_part; - val = val >> (64-bits); - } + val = (static_cast(low_part) << 32) | high_part; + val = val >> (64-bits); + } - int bytes = (bits + 7) / 8; + int bytes = (bits + 7) / 8; - t->set_mask(&val, bytes); -} + t->set_mask(&val, bytes); + } - template -void u64SetMask(const sai_attribute_value_t &value, T &t, int bits = 64) -{ - u64SetMask(value.u64, t, bits); -} + template + void u64SetMask(const sai_attribute_value_t &value, T &t, int bits = 64) + { + u64SetMask(value.u64, t, bits); + } -const sai_attribute_t *getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list); + const sai_attribute_t* getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list); -grpc::StatusCode MutateTableEntry(std::shared_ptr, p4::v1::Update_Type updateType); + grpc::StatusCode MutateTableEntry(std::shared_ptr, p4::v1::Update_Type updateType); -sai_object_id_t NextObjectId(sai_object_type_t objectType); + sai_object_id_t NextObjectId(sai_object_type_t objectType); -bool InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId); + bool InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId); -bool RemoveFromTable(sai_object_id_t id); + bool RemoveFromTable(sai_object_id_t id); + } +} From 5f519dd882b84f1d18b9835d7f6bdd6df2416041 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Tue, 8 Aug 2023 20:05:31 +0200 Subject: [PATCH 03/11] [SAI] Move fixed api implementation to proper DashSai class --- dash-pipeline/SAI/sai_api_gen.py | 2 +- dash-pipeline/SAI/templates/Makefile.j2 | 3 +- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 475 ++++++++++++++++++ dash-pipeline/SAI/templates/dashsai.h.j2 | 106 ++++ dash-pipeline/SAI/templates/saiapi.cpp.j2 | 17 +- .../SAI/templates/saifixedapis.cpp.j2 | 218 +------- dash-pipeline/SAI/templates/saiimpl.h.j2 | 4 + dash-pipeline/SAI/templates/utils.cpp.j2 | 155 +----- dash-pipeline/SAI/templates/utils.h.j2 | 10 +- 9 files changed, 621 insertions(+), 369 deletions(-) create mode 100644 dash-pipeline/SAI/templates/dashsai.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/dashsai.h.j2 diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 07e1acc93..aafaa9275 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -381,7 +381,7 @@ def write_sai_makefile(sai_api_name_list, sai_api_full_name_list): def write_sai_fixed_api_files(sai_api_full_name_list): env = Environment(loader=FileSystemLoader('.')) - for filename in ['utils.cpp', 'utils.h', 'saifixedapis.cpp', 'saiimpl.h', 'logger.h', 'logger.cpp', 'saidash.h', 'config.h', 'config.cpp']: + for filename in ['utils.cpp', 'utils.h', 'saifixedapis.cpp', 'saiimpl.h', 'logger.h', 'logger.cpp', 'saidash.h', 'dashsai.h', 'dashsai.cpp', 'config.h', 'config.cpp']: env = Environment(loader=FileSystemLoader('.'), trim_blocks=True, lstrip_blocks=True) sai_impl_tm = env.get_template('/templates/%s.j2' % filename) sai_impl_str = sai_impl_tm.render(tables = sai_api[TABLES_TAG], app_name = sai_api['app_name'], api_names = sai_api_full_name_list) diff --git a/dash-pipeline/SAI/templates/Makefile.j2 b/dash-pipeline/SAI/templates/Makefile.j2 index aac6a2183..65f05ad7d 100644 --- a/dash-pipeline/SAI/templates/Makefile.j2 +++ b/dash-pipeline/SAI/templates/Makefile.j2 @@ -61,7 +61,8 @@ SAI_OBJS=$(SAI_SRCS:.c=.o) DASH_FIXED_SAI_SRCS=utils.cpp \ saifixedapis.cpp \ logger.cpp \ - config.cpp + config.cpp \ + dashsai.cpp DASH_FIXED_SAI_OBJ=$(DASH_FIXED_SAI_SRCS:.cpp=.o) # DASH libsai "generated" sources (from P4 code) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 new file mode 100644 index 000000000..746e4f944 --- /dev/null +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -0,0 +1,475 @@ +#include "dashsai.h" + +using namespace dash; + +#define DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES 0 + +#define DASH_OBJECT_SHFT 48 +#define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype< _lock(m_tableLock); + +DashSai::DashSai(): + m_apiInitialized(false) +{ + DASH_LOG_ENTER(); + + // those oids are constant + + m_switchId = DASH_MAKE_OID(SAI_OBJECT_TYPE_SWITCH, 1); + m_defaultCpuPortId = DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT, 64); + m_defaultVlanId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VLAN, 1); + m_defaultVrfId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, 1); + m_default1QBridgeId = DASH_MAKE_OID(SAI_OBJECT_TYPE_BRIDGE, 1); +} + +DashSai::~DashSai() +{ + DASH_LOG_ENTER(); + + if (m_apiInitialized) + { + apiUninitialize(); + } +} + +sai_status_t DashSai::apiInitialize( + _In_ uint64_t flags, + _In_ const sai_service_method_table_t *services) +{ + DASH_LOG_ENTER(); + + if (m_apiInitialized) + { + DASH_LOG_ERROR("api already initialized"); + + return SAI_STATUS_FAILURE; + } + + m_cfg = dash::Config::getConfig(services); + + DASH_LOG_NOTICE("config: %s", m_cfg->getConfigString().c_str()); + + for (uint32_t i = 1; i <= m_cfg->m_bmv2NumPorts; i++) + { + m_portList.push_back(DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT,i)); + } + + assert(m_cfg->m_bmv2NumPorts == (uint32_t)m_portList.size()); + + const grpc::string _grpcTarget = m_cfg->m_grpcTarget; + const char* test_json = m_cfg->m_pipelineJson.c_str(); + const char* test_proto_json = m_cfg->m_pipelineProto.c_str(); + + DASH_LOG_NOTICE("GRPC call SetForwardingPipelineConfig %s => %s, %s", _grpcTarget.c_str(), test_json, test_proto_json); + + auto p4info = parse_p4info(test_proto_json); + + auto set_election_id = [](p4::v1::Uint128 *election_id) + { + election_id->set_high(0); + election_id->set_low(1); + }; + + grpc::ClientContext stream_context; + + m_grpcChannel = grpc::CreateChannel(_grpcTarget, grpc::InsecureChannelCredentials()); + + m_stub = p4::v1::P4Runtime::NewStub(m_grpcChannel); + + auto stream = m_stub->StreamChannel(&stream_context); + + { + p4::v1::StreamMessageRequest request; + auto arbitration = request.mutable_arbitration(); + arbitration->set_device_id(m_cfg->m_deviceId); + set_election_id(arbitration->mutable_election_id()); + stream->Write(request); + p4::v1::StreamMessageResponse response; + stream->Read(&response); + assert(response.update_case() == p4::v1::StreamMessageResponse::kArbitration); + assert(response.arbitration().status().code() == ::google::rpc::Code::OK); + } + + { + p4::v1::SetForwardingPipelineConfigRequest request; + request.set_device_id(m_cfg->m_deviceId); + request.set_action( + p4::v1::SetForwardingPipelineConfigRequest_Action_VERIFY_AND_COMMIT); + set_election_id(request.mutable_election_id()); + auto config = request.mutable_config(); + config->set_allocated_p4info(&p4info); + std::ifstream istream(test_json); + config->mutable_p4_device_config()->assign( + (std::istreambuf_iterator(istream)), + std::istreambuf_iterator()); + + p4::v1::SetForwardingPipelineConfigResponse rep; + grpc::ClientContext context; + + auto status = m_stub->SetForwardingPipelineConfig(&context, request, &rep); + + assert(status.ok()); + + config->release_p4info(); + } + + m_apiInitialized = true; + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::apiUninitialize(void) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + m_cfg = nullptr; + + m_portList.clear(); + + m_tableEntryMap.clear(); + + m_nextId = 0; + + m_grpcChannel = nullptr; + + m_stub = nullptr; + + m_apiInitialized = false; + + return SAI_STATUS_SUCCESS; +} + +sai_object_type_t DashSai::objectTypeQuery( + _In_ sai_object_id_t object_id) +{ + DASH_LOG_ENTER(); + + if (!m_apiInitialized) + { + DASH_LOG_ERROR("api not initialized"); + + return SAI_OBJECT_TYPE_NULL; + + } + + return sai_object_type_t(object_id >> (DASH_OBJECT_SHFT)); +} + +sai_object_id_t DashSai::switchIdQuery( + _In_ sai_object_id_t object_id) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + if (object_id == SAI_NULL_OBJECT_ID) + { + return SAI_NULL_OBJECT_ID; + } + + return m_switchId; +} + +sai_status_t DashSai::createSwitch( + _Out_ sai_object_id_t *switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + *switch_id = m_switchId; + + DASH_LOG_NOTICE("created switch id: %ld", *switch_id); + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::getSwitchAttribute( + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + DASH_LOG_NOTICE("dash_get_switch_attribute()"); + + sai_attribute_t *attr = attr_list; + + for (uint32_t i = 0; i < attr_count ; i++, attr++) + { + switch(attr->id) + { + case SAI_SWITCH_ATTR_NUMBER_OF_ACTIVE_PORTS: + + attr->value.u32 = m_cfg->m_bmv2NumPorts; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_NUMBER_OF_ACTIVE_PORTS = %d", i, attr->value.u32); + + break; + + case SAI_SWITCH_ATTR_PORT_LIST: + + attr->value.objlist.count = m_cfg->m_bmv2NumPorts; + + for (size_t j = 0; j < m_cfg->m_bmv2NumPorts; j++) + { + attr->value.objlist.list[j] = m_portList.at(j); + } + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_PORT_LIST = [%d objids]", i, m_cfg->m_bmv2NumPorts); + + break; + + case SAI_SWITCH_ATTR_DEFAULT_VLAN_ID: + + attr->value.oid = m_defaultVlanId; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VLAN_ID = %lx", i, attr->value.oid); + + break; + + case SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID: + + attr->value.oid = m_defaultVrfId; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID = %lx", i, attr->value.oid); + + break; + + case SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID: + + attr->value.oid = m_default1QBridgeId; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID = %lx", i, attr->value.oid); + + break; + + case SAI_SWITCH_ATTR_CPU_PORT: + + attr->value.oid = m_defaultCpuPortId; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_CPU_PORT = %lx", i, attr->value.oid); + + break; + + default: + + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); + + memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage + + break; // TODO FIXME should return NOT SUPPORTED + } + } + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::getPortAttribute( + _In_ sai_object_id_t port_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + DASH_LOG_NOTICE("getPortAttribute()"); + + sai_attribute_t *attr = attr_list; + + for (uint32_t i = 0; i < attr_count ; i++, attr++) + { + switch(attr->id) + { + case SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES: + + attr->value.u32 = DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES; + + DASH_LOG_NOTICE("[%d] SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES = %d", i, attr->value.u32); + + break; + + default: + + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); + + memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage + + break; // TODO FIXME should return NOT SUPPORTED + } + } + + return SAI_STATUS_SUCCESS; +} + +// private helper methods + +p4::config::v1::P4Info DashSai::parse_p4info( + _In_ const char *path) +{ + DASH_LOG_ENTER(); + + p4::config::v1::P4Info p4info; + std::ifstream istream(path); + assert(istream.good()); + google::protobuf::io::IstreamInputStream istream_(&istream); + google::protobuf::TextFormat::Parse(&istream_, &p4info); + + return p4info; +} + +std::string DashSai::updateTypeStr( + _In_ p4::v1::Update_Type updateType) +{ + DASH_LOG_ENTER(); + + const google::protobuf::EnumDescriptor *descriptor = p4::v1::Update_Type_descriptor(); + + return descriptor->FindValueByNumber(updateType)->name(); +} + +// helper methods + +grpc::StatusCode DashSai::mutateTableEntry( + _In_ std::shared_ptr entry, + _In_ p4::v1::Update_Type updateType) +{ + DASH_LOG_ENTER(); + + if (!m_apiInitialized) + { + DASH_LOG_ERROR("api not initialized"); + + return grpc::StatusCode::CANCELLED; + } + + p4::v1::WriteRequest request; + + request.set_device_id(m_cfg->m_deviceId); + + auto update = request.add_updates(); + + update->set_type(updateType); + + auto entity = update->mutable_entity(); + + entity->set_allocated_table_entry(entry.get()); + + p4::v1::WriteResponse rep; + + grpc::ClientContext context; + + grpc::Status status = m_stub->Write(&context, request, &rep); + + if (status.ok()) + { + DASH_LOG_NOTICE("GRPC call Write::%s OK %s", updateTypeStr(updateType).c_str(), entry->ShortDebugString().c_str()); + } + else + { + DASH_LOG_ERROR("GRPC ERROR[%d]: %s, %s", status.error_code(), status.error_message().c_str(), status.error_details().c_str()); + DASH_LOG_ERROR("GRPC call Write::%s ERROR: %s", updateTypeStr(updateType).c_str(), entry->ShortDebugString().c_str()); + } + + //MILIND?? What is this? reference release? memory release? + entity->release_table_entry(); + + return status.error_code(); +} + +bool DashSai::insertInTable( + _In_ std::shared_ptr entry, + _In_ sai_object_type_t objectType, + _Out_ sai_object_id_t *objId) +{ + DASH_LOG_ENTER(); + + if (!m_apiInitialized) + { + DASH_LOG_ERROR("api not initialized"); + + return false; + } + + auto retCode = mutateTableEntry(entry, p4::v1::Update_Type_INSERT); + + if (grpc::StatusCode::OK != retCode) + { + return false; + } + + MUTEX; + + if (*objId == 0) + { + *objId = getNextObjectId(objectType); + } + + m_tableEntryMap.insert(std::make_pair(*objId, entry)); + + return true; +} + +sai_object_id_t DashSai::getNextObjectId( + _In_ sai_object_type_t objectType) +{ + DASH_LOG_ENTER(); + + if (!m_apiInitialized) + { + DASH_LOG_ERROR("api not initialized"); + + return SAI_NULL_OBJECT_ID; + } + + return DASH_MAKE_OID(objectType, ++m_nextId); +} + +bool DashSai::removeFromTable( + _In_ sai_object_id_t id) +{ + DASH_LOG_ENTER(); + + if (!m_apiInitialized) + { + DASH_LOG_ERROR("api not initialized"); + + return false; + } + + MUTEX; + + auto range = m_tableEntryMap.equal_range(id); + + if (range.first == range.second) + { + DASH_LOG_ERROR("id: %ld not present in the table for deletion!", id); + + return false; + } + + grpc::StatusCode retCode = grpc::StatusCode::OK; + + for (auto itr = range.first; itr != range.second; ++itr) + { + auto entry = itr->second; + auto tempRet = mutateTableEntry(entry, p4::v1::Update_Type_DELETE); + + if (grpc::StatusCode::OK != tempRet) + { + retCode = tempRet; + } + } + + m_tableEntryMap.erase(id); + + return retCode == grpc::StatusCode::OK; +} diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/templates/dashsai.h.j2 new file mode 100644 index 000000000..e92b37133 --- /dev/null +++ b/dash-pipeline/SAI/templates/dashsai.h.j2 @@ -0,0 +1,106 @@ +#pragma once + +#include "utils.h" +#include "config.h" + +namespace dash +{ + class DashSai + { + public: + + DashSai(); + virtual ~DashSai(); + + public: // sai global api + + sai_status_t apiInitialize( + _In_ uint64_t flags, + _In_ const sai_service_method_table_t *services); + + sai_status_t apiUninitialize(void); + + sai_object_type_t objectTypeQuery( + _In_ sai_object_id_t object_id); + + sai_object_id_t switchIdQuery( + _In_ sai_object_id_t object_id); + + public: // QUAD api implementation + + sai_status_t createSwitch( + _Out_ sai_object_id_t *switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t getSwitchAttribute( + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + + sai_status_t getPortAttribute( + _In_ sai_object_id_t port_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + + public: // helper methods + + const sai_attribute_t* getMaskAttr( + _In_ sai_attr_id_t id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + grpc::StatusCode mutateTableEntry( + _In_ std::shared_ptr, + _In_ p4::v1::Update_Type updateType); + + sai_object_id_t getNextObjectId( + _In_ sai_object_type_t objectType); + + bool insertInTable( + _In_ std::shared_ptr entry, + _In_ sai_object_type_t objectType, + _Out_ sai_object_id_t *objId); + + bool removeFromTable( + _In_ sai_object_id_t id); + + private: // private helper methods + + p4::config::v1::P4Info parse_p4info( + _In_ const char *path); + + std::string updateTypeStr( + _In_ p4::v1::Update_Type updateType); + + private: // internal sai objects + + sai_object_id_t m_switchId; + + sai_object_id_t m_defaultCpuPortId; + + sai_object_id_t m_defaultVlanId; + + sai_object_id_t m_defaultVrfId; + + sai_object_id_t m_default1QBridgeId; + + private: + + bool m_apiInitialized; + + std::shared_ptr m_cfg; + + std::vector m_portList; + + std::unordered_multimap > m_tableEntryMap; + + std::mutex m_tableLock; + + std::atomic m_nextId; + + std::shared_ptr m_grpcChannel; + + std::unique_ptr m_stub; + }; +} diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 4e815bc47..5c6496805 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -1,4 +1,5 @@ #include "utils.h" +#include "saiimpl.h" using namespace dash::utils; @@ -48,7 +49,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( // Generate a SAI object ID and fill it as the P4 table key auto mf = matchActionEntry->add_match(); mf->set_field_id({{table['keys'][0].id}}); - objId = NextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}); + objId = dashSai->getNextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}); auto mf_exact = mf->mutable_exact(); {{table['keys'][0].field}}SetVal(objId, mf_exact, {{table['keys'][0].bitwidth}}); {% else %} @@ -172,7 +173,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( //if (matchedParams != expectedParams) { // goto ErrRet; //} - if (false == InsertInTable(matchActionEntry, (sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}, &objId)) { + if (false == dashSai->insertInTable(matchActionEntry, (sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}, &objId)) { goto ErrRet; } @@ -181,7 +182,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( *{{ table.name }}_id = objId; return SAI_STATUS_SUCCESS; ErrRet: - RemoveFromTable(*{{ table.name }}_id); + dashSai->removeFromTable(*{{ table.name }}_id); return SAI_STATUS_FAILURE; } @@ -217,7 +218,7 @@ static sai_status_t dash_sai_remove_{{ table.name }}(_In_ sai_object_id_t {{ tab { DASH_LOG_ENTER(); - if (RemoveFromTable({{ table.name }}_id)) + if (dashSai->removeFromTable({{ table.name }}_id)) { return SAI_STATUS_SUCCESS; } @@ -378,7 +379,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( // goto ErrRet; //} // TODO: ternaly needs to set priority - retCode = MutateTableEntry(matchActionEntry, p4::v1::Update_Type_INSERT); + retCode = dashSai->mutateTableEntry(matchActionEntry, p4::v1::Update_Type_INSERT); if (grpc::StatusCode::OK == retCode) { return SAI_STATUS_SUCCESS; } @@ -458,8 +459,10 @@ static sai_status_t dash_sai_remove_{{ table.name }}( {% endif %} {% endfor %} - retCode = MutateTableEntry(matchActionEntry, p4::v1::Update_Type_DELETE); - if (grpc::StatusCode::OK == retCode) { + retCode = dashSai->mutateTableEntry(matchActionEntry, p4::v1::Update_Type_DELETE); + + if (grpc::StatusCode::OK == retCode) + { return SAI_STATUS_SUCCESS; } diff --git a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 index 23a12e1e2..52cee8867 100644 --- a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 +++ b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 @@ -8,24 +8,7 @@ #include -// TODO to be moved to separate class/namespace - -static std::shared_ptr _grpcChannel; -extern std::unique_ptr stub; - -#define DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES 0 - -#define DASH_OBJECT_SHFT 48 -#define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype< cfg; - -static std::vector port_list; +std::shared_ptr dashSai = std::make_shared(); static sai_status_t dash_sai_create_switch( _Out_ sai_object_id_t *switch_id, @@ -34,11 +17,7 @@ static sai_status_t dash_sai_create_switch( { DASH_LOG_ENTER(); - *switch_id = DASH_MAKE_OID(SAI_OBJECT_TYPE_SWITCH,1), - - DASH_LOG_NOTICE("created switch id: %ld", *switch_id); - - return SAI_STATUS_SUCCESS; + return dashSai->createSwitch(switch_id, attr_count, attr_list); } static sai_status_t dash_sai_get_switch_attribute( @@ -48,78 +27,7 @@ static sai_status_t dash_sai_get_switch_attribute( { DASH_LOG_ENTER(); - DASH_LOG_NOTICE("dash_get_switch_attribute()"); - - sai_attribute_t *attr = attr_list; - - for (uint32_t i = 0; i < attr_count ; i++, attr++) - { - switch(attr->id) - { - case SAI_SWITCH_ATTR_NUMBER_OF_ACTIVE_PORTS: - - attr->value.u32 = cfg->m_bmv2NumPorts; - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_NUMBER_OF_ACTIVE_PORTS = %d", i, attr->value.u32); - - break; - - case SAI_SWITCH_ATTR_PORT_LIST: - - attr->value.objlist.count = cfg->m_bmv2NumPorts; - - for (size_t j = 0; j < cfg->m_bmv2NumPorts; j++) - { - attr->value.objlist.list[j] = port_list.at(j); - } - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_PORT_LIST = [%d objids]", i, cfg->m_bmv2NumPorts); - - break; - - case SAI_SWITCH_ATTR_DEFAULT_VLAN_ID: - - attr->value.oid = DASH_BMV2_DEFAULT_VLAN_ID; - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VLAN_ID = %lx", i, attr->value.oid); - - break; - - case SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID: - - attr->value.oid = DASH_BMV2_DEFAULT_VRF_ID; - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID = %lx", i, attr->value.oid); - - break; - - case SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID: - - attr->value.oid = DASH_BMV2_DEFAULT_1Q_BRIDGE_ID; - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID = %lx", i, attr->value.oid); - - break; - - case SAI_SWITCH_ATTR_CPU_PORT: - - attr->value.oid = DASH_BMV2_DEFAULT_CPU_PORT_ID; - - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_CPU_PORT = %lx", i, attr->value.oid); - - break; - - default: - - DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); - - memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage - - break; // TODO FIXME should return NOT SUPPORTED - } - } - - return SAI_STATUS_SUCCESS; + return dashSai->getSwitchAttribute(switch_id, attr_count, attr_list); } sai_switch_api_t dash_sai_switch_api_impl = { @@ -147,33 +55,7 @@ static sai_status_t dash_sai_get_port_attribute( { DASH_LOG_ENTER(); - DASH_LOG_NOTICE("dash_sai_get_port_attribute()"); - - sai_attribute_t *attr = attr_list; - - for (uint32_t i = 0; i < attr_count ; i++, attr++) - { - switch(attr->id) - { - case SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES: - - attr->value.u32 = DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES; - - DASH_LOG_NOTICE("[%d] SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES = %d", i, attr->value.u32); - - break; - - default: - - DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); - - memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage - - break; // TODO FIXME should return NOT SUPPORTED - } - } - - return SAI_STATUS_SUCCESS; + return dashSai->getPortAttribute(port_id, attr_count, attr_list); } sai_port_api_t dash_sai_port_api_impl = { @@ -256,7 +138,7 @@ sai_object_type_t sai_object_type_query( { DASH_LOG_ENTER(); - return sai_object_type_t(object_id>>DASH_OBJECT_SHFT); + return dashSai->objectTypeQuery(object_id); } sai_object_id_t sai_switch_id_query( @@ -264,12 +146,7 @@ sai_object_id_t sai_switch_id_query( { DASH_LOG_ENTER(); - if (object_id == SAI_NULL_OBJECT_ID) - { - return SAI_NULL_OBJECT_ID; - } - - return DASH_MAKE_OID(SAI_OBJECT_TYPE_SWITCH,1); + return dashSai->switchIdQuery(object_id); } sai_status_t sai_query_attribute_enum_values_capability( @@ -285,97 +162,20 @@ sai_status_t sai_query_attribute_enum_values_capability( return SAI_STATUS_NOT_IMPLEMENTED; } -static p4::config::v1::P4Info parse_p4info(const char *path) -{ - DASH_LOG_ENTER(); - - p4::config::v1::P4Info p4info; - std::ifstream istream(path); - assert(istream.good()); - google::protobuf::io::IstreamInputStream istream_(&istream); - google::protobuf::TextFormat::Parse(&istream_, &p4info); - - return p4info; -} - sai_status_t sai_api_initialize( _In_ uint64_t flags, _In_ const sai_service_method_table_t *services) { DASH_LOG_ENTER(); - cfg = dash::Config::getConfig(services); - - DASH_LOG_NOTICE("config: %s", cfg->getConfigString().c_str()); - - for (uint32_t i = 1; i <= cfg->m_bmv2NumPorts; i++) - { - port_list.push_back(DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT,i)); - } - - assert(cfg->m_bmv2NumPorts == (uint32_t)port_list.size()); - - const grpc::string _grpcTarget = cfg->m_grpcTarget; - const char* test_json = cfg->m_pipelineJson.c_str(); - const char* test_proto_json = cfg->m_pipelineProto.c_str(); - int dev_id = cfg->m_deviceId; - - DASH_LOG_NOTICE("GRPC call SetForwardingPipelineConfig %s => %s, %s", _grpcTarget.c_str(), test_json, test_proto_json); - - auto p4info = parse_p4info(test_proto_json); - - auto set_election_id = [](p4::v1::Uint128 *election_id) { - election_id->set_high(0); - election_id->set_low(1); - }; - - grpc::ClientContext stream_context; - _grpcChannel = grpc::CreateChannel(_grpcTarget, grpc::InsecureChannelCredentials()); - stub = p4::v1::P4Runtime::NewStub(_grpcChannel); - auto stream = stub->StreamChannel(&stream_context); - { - p4::v1::StreamMessageRequest request; - auto arbitration = request.mutable_arbitration(); - arbitration->set_device_id(dev_id); - set_election_id(arbitration->mutable_election_id()); - stream->Write(request); - p4::v1::StreamMessageResponse response; - stream->Read(&response); - assert(response.update_case() == p4::v1::StreamMessageResponse::kArbitration); - assert(response.arbitration().status().code() == ::google::rpc::Code::OK); - } - { - p4::v1::SetForwardingPipelineConfigRequest request; - request.set_device_id(dev_id); - request.set_action( - p4::v1::SetForwardingPipelineConfigRequest_Action_VERIFY_AND_COMMIT); - set_election_id(request.mutable_election_id()); - auto config = request.mutable_config(); - config->set_allocated_p4info(&p4info); - std::ifstream istream(test_json); - config->mutable_p4_device_config()->assign( - (std::istreambuf_iterator(istream)), - std::istreambuf_iterator()); - - p4::v1::SetForwardingPipelineConfigResponse rep; - grpc::ClientContext context; - - auto status = stub->SetForwardingPipelineConfig( - &context, request, &rep); - assert(status.ok()); - config->release_p4info(); - } - - return SAI_STATUS_SUCCESS; + return dashSai->apiInitialize(flags, services); } sai_status_t sai_api_uninitialize(void) { DASH_LOG_ENTER(); - stub = nullptr; - - return SAI_STATUS_SUCCESS; + return dashSai->apiUninitialize(); } sai_status_t sai_log_set( @@ -396,6 +196,8 @@ sai_status_t sai_query_api_version( { *version = SAI_API_VERSION; + DASH_LOG_NOTICE("SAI headers version: %d", SAI_API_VERSION); + return SAI_STATUS_SUCCESS; } diff --git a/dash-pipeline/SAI/templates/saiimpl.h.j2 b/dash-pipeline/SAI/templates/saiimpl.h.j2 index 039e387cd..a0dad0c4e 100644 --- a/dash-pipeline/SAI/templates/saiimpl.h.j2 +++ b/dash-pipeline/SAI/templates/saiimpl.h.j2 @@ -1,5 +1,7 @@ #pragma once +#include "dashsai.h" + #define DASH_PRIVATE __attribute__((visibility("hidden"))) DASH_PRIVATE extern sai_switch_api_t dash_sai_switch_api_impl; @@ -8,3 +10,5 @@ DASH_PRIVATE extern sai_port_api_t dash_sai_port_api_impl; {% for api in api_names %} DASH_PRIVATE extern sai_{{ api }}_api_t dash_sai_{{ api }}_api_impl; {% endfor %} + +DASH_PRIVATE extern std::shared_ptr dashSai; diff --git a/dash-pipeline/SAI/templates/utils.cpp.j2 b/dash-pipeline/SAI/templates/utils.cpp.j2 index 4a80b64f0..73abacddf 100644 --- a/dash-pipeline/SAI/templates/utils.cpp.j2 +++ b/dash-pipeline/SAI/templates/utils.cpp.j2 @@ -1,14 +1,19 @@ #include "utils.h" -static int deviceId = 0; - -static std::unordered_multimap > tableEntryMap; -static std::mutex tableLock; -static std::atomic nextId; +const sai_attribute_t* dash::utils::getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); -#define MUTEX std::lock_guard _lock(tableLock); + for (uint32_t i = 0; i < attr_count; i++) + { + if (attr_list[i].id == id) + { + return &attr_list[i]; + } + } -std::unique_ptr stub; + return nullptr; +} void dash::utils::correctIpPrefix(void *ip, const void *mask, size_t length) { @@ -62,139 +67,3 @@ int dash::utils::leadingNonZeroBits(const sai_ip6_t& ipv6) return 0; } - -static int GetDeviceId() -{ - DASH_LOG_ENTER(); - - return deviceId; -} - -static std::string updateTypeStr(p4::v1::Update_Type updateType) -{ - DASH_LOG_ENTER(); - - const google::protobuf::EnumDescriptor *descriptor = p4::v1::Update_Type_descriptor(); - - return descriptor->FindValueByNumber(updateType)->name(); -} - -const sai_attribute_t* dash::utils::getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list) -{ - DASH_LOG_ENTER(); - - for (uint32_t i = 0; i < attr_count; i++) - { - if (attr_list[i].id == id) - { - return &attr_list[i]; - } - } - - return nullptr; -} - -grpc::StatusCode dash::utils::MutateTableEntry(std::shared_ptr entry, p4::v1::Update_Type updateType) -{ - DASH_LOG_ENTER(); - - p4::v1::WriteRequest request; - - request.set_device_id(GetDeviceId()); - - auto update = request.add_updates(); - - update->set_type(updateType); - - auto entity = update->mutable_entity(); - - entity->set_allocated_table_entry(entry.get()); - - p4::v1::WriteResponse rep; - - grpc::ClientContext context; - - grpc::Status status = stub->Write(&context, request, &rep); - - if (status.ok()) - { - DASH_LOG_NOTICE("GRPC call Write::%s OK %s", updateTypeStr(updateType).c_str(), entry->ShortDebugString().c_str()); - } - else - { - DASH_LOG_ERROR("GRPC ERROR[%d]: %s, %s", status.error_code(), status.error_message().c_str(), status.error_details().c_str()); - DASH_LOG_ERROR("GRPC call Write::%s ERROR: %s", updateTypeStr(updateType).c_str(), entry->ShortDebugString().c_str()); - } - - //MILIND?? What is this? reference release? memory release? - entity->release_table_entry(); - - return status.error_code(); -} - -bool dash::utils::InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId) -{ - DASH_LOG_ENTER(); - - auto retCode = MutateTableEntry(entry, p4::v1::Update_Type_INSERT); - - if (grpc::StatusCode::OK != retCode) - { - return false; - } - - MUTEX; - - if (*objId == 0) - { - *objId = NextObjectId(objectType); - } - - tableEntryMap.insert(std::make_pair(*objId, entry)); - - return true; -} - -// TODO to be removed and merged -#define DASH_OBJECT_SHFT 48 -#define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype<second; - auto tempRet = MutateTableEntry(entry, p4::v1::Update_Type_DELETE); - - if (grpc::StatusCode::OK != tempRet) - { - retCode = tempRet; - } - } - - tableEntryMap.erase(id); - - return retCode == grpc::StatusCode::OK; -} diff --git a/dash-pipeline/SAI/templates/utils.h.j2 b/dash-pipeline/SAI/templates/utils.h.j2 index 73a4722f6..b91e3da2b 100644 --- a/dash-pipeline/SAI/templates/utils.h.j2 +++ b/dash-pipeline/SAI/templates/utils.h.j2 @@ -400,14 +400,6 @@ namespace dash u64SetMask(value.u64, t, bits); } - const sai_attribute_t* getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t *attr_list); - - grpc::StatusCode MutateTableEntry(std::shared_ptr, p4::v1::Update_Type updateType); - - sai_object_id_t NextObjectId(sai_object_type_t objectType); - - bool InsertInTable(std::shared_ptr entry, sai_object_type_t objectType, sai_object_id_t *objId); - - bool RemoveFromTable(sai_object_id_t id); + const sai_attribute_t* getMaskAttr(sai_attr_id_t id, uint32_t attr_count, const sai_attribute_t* attr_list); } } From 2e553afbbd97e3ec9309002bebf1aee796c2c9c8 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Tue, 8 Aug 2023 20:10:56 +0200 Subject: [PATCH 04/11] [SAI] Remove unused methods --- dash-pipeline/SAI/templates/dashsai.h.j2 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/templates/dashsai.h.j2 index e92b37133..048906efb 100644 --- a/dash-pipeline/SAI/templates/dashsai.h.j2 +++ b/dash-pipeline/SAI/templates/dashsai.h.j2 @@ -45,11 +45,6 @@ namespace dash public: // helper methods - const sai_attribute_t* getMaskAttr( - _In_ sai_attr_id_t id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); - grpc::StatusCode mutateTableEntry( _In_ std::shared_ptr, _In_ p4::v1::Update_Type updateType); From 88b1ae698c175f374de714ae682345eaca3ba2ad Mon Sep 17 00:00:00 2001 From: kcudnik Date: Wed, 9 Aug 2023 12:06:05 +0200 Subject: [PATCH 05/11] [SAI] Add workaround to return not supported status on get api This will be required for syncd in sonic-sairedis --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 39 +++++++++++++++++++--- dash-pipeline/SAI/templates/dashsai.h.j2 | 6 ++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index 746e4f944..6149475a3 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -1,5 +1,7 @@ #include "dashsai.h" +#include + using namespace dash; #define DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES 0 @@ -12,6 +14,21 @@ using namespace dash; DASH_LOG_ERROR("%s: api not initialized", __PRETTY_FUNCTION__); \ return SAI_STATUS_FAILURE; } +/** + * @def DASH_USE_NOT_SUPPORTED + * + * Name of environment variable, when set to any value, will return proper + * SAI_STATUS_NOT_SUPPORTED on switch/port GET api. + * + * Currently because of limitation of saithrift, GET on switch/port is + * returning SAI_STATUS_SUCCESS on not implemented attribute. + * + * TODO FIXME needs to be addressed in saithrift. + * + * This is temporary workaround for syncd, it should be removed when fixed in saithrift. + */ +#define DASH_USE_NOT_SUPPORTED "DASH_USE_NOT_SUPPORTED" + #define MUTEX std::lock_guard _lock(m_tableLock); DashSai::DashSai(): @@ -51,6 +68,8 @@ sai_status_t DashSai::apiInitialize( return SAI_STATUS_FAILURE; } + m_serviceMethodTable = services; + m_cfg = dash::Config::getConfig(services); DASH_LOG_NOTICE("config: %s", m_cfg->getConfigString().c_str()); @@ -143,6 +162,8 @@ sai_status_t DashSai::apiUninitialize(void) m_apiInitialized = false; + m_serviceMethodTable = nullptr; + return SAI_STATUS_SUCCESS; } @@ -199,8 +220,6 @@ sai_status_t DashSai::getSwitchAttribute( DASH_LOG_ENTER(); DASH_CHECK_API_INITIALIZED(); - DASH_LOG_NOTICE("dash_get_switch_attribute()"); - sai_attribute_t *attr = attr_list; for (uint32_t i = 0; i < attr_count ; i++, attr++) @@ -262,6 +281,13 @@ sai_status_t DashSai::getSwitchAttribute( default: + if (getenv(DASH_USE_NOT_SUPPORTED)) + { + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED", i, attr->id); + + return SAI_STATUS_NOT_SUPPORTED; + } + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage @@ -281,8 +307,6 @@ sai_status_t DashSai::getPortAttribute( DASH_LOG_ENTER(); DASH_CHECK_API_INITIALIZED(); - DASH_LOG_NOTICE("getPortAttribute()"); - sai_attribute_t *attr = attr_list; for (uint32_t i = 0; i < attr_count ; i++, attr++) @@ -299,6 +323,13 @@ sai_status_t DashSai::getPortAttribute( default: + if (getenv(DASH_USE_NOT_SUPPORTED)) + { + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED", i, attr->id); + + return SAI_STATUS_NOT_SUPPORTED; + } + DASH_LOG_WARN("[%d] attr %d is NOT SUPPORTED, but returning SAI_STATUS_SUCCESS", i, attr->id); memset(&attr->value, 0, sizeof(attr->value)); // clear potential caller garbage diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/templates/dashsai.h.j2 index 048906efb..1e9d8f852 100644 --- a/dash-pipeline/SAI/templates/dashsai.h.j2 +++ b/dash-pipeline/SAI/templates/dashsai.h.j2 @@ -62,10 +62,10 @@ namespace dash private: // private helper methods - p4::config::v1::P4Info parse_p4info( + static p4::config::v1::P4Info parse_p4info( _In_ const char *path); - std::string updateTypeStr( + static std::string updateTypeStr( _In_ p4::v1::Update_Type updateType); private: // internal sai objects @@ -84,6 +84,8 @@ namespace dash bool m_apiInitialized; + const sai_service_method_table_t* m_serviceMethodTable; + std::shared_ptr m_cfg; std::vector m_portList; From 81c1347205f6ee32855346a641385e5a66265af0 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Wed, 9 Aug 2023 14:20:22 +0200 Subject: [PATCH 06/11] [SAI] Remove underscore from variable naming --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index 6149475a3..1c6f7e2bc 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -7,7 +7,7 @@ using namespace dash; #define DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES 0 #define DASH_OBJECT_SHFT 48 -#define DASH_MAKE_OID(_objtype, _objval) (sai_object_id_t)(((sai_object_id_t)_objtype<getConfigString().c_str()); + m_portList.clear(); + for (uint32_t i = 1; i <= m_cfg->m_bmv2NumPorts; i++) { m_portList.push_back(DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT,i)); @@ -81,11 +83,11 @@ sai_status_t DashSai::apiInitialize( assert(m_cfg->m_bmv2NumPorts == (uint32_t)m_portList.size()); - const grpc::string _grpcTarget = m_cfg->m_grpcTarget; + const grpc::string grpcTarget = m_cfg->m_grpcTarget; const char* test_json = m_cfg->m_pipelineJson.c_str(); const char* test_proto_json = m_cfg->m_pipelineProto.c_str(); - DASH_LOG_NOTICE("GRPC call SetForwardingPipelineConfig %s => %s, %s", _grpcTarget.c_str(), test_json, test_proto_json); + DASH_LOG_NOTICE("GRPC call SetForwardingPipelineConfig %s => %s, %s", grpcTarget.c_str(), test_json, test_proto_json); auto p4info = parse_p4info(test_proto_json); @@ -97,7 +99,7 @@ sai_status_t DashSai::apiInitialize( grpc::ClientContext stream_context; - m_grpcChannel = grpc::CreateChannel(_grpcTarget, grpc::InsecureChannelCredentials()); + m_grpcChannel = grpc::CreateChannel(grpcTarget, grpc::InsecureChannelCredentials()); m_stub = p4::v1::P4Runtime::NewStub(m_grpcChannel); @@ -351,8 +353,8 @@ p4::config::v1::P4Info DashSai::parse_p4info( p4::config::v1::P4Info p4info; std::ifstream istream(path); assert(istream.good()); - google::protobuf::io::IstreamInputStream istream_(&istream); - google::protobuf::TextFormat::Parse(&istream_, &p4info); + google::protobuf::io::IstreamInputStream is(&istream); + google::protobuf::TextFormat::Parse(&is, &p4info); return p4info; } From 656afdcbf14a3d2e9047a0f6a641f327a26bb8ff Mon Sep 17 00:00:00 2001 From: kcudnik Date: Wed, 9 Aug 2023 14:59:30 +0200 Subject: [PATCH 07/11] [SAI] Fix route bulk api set/get warnings --- dash-pipeline/SAI/templates/saiapi.cpp.j2 | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 5c6496805..1ac3fcbe8 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -514,6 +514,35 @@ static sai_status_t dash_sai_get_{{ table.name }}_attribute( assert(0 && "sai_get_{{ table.name }}_attribute NYI"); return SAI_STATUS_FAILURE; } + +{% if table.name == 'route_entry' %} + +static sai_status_t dash_sai_set_{{ table.name | replace("entry", "entries") }}_attribute( + _In_ uint32_t object_count, + _In_ const sai_route_entry_t *route_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_set_{{ table.name | replace("entry", "entries") }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} + +static sai_status_t dash_sai_get_{{ table.name | replace("entry", "entries") }}_attribute( + _In_ uint32_t object_count, + _In_ const sai_route_entry_t *route_entry, + _In_ const uint32_t *attr_count, + _Inout_ sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_get_{{ table.name | replace("entry", "entries") }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} + +{% endif %} {% endif %} {% endfor %} @@ -534,5 +563,9 @@ sai_{{ app_name }}_api_t dash_sai_{{ app_name }}_api_impl = { .create_{{ table.name | replace("entry", "entries") }} = dash_sai_create_{{ table.name | replace("entry", "entries") }}, .remove_{{ table.name | replace("entry", "entries") }} = dash_sai_remove_{{ table.name | replace("entry", "entries") }}, {% endif %} +{% if table.name == 'route_entry' %} + .set_{{ table.name | replace("entry", "entries") }}_attribute = dash_sai_set_{{ table.name | replace("entry", "entries") }}_attribute, + .get_{{ table.name | replace("entry", "entries") }}_attribute = dash_sai_get_{{ table.name | replace("entry", "entries") }}_attribute, +{% endif %} {% endfor %} }; From 5372b9649c8dfc0d9e3d41bb761cfe465b593d45 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Wed, 9 Aug 2023 15:13:30 +0200 Subject: [PATCH 08/11] [SAI] Simplify insertInTable method --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 26 +++++++++++++--------- dash-pipeline/SAI/templates/dashsai.h.j2 | 3 +-- dash-pipeline/SAI/templates/saiapi.cpp.j2 | 5 ++--- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index 1c6f7e2bc..004f09f3b 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -31,6 +31,10 @@ using namespace dash; #define MUTEX std::lock_guard _lock(m_tableLock); +// TODO replace assert with if and return error +// TODO replace DASH_MAKE_OID with ObjectIdManager +// TODO fix saiapi.cpp use insert/remove mutate getNextObjectId + DashSai::DashSai(): m_apiInitialized(false) { @@ -179,7 +183,6 @@ sai_object_type_t DashSai::objectTypeQuery( DASH_LOG_ERROR("api not initialized"); return SAI_OBJECT_TYPE_NULL; - } return sai_object_type_t(object_id >> (DASH_OBJECT_SHFT)); @@ -238,9 +241,9 @@ sai_status_t DashSai::getSwitchAttribute( case SAI_SWITCH_ATTR_PORT_LIST: - attr->value.objlist.count = m_cfg->m_bmv2NumPorts; + attr->value.objlist.count = std::min(m_cfg->m_bmv2NumPorts, attr->value.objlist.count); - for (size_t j = 0; j < m_cfg->m_bmv2NumPorts; j++) + for (size_t j = 0; j < attr->value.objlist.count; j++) { attr->value.objlist.list[j] = m_portList.at(j); } @@ -420,8 +423,7 @@ grpc::StatusCode DashSai::mutateTableEntry( bool DashSai::insertInTable( _In_ std::shared_ptr entry, - _In_ sai_object_type_t objectType, - _Out_ sai_object_id_t *objId) + _In_ sai_object_id_t objId) { DASH_LOG_ENTER(); @@ -432,6 +434,13 @@ bool DashSai::insertInTable( return false; } + if (objId == SAI_NULL_OBJECT_ID) + { + DASH_LOG_ERROR("objId is NULL"); + + return false; + } + auto retCode = mutateTableEntry(entry, p4::v1::Update_Type_INSERT); if (grpc::StatusCode::OK != retCode) @@ -441,12 +450,7 @@ bool DashSai::insertInTable( MUTEX; - if (*objId == 0) - { - *objId = getNextObjectId(objectType); - } - - m_tableEntryMap.insert(std::make_pair(*objId, entry)); + m_tableEntryMap.insert(std::make_pair(objId, entry)); return true; } diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/templates/dashsai.h.j2 index 1e9d8f852..a7e744227 100644 --- a/dash-pipeline/SAI/templates/dashsai.h.j2 +++ b/dash-pipeline/SAI/templates/dashsai.h.j2 @@ -54,8 +54,7 @@ namespace dash bool insertInTable( _In_ std::shared_ptr entry, - _In_ sai_object_type_t objectType, - _Out_ sai_object_id_t *objId); + _In_ sai_object_id_t objId); bool removeFromTable( _In_ sai_object_id_t id); diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 1ac3fcbe8..7db54710d 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -40,7 +40,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( action = entry->mutable_action(); //expectedParams = 0; //matchedParams = 0; - objId = 0; + objId = dashSai->getNextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}); matchActionEntry->set_table_id(tableId); @@ -49,7 +49,6 @@ static sai_status_t dash_sai_create_{{ table.name }}( // Generate a SAI object ID and fill it as the P4 table key auto mf = matchActionEntry->add_match(); mf->set_field_id({{table['keys'][0].id}}); - objId = dashSai->getNextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}); auto mf_exact = mf->mutable_exact(); {{table['keys'][0].field}}SetVal(objId, mf_exact, {{table['keys'][0].bitwidth}}); {% else %} @@ -173,7 +172,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( //if (matchedParams != expectedParams) { // goto ErrRet; //} - if (false == dashSai->insertInTable(matchActionEntry, (sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}, &objId)) { + if (false == dashSai->insertInTable(matchActionEntry, objId)) { goto ErrRet; } From 4f5cef592e4afbd24eac4b21c1451c643153a642 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 10 Aug 2023 11:29:33 +0200 Subject: [PATCH 09/11] [SAI] Change asserts to return error codes and add missing switch api --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 161 ++++++++++++++++-- dash-pipeline/SAI/templates/dashsai.h.j2 | 15 +- .../SAI/templates/saifixedapis.cpp.j2 | 21 ++- 3 files changed, 181 insertions(+), 16 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index 004f09f3b..f08f48764 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -31,9 +31,7 @@ using namespace dash; #define MUTEX std::lock_guard _lock(m_tableLock); -// TODO replace assert with if and return error // TODO replace DASH_MAKE_OID with ObjectIdManager -// TODO fix saiapi.cpp use insert/remove mutate getNextObjectId DashSai::DashSai(): m_apiInitialized(false) @@ -47,6 +45,7 @@ DashSai::DashSai(): m_defaultVlanId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VLAN, 1); m_defaultVrfId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, 1); m_default1QBridgeId = DASH_MAKE_OID(SAI_OBJECT_TYPE_BRIDGE, 1); + m_defaultTrapGroup = DASH_MAKE_OID(SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP, 1); } DashSai::~DashSai() @@ -72,6 +71,8 @@ sai_status_t DashSai::apiInitialize( return SAI_STATUS_FAILURE; } + DASH_LOG_NOTICE("env %s set to: %s", DASH_USE_NOT_SUPPORTED, getenv(DASH_USE_NOT_SUPPORTED)); + m_serviceMethodTable = services; m_cfg = dash::Config::getConfig(services); @@ -85,7 +86,14 @@ sai_status_t DashSai::apiInitialize( m_portList.push_back(DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT,i)); } - assert(m_cfg->m_bmv2NumPorts == (uint32_t)m_portList.size()); + if (m_cfg->m_bmv2NumPorts != (uint32_t)m_portList.size()) + { + DASH_LOG_ERROR("FATAL: number of ports is different: config: %u vs port list: %u", + m_cfg->m_bmv2NumPorts, + (uint32_t)m_portList.size()); + + return SAI_STATUS_FAILURE; + } const grpc::string grpcTarget = m_cfg->m_grpcTarget; const char* test_json = m_cfg->m_pipelineJson.c_str(); @@ -95,6 +103,13 @@ sai_status_t DashSai::apiInitialize( auto p4info = parse_p4info(test_proto_json); + if (p4info == nullptr) + { + DASH_LOG_ERROR("failed to parse p4info: %s", test_proto_json); + + return SAI_STATUS_FAILURE; + } + auto set_election_id = [](p4::v1::Uint128 *election_id) { election_id->set_high(0); @@ -117,8 +132,24 @@ sai_status_t DashSai::apiInitialize( stream->Write(request); p4::v1::StreamMessageResponse response; stream->Read(&response); - assert(response.update_case() == p4::v1::StreamMessageResponse::kArbitration); - assert(response.arbitration().status().code() == ::google::rpc::Code::OK); + + if (response.update_case() != p4::v1::StreamMessageResponse::kArbitration) + { + DASH_LOG_ERROR("FATAL: response: %d, expected %d (p4::v1::StreamMessageResponse::kArbitration)", + response.update_case(), + p4::v1::StreamMessageResponse::kArbitration); + + return SAI_STATUS_FAILURE; + } + + if (response.arbitration().status().code() != ::google::rpc::Code::OK) + { + DASH_LOG_ERROR("FATAL: arbitration status: %d, expected: %d (::google::rpc::Code::OK)", + response.arbitration().status().code(), + ::google::rpc::Code::OK); + + return SAI_STATUS_FAILURE; + } } { @@ -128,8 +159,17 @@ sai_status_t DashSai::apiInitialize( p4::v1::SetForwardingPipelineConfigRequest_Action_VERIFY_AND_COMMIT); set_election_id(request.mutable_election_id()); auto config = request.mutable_config(); - config->set_allocated_p4info(&p4info); + config->set_allocated_p4info(p4info.get()); + std::ifstream istream(test_json); + + if (!istream.good()) + { + DASH_LOG_ERROR("failed to open: %s", test_json); + + return SAI_STATUS_FAILURE; + } + config->mutable_p4_device_config()->assign( (std::istreambuf_iterator(istream)), std::istreambuf_iterator()); @@ -139,7 +179,12 @@ sai_status_t DashSai::apiInitialize( auto status = m_stub->SetForwardingPipelineConfig(&context, request, &rep); - assert(status.ok()); + if (!status.ok()) + { + DASH_LOG_ERROR("FATAL: SetForwardingPipelineConfig failed, error code: %d", status.error_code()); + + return SAI_STATUS_FAILURE; + } config->release_p4info(); } @@ -210,6 +255,11 @@ sai_status_t DashSai::createSwitch( DASH_LOG_ENTER(); DASH_CHECK_API_INITIALIZED(); + for (uint32_t i = 0; i < attr_count; i++) + { + DASH_LOG_WARN("attr id %d is NOT IMPLEMENTED, ignored", attr_list[i].id); + } + *switch_id = m_switchId; DASH_LOG_NOTICE("created switch id: %ld", *switch_id); @@ -217,6 +267,53 @@ sai_status_t DashSai::createSwitch( return SAI_STATUS_SUCCESS; } +sai_status_t DashSai::removeSwitch( + _In_ sai_object_id_t switch_id) +{ + DASH_LOG_ENTER(); + + if (switch_id != m_switchId) + { + DASH_LOG_ERROR("invalid switch_id: %lu, switch_id", switch_id); + + return SAI_STATUS_INVALID_PARAMETER; + } + + // dummy switch remove + + DASH_LOG_NOTICE("removing switch: %ld", switch_id); + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::setSwitchAttribute( + _In_ sai_object_id_t switch_id, + _In_ const sai_attribute_t *attr) +{ + DASH_LOG_ENTER(); + + switch (attr->id) + { + case SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY: + case SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY: + case SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY: + case SAI_SWITCH_ATTR_NAT_EVENT_NOTIFY: + case SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY: + case SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY: + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + + DASH_LOG_NOTICE("setting dummy notification callback (attr id: %d)", attr->id); + + return SAI_STATUS_SUCCESS; + + default: + + DASH_LOG_ERROR("set attr %d NOT IMPLEMENTED", attr->id); + + return SAI_STATUS_NOT_IMPLEMENTED; + } +} + sai_status_t DashSai::getSwitchAttribute( _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, @@ -284,6 +381,27 @@ sai_status_t DashSai::getSwitchAttribute( break; + case SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP: + + attr->value.oid = m_defaultTrapGroup; + + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP = %lx", i, attr->value.oid); + + break; + + case SAI_SWITCH_ATTR_SRC_MAC_ADDRESS: + + // dummy mac address + + attr->value.mac[0] = 0x00; + attr->value.mac[1] = 0x12; + attr->value.mac[2] = 0x34; + attr->value.mac[3] = 0x56; + attr->value.mac[4] = 0x78; + attr->value.mac[5] = 0x9A; + + break; + default: if (getenv(DASH_USE_NOT_SUPPORTED)) @@ -326,6 +444,15 @@ sai_status_t DashSai::getPortAttribute( break; + case SAI_PORT_ATTR_HW_LANE_LIST: + + // dummy hw lane list (required by syncd) + + attr->value.u32list.count = 1; + attr->value.u32list.list[0] = (uint32_t)(port_id & 0xffff); // get index from port ID to make lanes unique + + break; + default: if (getenv(DASH_USE_NOT_SUPPORTED)) @@ -348,18 +475,26 @@ sai_status_t DashSai::getPortAttribute( // private helper methods -p4::config::v1::P4Info DashSai::parse_p4info( +std::shared_ptr DashSai::parse_p4info( _In_ const char *path) { DASH_LOG_ENTER(); - p4::config::v1::P4Info p4info; + std::shared_ptr p4info = std::make_shared(); + std::ifstream istream(path); - assert(istream.good()); - google::protobuf::io::IstreamInputStream is(&istream); - google::protobuf::TextFormat::Parse(&is, &p4info); - return p4info; + if (istream.good()) + { + google::protobuf::io::IstreamInputStream is(&istream); + google::protobuf::TextFormat::Parse(&is, p4info.get()); + + return p4info; + } + + DASH_LOG_ERROR("failed to open: %s", path); + + return nullptr; } std::string DashSai::updateTypeStr( diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/templates/dashsai.h.j2 index a7e744227..2783461e3 100644 --- a/dash-pipeline/SAI/templates/dashsai.h.j2 +++ b/dash-pipeline/SAI/templates/dashsai.h.j2 @@ -28,16 +28,27 @@ namespace dash public: // QUAD api implementation + // switch + sai_status_t createSwitch( _Out_ sai_object_id_t *switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); + sai_status_t removeSwitch( + _In_ sai_object_id_t switch_id); + + sai_status_t setSwitchAttribute( + _In_ sai_object_id_t switch_id, + _In_ const sai_attribute_t *attr); + sai_status_t getSwitchAttribute( _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); + // port + sai_status_t getPortAttribute( _In_ sai_object_id_t port_id, _In_ uint32_t attr_count, @@ -61,7 +72,7 @@ namespace dash private: // private helper methods - static p4::config::v1::P4Info parse_p4info( + static std::shared_ptr parse_p4info( _In_ const char *path); static std::string updateTypeStr( @@ -79,6 +90,8 @@ namespace dash sai_object_id_t m_default1QBridgeId; + sai_object_id_t m_defaultTrapGroup; + private: bool m_apiInitialized; diff --git a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 index 52cee8867..6dd5d6511 100644 --- a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 +++ b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 @@ -30,10 +30,27 @@ static sai_status_t dash_sai_get_switch_attribute( return dashSai->getSwitchAttribute(switch_id, attr_count, attr_list); } +static sai_status_t dash_sai_remove_switch( + _In_ sai_object_id_t switch_id) +{ + DASH_LOG_ENTER(); + + return dashSai->removeSwitch(switch_id); +} + +static sai_status_t dash_sai_set_switch_attribute( + _In_ sai_object_id_t switch_id, + _In_ const sai_attribute_t *attr) +{ + DASH_LOG_ENTER(); + + return dashSai->setSwitchAttribute(switch_id, attr); +} + sai_switch_api_t dash_sai_switch_api_impl = { .create_switch = dash_sai_create_switch, - .remove_switch = 0, - .set_switch_attribute = 0, + .remove_switch = dash_sai_remove_switch, + .set_switch_attribute = dash_sai_set_switch_attribute, .get_switch_attribute = dash_sai_get_switch_attribute, .get_switch_stats = 0, .get_switch_stats_ext = 0, From 0cdd9aaefcbc92f9aaff565176b62a4c962673da Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 10 Aug 2023 12:56:41 +0200 Subject: [PATCH 10/11] [SAI] Print oids in hex form --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index f08f48764..b9be97d4c 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -262,7 +262,7 @@ sai_status_t DashSai::createSwitch( *switch_id = m_switchId; - DASH_LOG_NOTICE("created switch id: %ld", *switch_id); + DASH_LOG_NOTICE("created switch id: 0x%lx", *switch_id); return SAI_STATUS_SUCCESS; } @@ -274,14 +274,14 @@ sai_status_t DashSai::removeSwitch( if (switch_id != m_switchId) { - DASH_LOG_ERROR("invalid switch_id: %lu, switch_id", switch_id); + DASH_LOG_ERROR("invalid switch_id: 0x%lx, switch_id", switch_id); return SAI_STATUS_INVALID_PARAMETER; } // dummy switch remove - DASH_LOG_NOTICE("removing switch: %ld", switch_id); + DASH_LOG_NOTICE("removing switch: 0x%lx", switch_id); return SAI_STATUS_SUCCESS; } @@ -353,7 +353,7 @@ sai_status_t DashSai::getSwitchAttribute( attr->value.oid = m_defaultVlanId; - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VLAN_ID = %lx", i, attr->value.oid); + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VLAN_ID = 0x%lx", i, attr->value.oid); break; @@ -361,7 +361,7 @@ sai_status_t DashSai::getSwitchAttribute( attr->value.oid = m_defaultVrfId; - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID = %lx", i, attr->value.oid); + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID = 0x%lx", i, attr->value.oid); break; @@ -369,7 +369,7 @@ sai_status_t DashSai::getSwitchAttribute( attr->value.oid = m_default1QBridgeId; - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID = %lx", i, attr->value.oid); + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID = 0x%lx", i, attr->value.oid); break; @@ -377,7 +377,7 @@ sai_status_t DashSai::getSwitchAttribute( attr->value.oid = m_defaultCpuPortId; - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_CPU_PORT = %lx", i, attr->value.oid); + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_CPU_PORT = 0x%lx", i, attr->value.oid); break; @@ -385,7 +385,7 @@ sai_status_t DashSai::getSwitchAttribute( attr->value.oid = m_defaultTrapGroup; - DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP = %lx", i, attr->value.oid); + DASH_LOG_NOTICE("[%d] SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP = 0x%lx", i, attr->value.oid); break; @@ -623,7 +623,7 @@ bool DashSai::removeFromTable( if (range.first == range.second) { - DASH_LOG_ERROR("id: %ld not present in the table for deletion!", id); + DASH_LOG_ERROR("id: 0x%lx not present in the table for deletion!", id); return false; } From 4d0abc2f9542b509adbf56fc5298e4761c270eae Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 10 Aug 2023 13:26:40 +0200 Subject: [PATCH 11/11] [SAI] Add missing check for api initialized --- dash-pipeline/SAI/templates/dashsai.cpp.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/templates/dashsai.cpp.j2 index b9be97d4c..8f8defaf1 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/templates/dashsai.cpp.j2 @@ -271,6 +271,7 @@ sai_status_t DashSai::removeSwitch( _In_ sai_object_id_t switch_id) { DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); if (switch_id != m_switchId) { @@ -291,6 +292,7 @@ sai_status_t DashSai::setSwitchAttribute( _In_ const sai_attribute_t *attr) { DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); switch (attr->id) {