From 6d5bcfe4acbf6387ff8717ace027ef5af8ce89b0 Mon Sep 17 00:00:00 2001 From: Satish Pitchikala Date: Tue, 12 Sep 2023 08:42:50 +0530 Subject: [PATCH] Tdi operations and notifications (#126) * tdi::operations * notifications: compiling * tdi operations, notifications without parsing * notifications parsing * code clean up * c frontend changes for operations and notifications * c frontend for notifications * notification, operations minor fixes * cleaning up dead code * minor fix to take uint64 values * minor fixs * addressing review comments * cleaning up logging --- .../tdi/common/c_frontend/tdi_notifications.h | 63 ++++++ .../tdi/common/c_frontend/tdi_operations.h | 4 +- include/tdi/common/c_frontend/tdi_table.h | 28 ++- .../tdi/common/c_frontend/tdi_table_info.h | 8 + include/tdi/common/tdi_defs.h | 9 + .../tdi_json_parser/tdi_info_parser.hpp | 11 + .../common/tdi_json_parser/tdi_table_info.hpp | 209 ++++++++++++++++++ include/tdi/common/tdi_notifications.hpp | 93 ++++---- include/tdi/common/tdi_operations.hpp | 27 ++- include/tdi/common/tdi_table.hpp | 36 ++- src/CMakeLists.txt | 3 +- src/c_frontend/tdi_table_c.cpp | 66 +++++- src/c_frontend/tdi_table_info_c.cpp | 33 +++ src/c_frontend/tdi_table_notifications_c.cpp | 74 +++++++ src/c_frontend/tdi_table_operations_c.cpp | 41 ++++ src/tdi_json_parser/tdi_info_parser.cpp | 122 ++++++++++ src/tdi_json_parser/tdi_table_info.cpp | 43 ++++ src/tdi_table.cpp | 48 +++- tdi_python/tdiTable.py | 21 +- 19 files changed, 856 insertions(+), 83 deletions(-) create mode 100644 include/tdi/common/c_frontend/tdi_notifications.h create mode 100644 src/c_frontend/tdi_table_notifications_c.cpp create mode 100644 src/c_frontend/tdi_table_operations_c.cpp diff --git a/include/tdi/common/c_frontend/tdi_notifications.h b/include/tdi/common/c_frontend/tdi_notifications.h new file mode 100644 index 0000000..4244a26 --- /dev/null +++ b/include/tdi/common/c_frontend/tdi_notifications.h @@ -0,0 +1,63 @@ +/* + * Copyright(c) 2023 Intel Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this software except as stipulated in the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** @file tdi_notifications.h + * + * @brief Contains TDI Table notifications APIs + */ +#ifndef _TDI_NOTIFICATIONS_H +#define _TDI_NOTIFICATIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*tdi_notification_callback)( + const tdi_table_key_hdl *key, + const tdi_table_data_hdl *data, + const tdi_notification_param_hdl *params, + void *cookie); + +tdi_status_t tdi_notifications_set_value( + tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + const uint64_t value); + +tdi_status_t tdi_notifications_set_value_array( + tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + const uint64_t *value, + const uint32_t array_sz); + +tdi_status_t tdi_notifications_get_value( + const tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + uint64_t *value); + +tdi_status_t tdi_notifications_get_value_array_size( + const tdi_notification_param_hdl *notification_hdl, + const tdi_id_t field_id, + uint32_t *array_size); + +tdi_status_t tdi_notifications_get_value_array( + const tdi_notification_param_hdl *notification_hdl, + const tdi_id_t field_id, + uint64_t *val); + +#ifdef __cplusplus +} +#endif + +#endif // _TDI_NOTIFICATIONS_H diff --git a/include/tdi/common/c_frontend/tdi_operations.h b/include/tdi/common/c_frontend/tdi_operations.h index 6a4a9e6..d82f717 100644 --- a/include/tdi/common/c_frontend/tdi_operations.h +++ b/include/tdi/common/c_frontend/tdi_operations.h @@ -24,11 +24,11 @@ extern "C" { #endif -tdi_status_t tdi_operations_set_value(tdi_operations_hdl operations, +tdi_status_t tdi_operations_set_value(tdi_operations_hdl *operations, tdi_operations_field_type_e type, const uint64_t value); -tdi_status_t tdi_operations_get_value(tdi_operations_hdl operations, +tdi_status_t tdi_operations_get_value(const tdi_operations_hdl *operations, tdi_operations_field_type_e type, uint64_t *value); diff --git a/include/tdi/common/c_frontend/tdi_table.h b/include/tdi/common/c_frontend/tdi_table.h index 872f2ed..6fdcc2a 100644 --- a/include/tdi/common/c_frontend/tdi_table.h +++ b/include/tdi/common/c_frontend/tdi_table.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -781,8 +782,31 @@ tdi_status_t tdi_operations_deallocate(tdi_operations_hdl *tbl_op_hdl); * * @return Status of the API call */ -tdi_status_t tdi_table_operations_execute(const tdi_table_hdl *table_hdl, - const tdi_operations_hdl *tbl_ops); +tdi_status_t tdi_operations_execute(const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, + const tdi_operations_hdl *tbl_ops); + +tdi_status_t tdi_notifications_registration_params_allocate( + const tdi_table_hdl *table_hdl, + const tdi_id_t notification_id, + tdi_notification_param_hdl **tbl_notification_hdl); + +tdi_status_t tdi_notifications_registration_params_deallocate( + tdi_notification_param_hdl *tbl_notification_hdl); + +tdi_status_t tdi_notifications_register( + const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, + const tdi_id_t notification_id, + const tdi_notification_callback callback_fn, + const tdi_notification_param_hdl *tbl_notification_hdl, + void *cookie); + +tdi_status_t tdi_notifications_deregister( + const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, + const tdi_id_t notification_id, + const tdi_notification_param_hdl *tbl_notification_hdl); #ifdef __cplusplus } diff --git a/include/tdi/common/c_frontend/tdi_table_info.h b/include/tdi/common/c_frontend/tdi_table_info.h index d6f789c..bef4ed4 100644 --- a/include/tdi/common/c_frontend/tdi_table_info.h +++ b/include/tdi/common/c_frontend/tdi_table_info.h @@ -899,6 +899,14 @@ tdi_status_t tdi_table_operations_supported( tdi_operations_type_e *operations, uint32_t *num_returned); +tdi_status_t tdi_table_num_notifications_supported( + const tdi_table_info_hdl *table_info_hdl, uint32_t *num); + +tdi_status_t tdi_table_notifications_supported( + const tdi_table_info_hdl *table_info_hdl, + const char *notifications[], + uint32_t *num_returned); + /** * @brief Get size of list of tables that the given table is dependent on * diff --git a/include/tdi/common/tdi_defs.h b/include/tdi/common/tdi_defs.h index 01e5c89..5b7bf74 100644 --- a/include/tdi/common/tdi_defs.h +++ b/include/tdi/common/tdi_defs.h @@ -247,6 +247,14 @@ enum tdi_operations_field_type_e { }; typedef enum tdi_operations_field_type_e tdi_operations_field_type_e; +enum tdi_notifications_type_e { + TDI_NOTIFICATIONS_TYPE_CORE = 0, + TDI_NOTIFICATIONS_TYPE_ARCH = 0x08, + TDI_NOTIFICATIONS_TYPE_DEVICE = 0x80, +}; +typedef enum tdi_notifications_type_e tdi_notifications_type_e; + + /** Identifies an error code. */ typedef int tdi_status_t; @@ -328,6 +336,7 @@ DECLARE_HANDLE(tdi_learn_info_hdl); DECLARE_HANDLE(tdi_learn_field_info_hdl); DECLARE_HANDLE(tdi_operations_hdl); DECLARE_HANDLE(tdi_dev_config_hdl); +DECLARE_HANDLE(tdi_notification_param_hdl); /** * @brief learn_data_hdl and table_data_hdl are the same, diff --git a/include/tdi/common/tdi_json_parser/tdi_info_parser.hpp b/include/tdi/common/tdi_json_parser/tdi_info_parser.hpp index 2b903e8..8c569b3 100644 --- a/include/tdi/common/tdi_json_parser/tdi_info_parser.hpp +++ b/include/tdi/common/tdi_json_parser/tdi_info_parser.hpp @@ -76,6 +76,15 @@ const std::string LEARN_ID = "id"; const std::string LEARN_ANNOTATIONS = "annotations"; const std::string LEARN_FIELDS = "fields"; +const std::string TABLE_NOTIFICATIONS = "notifications"; +const std::string TABLE_NOTIFICATIONS_ID = "id"; +const std::string TABLE_NOTIFICATIONS_NAME = "name"; +const std::string TABLE_NOTIFICATIONS_REPEATED = "repeated"; +const std::string TABLE_NOTIFICATIONS_MANDATORY = "mandatory"; +const std::string TABLE_NOTIFICATIONS_ANNOTATIONS = "annotations"; +const std::string TABLE_NOTIFICATIONS_REGISTRATION_PARAMS = "registration_params"; +const std::string TABLE_NOTIFICATIONS_CALLBACK_PARAMS = "callback_params"; + } // namespace tdi_json // Forward declarations @@ -104,6 +113,8 @@ class TdiInfoParser { std::unique_ptr parseDataField(const tdi::Cjson &data_json, const uint64_t &oneof_index); std::unique_ptr parseAction(const tdi::Cjson &action_json); + std::unique_ptr parseNotificationInfo(const tdi::Cjson ¬ification_json); + std::unique_ptr parseNotificationParams(const tdi::Cjson ¬ification_param_json); std::set parseAnnotations( const tdi::Cjson &annotation_cjson); void parseFieldWidth(const tdi::Cjson &node, diff --git a/include/tdi/common/tdi_json_parser/tdi_table_info.hpp b/include/tdi/common/tdi_json_parser/tdi_table_info.hpp index f8cbdbf..0a29a2f 100644 --- a/include/tdi/common/tdi_json_parser/tdi_table_info.hpp +++ b/include/tdi/common/tdi_json_parser/tdi_table_info.hpp @@ -39,6 +39,8 @@ class KeyFieldInfo; class DataFieldInfo; class Cjson; class TdiInfoMapper; +class NotificationInfo; +class NotificationParamInfo; // Classes that need to be overridden by targets in order for them to // target-specific information in the info @@ -539,6 +541,187 @@ class ActionInfo { friend class TdiInfoParser; }; +class NotificationParamInfo { + public: + /** + * @name NotificationParam APIs + * @{ + */ + /** + * @brief Get name of field + * + * @return Field name + */ + const std::string &nameGet() const { return name_; }; + + /** + * @brief Get field ID + * @return field ID + */ + const tdi_id_t &idGet() const { return field_id_; }; + + /** + * @brief Get the Data type of a field (INT/BOOL/ENUM/INT_ARR/BOOL_ARR) + * + * @return Field Type (uint64, float, string etc) + */ + const tdi_field_data_type_e &dataTypeGet() const { return data_type_; }; + + /** + * @brief Get field size + * + * @return Field Size in bits + */ + const size_t &sizeGet() const { return size_bits_; }; + + /** + * @brief Get a list of all the allowed values that a particular field can + * have. This API is only for fields with string type. If the returned + * vector is empty, it indicates that the allowed choices have not been + * published in tdi json + * + * @return choices Vector of the string values that are + * allowed for this field + * + */ + const std::vector &choicesGet() const { return enum_choices_; }; + /** @} */ // End of group NotificationParamInfo + + private: + NotificationParamInfo(tdi_id_t field_id, + std::string name, + bool repeated, + size_t size_bits, + tdi_field_data_type_e data_type, + bool mandatory, + const std::vector &enum_choices, + const std::set &annotations, + uint64_t default_value, + float default_fl_value, + std::string default_str_value) + : field_id_(field_id), + name_(name), + repeated_(repeated), + size_bits_(size_bits), + data_type_(data_type), + mandatory_(mandatory), + enum_choices_(enum_choices), + annotations_(annotations), + default_value_(default_value), + default_fl_value_(default_fl_value), + default_str_value_(default_str_value){}; + const tdi_id_t field_id_; + const std::string name_; + const bool repeated_; + const size_t size_bits_; + const tdi_field_data_type_e data_type_; + const bool mandatory_; + const std::vector enum_choices_; + const std::set annotations_; + const uint64_t default_value_; + const float default_fl_value_; + const std::string default_str_value_; + + friend class TdiInfoParser; +}; // class NotificationParamInfo + +// Notification APIs +class NotificationInfo { + public: + /** + * @name Notification APIs + * @{ + */ + /** + * @brief Get Notification ID + * @return Notification ID + */ + const tdi_id_t &idGet() const { return notification_id_; }; + + /** + * @brief Get Notification Name + * @return Notification Name + */ + const std::string &nameGet() const { return name_; }; + + /** + * @brief Get a set of annotations for this notification + * + * @return Set of annotations + */ + const std::set &annotationsGet() const { + return annotations_; + }; + /** @} */ // End of group Action IDs + + /** + * @brief Get Notification RegistrationParams fields map. + * + * @return notification's id<->RegistrationParams map + * + */ + const std::map> + &RegistrationParamsMapGet() const { + return registration_params_fields_; + }; + + /** + * @brief Get Notification CallbackParams fields map. + * + * @return action's id<->CallbackParams map. + * + */ + const std::map> + &CallbackParamsMapGet() const { + return callback_params_fields_; + }; + + // Map of registration_params_fields with names + std::map + registration_params_fields_names_; + + // Map of callback_params_fields with names + std::map + callback_params_fields_names_; + + private: + NotificationInfo(tdi_id_t field_id, + std::string name, + std::map> + registration_params_fields, + std::map> + callback_params_fields, + std::set annotations) + : notification_id_(field_id), + name_(name), + registration_params_fields_(std::move(registration_params_fields)), + callback_params_fields_(std::move(callback_params_fields)), + annotations_(annotations) { + // update relevant maps + for (const auto &kv : registration_params_fields_) { + const auto registration_params_field = kv.second.get(); + registration_params_fields_names_[registration_params_field->nameGet()] = + registration_params_field; + } + for (const auto &kv : callback_params_fields_) { + const auto callback_params_field = kv.second.get(); + callback_params_fields_names_[callback_params_field->nameGet()] = + callback_params_field; + } + }; + + const tdi_id_t notification_id_; + const std::string name_; + // Map of table_params_fields + const std::map> + registration_params_fields_; + const std::map> + callback_params_fields_; + const std::set annotations_; + friend class TableInfo; + friend class TdiInfoParser; +}; + /** * @brief In memory representation of tdi.json Table */ @@ -754,6 +937,12 @@ class TableInfo { */ const ActionInfo *actionGet(const tdi_id_t &action_id) const; + const NotificationParamInfo *notificationRegistrationParamGet( + const tdi_id_t &field_id, const tdi_id_t ¬itication_id) const; + + const NotificationParamInfo *notificationCallbackParamGet( + const tdi_id_t &field_id, const tdi_id_t ¬itication_id) const; + /** * @brief Set tableContextInfo object. * @@ -808,9 +997,21 @@ class TableInfo { return table_action_map_; } + /** + * @brief Get table notifications map. + * + * @return table's id<->notifications map. + * + */ + const std::map> &tableNotificationsMapGet() + const { + return table_notification_map_; + } + std::map name_key_map_; std::map name_data_map_; std::map name_action_map_; + std::map name_notifications_map_; private: TableInfo(tdi_id_t id, @@ -822,6 +1023,7 @@ class TableInfo { std::map> table_key_map, std::map> table_data_map, std::map> table_action_map, + std::map> table_notifications_map, std::set depends_on_set, SupportedApis table_apis, std::set operations_type_set, @@ -836,6 +1038,7 @@ class TableInfo { table_key_map_(std::move(table_key_map)), table_data_map_(std::move(table_data_map)), table_action_map_(std::move(table_action_map)), + table_notification_map_(std::move(table_notifications_map)), depends_on_set_(depends_on_set), table_apis_(std::move(table_apis)), operations_type_set_(operations_type_set), @@ -856,6 +1059,11 @@ class TableInfo { const auto data_field = kv.second.get(); name_data_map_[data_field->nameGet()] = data_field; } + + for (const auto &kv : table_notification_map_) { + const auto notification = kv.second.get(); + name_notifications_map_[notification->nameGet()] = notification; + } }; const tdi_id_t id_; @@ -867,6 +1075,7 @@ class TableInfo { const std::map> table_key_map_; const std::map> table_data_map_; const std::map> table_action_map_; + const std::map> table_notification_map_; const std::set depends_on_set_; mutable tdi::SupportedApis table_apis_{}; const std::set operations_type_set_; diff --git a/include/tdi/common/tdi_notifications.hpp b/include/tdi/common/tdi_notifications.hpp index 05fb025..185a9ab 100644 --- a/include/tdi/common/tdi_notifications.hpp +++ b/include/tdi/common/tdi_notifications.hpp @@ -17,20 +17,17 @@ * * @brief Contains TDI Table Notifications APIs */ -#ifndef _TDI_TABLE_NOTIFICATIONS_HPP -#define _TDI_TABLE_NOTIFICATIONS_HPP +#ifndef _TDI_NOTIFICATIONS_HPP +#define _TDI_NOTIFICATIONS_HPP -#include #include -#include #include -#include #include +#include #include #include #include -#include #include namespace tdi { @@ -38,51 +35,65 @@ namespace tdi { class Table; /** - * @brief Contains Parmaters info of Notification - * get and set the value with a field_id + * @brief Contains input paramaters for notification register */ -class NotificationOutParams { -public: - virtual ~NotificationOutParams() = default; - NotificationOutParams(const Table* table, const tdi_id_t &tdi_id_type) - : table_(table), notification_id_(tdi_id_type){}; +class NotificationParams { + public: + virtual ~NotificationParams() = default; + + NotificationParams(const Table *table, tdi_id_t notification_id) + : table_(table), notification_id_(notification_id){}; + + virtual tdi_status_t setValue(const tdi_id_t & /*field_id*/, + const uint64_t & /*value*/) { + return TDI_NOT_SUPPORTED; + } - virtual tdi_status_t setValue(const tdi_id_t & /*field_id*/, - const uint64_t & /*value*/) const { - return TDI_NOT_SUPPORTED; - }; - virtual tdi_status_t getValue(const tdi_id_t & /*field_id*/, - uint64_t * /*value*/) const { - return TDI_NOT_SUPPORTED; - }; + virtual tdi_status_t setValue(const tdi_id_t & /*field_id*/, + const std::vector & /*value*/) { + return TDI_NOT_SUPPORTED; + } - virtual tdi_status_t setValue(const tdi_id_t & /*field_id*/, - const std::vector & /*value*/) const { - return TDI_NOT_SUPPORTED; - }; - virtual tdi_status_t getValue(const tdi_id_t & /*field_id*/, - std::vector * /*value*/) const { - return TDI_NOT_SUPPORTED; - }; + virtual tdi_status_t getValue(const tdi_id_t & /*field_id*/, + uint64_t * /*value*/) const { + return TDI_NOT_SUPPORTED; + } - virtual tdi_status_t getValue(const tdi_id_t & /*field_id*/, - uint8_t*const* /*value*/, - size_t * /*size*/) const { - return TDI_NOT_SUPPORTED; - }; + virtual tdi_status_t getValue(const tdi_id_t & /*field_id*/, + std::vector * /*value*/) const { + return TDI_NOT_SUPPORTED; + } + + const tdi_id_t ¬ificationIdGet() const { return notification_id_; }; + const Table *table_; private: - const Table* table_; - tdi_id_t notification_id_; + tdi_id_t notification_id_{0}; }; /** - * @brief Contains TDI Notification callback function + * @brief TDI Notification cpp callback function */ typedef std::function key, std::unique_ptr data, - std::unique_ptr params, - void *cookie)> tdiNotificationCallback; -} // tdi + std::unique_ptr params, + void *cookie)> + tdiNotificationCallback; +} // namespace tdi + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief TDI Notification c callback function + */ +typedef void (*tdi_notification_callback)( + const tdi_table_key_hdl *key, + const tdi_table_data_hdl *data, + const tdi_notification_param_hdl *params, + void *cookie); +#ifdef __cplusplus +} +#endif -#endif // _TDI_TABLE_NOTIFICATIONS_HPP +#endif // _TDI_NOTIFICATIONS_HPP diff --git a/include/tdi/common/tdi_operations.hpp b/include/tdi/common/tdi_operations.hpp index ac3f75c..d3b8efd 100644 --- a/include/tdi/common/tdi_operations.hpp +++ b/include/tdi/common/tdi_operations.hpp @@ -36,15 +36,24 @@ namespace tdi { class Table; class TableOperations { -public: - virtual ~TableOperations() = default; - TableOperations(const Table* table, const tdi_operations_type_e &oper_type) - : table_(table), oper_type_(oper_type){}; - tdi_status_t setValue(tdi_operations_field_type_e /*type*/, const uint64_t & /*value*/) { return TDI_NOT_SUPPORTED; }; - tdi_status_t getValue(tdi_operations_field_type_e /*type*/, uint64_t * /*value*/) {return TDI_NOT_SUPPORTED;}; -private: - const Table* table_; - tdi_operations_type_e oper_type_; + public: + virtual ~TableOperations() = default; + TableOperations(const Table *table, const tdi_operations_type_e &oper_type) + : table_(table), oper_type_(oper_type){}; + virtual tdi_status_t setValue(const tdi_operations_field_type_e &/*oper_type*/, + const uint64_t & /*value*/) { + return TDI_NOT_SUPPORTED; + }; + virtual tdi_status_t getValue(const tdi_operations_field_type_e &/*oper_type*/, + uint64_t * /*value*/) const { + return TDI_NOT_SUPPORTED; + }; + const tdi_operations_type_e &operationTypeGet() const { return oper_type_; }; + const Table *tableGet() const { return table_; }; + + private: + const Table *table_; + tdi_operations_type_e oper_type_; }; } // tdi diff --git a/include/tdi/common/tdi_table.hpp b/include/tdi/common/tdi_table.hpp index d69ff71..fb8895f 100644 --- a/include/tdi/common/tdi_table.hpp +++ b/include/tdi/common/tdi_table.hpp @@ -633,7 +633,8 @@ class Table { * * @return Status of the API call */ - virtual tdi_status_t tableOperationsExecute( + virtual tdi_status_t operationsExecute( + const tdi::Target &dev_tgt, const tdi::TableOperations &tableOperations) const; /** @} */ // End of group Operations const TableInfo *tableInfoGet() const { return table_info_; } @@ -653,13 +654,32 @@ class Table { const TdiInfo *tdiInfoGet() const { return tdi_info_; }; - virtual tdi_status_t notificationRegister(tdi::Target &target, - const tdi_id_t ¬ification_id, - tdiNotificationCallback &callback, - void *cookie); - - virtual tdi_status_t notificationDeregister(tdi::Target &target, - const tdi_id_t ¬ification_id) const; + virtual tdi_status_t notificationRegistrationParamsAllocate( + const tdi_id_t ¬ification_id, + std::unique_ptr *registration_params) const; + + virtual tdi_status_t notificationCallbackParamsAllocate( + const tdi_id_t ¬ification_id, + std::unique_ptr *registration_params) const; + + virtual tdi_status_t notificationRegister( + const tdi::Target &target, + const tdi_id_t ¬ification_id, + const tdiNotificationCallback &callback_fn, + const tdi::NotificationParams ®istration_params, + void *cookie) const; + + virtual tdi_status_t notificationRegisterC( + const tdi::Target &target, + const tdi_id_t ¬ification_id, + const tdi_notification_callback &callback_fn, + const tdi::NotificationParams ®istration_params, + void *cookie) const; + + virtual tdi_status_t notificationDeregister( + const tdi::Target &target, + const tdi_id_t ¬ification_id, + const tdi::NotificationParams ®istration_params) const; protected: // Targets can choose to use any ctor to create tables. The 2nd one diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc55ba2..da7ca87 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,7 +25,8 @@ set(TDI_C_FRONTEND_SRCS c_frontend/tdi_table_data_c.cpp c_frontend/tdi_table_key_c.cpp c_frontend/tdi_table_attributes_c.cpp - #c_frontend/tdi_table_operations_c.cpp + c_frontend/tdi_table_operations_c.cpp + c_frontend/tdi_table_notifications_c.cpp #c_frontend/tdi_learn_c.cpp c_frontend/tdi_state_c.cpp c_frontend/tdi_info_c.cpp diff --git a/src/c_frontend/tdi_table_c.cpp b/src/c_frontend/tdi_table_c.cpp index 28429dc..4be52b3 100644 --- a/src/c_frontend/tdi_table_c.cpp +++ b/src/c_frontend/tdi_table_c.cpp @@ -18,12 +18,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -532,11 +534,65 @@ tdi_status_t tdi_table_attributes_get(const tdi_table_hdl *table_hdl, reinterpret_cast(tbl_attr)); } -#ifdef _TDI_FROM_BFRT -tdi_status_t tdi_table_operations_execute(const tdi_table_hdl *table_hdl, +tdi_status_t tdi_operations_execute(const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, const tdi_operations_hdl *tbl_ops) { auto table = reinterpret_cast(table_hdl); - return (table->tableOperationsExecute( - reinterpret_cast(tbl_ops))); + return (table->operationsExecute( + *reinterpret_cast(target), + *reinterpret_cast(tbl_ops))); +} + +// notification APIs +tdi_status_t tdi_notifications_registration_params_allocate( + const tdi_table_hdl *table_hdl, + const tdi_id_t notification_id, + tdi_notification_param_hdl **tbl_notification_hdl) { + auto table = reinterpret_cast(table_hdl); + std::unique_ptr notification_params; + auto status = table->notificationRegistrationParamsAllocate( + notification_id, ¬ification_params); + *tbl_notification_hdl = reinterpret_cast( + notification_params.release()); + return status; +} + +tdi_status_t tdi_notifications_registration_params_deallocate(tdi_notification_param_hdl *tbl_notification_hdl) { + auto notification_params = reinterpret_cast(tbl_notification_hdl); + if (notification_params == nullptr) { + LOG_ERROR("%s:%d null param passed", __func__, __LINE__); + return TDI_INVALID_ARG; + } + delete notification_params; + return TDI_SUCCESS; +} + +tdi_status_t tdi_notifications_register( + const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, + const tdi_id_t notification_id, + const tdi_notification_callback callback_fn, + const tdi_notification_param_hdl *tbl_notification_hdl, + void *cookie) { + auto table = reinterpret_cast(table_hdl); + + return table->notificationRegisterC( + *reinterpret_cast(target), + notification_id, + callback_fn, + *reinterpret_cast(tbl_notification_hdl), + cookie); +} + +tdi_status_t tdi_notifications_deregister( + const tdi_table_hdl *table_hdl, + const tdi_target_hdl *target, + const tdi_id_t notification_id, + const tdi_notification_param_hdl *tbl_notification_hdl) { + auto table = reinterpret_cast(table_hdl); + + return table->notificationDeregister( + *reinterpret_cast(target), + notification_id, + *reinterpret_cast(tbl_notification_hdl)); } -#endif diff --git a/src/c_frontend/tdi_table_info_c.cpp b/src/c_frontend/tdi_table_info_c.cpp index 1769392..764127d 100644 --- a/src/c_frontend/tdi_table_info_c.cpp +++ b/src/c_frontend/tdi_table_info_c.cpp @@ -22,11 +22,13 @@ //#include #include #include +#include #include #include //#include #//include #include +#include #include namespace { @@ -896,6 +898,37 @@ tdi_status_t tdi_table_operations_supported( return TDI_SUCCESS; } +tdi_status_t tdi_table_num_notifications_supported( + const tdi_table_info_hdl *table_info_hdl, uint32_t *num_notifications) { + if (table_info_hdl == nullptr || num_notifications == nullptr) { + LOG_ERROR("%s:%d Invalid arg", __func__, __LINE__); + return TDI_INVALID_ARG; + } + auto tableInfo = reinterpret_cast(table_info_hdl); + auto ¬ifications_map = tableInfo->name_notifications_map_; + *num_notifications = notifications_map.size(); + return TDI_SUCCESS; +} + +tdi_status_t tdi_table_notifications_supported( + const tdi_table_info_hdl *table_info_hdl, const char *notifications[], + uint32_t *num_returned) { + if (table_info_hdl == nullptr || num_returned == nullptr || + notifications == nullptr) { + LOG_ERROR("%s:%d Invalid arg", __func__, __LINE__); + return TDI_INVALID_ARG; + } + auto tableInfo = reinterpret_cast(table_info_hdl); + auto ¬ifications_map = tableInfo->name_notifications_map_; + int i = 0; + for (const auto &pair : notifications_map) { + notifications[i++] = pair.first.c_str(); + } + + *num_returned = i; + return TDI_SUCCESS; +} + tdi_status_t tdi_table_num_api_supported( const tdi_table_info_hdl *table_info_hdl, uint32_t *num_apis) { if (table_info_hdl == nullptr || num_apis == nullptr) { diff --git a/src/c_frontend/tdi_table_notifications_c.cpp b/src/c_frontend/tdi_table_notifications_c.cpp new file mode 100644 index 0000000..3af95bd --- /dev/null +++ b/src/c_frontend/tdi_table_notifications_c.cpp @@ -0,0 +1,74 @@ +/* + * Copyright(c) 2023 Intel Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this software except as stipulated in the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef __cplusplus +extern "C" { +#endif +#include + +#include + +#ifdef __cplusplus +} +#endif +#include + +tdi_status_t tdi_notifications_set_value(tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + const uint64_t value) { + auto notification_param = reinterpret_cast(notifications_hdl); + return notification_param->setValue(field_id, value); +} + +tdi_status_t tdi_notifications_set_value_array(tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + const uint64_t *value, + const uint32_t array_sz) { + auto notification_param = reinterpret_cast(notifications_hdl); + const auto vec = std::vector(value, value + array_sz); + return notification_param->setValue(field_id, vec); +} + +tdi_status_t tdi_notifications_get_value(const tdi_notification_param_hdl *notifications_hdl, + const tdi_id_t field_id, + uint64_t *value) { + auto notification_param = reinterpret_cast(notifications_hdl); + return notification_param->getValue(field_id, value); +} + +tdi_status_t tdi_notifications_get_value_array( + const tdi_notification_param_hdl *notification_hdl, + const tdi_id_t field_id, + uint64_t *val) { + auto notification_param = reinterpret_cast(notification_hdl); + std::vector vec; + auto status = notification_param->getValue(field_id, &vec); + int i = 0; + for (auto const &item : vec) { + val[i++] = item; + } + return status; +} + +tdi_status_t tdi_notifications_get_value_array_size( + const tdi_notification_param_hdl *notification_hdl, + const tdi_id_t field_id, + uint32_t *array_size) { + auto notification_param = reinterpret_cast(notification_hdl); + std::vector vec; + auto status = notification_param->getValue(field_id, &vec); + *array_size = vec.size(); + return status; +} diff --git a/src/c_frontend/tdi_table_operations_c.cpp b/src/c_frontend/tdi_table_operations_c.cpp new file mode 100644 index 0000000..b6f581a --- /dev/null +++ b/src/c_frontend/tdi_table_operations_c.cpp @@ -0,0 +1,41 @@ +/* + * Copyright(c) 2023 Intel Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this software except as stipulated in the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef __cplusplus +extern "C" { +#endif +#include + +#include + +#ifdef __cplusplus +} +#endif +#include + +tdi_status_t tdi_operations_set_value(tdi_operations_hdl *operations_hdl, + tdi_operations_field_type_e type, + const uint64_t value) { + auto operations_field = reinterpret_cast(operations_hdl); + return operations_field->setValue(type, value); +} + +tdi_status_t tdi_operations_get_value(const tdi_operations_hdl *operations_hdl, + tdi_operations_field_type_e type, + uint64_t *value) { + auto operations_field = reinterpret_cast(operations_hdl); + return operations_field->getValue(type, value); +} + diff --git a/src/tdi_json_parser/tdi_info_parser.cpp b/src/tdi_json_parser/tdi_info_parser.cpp index b49aa7c..61c1bb6 100644 --- a/src/tdi_json_parser/tdi_info_parser.cpp +++ b/src/tdi_json_parser/tdi_info_parser.cpp @@ -360,6 +360,107 @@ std::unique_ptr TdiInfoParser::parseAction( return action_info; } +// To parse Notification params fields in a table +std::unique_ptr TdiInfoParser::parseNotificationParams( + const tdi::Cjson ¬ification_param_json) { + tdi_id_t id = static_cast( + notification_param_json[tdi_json::TABLE_NOTIFICATIONS_ID]); + std::string name = + notification_param_json[tdi_json::TABLE_NOTIFICATIONS_NAME]; + bool mandatory = + notification_param_json[tdi_json::TABLE_NOTIFICATIONS_MANDATORY]; + bool repeated = + notification_param_json[tdi_json::TABLE_NOTIFICATIONS_REPEATED]; + tdi_field_data_type_e field_data_type; + size_t width; + uint64_t default_value; + float default_fl_value; + std::string default_str_value; + std::vector choices; + std::string data_type; + parseFieldWidth(notification_param_json, + field_data_type, + width, + default_value, + default_fl_value, + default_str_value, + choices); + + // create notification_params structure and fill it + std::unique_ptr notification_params( + new NotificationParamInfo( + id, + name, + repeated, + width, + field_data_type, + mandatory, + choices, + parseAnnotations(notification_param_json + [tdi_json::TABLE_NOTIFICATIONS_ANNOTATIONS]), + default_value, + default_fl_value, + default_str_value)); + + return notification_params; +} + +// To parse Notification fields in a table +std::unique_ptr TdiInfoParser::parseNotificationInfo( + const tdi::Cjson ¬ification_json) { + std::string name = notification_json[tdi_json::TABLE_NOTIFICATIONS_NAME]; + tdi_id_t id = notification_json[tdi_json::TABLE_NOTIFICATIONS_ID]; + std::map> data_fields; + + // Get registration params fields + std::map> + registration_params_fields; + + tdi::Cjson registration_params_cjson = + notification_json[tdi_json::TABLE_NOTIFICATIONS_REGISTRATION_PARAMS]; + for (const auto ®istration_data : + registration_params_cjson.getCjsonChildVec()) { + auto notification_param = parseNotificationParams(*registration_data); + if (registration_params_fields.find(notification_param->idGet()) != + registration_params_fields.end()) { + LOG_ERROR("%s:%d ID \"%u\" Exists for registration params ", + __func__, + __LINE__, + notification_param->idGet()); + continue; + } + registration_params_fields[notification_param->idGet()] = + std::move(notification_param); + } + + // Get callback params fields + std::map> + callback_params_fields; + + tdi::Cjson callback_params_cjson = + notification_json[tdi_json::TABLE_NOTIFICATIONS_CALLBACK_PARAMS]; + for (const auto &callback_data : callback_params_cjson.getCjsonChildVec()) { + auto notification_param = parseNotificationParams(*callback_data); + if (callback_params_fields.find(notification_param->idGet()) != + callback_params_fields.end()) { + LOG_ERROR("%s:%d ID \"%u\" Exists for callback params ", + __func__, + __LINE__, + notification_param->idGet()); + continue; + } + callback_params_fields[notification_param->idGet()] = + std::move(notification_param); + } + std::unique_ptr notification_info( + new NotificationInfo(id, + name, + std::move(registration_params_fields), + std::move(callback_params_fields), + parseAnnotations(notification_json["annotations"]))); + return notification_info; +} + std::unique_ptr TdiInfoParser::parseLearn( const tdi::Cjson &learn_tdi) { tdi_id_t learn_id = learn_tdi[tdi_json::LEARN_ID]; @@ -423,6 +524,7 @@ std::unique_ptr TdiInfoParser::parseTable( std::map> table_key_map; std::map> table_data_map; std::map> table_action_map; + std::map> table_notifications_map; std::set depends_on_set; SupportedApis table_apis; std::set operations_type_set; @@ -528,6 +630,25 @@ std::unique_ptr TdiInfoParser::parseTable( } } + /////////////////////////// + // getting notifications // + /////////////////////////// + tdi::Cjson table_notifications_cjson = table_tdi[tdi_json::TABLE_NOTIFICATIONS]; + for (const auto ¬ifications : table_notifications_cjson.getCjsonChildVec()) { + auto notification_info = parseNotificationInfo(*notifications); + auto elem = table_notifications_map.find(notification_info->idGet()); + if (elem == table_notifications_map.end()) { + table_notifications_map[notification_info->idGet()] = (std::move(notification_info)); + } else { + // Action id is repeating. Log an error message + LOG_ERROR("%s:%d Notification ID %d is repeating", + __func__, + __LINE__, + notification_info->idGet()); + return nullptr; + } + } + ////////////////////////// // create tableInfo // ////////////////////////// @@ -541,6 +662,7 @@ std::unique_ptr TdiInfoParser::parseTable( std::move(table_key_map), std::move(table_data_map), std::move(table_action_map), + std::move(table_notifications_map), depends_on_set, std::move(table_apis), operations_type_set, diff --git a/src/tdi_json_parser/tdi_table_info.cpp b/src/tdi_json_parser/tdi_table_info.cpp index 493729b..8d5e27d 100644 --- a/src/tdi_json_parser/tdi_table_info.cpp +++ b/src/tdi_json_parser/tdi_table_info.cpp @@ -198,6 +198,49 @@ std::vector TableInfo::actionIdListGet() const { return id_vec; } +const NotificationParamInfo * +TableInfo::notificationRegistrationParamGet( + const tdi_id_t &field_id, const tdi_id_t ¬ification_id) const { + if (notification_id && table_notification_map_.find(notification_id) != + table_notification_map_.end()) { + auto notification_info = table_notification_map_.at(notification_id).get(); + if (notification_info->registration_params_fields_.find(field_id) != + notification_info->registration_params_fields_.end()) { + return notification_info->registration_params_fields_.at(field_id).get(); + } + } + LOG_WARN( + "%s:%d %s Field \"%d\" not found in registration params list of " + "notification: %d", + __func__, + __LINE__, + nameGet().c_str(), + field_id, + notification_id); + return nullptr; +} + +const NotificationParamInfo *TableInfo::notificationCallbackParamGet( + const tdi_id_t &field_id, const tdi_id_t ¬ification_id) const { + if (notification_id && table_notification_map_.find(notification_id) != + table_notification_map_.end()) { + auto notification_info = table_notification_map_.at(notification_id).get(); + if (notification_info->callback_params_fields_.find(field_id) != + notification_info->callback_params_fields_.end()) { + return notification_info->callback_params_fields_.at(field_id).get(); + } + } + LOG_WARN( + "%s:%d %s Field \"%d\" not found in callback params list of " + "notification: %d", + __func__, + __LINE__, + nameGet().c_str(), + field_id, + notification_id); + return nullptr; +} + #if 0 tdi_status_t Table::getDataField(const tdi_id_t &field_id, const TableDataField **field) const { diff --git a/src/tdi_table.cpp b/src/tdi_table.cpp index f99dc93..9227766 100644 --- a/src/tdi_table.cpp +++ b/src/tdi_table.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ #include -#include #include // local includes @@ -349,18 +348,46 @@ tdi_status_t Table::tableAttributesGet( return TDI_NOT_SUPPORTED; } -tdi_status_t Table::notificationRegister(tdi::Target &,//target, - const tdi_id_t &,//notification_id, - tdiNotificationCallback &,//callback, - void * /*cookie*/) { +tdi_status_t Table::notificationRegistrationParamsAllocate( + const tdi_id_t & /*notification_id*/, + std::unique_ptr * /*registration_params*/) const { LOG_ERROR("%s:%d Not supported", __func__, __LINE__); return TDI_NOT_SUPPORTED; } -tdi_status_t Table::notificationDeregister(tdi::Target &,//target, - const tdi_id_t & /*notification_id*/) const{ - LOG_ERROR("%s:%d Not supported", __func__, __LINE__); - return TDI_NOT_SUPPORTED; +tdi_status_t Table::notificationCallbackParamsAllocate( + const tdi_id_t & /*notification_id*/, + std::unique_ptr * /*registration_params*/) const { + LOG_ERROR("%s:%d Not supported", __func__, __LINE__); + return TDI_NOT_SUPPORTED; +} + +tdi_status_t Table::notificationRegister( + const tdi::Target & /*target*/, + const tdi_id_t & /*notification_id*/, + const tdiNotificationCallback & /*callback_fn*/, + const tdi::NotificationParams & /*in_params*/, + void * /*cookie*/) const { + LOG_ERROR("%s:%d Not supported", __func__, __LINE__); + return TDI_NOT_SUPPORTED; +} + +tdi_status_t Table::notificationRegisterC( + const tdi::Target & /*target*/, + const tdi_id_t & /*notification_id*/, + const tdi_notification_callback & /*callback_fn*/, + const tdi::NotificationParams & /*in_params*/, + void * /*cookie*/) const { + LOG_ERROR("%s:%d Not supported", __func__, __LINE__); + return TDI_NOT_SUPPORTED; +} + +tdi_status_t Table::notificationDeregister( + const tdi::Target &/*target*/, + const tdi_id_t &/*notification_id*/, + const tdi::NotificationParams &/*registration_params*/) const { + LOG_ERROR("%s:%d Not supported", __func__, __LINE__); + return TDI_NOT_SUPPORTED; } tdi_status_t Table::operationsAllocate( @@ -381,7 +408,8 @@ tdi_status_t Table::operationsAllocate( return TDI_SUCCESS; } -tdi_status_t Table::tableOperationsExecute( +tdi_status_t Table::operationsExecute( + const tdi::Target & /*dev_tgt*/, const tdi::TableOperations & /*tableOperations*/) const { return TDI_NOT_SUPPORTED; } diff --git a/tdi_python/tdiTable.py b/tdi_python/tdiTable.py index 14cb8f4..1cd87d4 100644 --- a/tdi_python/tdiTable.py +++ b/tdi_python/tdiTable.py @@ -97,6 +97,7 @@ def __init__(self, cintf, handle, info, info_handle): self.supported_commands = ["info", "entry", "string_choices"] self.set_supported_attributes_to_supported_commands() self.set_supported_operations_to_supported_commands() + self.set_supported_notifications_to_supported_commands() self.set_supported_apis_to_supported_commands() if not self.table_ready: return @@ -1801,12 +1802,22 @@ def set_supported_operations_to_supported_commands(self): logging.debug("For Table={} operations_arr ==={}".format(self.name, str(operations_arr[0:]))); keys_list = self.operations_type_cls.operations_dict.keys() - # TODO: Enable this when operations are supported - ''' for i in range(len(operations_arr)): if operations_arr[i] in keys_list: self.supported_commands.append(self.operations_type_cls.operations_dict[operations_arr[i]]) - ''' + + def set_supported_notifications_to_supported_commands(self): + num_notifs = c_uint(0) + sts = self._cintf.get_driver().tdi_table_num_notifications_supported(self._info_handle, byref(num_notifs)) + if sts != 0: + raise TdiTableError("Error: num notifications supported get failed on table {}. [{}]".format(self.name, self._cintf.err_str(sts)), self, sts) + + arr_type = c_char_p * num_notifs.value + notifs_arr = arr_type() + sts = self._cintf.get_driver().tdi_table_notifications_supported(self._info_handle, byref(notifs_arr), byref(num_notifs)) + + for notif in notifs_arr: + self.supported_commands += [notif.decode('ascii')] #self.attributes_type_cls.attributes_dict[notifs_arr[i]] def set_supported_apis_to_supported_commands(self): num_api = c_uint(0) @@ -1877,7 +1888,7 @@ def _attr_get(self, attr_hdl): def _table_operation_set(self, callback, operation): ops_hdl = self._cintf.handle_type() - sts = self._cintf.get_driver().tdi_table_operations_allocate(self._handle, operation, byref(ops_hdl)) + sts = self._cintf.get_driver().tdi_operations_allocate(self._handle, operation, byref(ops_hdl)) if not sts == 0: print("table_operations_allocate failed on table {}. [{}]".format(self.name, self._cintf.err_str(sts))) return -1 @@ -1893,7 +1904,7 @@ def _table_operation_set(self, callback, operation): self._cintf.get_driver().tdi_table_operations_deallocate(ops_hdl) return -1 - sts = self._cintf.get_driver().tdi_table_operations_execute(self._handle, ops_hdl) + sts = self._cintf.get_driver().tdi_operations_execute(self._handle, ops_hdl) if not sts == 0: print("table_operations_execute failed on table {}. [{}]".format(self.name, self._cintf.err_str(sts))) sts1 = self._cintf.get_driver().tdi_table_operations_deallocate(ops_hdl)