diff --git a/doc/OCP/SAI Demo 2017 topology.pdf b/doc/OCP/SAI Demo 2017 topology.pdf new file mode 100755 index 000000000..acb2da3fc Binary files /dev/null and b/doc/OCP/SAI Demo 2017 topology.pdf differ diff --git a/doc/SAI-Proposal-BroadView-BST.docx b/doc/TAM/SAI-Proposal-BroadView-BST.docx similarity index 100% rename from doc/SAI-Proposal-BroadView-BST.docx rename to doc/TAM/SAI-Proposal-BroadView-BST.docx diff --git a/doc/TAM/SAI-Proposal-TAM-v0.10.docx b/doc/TAM/SAI-Proposal-TAM-v0.10.docx new file mode 100644 index 000000000..2f5f60160 Binary files /dev/null and b/doc/TAM/SAI-Proposal-TAM-v0.10.docx differ diff --git a/doc/TAM/SAI-Proposal-TAM-v0.9.docx b/doc/TAM/SAI-Proposal-TAM-v0.9.docx new file mode 100644 index 000000000..a8dbb03d3 Binary files /dev/null and b/doc/TAM/SAI-Proposal-TAM-v0.9.docx differ diff --git a/doc/Visibility/SAI_Proposal_Visibility_v0.1.docx b/doc/TAM/SAI_Proposal_Visibility_v0.1.docx similarity index 100% rename from doc/Visibility/SAI_Proposal_Visibility_v0.1.docx rename to doc/TAM/SAI_Proposal_Visibility_v0.1.docx diff --git a/doc/object-model/pipeline_object_model.pdf b/doc/object-model/pipeline_object_model.pdf new file mode 100644 index 000000000..abef6aabe Binary files /dev/null and b/doc/object-model/pipeline_object_model.pdf differ diff --git a/inc/sai.h b/inc/sai.h index b8cd74fcb..58c1f77dd 100644 --- a/inc/sai.h +++ b/inc/sai.h @@ -31,7 +31,7 @@ #include "saibuffer.h" #include "saifdb.h" #include "saihash.h" -#include "saihostintf.h" +#include "saihostif.h" #include "sailag.h" #include "saimirror.h" #include "saineighbor.h" @@ -40,11 +40,11 @@ #include "saiobject.h" #include "saipolicer.h" #include "saiport.h" -#include "saiqosmaps.h" +#include "saiqosmap.h" #include "saiqueue.h" #include "sairoute.h" -#include "sairouter.h" -#include "sairouterintf.h" +#include "saivirtualrouter.h" +#include "sairouterinterface.h" #include "saisamplepacket.h" #include "saischedulergroup.h" #include "saischeduler.h" @@ -60,7 +60,7 @@ #include "sairpfgroup.h" #include "sail2mcgroup.h" #include "saiipmcgroup.h" -#include "saimcfdb.h" +#include "saimcastfdb.h" /** * @defgroup SAI SAI - Entry point specific API definitions. @@ -89,18 +89,18 @@ typedef enum _sai_api_t SAI_API_ROUTER_INTERFACE = 9, /**< sai_router_interface_api_t */ SAI_API_NEIGHBOR = 10, /**< sai_neighbor_api_t */ SAI_API_ACL = 11, /**< sai_acl_api_t */ - SAI_API_HOST_INTERFACE = 12, /**< sai_host_interface_api_t */ + SAI_API_HOSTIF = 12, /**< sai_hostif_api_t */ SAI_API_MIRROR = 13, /**< sai_mirror_api_t */ SAI_API_SAMPLEPACKET = 14, /**< sai_samplepacket_api_t */ SAI_API_STP = 15, /**< sai_stp_api_t */ SAI_API_LAG = 16, /**< sai_lag_api_t */ SAI_API_POLICER = 17, /**< sai_policer_api_t */ SAI_API_WRED = 18, /**< sai_wred_api_t */ - SAI_API_QOS_MAPS = 19, /**< sai_qos_map_api_t */ + SAI_API_QOS_MAP = 19, /**< sai_qos_map_api_t */ SAI_API_QUEUE = 20, /**< sai_queue_api_t */ SAI_API_SCHEDULER = 21, /**< sai_scheduler_api_t */ SAI_API_SCHEDULER_GROUP = 22, /**< sai_scheduler_group_api_t */ - SAI_API_BUFFERS = 23, /**< sai_buffer_api_t */ + SAI_API_BUFFER = 23, /**< sai_buffer_api_t */ SAI_API_HASH = 24, /**< sai_hash_api_t */ SAI_API_UDF = 25, /**< sai_udf_api_t */ SAI_API_TUNNEL = 26, /**< sai_tunnel_api_t */ @@ -111,6 +111,7 @@ typedef enum _sai_api_t SAI_API_IPMC_GROUP = 31, /**< sai_ipmc_group_api_t */ SAI_API_MCAST_FDB = 32, /**< sai_mcast_fdb_api_t */ SAI_API_BRIDGE = 33, /**< sai_bridge_api_t */ + SAI_API_MAX = 34, /**< total number of apis */ } sai_api_t; /** @@ -138,6 +139,15 @@ typedef enum _sai_log_level_t } sai_log_level_t; +typedef const char* (*sai_profile_get_value_fn)( + _In_ sai_switch_profile_id_t profile_id, + _In_ const char *variable); + +typedef int (*sai_profile_get_next_value_fn)( + _In_ sai_switch_profile_id_t profile_id, + _Out_ const char** variable, + _Out_ const char** value); + /** * @brief Method table that contains function pointers for services exposed by * adapter host for adapter. @@ -147,9 +157,7 @@ typedef struct _service_method_table_t /** * @brief Get variable value given its name */ - const char* (*profile_get_value)( - _In_ sai_switch_profile_id_t profile_id, - _In_ const char *variable); + sai_profile_get_value_fn profile_get_value; /** * @brief Enumerate all the K/V pairs in a profile. @@ -157,10 +165,7 @@ typedef struct _service_method_table_t * Pointer to NULL passed as variable restarts enumeration. Function * returns 0 if next value exists, -1 at the end of the list. */ - int (*profile_get_next_value)( - _In_ sai_switch_profile_id_t profile_id, - _Out_ const char** variable, - _Out_ const char** value); + sai_profile_get_next_value_fn profile_get_next_value; } service_method_table_t; @@ -222,14 +227,27 @@ sai_object_type_t sai_object_type_query( _In_ sai_object_id_t sai_object_id); /** -* @brief Generate dump file. The dump file may include SAI state information and vendor SDK information. -* -* @param[in] dump_file_name Full path for dump file -* -* @return #SAI_STATUS_SUCCESS on success Failure status code on error -*/ + * @brief Query sai switch id. + * + * @param[in] sai_object_id Object id + * + * @return Return #SAI_NULL_OBJECT_ID when sai_object_id is not valid. + * Otherwise, return a valid SAI_OBJECT_TYPE_SWITCH object on which + * provided object id belongs. If valid switch id object is provided + * as input parameter it should returin itself. + */ +sai_object_id_t sai_switch_id_query( + _In_ sai_object_id_t sai_object_id); + +/** + * @brief Generate dump file. The dump file may include SAI state information and vendor SDK information. + * + * @param[in] dump_file_name Full path for dump file + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ sai_status_t sai_dbg_generate_dump( - _In_ const char *dump_file_name); + _In_ const char *dump_file_name); /** * @} diff --git a/inc/saiacl.h b/inc/saiacl.h index 3c6e61a85..e43405e2c 100644 --- a/inc/saiacl.h +++ b/inc/saiacl.h @@ -83,16 +83,16 @@ typedef enum _sai_acl_ip_type_t SAI_ACL_IP_TYPE_NON_IP, /** Any IPv4 packet */ - SAI_ACL_IP_TYPE_IPv4ANY, + SAI_ACL_IP_TYPE_IPV4ANY, /** Anything but IPv4 packets */ - SAI_ACL_IP_TYPE_NON_IPv4, + SAI_ACL_IP_TYPE_NON_IPV4, /** IPv6 packet */ - SAI_ACL_IP_TYPE_IPv6ANY, + SAI_ACL_IP_TYPE_IPV6ANY, /** Anything but IPv6 packets */ - SAI_ACL_IP_TYPE_NON_IPv6, + SAI_ACL_IP_TYPE_NON_IPV6, /** ARP/RARP */ SAI_ACL_IP_TYPE_ARP, @@ -190,10 +190,10 @@ typedef enum _sai_acl_action_type_t SAI_ACL_ACTION_TYPE_SET_DST_IP, /** Set Packet Src IPv6 Address */ - SAI_ACL_ACTION_TYPE_SET_SRC_IPv6, + SAI_ACL_ACTION_TYPE_SET_SRC_IPV6, /** Set Packet Src IPv6 Address */ - SAI_ACL_ACTION_TYPE_SET_DST_IPv6, + SAI_ACL_ACTION_TYPE_SET_DST_IPV6, /** Set Packet DSCP */ SAI_ACL_ACTION_TYPE_SET_DSCP, @@ -225,7 +225,7 @@ typedef enum _sai_acl_action_type_t /** Set user defined trap id */ SAI_ACL_ACTION_TYPE_SET_USER_TRAP_ID, - /** Set Do Not Learn unknow source MAC*/ + /** Set Do Not Learn unknow source MAC */ SAI_ACL_ACTION_TYPE_SET_DO_NOT_LEARN, } sai_acl_action_type_t; @@ -337,16 +337,17 @@ typedef enum _sai_acl_table_group_member_attr_t * actions are resolved in case of parallel. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ACL_TABLE_GROUP */ SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID = SAI_ACL_TABLE_GROUP_MEMBER_ATTR_START, /** * @brief ACL table id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ACL_TABLE */ SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID, @@ -441,9 +442,20 @@ typedef enum _sai_acl_table_attr_t SAI_ACL_TABLE_ATTR_SIZE, /** - * @brief End of ACL Table attributes + * @brief List of actions in sai_acl_action_type_t + * + * Based on the ACL capability per stage obtained from the switch + * attributes #SAI_SWITCH_ATTR_ACL_STAGE_INGRESS and #SAI_SWITCH_ATTR_ACL_STAGE_EGRESS + * application should pass the action list if its mandatory per stage. + * pass the action list if its mandatory per stage. + * If its not mandatory application can either pass the action list + * or ignore it. + * + * @type sai_s32_list_t sai_acl_action_type_t + * @flags CREATE_ONLY + * @default empty */ - SAI_ACL_TABLE_ATTR_END, + SAI_ACL_TABLE_ATTR_ACL_ACTION_TYPE_LIST, /* * Match fields [bool] @@ -463,7 +475,7 @@ typedef enum _sai_acl_table_attr_t * @flags CREATE_ONLY * @default false */ - SAI_ACL_TABLE_ATTR_FIELD_SRC_IPv6 = SAI_ACL_TABLE_ATTR_FIELD_START, + SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6 = SAI_ACL_TABLE_ATTR_FIELD_START, /** * @brief Dst IPv6 Address @@ -472,25 +484,25 @@ typedef enum _sai_acl_table_attr_t * @flags CREATE_ONLY * @default false */ - SAI_ACL_TABLE_ATTR_FIELD_DST_IPv6, + SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6, /** - * @brief Inner Src IPv6 Address - * - * @type bool - * @flags CREATE_ONLY - * @default false - */ - SAI_ACL_TABLE_ATTR_FIELD_INNER_SRC_IPv6, + * @brief Inner Src IPv6 Address + * + * @type bool + * @flags CREATE_ONLY + * @default false + */ + SAI_ACL_TABLE_ATTR_FIELD_INNER_SRC_IPV6, /** - * @brief Inner Dst IPv6 Address - * - * @type bool - * @flags CREATE_ONLY - * @default false - */ - SAI_ACL_TABLE_ATTR_FIELD_INNER_DST_IPv6, + * @brief Inner Dst IPv6 Address + * + * @type bool + * @flags CREATE_ONLY + * @default false + */ + SAI_ACL_TABLE_ATTR_FIELD_INNER_DST_IPV6, /** * @brief Src MAC Address @@ -504,7 +516,6 @@ typedef enum _sai_acl_table_attr_t /** * @brief Dst MAC Address * - * * @type bool * @flags CREATE_ONLY * @default false @@ -530,21 +541,21 @@ typedef enum _sai_acl_table_attr_t SAI_ACL_TABLE_ATTR_FIELD_DST_IP, /** - * @brief Inner Src IPv4 Address - * - * @type bool - * @flags CREATE_ONLY - * @default false - */ + * @brief Inner Src IPv4 Address + * + * @type bool + * @flags CREATE_ONLY + * @default false + */ SAI_ACL_TABLE_ATTR_FIELD_INNER_SRC_IP, /** - * @brief Inner Dst IPv4 Address - * - * @type bool - * @flags CREATE_ONLY - * @default false - */ + * @brief Inner Dst IPv4 Address + * + * @type bool + * @flags CREATE_ONLY + * @default false + */ SAI_ACL_TABLE_ATTR_FIELD_INNER_DST_IP, /** @@ -683,12 +694,12 @@ typedef enum _sai_acl_table_attr_t SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL, /** - * @brief IP Identification - * - * @type bool - * @flags CREATE_ONLY - * @default false - */ + * @brief IP Identification + * + * @type bool + * @flags CREATE_ONLY + * @default false + */ SAI_ACL_TABLE_ATTR_FIELD_IP_IDENTIFICATION, /** @@ -770,7 +781,7 @@ typedef enum _sai_acl_table_attr_t * @flags CREATE_ONLY * @default false */ - SAI_ACL_TABLE_ATTR_FIELD_IPv6_FLOW_LABEL, + SAI_ACL_TABLE_ATTR_FIELD_IPV6_FLOW_LABEL, /** * @brief Class-of-Service (Traffic Class) @@ -917,22 +928,23 @@ typedef enum _sai_acl_table_attr_t SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE, /** - * @brief List of actions in sai_acl_table_action_list_t [sai_s32_list_t] - * - * Based on the ACL capability per stage obtained from the switch - * attribute #SAI_SWITCH_ATTR_ACL_CAPABILITY application should - * pass the action list if its mandatory per stage. - * If its not mandatory application can either pass the action list - * or ignore it. + * @brief IPv6 Next Header * - * @ignore + * @type bool + * @flags CREATE_ONLY + * @default false */ - SAI_ACL_TABLE_ATTR_ACTION_LIST, + SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER, /** * @brief End of ACL Table Match Field */ - SAI_ACL_TABLE_ATTR_FIELD_END = SAI_ACL_TABLE_ATTR_ACTION_LIST, + SAI_ACL_TABLE_ATTR_FIELD_END = SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER, + + /** + * @brief End of ACL Table attributes + */ + SAI_ACL_TABLE_ATTR_END, /** * @brief Custom range base value start @@ -960,8 +972,8 @@ typedef enum _sai_acl_entry_attr_t * @brief SAI ACL table object id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ACL_TABLE */ SAI_ACL_ENTRY_ATTR_TABLE_ID = SAI_ACL_ENTRY_ATTR_START, @@ -988,11 +1000,6 @@ typedef enum _sai_acl_entry_attr_t */ SAI_ACL_ENTRY_ATTR_ADMIN_STATE, - /** - * @brief End of ACL Entry attributes - */ - SAI_ACL_ENTRY_ATTR_END, - /* * Match fields [sai_acl_field_data_t] * - Mandatory to pass at least one field during ACL Rule creation. @@ -1012,7 +1019,7 @@ typedef enum _sai_acl_entry_attr_t * @type sai_acl_field_data_t sai_ip6_t * @flags CREATE_AND_SET */ - SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPv6 = SAI_ACL_ENTRY_ATTR_FIELD_START, + SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6 = SAI_ACL_ENTRY_ATTR_FIELD_START, /** * @brief Dst IPv6 Address @@ -1020,23 +1027,23 @@ typedef enum _sai_acl_entry_attr_t * @type sai_acl_field_data_t sai_ip6_t * @flags CREATE_AND_SET */ - SAI_ACL_ENTRY_ATTR_FIELD_DST_IPv6, + SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6, /** - * @brief Inner Src IPv6 Address - * - * @type sai_acl_field_data_t sai_ip6_t - * @flags CREATE_AND_SET - */ - SAI_ACL_ENTRY_ATTR_FIELD_INNER_SRC_IPv6, + * @brief Inner Src IPv6 Address + * + * @type sai_acl_field_data_t sai_ip6_t + * @flags CREATE_AND_SET + */ + SAI_ACL_ENTRY_ATTR_FIELD_INNER_SRC_IPV6, /** - * @brief Inner Dst IPv6 Address - * - * @type sai_acl_field_data_t sai_ip6_t - * @flags CREATE_AND_SET - */ - SAI_ACL_ENTRY_ATTR_FIELD_INNER_DST_IPv6, + * @brief Inner Dst IPv6 Address + * + * @type sai_acl_field_data_t sai_ip6_t + * @flags CREATE_AND_SET + */ + SAI_ACL_ENTRY_ATTR_FIELD_INNER_DST_IPV6, /** * @brief Src MAC Address @@ -1071,27 +1078,27 @@ typedef enum _sai_acl_entry_attr_t SAI_ACL_ENTRY_ATTR_FIELD_DST_IP, /** - * @brief Inner Src IPv4 Address - * - * @type sai_acl_field_data_t sai_ip4_t - * @flags CREATE_AND_SET - */ + * @brief Inner Src IPv4 Address + * + * @type sai_acl_field_data_t sai_ip4_t + * @flags CREATE_AND_SET + */ SAI_ACL_ENTRY_ATTR_FIELD_INNER_SRC_IP, /** - * @brief Inner Dst IPv4 Address - * - * @type sai_acl_field_data_t sai_ip4_t - * @flags CREATE_AND_SET - */ + * @brief Inner Dst IPv4 Address + * + * @type sai_acl_field_data_t sai_ip4_t + * @flags CREATE_AND_SET + */ SAI_ACL_ENTRY_ATTR_FIELD_INNER_DST_IP, /** * @brief In-Ports (mask is not needed) * * @type sai_acl_field_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS, @@ -1099,8 +1106,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Out-Ports (mask is not needed) * * @type sai_acl_field_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS, @@ -1108,8 +1115,8 @@ typedef enum _sai_acl_entry_attr_t * @brief In-Port (mask is not needed) * * @type sai_acl_field_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT, @@ -1117,8 +1124,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Out-Port (mask is not needed) * * @type sai_acl_field_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT, @@ -1127,8 +1134,8 @@ typedef enum _sai_acl_entry_attr_t * (mask is not needed) * * @type sai_acl_field_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT, @@ -1137,6 +1144,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan true */ SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID, @@ -1161,6 +1169,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan true */ SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID, @@ -1185,6 +1194,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false */ SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT, @@ -1193,6 +1203,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false */ SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT, @@ -1201,6 +1212,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false */ SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE, @@ -1213,11 +1225,12 @@ typedef enum _sai_acl_entry_attr_t SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL, /** - * @brief IP Identification - * - * @type sai_acl_field_data_t sai_uint16_t - * @flags CREATE_AND_SET - */ + * @brief IP Identification + * + * @type sai_acl_field_data_t sai_uint16_t + * @flags CREATE_AND_SET + * @isvlan false + */ SAI_ACL_ENTRY_ATTR_FIELD_IP_IDENTIFICATION, /** @@ -1290,7 +1303,7 @@ typedef enum _sai_acl_entry_attr_t * @type sai_acl_field_data_t sai_uint32_t * @flags CREATE_AND_SET */ - SAI_ACL_ENTRY_ATTR_FIELD_IPv6_FLOW_LABEL, + SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL, /** * @brief Class-of-Service (Traffic Class) @@ -1328,6 +1341,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief DST MAC address match user meta data in FDB + * * Value must be in the range defined in * #SAI_SWITCH_ATTR_FDB_DST_USER_META_DATA_RANGE * @@ -1338,6 +1352,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief DST IP address match user meta data in Route Table + * * Value must be in the range defined in * #SAI_SWITCH_ATTR_ROUTE_DST_USER_META_DATA_RANGE * @@ -1348,6 +1363,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief DST IP address match user meta data in Neighbor Table + * * Value must be in the range defined in * #SAI_SWITCH_ATTR_NEIGHBOR_DST_USER_META_DATA_RANGE * @@ -1358,6 +1374,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief Port User Meta Data + * * Value must be in the range defined in * SAI_SWITCH_ATTR_PORT_USER_META_DATA_RANGE * @@ -1368,6 +1385,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief Vlan User Meta Data + * * Value must be in the range defined in * #SAI_SWITCH_ATTR_VLAN_USER_META_DATA_RANGE * @@ -1378,6 +1396,7 @@ typedef enum _sai_acl_entry_attr_t /** * @brief Meta Data carried from previous ACL Stage. + * * When an ACL entry set the meta data, the ACL meta data * form previous stages are overriden. * Value must be in the range defined in @@ -1430,18 +1449,28 @@ typedef enum _sai_acl_entry_attr_t /** * @brief Range Type defined in sai_acl_range_type_t + * * List of SAI ACL Range Object Id * * @type sai_acl_field_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_ACL_RANGE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_RANGE */ SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE, + /** + * @brief IPv6 Next Header (8 bits) + * This is to qualify 6th Byte value in IPv6 header. + * + * @type sai_acl_field_data_t sai_uint8_t + * @flags CREATE_AND_SET + */ + SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER, + /** * @brief End of Rule Match Fields */ - SAI_ACL_ENTRY_ATTR_FIELD_END = SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE, + SAI_ACL_ENTRY_ATTR_FIELD_END = SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER, /* * Actions [sai_acl_action_data_t] @@ -1459,8 +1488,8 @@ typedef enum _sai_acl_entry_attr_t * lag, nexthop, nexthopgroup * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP */ SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT = SAI_ACL_ENTRY_ATTR_ACTION_START, @@ -1469,8 +1498,8 @@ typedef enum _sai_acl_entry_attr_t * a port list. * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP */ SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT_LIST, @@ -1494,8 +1523,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Attach/detach counter id to the entry * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_COUNTER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_COUNTER */ SAI_ACL_ENTRY_ATTR_ACTION_COUNTER, @@ -1503,8 +1532,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Ingress Mirror (mirror session id list) * * @type sai_acl_action_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_MIRROR_SESSION */ SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS, @@ -1512,8 +1541,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Egress Mirror (mirror session id list) * * @type sai_acl_action_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_MIRROR_SESSION */ SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS, @@ -1521,8 +1550,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Assosiate with policer (policer id) * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER */ SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER, @@ -1571,6 +1600,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_action_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan true */ SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_ID, @@ -1620,7 +1650,7 @@ typedef enum _sai_acl_entry_attr_t * @type sai_acl_action_data_t sai_ip6_t * @flags CREATE_AND_SET */ - SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IPv6, + SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IPV6, /** * @brief Set Packet Src IPv6 Address @@ -1628,7 +1658,7 @@ typedef enum _sai_acl_entry_attr_t * @type sai_acl_action_data_t sai_ip6_t * @flags CREATE_AND_SET */ - SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IPv6, + SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IPV6, /** * @brief Set Packet DSCP (6 bits) @@ -1651,6 +1681,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_action_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false */ SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_SRC_PORT, @@ -1659,6 +1690,7 @@ typedef enum _sai_acl_entry_attr_t * * @type sai_acl_action_data_t sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false */ SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_DST_PORT, @@ -1666,8 +1698,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Set ingress packet sampling (samplepacket session id) * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SAMPLEPACKET */ SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE, @@ -1675,8 +1707,8 @@ typedef enum _sai_acl_entry_attr_t * @brief Set egress packet sampling (samplepacket session id) * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SAMPLEPACKET */ SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE, @@ -1688,13 +1720,14 @@ typedef enum _sai_acl_entry_attr_t * to CPU (Trap/Log) or the destination port points to CPU. * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_QUEUE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QUEUE */ SAI_ACL_ENTRY_ATTR_ACTION_SET_CPU_QUEUE, /** * @brief Set Meta Data to carry forward to next ACL Stage + * * Value Range #SAI_SWITCH_ATTR_ACL_USER_META_DATA_RANGE * * @type sai_acl_action_data_t sai_uint32_t @@ -1704,12 +1737,13 @@ typedef enum _sai_acl_entry_attr_t /** * @brief Egress block port list + * * Packets matching the ACL entry and egressing out of the ports in the * given port list will be dropped. * * @type sai_acl_action_data_t sai_object_list_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_BLOCK_PORT_LIST, @@ -1720,8 +1754,8 @@ typedef enum _sai_acl_entry_attr_t * Value Range #SAI_SWITCH_ATTR_ACL_USER_TRAP_ID_RANGE * * @type sai_acl_action_data_t sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP */ SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID, @@ -1737,7 +1771,12 @@ typedef enum _sai_acl_entry_attr_t /** * @brief End of Rule Actions */ - SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_DO_NOT_LEARN + SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_DO_NOT_LEARN, + + /** + * @brief End of ACL Entry attributes + */ + SAI_ACL_ENTRY_ATTR_END, } sai_acl_entry_attr_t; @@ -1755,8 +1794,8 @@ typedef enum _sai_acl_counter_attr_t * @brief SAI ACL table object id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ACL_TABLE */ SAI_ACL_COUNTER_ATTR_TABLE_ID = SAI_ACL_COUNTER_ATTR_START, @@ -2091,6 +2130,7 @@ typedef sai_status_t (*sai_get_acl_range_attribute_fn)( */ typedef sai_status_t (*sai_create_acl_table_group_fn)( _Out_ sai_object_id_t *acl_table_group_id, + _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); @@ -2141,6 +2181,7 @@ typedef sai_status_t (*sai_get_acl_table_group_attribute_fn)( */ typedef sai_status_t (*sai_create_acl_table_group_member_fn)( _Out_ sai_object_id_t *acl_table_group_member_id, + _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); diff --git a/inc/saibridge.h b/inc/saibridge.h index 6da7d880d..d8ea29a7b 100644 --- a/inc/saibridge.h +++ b/inc/saibridge.h @@ -53,11 +53,14 @@ typedef enum _sai_bridge_port_fdb_learning_mode_t /** Trap packets with unknown source MAC to CPU. Do not learn. Forward based on destination MAC */ SAI_BRIDGE_PORT_FDB_LEARNING_MODE_CPU_LOG, - /** Notify unknown source MAC using FDB callback. Do not learn in hardware. Do not forward. - * When a packet from unknown source MAC comes this mode will trigger a new learn notification - * via FDB callback for the MAC address. This mode will generate only one notification - * per unknown source MAC to FDB callback. - */ + /** + * @brief Notify unknown source MAC using FDB callback. + * + * Do not learn in hardware. Do not forward. When a packet from unknown + * source MAC comes this mode will trigger a new learn notification via FDB + * callback for the MAC address. This mode will generate only one + * notification per unknown source MAC to FDB callback. + */ SAI_BRIDGE_PORT_FDB_LEARNING_MODE_FDB_NOTIFICATION, } sai_bridge_port_fdb_learning_mode_t; @@ -67,26 +70,26 @@ typedef enum _sai_bridge_port_fdb_learning_mode_t */ typedef enum _sai_bridge_port_type_t { - /** Port or Lag */ + /** Port or Lag */ SAI_BRIDGE_PORT_TYPE_PORT, - /** {Port or Lag.vlan} */ + /** {Port or Lag.vlan} */ SAI_BRIDGE_PORT_TYPE_SUB_PORT, - /** bridge router port */ + /** bridge router port */ SAI_BRIDGE_PORT_TYPE_1Q_ROUTER, - /** bridge router port */ + /** bridge router port */ SAI_BRIDGE_PORT_TYPE_1D_ROUTER, - /** bridge tunnel port */ + /** bridge tunnel port */ SAI_BRIDGE_PORT_TYPE_TUNNEL, } sai_bridge_port_type_t; /** -* @brief SAI attributes for Bridge Port -*/ + * @brief SAI attributes for Bridge Port + */ typedef enum _sai_bridge_port_attr_t { /** @@ -106,8 +109,8 @@ typedef enum _sai_bridge_port_attr_t * @brief Associated Port or Lag object id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_PORT or SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_SUB_PORT */ SAI_BRIDGE_PORT_ATTR_PORT_ID, @@ -117,19 +120,20 @@ typedef enum _sai_bridge_port_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY - * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_SUB_PORT * @isvlan true + * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_SUB_PORT */ SAI_BRIDGE_PORT_ATTR_VLAN_ID, /** * @brief Associated router inerface object id + * * Please note that for SAI_BRIDGE_PORT_TYPE_1Q_ROUTER, * all vlan interfaces are auto bounded for the bridge port. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_1D_ROUTER */ SAI_BRIDGE_PORT_ATTR_RIF_ID, @@ -138,8 +142,8 @@ typedef enum _sai_bridge_port_attr_t * @brief Associated tunnel id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_TUNNEL * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_TUNNEL */ SAI_BRIDGE_PORT_ATTR_TUNNEL_ID, @@ -148,8 +152,8 @@ typedef enum _sai_bridge_port_attr_t * @brief Associated bridge id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BRIDGE * @condition SAI_BRIDGE_PORT_ATTR_TYPE == SAI_BRIDGE_PORT_TYPE_1D_ROUTER */ SAI_BRIDGE_PORT_ATTR_BRIDGE_ID, @@ -195,7 +199,6 @@ typedef enum _sai_bridge_port_attr_t } sai_bridge_port_attr_t; - /** * @brief Create bridge port * @@ -207,10 +210,10 @@ typedef enum _sai_bridge_port_attr_t * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_create_bridge_port_fn)( - _Out_ sai_object_id_t* bridge_port_id, - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); + _Out_ sai_object_id_t* bridge_port_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove bridge port @@ -220,7 +223,7 @@ typedef sai_status_t(*sai_create_bridge_port_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_remove_bridge_port_fn) ( - _In_ sai_object_id_t bridge_port_id); + _In_ sai_object_id_t bridge_port_id); /** * @brief Set attribute for bridge port @@ -231,8 +234,8 @@ typedef sai_status_t(*sai_remove_bridge_port_fn) ( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_set_bridge_port_attribute_fn)( - _In_ sai_object_id_t bridge_port_id, - _In_ const sai_attribute_t *attr); + _In_ sai_object_id_t bridge_port_id, + _In_ const sai_attribute_t *attr); /** * @brief Get attributes of bridge port @@ -244,9 +247,9 @@ typedef sai_status_t(*sai_set_bridge_port_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_get_bridge_port_attribute_fn)( - _In_ sai_object_id_t bridge_port_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list); + _In_ sai_object_id_t bridge_port_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** * @brief Attribute data for #SAI_BRIDGE_ATTR_TYPE @@ -283,8 +286,8 @@ typedef enum _sai_bridge_attr_t * @brief List of bridge ports associated to this bridge * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT */ SAI_BRIDGE_ATTR_PORT_LIST, @@ -332,11 +335,10 @@ typedef enum _sai_bridge_attr_t * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_create_bridge_fn)( - _Out_ sai_object_id_t* bridge_id, - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list - ); + _Out_ sai_object_id_t* bridge_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove bridge @@ -346,8 +348,7 @@ typedef sai_status_t(*sai_create_bridge_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_remove_bridge_fn) ( - _In_ sai_object_id_t bridge_id - ); + _In_ sai_object_id_t bridge_id); /** * @brief Set attribute for bridge @@ -358,8 +359,8 @@ typedef sai_status_t(*sai_remove_bridge_fn) ( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_set_bridge_attribute_fn)( - _In_ sai_object_id_t bridge_id, - _In_ const sai_attribute_t *attr); + _In_ sai_object_id_t bridge_id, + _In_ const sai_attribute_t *attr); /** * @brief Get attributes of bridge @@ -371,13 +372,13 @@ typedef sai_status_t(*sai_set_bridge_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t(*sai_get_bridge_attribute_fn)( - _In_ sai_object_id_t bridge_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list); + _In_ sai_object_id_t bridge_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** -* @brief bridge methods table retrieved with sai_api_query() -*/ + * @brief bridge methods table retrieved with sai_api_query() + */ typedef struct _sai_bridge_api_t { sai_create_bridge_fn create_bridge; diff --git a/inc/saibuffer.h b/inc/saibuffer.h index 4668d3208..0158d3835 100644 --- a/inc/saibuffer.h +++ b/inc/saibuffer.h @@ -45,11 +45,12 @@ typedef enum _sai_ingress_priority_group_attr_t /** * @brief Buffer profile pointer + * * Default no profile * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -99,6 +100,32 @@ typedef enum _sai_ingress_priority_group_stat_t } sai_ingress_priority_group_stat_t; +/** + * @brief Create ingress priority group + * + * @param[out] ingress_pg_id Ingress priority group + * @param[in] switch_id Switch id + * @param[in] attr_count Number of attributes + * @param[in] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t(*sai_create_ingress_priority_group_fn)( + _Out_ sai_object_id_t* ingress_pg_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Remove ingress priority group + * + * @param[in] ingress_pg_id Ingress priority group + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t(*sai_remove_ingress_priority_group_fn)( + _In_ sai_object_id_t ingress_pg_id); + /** * @brief Set ingress priority group attribute * @@ -107,7 +134,7 @@ typedef enum _sai_ingress_priority_group_stat_t * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_set_ingress_priority_group_attr_fn)( +typedef sai_status_t(*sai_set_ingress_priority_group_attribute_fn)( _In_ sai_object_id_t ingress_pg_id, _In_ const sai_attribute_t *attr); @@ -120,7 +147,7 @@ typedef sai_status_t(*sai_set_ingress_priority_group_attr_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_get_ingress_priority_group_attr_fn)( +typedef sai_status_t(*sai_get_ingress_priority_group_attribute_fn)( _In_ sai_object_id_t ingress_pg_id, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); @@ -227,9 +254,11 @@ typedef enum _sai_buffer_pool_attr_t */ SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE, - /** @brief shared headroom pool size in bytes for lossless traffic + /** + * @brief shared headroom pool size in bytes for lossless traffic * * Only valid for the ingress buffer pool + * * @type sai_uint32_t * @flags CREATE_AND_SET * @default 0 @@ -296,7 +325,7 @@ typedef sai_status_t(*sai_remove_buffer_pool_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_set_buffer_pool_attr_fn)( +typedef sai_status_t(*sai_set_buffer_pool_attribute_fn)( _In_ sai_object_id_t pool_id, _In_ const sai_attribute_t *attr); @@ -309,7 +338,7 @@ typedef sai_status_t(*sai_set_buffer_pool_attr_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_get_buffer_pool_attr_fn)( +typedef sai_status_t(*sai_get_buffer_pool_attribute_fn)( _In_ sai_object_id_t pool_id, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); @@ -378,8 +407,8 @@ typedef enum _sai_buffer_profile_attr_t * to priority group or queue buffer profile. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BUFFER_POOL * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BUFFER_POOL * @allownull true */ SAI_BUFFER_PROFILE_ATTR_POOL_ID = SAI_BUFFER_PROFILE_ATTR_START, @@ -453,7 +482,7 @@ typedef enum _sai_buffer_profile_attr_t * and the total buffer limit minus XON_OFFSET_TH, and available buffer in the PG buffer * is larger than the XOFF_TH. * The XON trigger condition is governed by: - * total buffer usage <= max(XON_TH, total buffer limit - XON_OFFSET_TH) + * total buffer usage <= max(XON_TH, total buffer limit - XON_OFFSET_TH) * * @type sai_uint32_t * @flags CREATE_AND_SET @@ -469,7 +498,7 @@ typedef enum _sai_buffer_profile_attr_t * and the total buffer limit minus XON_OFFSET_TH, and available buffer in the PG buffer * is larger than the XOFF_TH. * The XON trigger condition is governed by: - * total buffer usage <= max(XON_TH, total buffer limit - XON_OFFSET_TH) + * total buffer usage <= max(XON_TH, total buffer limit - XON_OFFSET_TH) * * @type sai_uint32_t * @flags CREATE_AND_SET @@ -518,7 +547,7 @@ typedef sai_status_t(*sai_remove_buffer_profile_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_set_buffer_profile_attr_fn)( +typedef sai_status_t(*sai_set_buffer_profile_attribute_fn)( _In_ sai_object_id_t buffer_profile_id, _In_ const sai_attribute_t *attr); @@ -531,34 +560,35 @@ typedef sai_status_t(*sai_set_buffer_profile_attr_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_get_buffer_profile_attr_fn)( +typedef sai_status_t(*sai_get_buffer_profile_attribute_fn)( _In_ sai_object_id_t buffer_profile_id, _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _Inout_ sai_attribute_t *attr_list); /** * @brief buffer methods table retrieved with sai_api_query() */ typedef struct _sai_buffer_api_t { - sai_create_buffer_pool_fn create_buffer_pool; - sai_remove_buffer_pool_fn remove_buffer_pool; - sai_set_buffer_pool_attr_fn set_buffer_pool_attr; - sai_get_buffer_pool_attr_fn get_buffer_pool_attr; - sai_get_buffer_pool_stats_fn get_buffer_pool_stats; - sai_clear_buffer_pool_stats_fn clear_buffer_pool_stats; - sai_set_ingress_priority_group_attr_fn set_ingress_priority_group_attr; - sai_get_ingress_priority_group_attr_fn get_ingress_priority_group_attr; - sai_get_ingress_priority_group_stats_fn get_ingress_priority_group_stats; - sai_clear_ingress_priority_group_stats_fn clear_ingress_priority_group_stats; - sai_create_buffer_profile_fn create_buffer_profile; - sai_remove_buffer_profile_fn remove_buffer_profile; - sai_set_buffer_profile_attr_fn set_buffer_profile_attr; - sai_get_buffer_profile_attr_fn get_buffer_profile_attr; + sai_create_buffer_pool_fn create_buffer_pool; + sai_remove_buffer_pool_fn remove_buffer_pool; + sai_set_buffer_pool_attribute_fn set_buffer_pool_attribute; + sai_get_buffer_pool_attribute_fn get_buffer_pool_attribute; + sai_get_buffer_pool_stats_fn get_buffer_pool_stats; + sai_clear_buffer_pool_stats_fn clear_buffer_pool_stats; + sai_create_ingress_priority_group_fn create_ingress_priority_group; + sai_remove_ingress_priority_group_fn remove_ingress_priority_group; + sai_set_ingress_priority_group_attribute_fn set_ingress_priority_group_attribute; + sai_get_ingress_priority_group_attribute_fn get_ingress_priority_group_attribute; + sai_get_ingress_priority_group_stats_fn get_ingress_priority_group_stats; + sai_clear_ingress_priority_group_stats_fn clear_ingress_priority_group_stats; + sai_create_buffer_profile_fn create_buffer_profile; + sai_remove_buffer_profile_fn remove_buffer_profile; + sai_set_buffer_profile_attribute_fn set_buffer_profile_attribute; + sai_get_buffer_profile_attribute_fn get_buffer_profile_attribute; } sai_buffer_api_t; /** - *@} + * @} */ #endif /** __SAIBUFFER_H_ */ diff --git a/inc/saifdb.h b/inc/saifdb.h index 85c280842..9a5c681ed 100644 --- a/inc/saifdb.h +++ b/inc/saifdb.h @@ -68,7 +68,7 @@ typedef struct _sai_fdb_entry_t sai_vlan_id_t vlan_id; /** - * Bridge ID. Valid for .1D + * @brief Bridge ID. Valid for .1D * * @objects SAI_OBJECT_TYPE_BRIDGE */ @@ -108,7 +108,6 @@ typedef enum _sai_fdb_entry_attr_t /** * @brief FDB entry type * - * * @type sai_fdb_entry_type_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET */ @@ -127,15 +126,15 @@ typedef enum _sai_fdb_entry_attr_t * @brief FDB entry bridge port id * * The port id is only effective when the packet action is one of the following: - * FORWARD, COPY, LOG, TRANSIT + * FORWARD, COPY, LOG, TRANSIT * * When it is SAI_NULL_OBJECT_ID, then packet will be dropped. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT - * @default SAI_NULL_OBJECT_ID * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID, @@ -150,6 +149,15 @@ typedef enum _sai_fdb_entry_attr_t */ SAI_FDB_ENTRY_ATTR_META_DATA, + /** + * @brief Tunnel Endpoint IP. valid for SAI_BRIDGE_PORT_TYPE_TUNNEL + * + * @type sai_ip_address_t + * @flags CREATE_AND_SET + * @default 0.0.0.0 + */ + SAI_FDB_ENTRY_ATTR_ENDPOINT_IP, + /** * @brief End of attributes */ @@ -203,8 +211,8 @@ typedef enum _sai_fdb_flush_attr_t * @brief Flush based on bridge port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @flags CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @allownull true * @default SAI_NULL_OBJECT_ID */ diff --git a/inc/saihash.h b/inc/saihash.h index ad12d47d3..67f8eb21c 100644 --- a/inc/saihash.h +++ b/inc/saihash.h @@ -107,8 +107,8 @@ typedef enum _sai_hash_attr_t * @brief Hash UDF group * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_UDF_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_UDF_GROUP * @default empty */ SAI_HASH_ATTR_UDF_GROUP_LIST, diff --git a/inc/saihostintf.h b/inc/saihostif.h similarity index 81% rename from inc/saihostintf.h rename to inc/saihostif.h index b1568b133..1f4f636f2 100644 --- a/inc/saihostintf.h +++ b/inc/saihostif.h @@ -17,7 +17,7 @@ * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, * Dell Products, L.P., Facebook, Inc * - * @file saihostintf.h + * @file saihostif.h * * @brief This module defines SAI host interface * @@ -78,8 +78,8 @@ typedef enum _sai_hostif_trap_group_attr_t * @brief Sai policer object id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -245,7 +245,7 @@ typedef enum _sai_hostif_trap_type_t SAI_HOSTIF_TRAP_TYPE_MLD_V2_REPORT = 0x0000200d, /** - * Unknown L3 multicast packets + * @brief Unknown L3 multicast packets * (default packet action is drop) */ SAI_HOSTIF_TRAP_TYPE_UNKNOWN_L3_MULTICAST = 0x0000200e, @@ -275,15 +275,15 @@ typedef enum _sai_hostif_trap_type_t SAI_HOSTIF_TRAP_TYPE_SNMP = 0x00004002, /** - * @brief BGP traffic (tcp src port == 179 or tcp dst port == 179) to local - * router IP address (default packet action is drop) - */ + * @brief BGP traffic (tcp src port == 179 or tcp dst port == 179) to local + * router IP address (default packet action is drop) + */ SAI_HOSTIF_TRAP_TYPE_BGP = 0x00004003, /** - * @brief BGPv6 traffic (tcp src port == 179 or tcp dst port == 179) to - * local router IP address (default packet action is drop) - */ + * @brief BGPv6 traffic (tcp src port == 179 or tcp dst port == 179) to + * local router IP address (default packet action is drop) + */ SAI_HOSTIF_TRAP_TYPE_BGPV6 = 0x00004004, /** Local IP traps custom range start */ @@ -324,7 +324,7 @@ typedef enum _sai_hostif_trap_attr_t SAI_HOSTIF_TRAP_ATTR_START, /** - * @brief Host interface trap type [] + * @brief Host interface trap type * * @type sai_hostif_trap_type_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY | KEY @@ -335,17 +335,10 @@ typedef enum _sai_hostif_trap_attr_t * @brief Trap action * * @type sai_packet_action_t - * @flags CREATE_AND_SET | MANDATORY_ON_CREATE + * @flags MANDATORY_ON_CREATE | CREATE_AND_SET */ SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION, - /* - * Below attributes are only valid when - * - * SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_TRAP or - * SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_LOG - */ - /** * @brief Trap priority. This is equivalent to ACL entry priority * #SAI_ACL_ENTRY_ATTR_PRIORITY @@ -353,6 +346,7 @@ typedef enum _sai_hostif_trap_attr_t * @type sai_uint32_t * @flags CREATE_AND_SET * @default attrvalue SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY + * @validonly SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_TRAP or SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_LOG */ SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY, @@ -360,9 +354,10 @@ typedef enum _sai_hostif_trap_attr_t * @brief List of SAI ports to be excluded (disabled) from the trap generation * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT * @default empty + * @validonly SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_TRAP or SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_LOG */ SAI_HOSTIF_TRAP_ATTR_EXCLUDE_PORT_LIST, @@ -370,9 +365,10 @@ typedef enum _sai_hostif_trap_attr_t * @brief Trap-group ID for the trap * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP * @default attrvalue SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP + * @validonly SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_TRAP or SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_LOG */ SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP, @@ -442,8 +438,8 @@ typedef sai_status_t(*sai_get_hostif_trap_attribute_fn)( _Inout_ sai_attribute_t *attr_list); /** -* @brief Host interface user defined trap type -*/ + * @brief Host interface user defined trap type + */ typedef enum _sai_hostif_user_defined_trap_type_t { /** @@ -484,7 +480,8 @@ typedef enum _sai_hostif_user_defined_trap_attr_t SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_START, /** - * @brief Host interface user defined trap type []. + * @brief Host interface user defined trap type + * * It is valid to create multiple instances of the same user defined type * * @type sai_hostif_user_defined_trap_type_t @@ -506,8 +503,8 @@ typedef enum _sai_hostif_user_defined_trap_attr_t * @brief Trap-group ID for the trap * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP * @default attrvalue SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP */ SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TRAP_GROUP, @@ -617,8 +614,8 @@ typedef enum _sai_hostif_attr_t * VLAN netdev will be created when object type is SAI_OBJECT_TYPE_VLAN * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_VLAN * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_VLAN * @condition SAI_HOSTIF_ATTR_TYPE == SAI_HOSTIF_TYPE_NETDEV */ SAI_HOSTIF_ATTR_OBJ_ID, @@ -721,8 +718,8 @@ typedef sai_status_t(*sai_get_hostif_attribute_fn)( _Inout_ sai_attribute_t *attr_list); /** -* @brief Attribute data for SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE -*/ + * @brief Attribute data for SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE + */ typedef enum _sai_hostif_table_entry_type_t { /** Port-based Host Interface entry Type */ @@ -743,8 +740,8 @@ typedef enum _sai_hostif_table_entry_type_t } sai_hostif_table_entry_type_t; /** -* @brief Attribute data for SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE -*/ + * @brief Attribute data for SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE + */ typedef enum _sai_hostif_table_entry_channel_type_t { /** receive packets via callback */ @@ -765,74 +762,76 @@ typedef enum _sai_hostif_table_entry_channel_type_t } sai_hostif_table_entry_channel_type_t; /** -* @brief Host interface table entry attribute IDs -*/ + * @brief Host interface table entry attribute IDs + */ typedef enum _sai_hostif_table_entry_attr_t { /** - * @brief Start of attributes - */ + * @brief Start of attributes + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_START, /** - * @brief Host interface table entry type - * - * @type sai_hostif_table_entry_type_t - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - */ + * @brief Host interface table entry type + * + * @type sai_hostif_table_entry_type_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE = SAI_HOSTIF_ATTR_START, /** - * @brief Host interface table entry match field object-id - * - * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == #SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT - * || #SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG || #SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN - * should be port object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT - * should be lag object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG - * should be VLAN ID object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN - * - * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_ROUTER_INTERFACE - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG - */ + * @brief Host interface table entry match field object-id + * + * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == #SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT + * || #SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG || #SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN + * should be port object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT + * should be lag object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG + * should be VLAN ID object when type is SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_ROUTER_INTERFACE + * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_OBJ_ID, /** - * @brief Host interface table entry match field trap-id - * - * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == #SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT || - * #SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG || #SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN || - * #SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID - * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP, SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID - */ + * @brief Host interface table entry match field trap-id + * + * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == #SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT || + * #SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG || #SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN || + * #SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP, SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP + * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_PORT or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_VLAN or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_LAG or SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE == SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID, /** - * @brief Host interface table entry action channel - * - * @type sai_hostif_table_entry_channel_type_t - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - */ + * @brief Host interface table entry action channel + * + * @type sai_hostif_table_entry_channel_type_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE, /** - * @brief Host interface table entry action target host interface object - * - * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE = #SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_FD - * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE == SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_FD - */ + * @brief Host interface table entry action target host interface object + * + * Valid only when #SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE = #SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_FD + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_HOSTIF + * @condition SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE == SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_FD + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF, /** - * @brief Rnd of attributes - */ + * @brief Rnd of attributes + */ SAI_HOSTIF_TABLE_ENTRY_ATTR_END, /** Custom range base value */ @@ -844,56 +843,56 @@ typedef enum _sai_hostif_table_entry_attr_t } sai_hostif_table_entry_attr_t; /** -* @brief Create host interface table entry -* -* @param[out] hif_table_entry Host interface table entry -* @param[in] switch_id Switch object id -* @param[in] attr_count Number of attributes -* @param[in] attr_list Aarray of attributes -* -* @return #SAI_STATUS_SUCCESS on success Failure status code on error -*/ + * @brief Create host interface table entry + * + * @param[out] hif_table_entry Host interface table entry + * @param[in] switch_id Switch object id + * @param[in] attr_count Number of attributes + * @param[in] attr_list Aarray of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ typedef sai_status_t(*sai_create_hostif_table_entry_fn)( - _Out_ sai_object_id_t *hif_table_entry, - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); + _Out_ sai_object_id_t *hif_table_entry, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** -* @brief Remove host interface table entry -* -* @param[in] hif_table_entry - host interface table entry -* -* @return #SAI_STATUS_SUCCESS on success Failure status code on error -*/ + * @brief Remove host interface table entry + * + * @param[in] hif_table_entry - host interface table entry + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ typedef sai_status_t(*sai_remove_hostif_table_entry_fn)( - _In_ sai_object_id_t hif_table_entry); + _In_ sai_object_id_t hif_table_entry); /** -* @brief Set host interface table entry attribute -* -* @param[in] hif_table_entry - host interface table entry -* @param[in] attr Attribute -* -* @return #SAI_STATUS_SUCCESS on success Failure status code on error -*/ + * @brief Set host interface table entry attribute + * + * @param[in] hif_table_entry - host interface table entry + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ typedef sai_status_t(*sai_set_hostif_table_entry_attribute_fn)( - _In_ sai_object_id_t hif_table_entry, - _In_ const sai_attribute_t *attr); + _In_ sai_object_id_t hif_table_entry, + _In_ const sai_attribute_t *attr); /** -* @brief Get host interface table entry attribute -* -* @param[in] hif_table_entry - host interface table entry -* @param[in] attr_count Number of attributes -* @param[inout] attr_list Array of attributes -* -* @return #SAI_STATUS_SUCCESS on success Failure status code on error -*/ + * @brief Get host interface table entry attribute + * + * @param[in] hif_table_entry - host interface table entry + * @param[in] attr_count Number of attributes + * @param[inout] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ typedef sai_status_t(*sai_get_hostif_table_entry_attribute_fn)( - _In_ sai_object_id_t hif_table_entry, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list); + _In_ sai_object_id_t hif_table_entry, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** * @brief Host interface TX type @@ -928,8 +927,8 @@ typedef enum _sai_hostif_packet_attr_t * @brief Trap ID (for receive-only) * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP, SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP, SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP */ SAI_HOSTIF_PACKET_ATTR_HOSTIF_TRAP_ID = SAI_HOSTIF_PACKET_ATTR_START, @@ -937,8 +936,8 @@ typedef enum _sai_hostif_packet_attr_t * @brief Ingress port (for receive-only) * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_PORT */ SAI_HOSTIF_PACKET_ATTR_INGRESS_PORT, @@ -946,8 +945,8 @@ typedef enum _sai_hostif_packet_attr_t * @brief Ingress LAG (for receive-only) * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_LAG * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_LAG */ SAI_HOSTIF_PACKET_ATTR_INGRESS_LAG, @@ -961,13 +960,14 @@ typedef enum _sai_hostif_packet_attr_t /** * @brief Egress port + * * For receive case, filled with the egress destination port for unicast packets. * Egress LAG member port id to be filled for the LAG destination case. * Applicable for use-case like SAMPLEPACKET traps * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT * @condition SAI_HOSTIF_PACKET_ATTR_HOSTIF_TX_TYPE == SAI_HOSTIF_TX_TYPE_PIPELINE_BYPASS */ SAI_HOSTIF_PACKET_ATTR_EGRESS_PORT_OR_LAG, @@ -1051,18 +1051,18 @@ typedef struct _sai_hostif_api_t sai_get_hostif_table_entry_attribute_fn get_hostif_table_entry_attribute; sai_create_hostif_trap_group_fn create_hostif_trap_group; sai_remove_hostif_trap_group_fn remove_hostif_trap_group; - sai_set_hostif_trap_group_attribute_fn set_trap_group_attribute; - sai_get_hostif_trap_group_attribute_fn get_trap_group_attribute; - sai_create_hostif_trap_fn create_trap; - sai_remove_hostif_trap_fn remove_trap; - sai_set_hostif_trap_attribute_fn set_trap_attribute; - sai_get_hostif_trap_attribute_fn get_trap_attribute; - sai_create_hostif_user_defined_trap_fn create_user_defined_trap; - sai_remove_hostif_user_defined_trap_fn remove_user_defined_trap; - sai_set_hostif_user_defined_trap_attribute_fn set_user_defined_trap_attribute; - sai_get_hostif_user_defined_trap_attribute_fn get_user_defined_trap_attribute; - sai_recv_hostif_packet_fn recv_packet; - sai_send_hostif_packet_fn send_packet; + sai_set_hostif_trap_group_attribute_fn set_hostif_trap_group_attribute; + sai_get_hostif_trap_group_attribute_fn get_hostif_trap_group_attribute; + sai_create_hostif_trap_fn create_hostif_trap; + sai_remove_hostif_trap_fn remove_hostif_trap; + sai_set_hostif_trap_attribute_fn set_hostif_trap_attribute; + sai_get_hostif_trap_attribute_fn get_hostif_trap_attribute; + sai_create_hostif_user_defined_trap_fn create_hostif_user_defined_trap; + sai_remove_hostif_user_defined_trap_fn remove_hostif_user_defined_trap; + sai_set_hostif_user_defined_trap_attribute_fn set_hostif_user_defined_trap_attribute; + sai_get_hostif_user_defined_trap_attribute_fn get_hostif_user_defined_trap_attribute; + sai_recv_hostif_packet_fn recv_hostif_packet; + sai_send_hostif_packet_fn send_hostif_packet; } sai_hostif_api_t; /** diff --git a/inc/saiipmc.h b/inc/saiipmc.h index d89d88d59..c208075fe 100644 --- a/inc/saiipmc.h +++ b/inc/saiipmc.h @@ -100,8 +100,8 @@ typedef enum _sai_ipmc_entry_attr_t * If the group has no member, packets will be discarded * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_IPMC_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_IPMC_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID * @validonly SAI_IPMC_ENTRY_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_FORWARD @@ -114,8 +114,8 @@ typedef enum _sai_ipmc_entry_attr_t * If not set or the group has no member, RPF checking will be disabled * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_RPF_GROUP * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_RPF_GROUP */ SAI_IPMC_ENTRY_ATTR_RPF_GROUP_ID, @@ -127,7 +127,7 @@ typedef enum _sai_ipmc_entry_attr_t /* Custom range base value */ SAI_IPMC_ENTRY_ATTR_CUSTOM_RANGE_BASE = 0x10000000, - /* --*/ + /* -- */ SAI_IPMC_ENTRY_ATTR_CUSTOM_RANGE_END } sai_ipmc_entry_attr_t; diff --git a/inc/saiipmcgroup.h b/inc/saiipmcgroup.h index 467551044..b53b98550 100644 --- a/inc/saiipmcgroup.h +++ b/inc/saiipmcgroup.h @@ -53,9 +53,10 @@ typedef enum _sai_ipmc_group_attr_t /** * @brief IPMC member list + * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER */ SAI_IPMC_GROUP_ATTR_IPMC_MEMBER_LIST, @@ -81,17 +82,19 @@ typedef enum _sai_ipmc_group_member_attr_t /** * @brief IPMC group id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_IPMC_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_IPMC_GROUP */ SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_GROUP_ID = SAI_IPMC_GROUP_MEMBER_ATTR_START, /** * @brief IPMC output id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_TUNNEL * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_TUNNEL */ SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_OUTPUT_ID, @@ -170,10 +173,10 @@ typedef sai_status_t (*sai_get_ipmc_group_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_create_ipmc_group_member_fn)( - _Out_ sai_object_id_t* ipmc_group_member_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list - ); + _Out_ sai_object_id_t* ipmc_group_member_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove IPMC group member @@ -183,8 +186,7 @@ typedef sai_status_t (*sai_create_ipmc_group_member_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_remove_ipmc_group_member_fn)( - _In_ sai_object_id_t ipmc_group_member_id - ); + _In_ sai_object_id_t ipmc_group_member_id); /** * @brief Set IPMC Group attribute @@ -195,9 +197,8 @@ typedef sai_status_t (*sai_remove_ipmc_group_member_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_set_ipmc_group_member_attribute_fn)( - _In_ sai_object_id_t ipmc_group_member_id, - _In_ const sai_attribute_t *attr - ); + _In_ sai_object_id_t ipmc_group_member_id, + _In_ const sai_attribute_t *attr); /** * @brief Get IPMC Group attribute @@ -209,13 +210,12 @@ typedef sai_status_t (*sai_set_ipmc_group_member_attribute_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_get_ipmc_group_member_attribute_fn)( - _In_ sai_object_id_t ipmc_group_member_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _In_ sai_object_id_t ipmc_group_member_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** - * @brief IPMC group methods table retrieved with sai_api_query() + * @brief IPMC group methods table retrieved with sai_api_query() */ typedef struct _sai_ipmc_group_api_t { diff --git a/inc/sail2mc.h b/inc/sail2mc.h index 2dfc1b275..c18139203 100644 --- a/inc/sail2mc.h +++ b/inc/sail2mc.h @@ -65,7 +65,7 @@ typedef struct _sai_l2mc_entry_t sai_vlan_id_t vlan_id; /** - * Bridge ID. Valid for .1D + * @brief Bridge ID. Valid for .1D * * @objects SAI_OBJECT_TYPE_BRIDGE */ @@ -106,8 +106,8 @@ typedef enum _sai_l2mc_entry_attr_t * If the group has no member, packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID * @validonly SAI_L2MC_ENTRY_ATTR_PACKET_ACTION == SAI_PACKET_ACTION_FORWARD @@ -122,7 +122,7 @@ typedef enum _sai_l2mc_entry_attr_t /* Custom range base value */ SAI_L2MC_ENTRY_ATTR_CUSTOM_RANGE_BASE = 0x10000000, - /* --*/ + /* -- */ SAI_L2MC_ENTRY_ATTR_CUSTOM_RANGE_END } sai_l2mc_entry_attr_t; diff --git a/inc/sail2mcgroup.h b/inc/sail2mcgroup.h index 007c0db60..3850d11c2 100644 --- a/inc/sail2mcgroup.h +++ b/inc/sail2mcgroup.h @@ -53,9 +53,10 @@ typedef enum _sai_l2mc_group_attr_t /** * @brief L2MC member list + * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_L2MC_GROUP_MEMBER */ SAI_L2MC_GROUP_ATTR_L2MC_MEMBER_LIST, @@ -81,17 +82,19 @@ typedef enum _sai_l2mc_group_member_attr_t /** * @brief L2MC group id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_L2MC_GROUP */ SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_GROUP_ID = SAI_L2MC_GROUP_MEMBER_ATTR_START, /** * @brief L2MC output id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT */ SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_OUTPUT_ID, @@ -170,10 +173,10 @@ typedef sai_status_t (*sai_get_l2mc_group_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_create_l2mc_group_member_fn)( - _Out_ sai_object_id_t* l2mc_group_member_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list - ); + _Out_ sai_object_id_t* l2mc_group_member_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove L2MC group member @@ -183,8 +186,7 @@ typedef sai_status_t (*sai_create_l2mc_group_member_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_remove_l2mc_group_member_fn)( - _In_ sai_object_id_t l2mc_group_member_id - ); + _In_ sai_object_id_t l2mc_group_member_id); /** * @brief Set L2MC Group attribute @@ -195,9 +197,8 @@ typedef sai_status_t (*sai_remove_l2mc_group_member_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_set_l2mc_group_member_attribute_fn)( - _In_ sai_object_id_t l2mc_group_member_id, - _In_ const sai_attribute_t *attr - ); + _In_ sai_object_id_t l2mc_group_member_id, + _In_ const sai_attribute_t *attr); /** * @brief Get L2MC Group attribute @@ -209,13 +210,12 @@ typedef sai_status_t (*sai_set_l2mc_group_member_attribute_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_get_l2mc_group_member_attribute_fn)( - _In_ sai_object_id_t l2mc_group_member_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _In_ sai_object_id_t l2mc_group_member_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** - * @brief L2MC group methods table retrieved with sai_api_query() + * @brief L2MC group methods table retrieved with sai_api_query() */ typedef struct _sai_l2mc_group_api_t { diff --git a/inc/sailag.h b/inc/sailag.h index f318a1aed..678463fae 100644 --- a/inc/sailag.h +++ b/inc/sailag.h @@ -47,8 +47,8 @@ typedef enum _sai_lag_attr_t * @brief SAI port list * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_LAG_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_LAG_MEMBER */ SAI_LAG_ATTR_PORT_LIST = SAI_LAG_ATTR_START, @@ -63,8 +63,8 @@ typedef enum _sai_lag_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -79,8 +79,8 @@ typedef enum _sai_lag_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -165,8 +165,8 @@ typedef enum _sai_lag_member_attr_t * @brief LAG ID * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_LAG * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_LAG */ SAI_LAG_MEMBER_ATTR_LAG_ID = SAI_LAG_MEMBER_ATTR_START, @@ -174,8 +174,8 @@ typedef enum _sai_lag_member_attr_t * @brief Logical port ID * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT */ SAI_LAG_MEMBER_ATTR_PORT_ID, diff --git a/inc/saimcfdb.h b/inc/saimcastfdb.h similarity index 99% rename from inc/saimcfdb.h rename to inc/saimcastfdb.h index 5da2d7fdc..304a4a9c9 100644 --- a/inc/saimcfdb.h +++ b/inc/saimcastfdb.h @@ -17,7 +17,7 @@ * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, * Dell Products, L.P., Facebook, Inc * - * @file saimcfdb.h + * @file saimcastfdb.h * * @brief This module defines SAI multicast FDB interface */ @@ -70,8 +70,8 @@ typedef enum _sai_mcast_fdb_entry_attr_t * packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_L2MC_GROUP */ SAI_MCAST_FDB_ENTRY_ATTR_GROUP_ID = SAI_MCAST_FDB_ENTRY_ATTR_START, diff --git a/inc/saimirror.h b/inc/saimirror.h index a32468089..d23f9abf5 100644 --- a/inc/saimirror.h +++ b/inc/saimirror.h @@ -83,8 +83,8 @@ typedef enum _sai_mirror_session_attr_t * @brief Destination/Analyser/Monitor Port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT */ SAI_MIRROR_SESSION_ATTR_MONITOR_PORT, @@ -95,6 +95,7 @@ typedef enum _sai_mirror_session_attr_t * * @type sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false * @default 0 */ SAI_MIRROR_SESSION_ATTR_TRUNCATE_SIZE, @@ -115,6 +116,7 @@ typedef enum _sai_mirror_session_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @isvlan false * @condition SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE or SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_REMOTE */ SAI_MIRROR_SESSION_ATTR_VLAN_TPID, @@ -124,8 +126,8 @@ typedef enum _sai_mirror_session_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET - * @condition SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE or SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_REMOTE * @isvlan true + * @condition SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE or SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_REMOTE */ SAI_MIRROR_SESSION_ATTR_VLAN_ID, @@ -180,7 +182,7 @@ typedef enum _sai_mirror_session_attr_t SAI_MIRROR_SESSION_ATTR_TOS, /** - * Tunnel header TTL + * @brief Tunnel header TTL * * @type sai_uint8_t * @flags CREATE_AND_SET @@ -229,6 +231,7 @@ typedef enum _sai_mirror_session_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @isvlan false * @condition SAI_MIRROR_SESSION_ATTR_TYPE == SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE */ SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE, diff --git a/inc/saineighbor.h b/inc/saineighbor.h index c6a2d3d79..588b33e63 100644 --- a/inc/saineighbor.h +++ b/inc/saineighbor.h @@ -68,8 +68,10 @@ typedef enum _sai_neighbor_entry_attr_t /** * @brief Neighbor not to be programmed as a host route entry in ASIC and - * to be only used to setup next-hop purpose. Typical use-case is to set - * this true for neighbor with IPv6 link-local addresses. + * to be only used to setup next-hop purpose. + * + * Typical use-case is to set this true for neighbor with IPv6 link-local + * addresses. * * @type bool * @flags CREATE_AND_SET @@ -163,7 +165,7 @@ typedef sai_status_t (*sai_remove_neighbor_entry_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_set_neighbor_attribute_fn)( +typedef sai_status_t (*sai_set_neighbor_entry_attribute_fn)( _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ const sai_attribute_t *attr); @@ -176,7 +178,7 @@ typedef sai_status_t (*sai_set_neighbor_attribute_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_get_neighbor_attribute_fn)( +typedef sai_status_t (*sai_get_neighbor_entry_attribute_fn)( _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); @@ -191,14 +193,14 @@ typedef sai_status_t (*sai_remove_all_neighbor_entries_fn)( _In_ sai_object_id_t switch_id); /** - * @brief neighbor table methods, retrieved via sai_api_query() + * @brief neighbor table methods, retrieved via sai_api_query() */ typedef struct _sai_neighbor_api_t { sai_create_neighbor_entry_fn create_neighbor_entry; sai_remove_neighbor_entry_fn remove_neighbor_entry; - sai_set_neighbor_attribute_fn set_neighbor_attribute; - sai_get_neighbor_attribute_fn get_neighbor_attribute; + sai_set_neighbor_entry_attribute_fn set_neighbor_entry_attribute; + sai_get_neighbor_entry_attribute_fn get_neighbor_entry_attribute; sai_remove_all_neighbor_entries_fn remove_all_neighbor_entries; } sai_neighbor_api_t; diff --git a/inc/sainexthop.h b/inc/sainexthop.h index de40163ea..b833a502c 100644 --- a/inc/sainexthop.h +++ b/inc/sainexthop.h @@ -80,8 +80,8 @@ typedef enum _sai_next_hop_attr_t * @brief Next hop entry router interface id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE */ SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID, @@ -89,8 +89,8 @@ typedef enum _sai_next_hop_attr_t * @brief Next hop entry tunnel-id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_TUNNEL * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL * @condition SAI_NEXT_HOP_ATTR_TYPE == SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP */ SAI_NEXT_HOP_ATTR_TUNNEL_ID, diff --git a/inc/sainexthopgroup.h b/inc/sainexthopgroup.h index e8c545408..16cbb1590 100644 --- a/inc/sainexthopgroup.h +++ b/inc/sainexthopgroup.h @@ -65,9 +65,10 @@ typedef enum _sai_next_hop_group_attr_t /** * @brief Next hop member list + * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER */ SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_MEMBER_LIST, @@ -101,22 +102,25 @@ typedef enum _sai_next_hop_group_member_attr_t /** * @brief Next hop group id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP */ SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_START, /** * @brief Next hop id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_NEXT_HOP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_NEXT_HOP */ SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID, /** * @brief Member weights + * * @type sai_uint32_t * @flags CREATE_AND_SET * @default 1 @@ -198,11 +202,10 @@ typedef sai_status_t (*sai_get_next_hop_group_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_create_next_hop_group_member_fn)( - _Out_ sai_object_id_t* next_hop_group_member_id, - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list - ); + _Out_ sai_object_id_t* next_hop_group_member_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove next hop group member @@ -212,8 +215,7 @@ typedef sai_status_t (*sai_create_next_hop_group_member_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_remove_next_hop_group_member_fn)( - _In_ sai_object_id_t next_hop_group_member_id - ); + _In_ sai_object_id_t next_hop_group_member_id); /** * @brief Set Next Hop Group attribute @@ -224,10 +226,8 @@ typedef sai_status_t (*sai_remove_next_hop_group_member_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_set_next_hop_group_member_attribute_fn)( - _In_ sai_object_id_t next_hop_group_member_id, - _In_ const sai_attribute_t *attr - ); - + _In_ sai_object_id_t next_hop_group_member_id, + _In_ const sai_attribute_t *attr); /** * @brief Get Next Hop Group attribute @@ -239,13 +239,12 @@ typedef sai_status_t (*sai_set_next_hop_group_member_attribute_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_get_next_hop_group_member_attribute_fn)( - _In_ sai_object_id_t next_hop_group_member_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _In_ sai_object_id_t next_hop_group_member_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** - * @brief Next Hop methods table retrieved with sai_api_query() + * @brief Next Hop methods table retrieved with sai_api_query() */ typedef struct _sai_next_hop_group_api_t { diff --git a/inc/saiobject.h b/inc/saiobject.h index c0e15c0ad..e800eaee1 100644 --- a/inc/saiobject.h +++ b/inc/saiobject.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -113,23 +113,23 @@ sai_status_t sai_get_object_key( * @param[in] object_count Number of objects * @param[in] object_key List of object keys * @param[inout] attr_count List of attr_count. Caller passes the number - * of attribute allocated in. Callee returns with the actual - * number of attributes filled in. If the count is less than - * needed, callee fills with the needed count and do not fill - * the attributes. Callee also set the corresponding status to - * #SAI_STATUS_BUFFER_OVERFLOW. + * of attribute allocated in. Callee returns with the actual + * number of attributes filled in. If the count is less than + * needed, callee fills with the needed count and do not fill + * the attributes. Callee also set the corresponding status to + * #SAI_STATUS_BUFFER_OVERFLOW. * * @param[inout] attrs Nist of attributes for every object. Caller is - * responsible for allocating and freeing buffer for the attributes. - * For list based attribute, e.g., s32list, oidlist, callee should - * assume the caller has not allocate the memory for the list and - * should only to fill the count but not list. Then, caller - * can use corresponding get_attribute to get the list. + * responsible for allocating and freeing buffer for the attributes. + * For list based attribute, e.g., s32list, oidlist, callee should + * assume the caller has not allocate the memory for the list and + * should only to fill the count but not list. Then, caller + * can use corresponding get_attribute to get the list. * * @param[inout] object_statuses Status for each object. If the object does - * not exist, callee sets the correpsonding status to #SAI_STATUS_INVALID_OBJECT_ID. - * If the allocated attribute count is not large enough, - * set the status to #SAI_STATUS_BUFFER_OVERFLOW. + * not exist, callee sets the correpsonding status to #SAI_STATUS_INVALID_OBJECT_ID. + * If the allocated attribute count is not large enough, + * set the status to #SAI_STATUS_BUFFER_OVERFLOW. * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ diff --git a/inc/saipolicer.h b/inc/saipolicer.h index 2d2aa965b..c34cbeb3d 100644 --- a/inc/saipolicer.h +++ b/inc/saipolicer.h @@ -190,6 +190,7 @@ typedef enum _sai_policer_attr_t /** * @brief Enable/disable counter + * * Default disabled. Modify List Needs full new set * * @type sai_s32_list_t sai_packet_action_t @@ -321,13 +322,12 @@ typedef sai_status_t (*sai_get_policer_stats_fn)( * @param[in] counter_ids specifies the array of counter ids * * @return SAI_STATUS_SUCCESS on success - * Failure status code on error + * Failure status code on error */ typedef sai_status_t (*sai_clear_policer_stats_fn)( - _In_ sai_object_id_t policer_id, - _In_ uint32_t number_of_counters, - _In_ const sai_policer_stat_t *counter_ids - ); + _In_ sai_object_id_t policer_id, + _In_ uint32_t number_of_counters, + _In_ const sai_policer_stat_t *counter_ids); /** * @brief Policer methods table retrieved with sai_api_query() @@ -338,7 +338,7 @@ typedef struct _sai_policer_api_t sai_remove_policer_fn remove_policer; sai_set_policer_attribute_fn set_policer_attribute; sai_get_policer_attribute_fn get_policer_attribute; - sai_get_policer_stats_fn get_policer_statistics; + sai_get_policer_stats_fn get_policer_stats; sai_clear_policer_stats_fn clear_policer_stats; } sai_policer_api_t; diff --git a/inc/saiport.h b/inc/saiport.h index 05ae94ccb..bbb62e3a1 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -47,8 +47,8 @@ typedef enum _sai_port_type_t } sai_port_type_t; /** -* @brief Attribute data for #SAI_PORT_ATTR_BIND_MODE -*/ + * @brief Attribute data for #SAI_PORT_ATTR_BIND_MODE + */ typedef enum _sai_port_bind_mode_t { /** Port */ @@ -166,6 +166,21 @@ typedef enum _sai_port_breakout_mode_type_t SAI_PORT_BREAKOUT_MODE_TYPE_MAX } sai_port_breakout_mode_type_t; +/** + * @brief Attribute data for #SAI_PORT_ATTR_FEC_MODE + */ +typedef enum _sai_port_fec_mode_t +{ + /** No FEC */ + SAI_PORT_FEC_MODE_NONE, + + /** Enable RS-FEC - 25G, 50G, 100G ports */ + SAI_PORT_FEC_MODE_RS, + + /** Enable FC-FEC - 10G, 25G, 40G, 50G ports */ + SAI_PORT_FEC_MODE_FC, +} sai_port_fec_mode_t; + /** * @brief Attribute Id in sai_set_port_attribute() and * sai_get_port_attribute() calls @@ -198,7 +213,7 @@ typedef enum _sai_port_attr_t /** * @brief Breakout mode(s) supported * - * @type sai_s32_list_t + * @type sai_s32_list_t sai_port_breakout_mode_type_t * @flags READ_ONLY */ SAI_PORT_ATTR_SUPPORTED_BREAKOUT_MODE_TYPE, @@ -223,8 +238,8 @@ typedef enum _sai_port_attr_t * @brief List of Queues for the port * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_QUEUE * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_QUEUE */ SAI_PORT_ATTR_QOS_QUEUE_LIST, @@ -240,8 +255,8 @@ typedef enum _sai_port_attr_t * @brief List of Scheduler groups for the port * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP */ SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST, @@ -253,6 +268,14 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_SUPPORTED_SPEED, + /** + * @brief Query list of supported port FEC mode + * + * @type sai_s32_list_t sai_port_fec_mode_t + * @flags READ_ONLY + */ + SAI_PORT_ATTR_SUPPORTED_FEC_MODE, + /** * @brief Query list of Supported HALF-Duplex speed in Mbps * @@ -294,60 +317,20 @@ typedef enum _sai_port_attr_t SAI_PORT_ATTR_SUPPORTED_MEDIA_TYPE, /** - * @brief Query list of supported remote port speed (Full-Duplex) in Mbps - * - * @type sai_u32_list_t - * @flags READ_ONLY - */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_SPEED, - - /** - * @brief Query list of Remote Port's Supported HALF-Duplex speed in Mbps + * @brief Query list of Advertised remote port speed (Full-Duplex) in Mbps * * @type sai_u32_list_t * @flags READ_ONLY */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_HALF_DUPLEX_SPEED, - - /** - * @brief Query Remote Port's auto-negotiation support - * - * @type bool - * @flags READ_ONLY - */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_AUTO_NEG_MODE, - - /** - * @brief Query Remote port supported flow control mode - * - * @type sai_port_flow_control_mode_t - * @flags READ_ONLY - */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_FLOW_CONTROL_MODE, - - /** - * @brief Query Remote port supported asymmetric pause mode - * - * @type bool - * @flags READ_ONLY - */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_ASYMMETRIC_PAUSE_MODE, - - /** - * @brief Query Remote port MEDIA type - * - * @type sai_port_media_type_t - * @flags READ_ONLY - */ - SAI_PORT_ATTR_REMOTE_SUPPORTED_MEDIA_TYPE, + SAI_PORT_ATTR_REMOTE_ADVERTISED_SPEED, /** - * @brief Query list of Advertised remote port speed (Full-Duplex) in Mbps + * @brief Query list of Advertised remote port FEC control * - * @type sai_u32_list_t + * @type sai_s32_list_t sai_port_fec_mode_t * @flags READ_ONLY */ - SAI_PORT_ATTR_REMOTE_ADVERTISED_SPEED, + SAI_PORT_ATTR_REMOTE_ADVERTISED_FEC_MODE, /** * @brief Query list of Remote Port's Advertised HALF-Duplex speed in Mbps @@ -401,8 +384,8 @@ typedef enum _sai_port_attr_t * @brief list of ingress priority groups * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP */ SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST, @@ -469,6 +452,15 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_ADVERTISED_SPEED, + /** + * @brief Query/Configure list of Advertised port FEC Mode + * + * @type sai_s32_list_t sai_port_fec_mode_t + * @flags CREATE_AND_SET + * @default empty + */ + SAI_PORT_ATTR_ADVERTISED_FEC_MODE, + /** * @brief Query/Configure list of Advertised HALF-Duplex speed in Mbps * @@ -521,8 +513,8 @@ typedef enum _sai_port_attr_t * * @type sai_uint16_t * @flags CREATE_AND_SET - * @default 1 * @isvlan true + * @default 1 */ SAI_PORT_ATTR_PORT_VLAN_ID, @@ -571,6 +563,15 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_INTERNAL_LOOPBACK_MODE, + /** + * @brief Forward Error Correction (FEC) control + * + * @type sai_port_fec_mode_t + * @flags CREATE_AND_SET + * @default SAI_PORT_FEC_MODE_NONE + */ + SAI_PORT_ATTR_FEC_MODE, + /** * @brief Update DSCP of outgoing packets * @@ -595,8 +596,8 @@ typedef enum _sai_port_attr_t * disable policer on port. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -607,8 +608,8 @@ typedef enum _sai_port_attr_t * Policer id = #SAI_NULL_OBJECT_ID to disable policer on port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -619,8 +620,8 @@ typedef enum _sai_port_attr_t * policer id = #SAI_NULL_OBJECT_ID to disable policer on port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -644,8 +645,8 @@ typedef enum _sai_port_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -660,8 +661,8 @@ typedef enum _sai_port_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -675,8 +676,8 @@ typedef enum _sai_port_attr_t * as 0 in objlist * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @default empty */ SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, @@ -689,8 +690,8 @@ typedef enum _sai_port_attr_t * in objlist * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_MIRROR_SESSION * @default empty */ SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, @@ -703,8 +704,8 @@ typedef enum _sai_port_attr_t * attribute value * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -718,8 +719,8 @@ typedef enum _sai_port_attr_t * attribute value * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SAMPLEPACKET * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -731,8 +732,8 @@ typedef enum _sai_port_attr_t * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_POLICER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -755,8 +756,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -769,8 +770,8 @@ typedef enum _sai_port_attr_t * To enable/disable trust Dot1p, Map ID should be add/remove on port. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -784,8 +785,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -798,8 +799,8 @@ typedef enum _sai_port_attr_t * To enable/disable trust DSCP, Map ID should be add/remove on port. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -812,8 +813,8 @@ typedef enum _sai_port_attr_t * Default no map i.e All packets to queue 0 * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -826,8 +827,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -840,8 +841,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -854,8 +855,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -868,8 +869,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -881,8 +882,8 @@ typedef enum _sai_port_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -894,8 +895,8 @@ typedef enum _sai_port_attr_t * ID = #SAI_NULL_OBJECT_ID to disable WRED. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_WRED * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_WRED * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -908,8 +909,8 @@ typedef enum _sai_port_attr_t * attributes alone valid. Rest will be ignored * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SCHEDULER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SCHEDULER * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -921,8 +922,8 @@ typedef enum _sai_port_attr_t * There can be up to #SAI_SWITCH_ATTR_INGRESS_BUFFER_POOL_NUM profiles * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @default empty */ SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST, @@ -933,8 +934,8 @@ typedef enum _sai_port_attr_t * There can be up to #SAI_SWITCH_ATTR_EGRESS_BUFFER_POOL_NUM profiles * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @default empty */ SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST, @@ -968,8 +969,8 @@ typedef enum _sai_port_attr_t * given port list will be dropped. * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_PORT * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT * @default empty */ SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST, @@ -1010,6 +1011,7 @@ typedef enum _sai_port_attr_t * * @type sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false * @default 2500 */ SAI_PORT_ATTR_EEE_IDLE_TIME, @@ -1021,17 +1023,18 @@ typedef enum _sai_port_attr_t * * @type sai_uint16_t * @flags CREATE_AND_SET + * @isvlan false * @default 5 */ SAI_PORT_ATTR_EEE_WAKE_TIME, /** - * @brief Port bind mode - * - * @type sai_port_bind_mode_t - * @flags CREATE_AND_SET - * @default SAI_PORT_BIND_MODE_PORT - */ + * @brief Port bind mode + * + * @type sai_port_bind_mode_t + * @flags CREATE_AND_SET + * @default SAI_PORT_BIND_MODE_PORT + */ SAI_PORT_ATTR_BIND_MODE, /** @@ -1409,20 +1412,54 @@ typedef enum _sai_port_stat_t /** sai port stat pfc 7 tx pkts */ SAI_PORT_STAT_PFC_7_TX_PKTS, - /** Number of times port state changed from - * high power mode to low power mode in TX direction [uint64_t] */ + /** PFC based ON to OFF pause transitions counter per PFC priority [uint64_t] */ + SAI_PORT_STAT_PFC_0_ON2OFF_RX_PKTS, + + /** sai port stat pfc 1 on to off rx pkts */ + SAI_PORT_STAT_PFC_1_ON2OFF_RX_PKTS, + + /** sai port stat pfc 2 on to off rx pkts */ + SAI_PORT_STAT_PFC_2_ON2OFF_RX_PKTS, + + /** sai port stat pfc 3 on to off rx pkts */ + SAI_PORT_STAT_PFC_3_ON2OFF_RX_PKTS, + + /** sai port stat pfc 4 on to off rx pkts */ + SAI_PORT_STAT_PFC_4_ON2OFF_RX_PKTS, + + /** sai port stat pfc 5 on to off rx pkts */ + SAI_PORT_STAT_PFC_5_ON2OFF_RX_PKTS, + + /** sai port stat pfc 6 on to off rx pkts */ + SAI_PORT_STAT_PFC_6_ON2OFF_RX_PKTS, + + /** sai port stat pfc 7 on to off rx pkts */ + SAI_PORT_STAT_PFC_7_ON2OFF_RX_PKTS, + + /** + * @brief Number of times port state changed from + * high power mode to low power mode in TX direction [uint64_t] + */ SAI_PORT_STAT_EEE_TX_EVENT_COUNT, - /** Number of times port state changed from - * high power mode to low power mode in RX direction [uint64_t] */ + /** + * @brief Number of times port state changed from + * high power mode to low power mode in RX direction [uint64_t] + */ SAI_PORT_STAT_EEE_RX_EVENT_COUNT, - /** Port Low power mode duration(micro secs) in TX direction [uint64_t]. - * This Duration is accumulative since EEE enable on port/from last clear stats*/ + /** + * @brief Port Low power mode duration(micro secs) in TX direction [uint64_t]. + * + * This Duration is accumulative since EEE enable on port/from last clear stats + */ SAI_PORT_STAT_EEE_TX_DURATION, - /** Port Low power mode duration(micro secs) in RX direction [uint64_t] - * This Duration is accumulative since EEE enable on port/from last clear stats*/ + /** + * @brief Port Low power mode duration(micro secs) in RX direction [uint64_t] + * + * This Duration is accumulative since EEE enable on port/from last clear stats + */ SAI_PORT_STAT_EEE_RX_DURATION, } sai_port_stat_t; diff --git a/inc/saiqosmaps.h b/inc/saiqosmap.h similarity index 95% rename from inc/saiqosmaps.h rename to inc/saiqosmap.h index 7af9f4ee4..2a7baafa7 100644 --- a/inc/saiqosmaps.h +++ b/inc/saiqosmap.h @@ -17,7 +17,7 @@ * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, * Dell Products, L.P., Facebook, Inc * - * @file saiqosmaps.h + * @file saiqosmap.h * * @brief This module defines SAI QOS Maps interface */ @@ -38,16 +38,16 @@ */ typedef enum _sai_qos_map_type_t { - /** Qos Map to set DOT1P to Traffic class*/ + /** Qos Map to set DOT1P to Traffic class */ SAI_QOS_MAP_TYPE_DOT1P_TO_TC = 0x00000000, - /** Qos Map to set DOT1P to color*/ + /** Qos Map to set DOT1P to color */ SAI_QOS_MAP_TYPE_DOT1P_TO_COLOR = 0x00000001, - /** Qos Map to set DSCP to Traffic class*/ + /** Qos Map to set DSCP to Traffic class */ SAI_QOS_MAP_TYPE_DSCP_TO_TC = 0x00000002, - /** Qos Map to set DSCP to color*/ + /** Qos Map to set DSCP to color */ SAI_QOS_MAP_TYPE_DSCP_TO_COLOR = 0x00000003, /** Qos Map to set traffic class to queue */ @@ -79,7 +79,7 @@ typedef enum _sai_qos_map_type_t typedef enum _sai_qos_map_attr_t { /** - * Start of attributes + * @brief Start of attributes */ SAI_QOS_MAP_ATTR_START, @@ -99,7 +99,6 @@ typedef enum _sai_qos_map_attr_t * - All Dot1p/DSCP maps to color #SAI_PACKET_COLOR_GREEN * - All traffic class maps to queue 0 * - * * @type sai_qos_map_list_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY */ diff --git a/inc/saiqueue.h b/inc/saiqueue.h index fdd105f53..29e5a970b 100644 --- a/inc/saiqueue.h +++ b/inc/saiqueue.h @@ -76,8 +76,8 @@ typedef enum _sai_queue_attr_t * @brief Pord id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY | KEY + * @objects SAI_OBJECT_TYPE_PORT */ SAI_QUEUE_ATTR_PORT = 0x00000001, @@ -97,8 +97,8 @@ typedef enum _sai_queue_attr_t * the MANDATORY_ON_CREATE FLAG when HQoS is introduced * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP, SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP, SAI_OBJECT_TYPE_PORT */ SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE = 0x00000003, @@ -110,36 +110,46 @@ typedef enum _sai_queue_attr_t * ID = #SAI_NULL_OBJECT_ID to disable WRED * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_WRED * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_WRED * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_QUEUE_ATTR_WRED_PROFILE_ID = 0x00000004, /** - * @brief Attach buffer profile to Queue - * Default no profile + * @brief Attach buffer profile to queue * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_BUFFER_PROFILE * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_QUEUE_ATTR_BUFFER_PROFILE_ID = 0x00000005, /** - * @brief Attach scheduler to Queue + * @brief Attach scheduler to queue * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SCHEDULER * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SCHEDULER * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_QUEUE_ATTR_SCHEDULER_PROFILE_ID = 0x00000006, + /** + * @brief Queue pause status + * + * This attribute represents the queue internal hardware state and is + * updated upon receiving PFC frames. True indicates the queue is paused. + * + * @type bool + * @flags READ_ONLY + */ + SAI_QUEUE_ATTR_PAUSE_STATUS = 0x00000007, + /** * @brief End of attributes */ @@ -297,8 +307,7 @@ typedef sai_status_t (*sai_set_queue_attribute_fn)( typedef sai_status_t (*sai_get_queue_attribute_fn)( _In_ sai_object_id_t queue_id, _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _Inout_ sai_attribute_t *attr_list); /** * @brief Get queue statistics counters. diff --git a/inc/sairoute.h b/inc/sairoute.h index c6f84b54e..e567edf37 100644 --- a/inc/sairoute.h +++ b/inc/sairoute.h @@ -68,7 +68,7 @@ typedef enum _sai_route_entry_attr_t * in case of directly reachable route, or the CPU port in case of IP2ME route * * The next hop id is only effective when the packet action is one of the following: - * FORWARD, COPY, LOG, TRANSIT + * FORWARD, COPY, LOG, TRANSIT * * The next hop id can be a generic next hop object, such as next hop, next * hop group. Directly reachable routes are the IP subnets that are @@ -80,10 +80,10 @@ typedef enum _sai_route_entry_attr_t * When it is SAI_NULL_OBJECT_ID, then packet will be dropped. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_PORT - * @default SAI_NULL_OBJECT_ID * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_PORT * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, @@ -148,7 +148,7 @@ typedef struct _sai_route_entry_t * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_create_route_fn)( +typedef sai_status_t (*sai_create_route_entry_fn)( _In_ const sai_route_entry_t *route_entry, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); @@ -162,7 +162,7 @@ typedef sai_status_t (*sai_create_route_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_remove_route_fn)( +typedef sai_status_t (*sai_remove_route_entry_fn)( _In_ const sai_route_entry_t *route_entry); /** @@ -173,7 +173,7 @@ typedef sai_status_t (*sai_remove_route_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_set_route_attribute_fn)( +typedef sai_status_t (*sai_set_route_entry_attribute_fn)( _In_ const sai_route_entry_t *route_entry, _In_ const sai_attribute_t *attr); @@ -186,7 +186,7 @@ typedef sai_status_t (*sai_set_route_attribute_fn)( * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t (*sai_get_route_attribute_fn)( +typedef sai_status_t (*sai_get_route_entry_attribute_fn)( _In_ const sai_route_entry_t *route_entry, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); @@ -196,10 +196,10 @@ typedef sai_status_t (*sai_get_route_attribute_fn)( */ typedef struct _sai_route_api_t { - sai_create_route_fn create_route; - sai_remove_route_fn remove_route; - sai_set_route_attribute_fn set_route_attribute; - sai_get_route_attribute_fn get_route_attribute; + sai_create_route_entry_fn create_route_entry; + sai_remove_route_entry_fn remove_route_entry; + sai_set_route_entry_attribute_fn set_route_entry_attribute; + sai_get_route_entry_attribute_fn get_route_entry_attribute; } sai_route_api_t; diff --git a/inc/sairouterintf.h b/inc/sairouterinterface.h similarity index 97% rename from inc/sairouterintf.h rename to inc/sairouterinterface.h index 318ce6ebf..d69ad8cbb 100644 --- a/inc/sairouterintf.h +++ b/inc/sairouterinterface.h @@ -17,7 +17,7 @@ * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, * Dell Products, L.P., Facebook, Inc * - * @file sairouterintf.h + * @file sairouterinterface.h * * @brief This module defines SAI Router interface */ @@ -71,8 +71,8 @@ typedef enum _sai_router_interface_attr_t * @brief Virtual router id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER */ SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID = SAI_ROUTER_INTERFACE_ATTR_START, @@ -88,8 +88,8 @@ typedef enum _sai_router_interface_attr_t * @brief Assosiated Port or Lag object id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG * @condition SAI_ROUTER_INTERFACE_ATTR_TYPE == SAI_ROUTER_INTERFACE_TYPE_PORT or SAI_ROUTER_INTERFACE_ATTR_TYPE == SAI_ROUTER_INTERFACE_TYPE_SUB_PORT */ SAI_ROUTER_INTERFACE_ATTR_PORT_ID, @@ -98,8 +98,8 @@ typedef enum _sai_router_interface_attr_t * @brief Assosiated Vlan * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_VLAN * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_VLAN * @condition SAI_ROUTER_INTERFACE_ATTR_TYPE == SAI_ROUTER_INTERFACE_TYPE_VLAN or SAI_ROUTER_INTERFACE_ATTR_TYPE == SAI_ROUTER_INTERFACE_TYPE_SUB_PORT */ SAI_ROUTER_INTERFACE_ATTR_VLAN_ID, @@ -154,8 +154,8 @@ typedef enum _sai_router_interface_attr_t * attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -170,15 +170,13 @@ typedef enum _sai_router_interface_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_ROUTER_INTERFACE_ATTR_EGRESS_ACL, - /** Packet action when neighbor table lookup miss for this router interface [sai_packet_action_t] - * (CREATE_AND_SET) (default to SAI_PACKET_ACTION_TRAP) */ /** * @brief Packet action when neighbor table lookup miss for this router interface * diff --git a/inc/sairpfgroup.h b/inc/sairpfgroup.h index d35c89e1e..cab384b93 100644 --- a/inc/sairpfgroup.h +++ b/inc/sairpfgroup.h @@ -53,9 +53,10 @@ typedef enum _sai_rpf_group_attr_t /** * @brief RPF member list + * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_RPF_GROUP_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_RPF_GROUP_MEMBER */ SAI_RPF_GROUP_ATTR_RPF_MEMBER_LIST, @@ -81,17 +82,19 @@ typedef enum _sai_rpf_group_member_attr_t /** * @brief RPF interface group id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_RPF_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_RPF_GROUP */ SAI_RPF_GROUP_MEMBER_ATTR_RPF_GROUP_ID = SAI_RPF_GROUP_MEMBER_ATTR_START, /** * @brief RPF interface id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE */ SAI_RPF_GROUP_MEMBER_ATTR_RPF_INTERFACE_ID, @@ -170,10 +173,10 @@ typedef sai_status_t (*sai_get_rpf_group_attribute_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_create_rpf_group_member_fn)( - _Out_ sai_object_id_t* rpf_group_member_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list - ); + _Out_ sai_object_id_t* rpf_group_member_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove RPF interface group member @@ -183,8 +186,7 @@ typedef sai_status_t (*sai_create_rpf_group_member_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_remove_rpf_group_member_fn)( - _In_ sai_object_id_t rpf_group_member_id - ); + _In_ sai_object_id_t rpf_group_member_id); /** * @brief Set RPF interface Group attribute @@ -195,9 +197,8 @@ typedef sai_status_t (*sai_remove_rpf_group_member_fn)( * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_set_rpf_group_member_attribute_fn)( - _In_ sai_object_id_t rpf_group_member_id, - _In_ const sai_attribute_t *attr - ); + _In_ sai_object_id_t rpf_group_member_id, + _In_ const sai_attribute_t *attr); /** * @brief Get RPF interface Group attribute @@ -209,13 +210,12 @@ typedef sai_status_t (*sai_set_rpf_group_member_attribute_fn)( * @return SAI_STATUS_SUCCESS on success Failure status code on error */ typedef sai_status_t (*sai_get_rpf_group_member_attribute_fn)( - _In_ sai_object_id_t rpf_group_member_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list - ); + _In_ sai_object_id_t rpf_group_member_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** - * @brief RPF group methods table retrieved with sai_api_query() + * @brief RPF group methods table retrieved with sai_api_query() */ typedef struct _sai_rpf_group_api_t { diff --git a/inc/saisamplepacket.h b/inc/saisamplepacket.h index 4df488957..5962bf3ce 100644 --- a/inc/saisamplepacket.h +++ b/inc/saisamplepacket.h @@ -127,8 +127,8 @@ typedef enum _sai_samplepacket_attr_t * @return #SAI_STATUS_SUCCESS if operation is successful otherwise a different * error code is returned. */ -typedef sai_status_t (*sai_create_samplepacket_session_fn)( - _Out_ sai_object_id_t *session_id, +typedef sai_status_t (*sai_create_samplepacket_fn)( + _Out_ sai_object_id_t *samplepacket_id, _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); @@ -141,8 +141,8 @@ typedef sai_status_t (*sai_create_samplepacket_session_fn)( * @return #SAI_STATUS_SUCCESS if operation is successful otherwise a different * error code is returned. */ -typedef sai_status_t (*sai_remove_samplepacket_session_fn)( - _In_ sai_object_id_t session_id); +typedef sai_status_t (*sai_remove_samplepacket_fn)( + _In_ sai_object_id_t samplepacket_id); /** * @brief Set samplepacket session attributes. @@ -154,7 +154,7 @@ typedef sai_status_t (*sai_remove_samplepacket_session_fn)( * error code is returned. */ typedef sai_status_t (*sai_set_samplepacket_attribute_fn)( - _In_ sai_object_id_t session_id, + _In_ sai_object_id_t samplepacket_id, _In_ const sai_attribute_t *attr); /** @@ -168,7 +168,7 @@ typedef sai_status_t (*sai_set_samplepacket_attribute_fn)( * error code is returned. */ typedef sai_status_t (*sai_get_samplepacket_attribute_fn)( - _In_ sai_object_id_t session_id, + _In_ sai_object_id_t sample_packet_id, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); @@ -177,8 +177,8 @@ typedef sai_status_t (*sai_get_samplepacket_attribute_fn)( */ typedef struct _sai_samplepacket_api_t { - sai_create_samplepacket_session_fn create_samplepacket_session; - sai_remove_samplepacket_session_fn remove_samplepacket_session; + sai_create_samplepacket_fn create_samplepacket; + sai_remove_samplepacket_fn remove_samplepacket; sai_set_samplepacket_attribute_fn set_samplepacket_attribute; sai_get_samplepacket_attribute_fn get_samplepacket_attribute; diff --git a/inc/saischeduler.h b/inc/saischeduler.h index 7262f5fc0..771c30c2a 100644 --- a/inc/saischeduler.h +++ b/inc/saischeduler.h @@ -199,8 +199,8 @@ typedef sai_status_t (*sai_get_scheduler_attribute_fn)( */ typedef struct _sai_scheduler_api_t { - sai_create_scheduler_fn create_scheduler_profile; - sai_remove_scheduler_fn remove_scheduler_profile; + sai_create_scheduler_fn create_scheduler; + sai_remove_scheduler_fn remove_scheduler; sai_set_scheduler_attribute_fn set_scheduler_attribute; sai_get_scheduler_attribute_fn get_scheduler_attribute; diff --git a/inc/saischedulergroup.h b/inc/saischedulergroup.h index a69205e8e..0beb7fa56 100644 --- a/inc/saischedulergroup.h +++ b/inc/saischedulergroup.h @@ -55,8 +55,8 @@ typedef enum _sai_scheduler_group_attr_t * @brief Scheduler Group child obejct id list * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_SCHEDULER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP, SAI_OBJECT_TYPE_QUEUE */ SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST = 0x00000001, @@ -64,8 +64,8 @@ typedef enum _sai_scheduler_group_attr_t * @brief Scheduler group on port * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT */ SAI_SCHEDULER_GROUP_ATTR_PORT_ID = 0x00000002, @@ -89,8 +89,8 @@ typedef enum _sai_scheduler_group_attr_t * @brief Scheucler ID * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SCHEDULER * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SCHEDULER */ SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID = 0x00000005, @@ -100,8 +100,8 @@ typedef enum _sai_scheduler_group_attr_t * This is conditional when the level > 0, when level == 0, the parent is the port. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_SCHEDULER_GROUP, SAI_OBJECT_TYPE_PORT */ SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE = 0x00000006, diff --git a/inc/saistp.h b/inc/saistp.h index 6fc3e2e89..28eb8c910 100644 --- a/inc/saistp.h +++ b/inc/saistp.h @@ -38,7 +38,7 @@ */ typedef enum _sai_stp_port_state_t { - /** Port is in Learning mode*/ + /** Port is in Learning mode */ SAI_STP_PORT_STATE_LEARNING, /** Port is in Forwarding mode */ @@ -68,12 +68,12 @@ typedef enum _sai_stp_attr_t SAI_STP_ATTR_VLAN_LIST = SAI_STP_ATTR_START, /** - * @brief Bridge attached to STP instance - * - * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE - * @flags READ_ONLY - */ + * @brief Bridge attached to STP instance + * + * @type sai_object_id_t + * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE + */ SAI_STP_ATTR_BRIDGE_ID, /** @@ -82,12 +82,11 @@ typedef enum _sai_stp_attr_t * When a stp is created, this list is empty, all ports state as blocking. * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_STP_PORT * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_STP_PORT */ SAI_STP_ATTR_PORT_LIST, - /** * @brief End of attributes */ @@ -107,22 +106,25 @@ typedef enum _sai_stp_port_attr_t /** * @brief STP id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_STP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_STP */ SAI_STP_PORT_ATTR_STP = SAI_STP_PORT_ATTR_START, /** * @brief Bridge Port id + * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT */ SAI_STP_PORT_ATTR_BRIDGE_PORT, /** * @brief STP port state + * * @type sai_stp_port_state_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET */ @@ -169,11 +171,11 @@ typedef sai_status_t (*sai_remove_stp_fn)( * @param[in] stp_id Stp instance id * @param[in] attr attribute value * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_set_stp_attribute_fn)( - _In_ sai_object_id_t stp_id, - _In_ const sai_attribute_t *attr); + _In_ sai_object_id_t stp_id, + _In_ const sai_attribute_t *attr); /** * @brief Get the attribute of STP instance. @@ -182,12 +184,12 @@ typedef sai_status_t (*sai_set_stp_attribute_fn)( * @param[in] attr_count number of the attribute * @param[in] attr_list attribute value * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_get_stp_attribute_fn)( - _In_ sai_object_id_t stp_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list); + _In_ sai_object_id_t stp_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** * @brief Create stp port object @@ -196,23 +198,23 @@ typedef sai_status_t (*sai_get_stp_attribute_fn)( * @param[in] attr_count Number of attributes * @param[in] attr_list Value of attributes * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_create_stp_port_fn)( - _Out_ sai_object_id_t *stp_port_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); - + _Out_ sai_object_id_t *stp_port_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); /** * @brief Remove stp port object. * * @param[in] stp_port_id stp object id * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_remove_stp_port_fn)( - _In_ sai_object_id_t stp_port_id); + _In_ sai_object_id_t stp_port_id); /** * @brief Set the attribute of STP port. @@ -220,11 +222,11 @@ typedef sai_status_t (*sai_remove_stp_port_fn)( * @param[in] stp_port_id stp port id * @param[in] attr attribute value * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_set_stp_port_attribute_fn)( - _In_ sai_object_id_t stp_port_id, - _In_ const sai_attribute_t *attr); + _In_ sai_object_id_t stp_port_id, + _In_ const sai_attribute_t *attr); /** * @brief Get the attribute of STP port. @@ -233,12 +235,12 @@ typedef sai_status_t (*sai_set_stp_port_attribute_fn)( * @param[in] attr_count number of the attribute * @param[in] attr_list attribute value * @return SAI_STATUS_SUCCESS if operation is successful otherwise a different - * error code is returned. + * error code is returned. */ typedef sai_status_t (*sai_get_stp_port_attribute_fn)( - _In_ sai_object_id_t stp_port_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list); + _In_ sai_object_id_t stp_port_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); /** * @brief STP method table retrieved with sai_api_query() diff --git a/inc/saiswitch.h b/inc/saiswitch.h index 3ee85c0cc..126aeffd6 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include /** * @defgroup SAISWITCH SAI - Switch specific API definitions @@ -248,9 +248,9 @@ typedef enum _sai_switch_attr_t * @brief Get the port list * * @type sai_object_list_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_PORT * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_PORT_LIST, @@ -266,9 +266,9 @@ typedef enum _sai_switch_attr_t * @brief Get the CPU Port * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_PORT * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_CPU_PORT, @@ -372,6 +372,7 @@ typedef enum _sai_switch_attr_t /** * @brief Local subnet routing supported. + * * Routes with next hop set to "on-link". * * @type bool @@ -504,20 +505,19 @@ typedef enum _sai_switch_attr_t * @brief Default SAI VLAN ID * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_VLAN * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_VLAN_ID, - /** * @brief Default SAI STP instance ID * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_STP * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID, @@ -527,9 +527,9 @@ typedef enum _sai_switch_attr_t * Must return #SAI_STATUS_OBJECT_IN_USE when try to delete this VR ID. * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID, @@ -537,21 +537,22 @@ typedef enum _sai_switch_attr_t * @brief Default .1Q Bridge ID * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_BRIDGE * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID, /** * @brief Default .1Q bridge router port ID + * * This bridge router port is associated with the default .1Q Bridge * #SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_PORT_ID, @@ -564,8 +565,8 @@ typedef enum _sai_switch_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -580,8 +581,8 @@ typedef enum _sai_switch_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -630,7 +631,7 @@ typedef enum _sai_switch_attr_t SAI_SWITCH_ATTR_TOTAL_BUFFER_SIZE, /** - * Switch number of ingress buffer pool + * @brief Switch number of ingress buffer pool * * @type sai_uint32_t * @flags READ_ONLY @@ -659,9 +660,9 @@ typedef enum _sai_switch_attr_t * may be modified * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP, @@ -678,9 +679,9 @@ typedef enum _sai_switch_attr_t * The object id is read only, while the object attributes can be modified * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_ECMP_HASH, @@ -697,9 +698,9 @@ typedef enum _sai_switch_attr_t * The object id is read only, while the object attributes can be modified * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_LAG_HASH, @@ -757,14 +758,6 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_MAX_ACL_ACTION_COUNT, - /** - * @brief Acl capabilities supported by the NPU - * - * @type sai_acl_capability_t - * @flags READ_ONLY - */ - SAI_SWITCH_ATTR_ACL_CAPABILITY, - /** * @brief Multicast snooping capability supported by the NPU * @@ -894,9 +887,9 @@ typedef enum _sai_switch_attr_t * @brief The hash object for IPv4 packets going through ECMP * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_ECMP_HASH_IPV4, @@ -904,9 +897,9 @@ typedef enum _sai_switch_attr_t * @brief The hash object for IPv4 in IPv4 packets going through ECMP * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_ECMP_HASH_IPV4_IN_IPV4, @@ -914,9 +907,9 @@ typedef enum _sai_switch_attr_t * @brief The hash object for IPv6 packets going through ECMP * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_ECMP_HASH_IPV6, @@ -955,18 +948,19 @@ typedef enum _sai_switch_attr_t * @brief The hash object for IPv4 packets going through LAG * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_LAG_HASH_IPV4, - /** @brief The hash object for IPv4 in IPv4 packets going through LAG + /** + * @brief The hash object for IPv4 in IPv4 packets going through LAG * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_LAG_HASH_IPV4_IN_IPV4, @@ -974,9 +968,9 @@ typedef enum _sai_switch_attr_t * @brief The hash object for IPv6 packets going through LAG * * @type sai_object_id_t + * @flags READ_ONLY * @objects SAI_OBJECT_TYPE_HASH * @default internal - * @flags READ_ONLY */ SAI_SWITCH_ATTR_LAG_HASH_IPV6, @@ -1027,8 +1021,8 @@ typedef enum _sai_switch_attr_t * Default disabled * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1042,8 +1036,8 @@ typedef enum _sai_switch_attr_t * Default disabled * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1057,8 +1051,8 @@ typedef enum _sai_switch_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1072,8 +1066,8 @@ typedef enum _sai_switch_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1085,10 +1079,9 @@ typedef enum _sai_switch_attr_t * Map id = #SAI_NULL_OBJECT_ID to disable map on switch. * Default no map i.e All packets to queue 0. * - * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1101,8 +1094,8 @@ typedef enum _sai_switch_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1115,8 +1108,8 @@ typedef enum _sai_switch_attr_t * Default no map * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_QOS_MAP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -1136,6 +1129,7 @@ typedef enum _sai_switch_attr_t * * Use this to retrive the Key-Vlaue pairs as part of switch * initialization. + * * @type sai_uint32_t * @flags CREATE_ONLY * @default 0 @@ -1147,7 +1141,7 @@ typedef enum _sai_switch_attr_t * * Hardware information format is based on SAI implementations by vendors. * String is NULL terminated. Format is vendor specific. - * Example: Like PCI location, I2C adddress etc. + * Example: Like PCI location, I2C adddress etc. * In case of NULL, First NPU attached to CPU will be initialized. * Single NPU case this attribute is optional. * @@ -1185,7 +1179,7 @@ typedef enum _sai_switch_attr_t * * Use sai_switch_state_change_notification_fn as notification function. * - * @type sai_pointer_t + * @type sai_pointer_t sai_switch_state_change_notification_fn * @flags CREATE_AND_SET * @default NULL */ @@ -1196,7 +1190,7 @@ typedef enum _sai_switch_attr_t * * Use sai_switch_shutdown_request_fn as notification function. * - * @type sai_pointer_t + * @type sai_pointer_t sai_switch_shutdown_request_fn * @flags CREATE_AND_SET * @default NULL */ @@ -1207,7 +1201,7 @@ typedef enum _sai_switch_attr_t * * Use sai_fdb_event_notification_fn as notification function. * - * @type sai_pointer_t + * @type sai_pointer_t sai_fdb_event_notification_fn * @flags CREATE_AND_SET * @default NULL */ @@ -1218,7 +1212,7 @@ typedef enum _sai_switch_attr_t * * Use sai_port_state_change_notification_fn as notification function. * - * @type sai_pointer_t + * @type sai_pointer_t sai_port_state_change_notification_fn * @flags CREATE_AND_SET * @default NULL */ @@ -1229,21 +1223,52 @@ typedef enum _sai_switch_attr_t * * Use sai_packet_event_notification_fn as notification function. * - * @type sai_pointer_t + * @type sai_pointer_t sai_packet_event_notification_fn * @flags CREATE_AND_SET * @default NULL */ SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY, /** - * @brief Enable SAI function call fast mode, which executes calls very quickly - * - * @type bool - * @flags CREATE_AND_SET - * @default false - */ + * @brief Enable SAI function call fast mode, which executes calls very quickly + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ SAI_SWITCH_ATTR_FAST_API_ENABLE, + /** + * @brief Set TC of mirrored packets + * + * This setting will apply to all mirror sessions. + * + * Default of 255 = disabled. When this attribute is disabled, + * the TC of the mirrored frame will be derived from the packet + * (the DOT1P priority in the VLAN Tag, for example). + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 255 + */ + SAI_SWITCH_ATTR_MIRROR_TC, + + /** + * @brief Ingress acl stage. + * + * @type sai_acl_capability_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_ACL_STAGE_INGRESS, + + /** + * @brief Egress acl stage. + * + * @type sai_acl_capability_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_ACL_STAGE_EGRESS, + /** * @brief End of attributes */ @@ -1342,7 +1367,7 @@ typedef enum _sai_switch_attr_t * 0: cold boot. Initialize NPU and external phys. * 1: warm boot. Do not re-initialize NPU or external phys, reconstruct SAI/SDK state from stored state. * 2: fast boot. Only initilize NPU. SAI/SDK state should not be persisted except for those related - * to physical port attributes such as SPEED, AUTONEG mode, admin state, oper status. + * to physical port attributes such as SPEED, AUTONEG mode, admin state, oper status. */ #define SAI_KEY_BOOT_TYPE "SAI_BOOT_TYPE" @@ -1375,7 +1400,7 @@ typedef enum _sai_switch_attr_t * @param[in] switch_id Switch Id */ typedef void (*sai_switch_shutdown_request_fn)( - _In_ sai_object_id_t switch_id); + _In_ sai_object_id_t switch_id); /** * @brief Switch oper state change notification @@ -1390,9 +1415,9 @@ typedef void (*sai_switch_state_change_notification_fn)( /** * @brief Create switch * - * SDK initialization/connect to SDK. After the call the capability attributes should be - * ready for retrieval via sai_get_switch_attribute(). Same Switch Object id should be - * given for create/connect for each NPU. + * SDK initialization/connect to SDK. After the call the capability attributes should be + * ready for retrieval via sai_get_switch_attribute(). Same Switch Object id should be + * given for create/connect for each NPU. * * @param[out] switch_id The Switch Object ID * @param[in] attr_count number of attributes @@ -1407,14 +1432,15 @@ typedef sai_status_t(*sai_create_switch_fn)( /** * @brief Remove/disconnect Switch - * Release all resources associated with currently opened switch + * + * Release all resources associated with currently opened switch * * @param[in] switch_id The Switch id * * @return #SAI_STATUS_SUCCESS on success Failure status code on error */ -typedef sai_status_t(*sai_remove_switch_fn)( - _In_ sai_object_id_t switch_id); +typedef sai_status_t (*sai_remove_switch_fn)( + _In_ sai_object_id_t switch_id); /** * @brief Set switch attribute value diff --git a/inc/saitunnel.h b/inc/saitunnel.h index b6c7e9209..30fc38859 100644 --- a/inc/saitunnel.h +++ b/inc/saitunnel.h @@ -61,6 +61,137 @@ typedef enum _sai_tunnel_map_type_t } sai_tunnel_map_type_t; +typedef enum _sai_tunnel_map_entry_attr_t +{ + /** + * @brief Start of attributes + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_START = 0x00000000, + + /** + * @brief Tunnel Map type + * + * @type sai_tunnel_map_type_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE = SAI_TUNNEL_MAP_ENTRY_ATTR_START, + + /** + * @brief Tunnel map ex + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL_MAP + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP = 0x00000001, + + /** + * @brief Inner ECN key + * + * @type sai_uint8_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_OECN_TO_UECN or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_UECN_OECN_TO_OECN + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_KEY = 0x00000002, + + /** + * @brief Inner ECN value + * + * @type sai_uint8_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_OECN_TO_UECN or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_UECN_OECN_TO_OECN + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_VALUE = 0x00000003, + + /** + * @brief Outer ECN key + * + * @type sai_uint8_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_OECN_TO_UECN or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_UECN_OECN_TO_OECN + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_KEY = 0x00000004, + + /** + * @brief Outer ECN value + * + * @type sai_uint8_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_OECN_TO_UECN or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_UECN_OECN_TO_OECN + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_VALUE = 0x00000005, + + /** + * @brief Vlan ID key + * + * @type sai_uint16_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan true + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_KEY = 0x00000006, + + /** + * @brief Vlan ID value + * + * @type sai_uint16_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan true + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE = 0x00000007, + + /** + * @brief VNI ID key + * + * @type sai_uint32_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_BRIDGE_IF or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY = 0x00000008, + + /** + * @brief VNI ID value + * + * @type sai_uint32_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_BRIDGE_IF or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_VALUE = 0x00000009, + + /** + * @brief Bridge ID key + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_BRIDGE_IF or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_KEY = 0x0000000a, + + /** + * @brief Bridge ID value + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE + * @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VNI_TO_BRIDGE_IF or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VNI + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_VALUE = 0x0000000b, + + /** + * @brief End of attributes + */ + SAI_TUNNEL_MAP_ENTRY_ATTR_END, + + /** Custom range base value */ + SAI_TUNNEL_MAP_ENTRY_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** End of custom range base */ + SAI_TUNNEL_MAP_ENTRY_ATTR_CUSTOM_RANGE_END + +} sai_tunnel_map_entry_attr_t; + /** * @brief Defines tunnel map attributes */ @@ -82,6 +213,9 @@ typedef enum _sai_tunnel_map_attr_t /** * @brief Tunnel mapper * + * If list is empty, TUNNEL_MAP can be used to assign + * TUNNEL_MAP_ENTRY objects. + * * @type sai_tunnel_map_list_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY */ @@ -217,7 +351,8 @@ typedef enum _sai_tunnel_dscp_mode_t * with nodes along the tunnel. * * DSCP field is user-defined for outer header on encapsulation. DSCP - * field of inner header remains the same on decapsulation. */ + * field of inner header remains the same on decapsulation. + */ SAI_TUNNEL_DSCP_MODE_PIPE_MODEL } sai_tunnel_dscp_mode_t; @@ -290,8 +425,8 @@ typedef enum _sai_tunnel_attr_t * Underlay interface is router interface when conditions are met * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @condition SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_GRE */ SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE, @@ -302,8 +437,8 @@ typedef enum _sai_tunnel_attr_t * Overlay interface is router interface when conditions are met * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_ROUTER_INTERFACE * @condition SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_GRE */ SAI_TUNNEL_ATTR_OVERLAY_INTERFACE, @@ -357,12 +492,11 @@ typedef enum _sai_tunnel_attr_t SAI_TUNNEL_ATTR_ENCAP_DSCP_VAL, /** - * Tunnel GRE key valid + * @brief Tunnel GRE key valid * * @type bool * @flags CREATE_ONLY * @default false - * @condition SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_GRE */ SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID, @@ -370,8 +504,9 @@ typedef enum _sai_tunnel_attr_t * @brief Tunnel GRE key * * @type sai_uint32_t - * @flags MANDATORY_ON_CREATE | CREATE_ONLY - * @condition SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID == true + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID == true */ SAI_TUNNEL_ATTR_ENCAP_GRE_KEY, @@ -388,13 +523,12 @@ typedef enum _sai_tunnel_attr_t * @brief Tunnel encap mappers * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_TUNNEL_MAP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL_MAP * @condition SAI_TUNNEL_ATTR_ENCAP_ECN_MODE == SAI_TUNNEL_ENCAP_ECN_MODE_USER_DEFINED */ SAI_TUNNEL_ATTR_ENCAP_MAPPERS, - /** tunnel decap attribute **/ /* Tunnel decap attributes */ /** @@ -410,8 +544,8 @@ typedef enum _sai_tunnel_attr_t * @brief Tunnel decap mappers * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_TUNNEL_MAP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL_MAP * @condition SAI_TUNNEL_ATTR_DECAP_ECN_MODE == SAI_TUNNEL_DECAP_ECN_MODE_USER_DEFINED */ SAI_TUNNEL_ATTR_DECAP_MAPPERS, @@ -508,10 +642,10 @@ typedef sai_status_t (*sai_get_tunnel_attribute_fn)( */ typedef enum _sai_tunnel_term_table_entry_type_t { - /** tunnel termination table point to point entry match on dst & src ip & tunnel type **/ + /** tunnel termination table point to point entry match on dst & src ip & tunnel type */ SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2P, - /** tunnel termination table point to multi point entry match on dst ip & tunnel type **/ + /** tunnel termination table point to multi point entry match on dst ip & tunnel type */ SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP, } sai_tunnel_term_table_entry_type_t; @@ -530,8 +664,8 @@ typedef enum _sai_tunnel_term_table_entry_attr_t * @brief Tunnel virtual router id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER */ SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_START, @@ -573,8 +707,8 @@ typedef enum _sai_tunnel_term_table_entry_attr_t * @brief Tunnel id to be use for decap * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_TUNNEL * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_TUNNEL */ SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID, @@ -643,6 +777,58 @@ typedef sai_status_t (*sai_get_tunnel_term_table_entry_attribute_fn)( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); +/** + * @brief Create tunnel map item + * + * @param[out] tunnel_map_entry_id Tunnel map item id + * @param[in] switch_id Switch Id + * @param[in] attr_count Number of attributes + * @param[in] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_create_tunnel_map_entry_fn)( + _Out_ sai_object_id_t *tunnel_map_entry_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Remove tunnel map item + * + * @param[in] tunnel_map_entry_id Tunnel map item id + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_remove_tunnel_map_entry_fn)( + _In_ sai_object_id_t tunnel_map_entry_id); + +/** + * @brief Set tunnel map item attribute + * + * @param[in] tunnel_map_entry_id Tunnel map item id + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_set_tunnel_map_entry_attribute_fn)( + _In_ sai_object_id_t tunnel_map_entry_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get tunnel map item attributes + * + * @param[in] tunnel_map_entry_id Tunnel map item id + * @param[in] attr_count Number of attributes + * @param[inout] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success Failure status code on error + */ +typedef sai_status_t (*sai_get_tunnel_map_entry_attribute_fn)( + _In_ sai_object_id_t tunnel_map_entry_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + /** * @brief tunnel methods table retrieved with sai_api_query() */ @@ -660,6 +846,10 @@ typedef struct _sai_tunnel_api_t sai_remove_tunnel_term_table_entry_fn remove_tunnel_term_table_entry; sai_set_tunnel_term_table_entry_attribute_fn set_tunnel_term_table_entry_attribute; sai_get_tunnel_term_table_entry_attribute_fn get_tunnel_term_table_entry_attribute; + sai_create_tunnel_map_entry_fn create_tunnel_map_entry; + sai_remove_tunnel_map_entry_fn remove_tunnel_map_entry; + sai_set_tunnel_map_entry_attribute_fn set_tunnel_map_entry_attribute; + sai_get_tunnel_map_entry_attribute_fn get_tunnel_map_entry_attribute; } sai_tunnel_api_t; diff --git a/inc/saitypes.h b/inc/saitypes.h index dfaf96827..9f399f452 100644 --- a/inc/saitypes.h +++ b/inc/saitypes.h @@ -122,7 +122,7 @@ typedef void *sai_pointer_t; #define SAI_NULL_OBJECT_ID 0L /** - * Defines a list of sai object ids used as sai attribute value. + * @brief Defines a list of sai object ids used as sai attribute value. * * In set attribute function call, the count member defines the number of * objects. @@ -216,7 +216,8 @@ typedef enum _sai_object_type_t { SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP = 56, SAI_OBJECT_TYPE_BRIDGE = 57, SAI_OBJECT_TYPE_BRIDGE_PORT = 58, - SAI_OBJECT_TYPE_MAX = 59 + SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY = 59, + SAI_OBJECT_TYPE_MAX = 60, } sai_object_type_t; typedef struct _sai_u8_list_t { @@ -268,10 +269,10 @@ typedef struct _sai_s32_range_t { */ typedef struct _sai_vlan_list_t { - /** Number of Vlans*/ + /** Number of Vlans */ uint32_t count; - /** List of Vlans*/ + /** List of Vlans */ sai_vlan_id_t *list; } sai_vlan_list_t; @@ -312,7 +313,7 @@ typedef struct _sai_ip_prefix_t { typedef struct _sai_acl_field_data_t { /** - * match enable/disable + * @brief Match enable/disable */ bool enable; @@ -434,8 +435,10 @@ typedef struct _sai_qos_map_params_t /** Priority group value */ sai_uint8_t pg; - /** Egress port queue UOID is not known at the time of map creation. - * Using queue index for maps. */ + /** + * @brief Egress port queue UOID is not known at the time of map creation. + * Using queue index for maps. + */ sai_queue_index_t queue_index; /** Color of the packet */ @@ -476,9 +479,6 @@ typedef struct _sai_tunnel_map_params_t /** VNI id */ sai_uint32_t vni_id; - /** Bridge IF */ - sai_object_id_t bridge_if; - } sai_tunnel_map_params_t; typedef struct _sai_tunnel_map_t @@ -497,7 +497,7 @@ typedef struct _sai_tunnel_map_list_t uint32_t count; /** Map list */ - sai_tunnel_map_t * list; + sai_tunnel_map_t *list; } sai_tunnel_map_list_t; @@ -508,12 +508,6 @@ typedef struct _sai_tunnel_map_list_t */ typedef struct _sai_acl_capability_t { - /** - * @brief Type of acl stage. Input to get the action list - * Failure to pass the stage as input will be treated as error - */ - sai_int32_t stage; - /** * @brief Output from get function. * boolean indicating whether action list is mandatory for table creation @@ -561,6 +555,7 @@ typedef union { sai_ip4_t ip4; sai_ip6_t ip6; sai_ip_address_t ipaddr; + sai_ip_prefix_t ipprefix; sai_object_id_t oid; sai_object_list_t objlist; sai_u8_list_t u8list; @@ -601,7 +596,7 @@ typedef enum _sai_bulk_op_type_t { * @param[in] switch_id SAI Switch object id * @param[in] object_count Number of objects to create * @param[in] attr_count List of attr_count. Caller passes the number - * of attribute for each object to create. + * of attribute for each object to create. * @param[in] attrs List of attributes for every object. * @param[in] type bulk operation type. * @@ -616,8 +611,8 @@ typedef enum _sai_bulk_op_type_t { typedef sai_status_t (*sai_bulk_object_create_fn)( _In_ sai_object_id_t switch_id, _In_ uint32_t object_count, - _In_ uint32_t *attr_count, - _In_ sai_attribute_t **attrs, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attrs, _In_ sai_bulk_op_type_t type, _Out_ sai_object_id_t *object_id, _Out_ sai_status_t *object_statuses); @@ -637,11 +632,10 @@ typedef sai_status_t (*sai_bulk_object_create_fn)( typedef sai_status_t (*sai_bulk_object_remove_fn)( _In_ uint32_t object_count, - _In_ sai_object_id_t *object_id, + _In_ const sai_object_id_t *object_id, _In_ sai_bulk_op_type_t type, _Out_ sai_status_t *object_statuses); - /** * @} */ diff --git a/inc/saiudf.h b/inc/saiudf.h index 09994b0de..540b94662 100644 --- a/inc/saiudf.h +++ b/inc/saiudf.h @@ -63,8 +63,8 @@ typedef enum _sai_udf_attr_t * @brief UDF match ID * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_UDF_MATCH * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_UDF_MATCH */ SAI_UDF_ATTR_MATCH_ID = SAI_UDF_ATTR_START, @@ -72,8 +72,8 @@ typedef enum _sai_udf_attr_t * @brief UDF group id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_UDF_GROUP * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_UDF_GROUP */ SAI_UDF_ATTR_GROUP_ID, @@ -91,6 +91,7 @@ typedef enum _sai_udf_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan false */ SAI_UDF_ATTR_OFFSET, @@ -133,6 +134,7 @@ typedef enum _sai_udf_match_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_ONLY + * @isvlan false * @default 0 */ SAI_UDF_MATCH_ATTR_L2_TYPE = SAI_UDF_MATCH_ATTR_START, @@ -155,6 +157,7 @@ typedef enum _sai_udf_match_attr_t * * @type sai_acl_field_data_t sai_uint16_t * @flags CREATE_ONLY + * @isvlan false * @default 0 */ SAI_UDF_MATCH_ATTR_GRE_TYPE, @@ -208,8 +211,8 @@ typedef enum _sai_udf_group_attr_t * @brief UDF list * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_UDF * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_UDF */ SAI_UDF_GROUP_ATTR_UDF_LIST = SAI_UDF_GROUP_ATTR_START, @@ -227,6 +230,7 @@ typedef enum _sai_udf_group_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan false */ SAI_UDF_GROUP_ATTR_LENGTH, diff --git a/inc/sairouter.h b/inc/saivirtualrouter.h similarity index 96% rename from inc/sairouter.h rename to inc/saivirtualrouter.h index 2463a37bd..980d53b3a 100644 --- a/inc/sairouter.h +++ b/inc/saivirtualrouter.h @@ -17,7 +17,7 @@ * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, * Dell Products, L.P., Facebook, Inc * - * @file sairouter.h + * @file saivirtualrouter.h * * @brief This module defines SAI Virtual Router interface * @@ -130,8 +130,8 @@ typedef enum _sai_virtual_router_attr_t * @param[in] attr_list Array of attributes * * @return #SAI_STATUS_SUCCESS on success - * #SAI_STATUS_ADDR_NOT_FOUND if neither #SAI_SWITCH_ATTR_SRC_MAC_ADDRESS nor - * #SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS is set. + * #SAI_STATUS_ADDR_NOT_FOUND if neither #SAI_SWITCH_ATTR_SRC_MAC_ADDRESS nor + * #SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS is set. */ typedef sai_status_t (*sai_create_virtual_router_fn)( _Out_ sai_object_id_t *vr_id, diff --git a/inc/saivlan.h b/inc/saivlan.h index e37838ba9..f0d2ac52c 100644 --- a/inc/saivlan.h +++ b/inc/saivlan.h @@ -82,16 +82,16 @@ typedef enum _sai_vlan_attr_t * * @type sai_uint16_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY | KEY + * @isvlan true */ SAI_VLAN_ATTR_VLAN_ID = SAI_VLAN_ATTR_START, - /** * @brief List of vlan members in a VLAN * * @type sai_object_list_t - * @objects SAI_OBJECT_TYPE_VLAN_MEMBER * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_VLAN_MEMBER */ SAI_VLAN_ATTR_MEMBER_LIST, @@ -112,8 +112,8 @@ typedef enum _sai_vlan_attr_t * Ddefault to default stp instance id * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_STP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_STP * @default attrvalue SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID */ SAI_VLAN_ATTR_STP_INSTANCE, @@ -161,10 +161,10 @@ typedef enum _sai_vlan_attr_t * If the group has no member, unknown multicast packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags CREATE_AND_SET - * @default SAI_NULL_OBJECT_ID + * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_VLAN_ATTR_UNKNOWN_NON_IP_MCAST_OUTPUT_GROUP_ID, @@ -178,10 +178,10 @@ typedef enum _sai_vlan_attr_t * If the group has no member, unknown multicast packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags CREATE_AND_SET - * @default SAI_NULL_OBJECT_ID + * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_VLAN_ATTR_UNKNOWN_IPV4_MCAST_OUTPUT_GROUP_ID, @@ -195,10 +195,10 @@ typedef enum _sai_vlan_attr_t * If the group has no member, unknown multicast packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags CREATE_AND_SET - * @default SAI_NULL_OBJECT_ID + * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_VLAN_ATTR_UNKNOWN_IPV6_MCAST_OUTPUT_GROUP_ID, @@ -213,10 +213,10 @@ typedef enum _sai_vlan_attr_t * If the group has no member, unknown multicast packets will be discarded. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @flags CREATE_AND_SET - * @default SAI_NULL_OBJECT_ID + * @objects SAI_OBJECT_TYPE_L2MC_GROUP * @allownull true + * @default SAI_NULL_OBJECT_ID */ SAI_VLAN_ATTR_UNKNOWN_LINKLOCAL_MCAST_OUTPUT_GROUP_ID, @@ -229,8 +229,8 @@ typedef enum _sai_vlan_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ @@ -245,16 +245,13 @@ typedef enum _sai_vlan_attr_t * in the attribute value. * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_ACL_TABLE, SAI_OBJECT_TYPE_ACL_TABLE_GROUP * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_VLAN_ATTR_EGRESS_ACL, - /** User based Meta Data - * [sai_uint32_t] (CREATE_AND_SET) - * Value Range SAI_SWITCH_ATTR_VLAN_USER_META_DATA_RANGE */ /** * @brief User based Meta Data * @@ -293,8 +290,8 @@ typedef enum _sai_vlan_member_attr_t * @brief VLAN ID * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_VLAN * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_VLAN */ SAI_VLAN_MEMBER_ATTR_VLAN_ID = SAI_VLAN_MEMBER_ATTR_START, @@ -302,8 +299,8 @@ typedef enum _sai_vlan_member_attr_t * @brief Bridge port ID. Valid only for .1Q Bridge ports * * @type sai_object_id_t - * @objects SAI_OBJECT_TYPE_BRIDGE_PORT * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_BRIDGE_PORT */ SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID, @@ -506,6 +503,6 @@ typedef struct _sai_vlan_api_t } sai_vlan_api_t; /** - *@} + * @} */ #endif /** __SAIVLAN_H_ */ diff --git a/inc/saiwred.h b/inc/saiwred.h index cb81872a5..c7986a2cb 100644 --- a/inc/saiwred.h +++ b/inc/saiwred.h @@ -91,8 +91,8 @@ typedef enum _sai_wred_attr_t * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_GREEN_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_GREEN_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_GREEN_MIN_THRESHOLD = 0x00000001, @@ -102,11 +102,10 @@ typedef enum _sai_wred_attr_t * Range 1 - Max Buffer size. * default to 0 i.e Maximum buffer size * - * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_GREEN_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_GREEN_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_GREEN_MAX_THRESHOLD = 0x00000002, @@ -136,8 +135,8 @@ typedef enum _sai_wred_attr_t * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_YELLOW_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_YELLOW_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_YELLOW_MIN_THRESHOLD = 0x00000005, @@ -147,12 +146,10 @@ typedef enum _sai_wred_attr_t * Range 1 - Max Buffer size. * default to 0 i.e Maximum buffer size * - * - * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_YELLOW_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_YELLOW_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_YELLOW or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_YELLOW_MAX_THRESHOLD = 0x00000006, @@ -180,11 +177,10 @@ typedef enum _sai_wred_attr_t * Range 1 - Max Buffer size. * default to 0 i.e Maximum buffer size * - * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_RED_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_RED_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_RED_MIN_THRESHOLD = 0x00000009, @@ -194,11 +190,10 @@ typedef enum _sai_wred_attr_t * Range 1 - Max Buffer size. * default to 0 i.e Maximum buffer size * - * * @type sai_uint32_t * @flags CREATE_AND_SET - * @validonly SAI_WRED_ATTR_RED_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL * @default 0 + * @validonly SAI_WRED_ATTR_RED_ENABLE == true or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_GREEN_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_YELLOW_RED or SAI_WRED_ATTR_ECN_MARK_MODE == SAI_ECN_MARK_MODE_ALL */ SAI_WRED_ATTR_RED_MAX_THRESHOLD = 0x0000000a, @@ -301,8 +296,8 @@ typedef sai_status_t (*sai_get_wred_attribute_fn)( */ typedef struct _sai_wred_api_t { - sai_create_wred_fn create_wred_profile; - sai_remove_wred_fn remove_wred_profile; + sai_create_wred_fn create_wred; + sai_remove_wred_fn remove_wred; sai_set_wred_attribute_fn set_wred_attribute; sai_get_wred_attribute_fn get_wred_attribute; diff --git a/meta/Doxyfile b/meta/Doxyfile index 1bb613763..be1b99001 100644 --- a/meta/Doxyfile +++ b/meta/Doxyfile @@ -742,7 +742,10 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = ../inc/ saimetadatatypes.h saimetadatautils.h +INPUT = ../inc/ +INPUT += saimetadatatypes.h +INPUT += saimetadatautils.h +INPUT += saimetadatalogger.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/meta/Makefile b/meta/Makefile index 36b3d9886..da7d0cea0 100644 --- a/meta/Makefile +++ b/meta/Makefile @@ -31,7 +31,7 @@ WARNINGS = \ -Wredundant-decls \ -Wshadow \ -Wstack-protector \ - -Wstrict-aliasing=2 \ + -Wstrict-aliasing=3 \ -Wswitch \ -Wswitch-default \ -Wunreachable-code \ @@ -47,24 +47,31 @@ XMLDEPS = $(wildcard xml/*.xml) %.o: %.c $(DEPS) gcc -c -o $@ $< $(CFLAGS) $(WARNINGS) -all: saisanitycheck saidepgraph.svg +all: saisanitycheck saimetadatatest saidepgraph.svg + ./saimetadatatest > /dev/null ./saisanitycheck -xml: $(DEPS) Doxyfile saimetadatatypes.h +CONSTHEADERS = saimetadatatypes.h saimetadatalogger.h saimetadatautils.h + +xml: $(DEPS) Doxyfile $(CONSTHEADERS) doxygen Doxyfile 2>&1 | perl -npe '$$e=1 if /warning/i; END{exit $$e}'; touch xml saimetadata.c saimetadata.h: xml $(XMLDEPS) parse.pl saimetadatatypes.h perl parse.pl -saisanitycheck: saisanitycheck.c saimetadata.c saimetadata.h saimetadatatypes.h saimetadatautils.c saimetadatautils.h - g++ -c saimetadatautils.c -o /dev/null $(CFLAGS) $(WARNINGS) - g++ -c saisanitycheck.c -o /dev/null $(CFLAGS) $(WARNINGS) - g++ -c saimetadata.c -o /dev/null $(CFLAGS) $(WARNINGS) - gcc -o $@ saisanitycheck.c saimetadata.c saimetadatautils.c $(CFLAGS) $(WARNINGS) +HEADERS = saimetadata.h $(CONSTHEADERS) + +COMMONSRC = saimetadata.c saimetadatautils.c + +saisanitycheck: saisanitycheck.c $(HEADERS) + gcc -o $@ saisanitycheck.c $(COMMONSRC) $(CFLAGS) $(WARNINGS) + +saimetadatatest: saimetadatatest.c $(COMMONSRC) $(HEADERS) + gcc -o $@ saimetadatatest.c $(COMMONSRC) $(CFLAGS) $(WARNINGS) -saidepgraphgen: saidepgraphgen.cpp - g++ -o $@ saidepgraphgen.cpp saimetadata.c saimetadatautils.c $(CFLAGS) $(WARNINGS) +saidepgraphgen: saidepgraphgen.cpp $(HEADERS) + g++ -o $@ saidepgraphgen.cpp $(COMMONSRC) $(CFLAGS) $(WARNINGS) saidepgraph.gv: saidepgraphgen ./saidepgraphgen > $@ @@ -75,5 +82,7 @@ saidepgraph.svg: saidepgraph.gv .PHONY: clean clean: - rm -f *.o *~ .*~ *.tmp .*.swp .*.swo *.bak saisanitycheck saimetadata.h saimetadata.c - rm -rf xml html dist saidepgraphgen sai*.gv sai*.svg + rm -f *.o *~ .*~ *.tmp .*.swp .*.swo *.bak sai*.gv sai*.svg + rm -f saimetadata.h saimetadata.c saimetadatatest.c + rm -f saisanitycheck saimetadatatest saidepgraphgen + rm -rf xml html dist diff --git a/meta/parse.pl b/meta/parse.pl index 496c57aeb..f6db542f0 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -7,17 +7,7 @@ use XML::Simple qw(:strict); use Getopt::Std; use Data::Dumper; - -# COLOR DEFINITIONS -my $colorDefault = "\033[01;00m"; -my $colorGreenBlue = "\033[104;92m"; -my $colorBlackYellow = "\033[103;30m"; -my $colorBlackRed = "\033[31;7m"; -my $colorRed = "\033[66;91m"; -my $colorGreen = "\033[66;92m"; -my $colorYellow = "\033[66;93m"; -my $colorBlue = "\033[66;94m"; -my $colorAqua = "\033[66;96m"; +use Term::ANSIColor; my $errors = 0; my $warnings = 0; @@ -28,8 +18,14 @@ my %STRUCTS = (); my %options =(); +my @TESTNAMES= (); + +my %OBJTOAPIMAP = (); +my %APITOOBJMAP = (); + my $HEADER_CONTENT = ""; my $SOURCE_CONTENT = ""; +my $TEST_CONTENT = ""; my $FLAGS = "MANDATORY_ON_CREATE|CREATE_ONLY|CREATE_AND_SET|READ_ONLY|KEY|DYNAMIC|SPECIAL"; @@ -57,28 +53,28 @@ sub LogInfo { - print "${colorGreen}@_${colorDefault}\n"; + print color('bright_green') . "@_" . color('reset') . "\n"; } sub LogWarning { $warnings++; - print "${colorYellow}@_${colorDefault}\n"; + print color('bright_yellow') . "@_" . color('reset') . "\n"; } sub LogError { $errors++; - print "${colorRed}@_${colorDefault}\n"; + print color('bright_red') . "@_" . color('reset') . "\n"; } sub LogDebug { - print "${colorBlue}@_${colorDefault}\n" if $optionPrintDebug; + print color('bright_blue') . "@_" . color('reset') . "\n" if $optionPrintDebug; } $SIG{__DIE__} = sub { - LogError "${colorBlackRed} FATAL ERROR === MUST FIX === : @_"; + LogError "FATAL ERROR === MUST FIX === : @_"; exit 1; }; @@ -215,6 +211,7 @@ sub ExtractDescription sai_ip4_t ip4 sai_ip6_t ip6 sai_ip_address_t ipaddr +sai_ip_prefix_t ipprefix sai_object_id_t oid sai_object_list_t objlist sai_u8_list_t u8list @@ -247,6 +244,7 @@ sub ExtractDescription sai_ip4_t IPV4 sai_ip6_t IPV6 sai_ip_address_t IP_ADDRESS +sai_ip_prefix_t IP_PREFIX sai_object_id_t OBJECT_ID sai_object_list_t OBJECT_LIST sai_u8_list_t UINT8_LIST @@ -292,6 +290,11 @@ sub ProcessTagType return $val; } + if ($val =~/^sai_pointer_t sai_\w+_fn$/) + { + return $val; + } + LogError "invalid type tag value '$val' expected sai type or enum"; return undef; @@ -400,8 +403,14 @@ sub ProcessTagDefault return $val; } - if ($val =~/^(true|false|NULL|SAI_\w+|\d+)$/ and not $val =~ /_ATTR_|OBJECT_TYPE/) + if ($val =~/^(true|false|NULL|SAI_\w+|-?\d+|0x[0-9A-F]+)$/ and not $val =~ /_ATTR_|OBJECT_TYPE/) + { + return $val; + } + + if ($val =~/^0\.0\.0\.0$/) { + # currently we only support default ip address return $val; } @@ -430,6 +439,8 @@ sub ProcessDescription { my ($type, $value, $desc) = @_; + my @order = (); + $desc =~ s/@@/\n@@/g; while ($desc =~ /@@(\w+)(.+)/g) @@ -437,6 +448,8 @@ sub ProcessDescription my $tag = $1; my $val = $2; + push @order,$tag; + $val =~ s/\s+/ /g; $val =~ s/^\s*//; $val =~ s/\s*$//; @@ -453,6 +466,17 @@ sub ProcessDescription $METADATA{$type}{$value}{objecttype} = $type; $METADATA{$type}{$value}{attrid} = $value; } + + my $count = @order; + + return if $count == 0; + + my $order = join(":",@order); + + return if $order =~/^type:flags(:objects)?(:allownull)?(:isvlan)?(:default)?(:condition|:validonly)?$/; + return if $order =~/^ignore$/; + + LogWarning "metadata tags are not in right order: $order on $value"; } sub ProcessEnumSection @@ -481,12 +505,28 @@ sub ProcessEnumSection push$SAI_ENUMS{$enumtypename}{values},$enumvaluename; + if (not $enumvaluename =~/^[A-Z0-9_]+$/) + { + LogError "enum $enumvaluename uses characters outside [A-Z0-9_]+"; + } } # remove unnecessary attributes my @values = @{ $SAI_ENUMS{$enumtypename}{values} }; @values = grep(!/^SAI_\w+_(START|END)$/, @values); @values = grep(!/^SAI_\w+(CUSTOM_RANGE_BASE)$/, @values); + + if ($enumtypename =~ /^(sai_\w+)_t$/) + { + my $last = $values[$#values]; + + if ($last eq uc("$1_MAX")) + { + $last = pop @values; + LogInfo "Removing last element $last"; + } + } + $SAI_ENUMS{$enumtypename}{values} = \@values; next if not $enumtypename =~ /^(sai_(\w+)_attr_)t$/; @@ -581,6 +621,13 @@ sub WriteSource $SOURCE_CONTENT .= $content . "\n"; } +sub WriteTest +{ + my $content = shift; + + $TEST_CONTENT .= $content . "\n"; +} + sub ProcessSingleEnum { my ($key, $typedef, $prefix) = @_; @@ -649,6 +696,7 @@ sub CreateMetadataHeaderAndSource WriteHeader "#include "; WriteHeader "#include \"saimetadatatypes.h\""; WriteHeader "#include \"saimetadatautils.h\""; + WriteHeader "#include \"saimetadatalogger.h\""; WriteSource $HEAD; WriteSource "#include "; @@ -826,6 +874,11 @@ sub ProcessType return "SAI_ATTR_VALUE_TYPE_CHARDATA"; } + if ($type =~ /^sai_pointer_t sai_\w+_fn$/) + { + return "SAI_ATTR_VALUE_TYPE_POINTER"; + } + LogError "invalid type '$type' for $attr"; return ""; } @@ -902,7 +955,7 @@ sub ProcessDefaultValueType return "SAI_DEFAULT_VALUE_TYPE_SWITCH_INTERNAL" if $default =~ /^internal$/; - return "SAI_DEFAULT_VALUE_TYPE_CONST" if $default =~ /^(true|false|const|NULL|\d+|SAI_\w+)$/ and not $default =~ /_ATTR_|SAI_OBJECT_TYPE_/; + return "SAI_DEFAULT_VALUE_TYPE_CONST" if $default =~ /^(true|false|const|NULL|-?\d+|0x[0-9A-F]+|SAI_\w+)$/ and not $default =~ /_ATTR_|SAI_OBJECT_TYPE_/; return "SAI_DEFAULT_VALUE_TYPE_EMPTY_LIST" if $default =~ /^empty$/; @@ -912,6 +965,8 @@ sub ProcessDefaultValueType return "SAI_DEFAULT_VALUE_TYPE_ATTR_RANGE" if $default =~ /^attrrange SAI_\w+$/ and $default =~ /_ATTR_/; + return "SAI_DEFAULT_VALUE_TYPE_CONST" if $default =~ /^0\.0\.0\.0$/; + LogError "invalid default value type '$default' on $attr"; return ""; @@ -945,18 +1000,30 @@ sub ProcessDefaultValue { WriteSource "$val = { };"; } - elsif ($default =~ /^\d+$/ and $type =~ /sai_u?int\d+_t/) + elsif ($default =~ /^(-?\d+|0x[0-9A-F]+)$/ and $type =~ /sai_u?int\d+_t/) { WriteSource "$val = { .$VALUE_TYPES{$type} = $default };"; } - elsif ($default =~ /^NULL$/ and $type =~ /sai_pointer_t/) + elsif ($default =~ /^NULL$/ and $type =~ /^(sai_pointer_t) (sai_\w+_fn)$/) { - WriteSource "$val = { .$VALUE_TYPES{$type} = $default };"; + WriteSource "$val = { .$VALUE_TYPES{$1} = $default };"; + + WriteSource "$2 var_$2 = NULL;"; } elsif ($default =~ /^(attrvalue|attrrange|vendor|empty|const|internal)/) { return "NULL"; } + elsif ($default =~ /^NULL$/ and $type =~ /^sai_pointer_t/) + { + LogError "missing typedef function in format 'sai_\\w+_fn' on $attr ($type)"; + } + elsif ($default =~ /^0\.0\.0\.0$/ and $type =~ /^(sai_ip_address_t)/) + { + # ipv4 address needs to be converted to uint32 number so we support now only 0.0.0.0 + + WriteSource "$val = { .$VALUE_TYPES{$1} = { .addr_family = SAI_IP_ADDR_FAMILY_IPV4, .addr = { .ip4 = 0 } } };"; + } else { LogError "invalid default value '$default' on $attr ($type)"; @@ -1027,7 +1094,12 @@ sub ProcessEnumMetadata sub ProcessIsVlan { - my ($attr, $value) = @_; + my ($attr, $value, $type) = @_; + + if (not defined $value and $type =~ /uint16/) + { + LogWarning "$attr is $type, must define TAG isvlan"; + } return "false" if not defined $value; @@ -1075,6 +1147,15 @@ sub ProcessConditions my $attrid = $1; my $val = $2; + my $main_attr = $1 if $attr =~ /^SAI_(\w+?)_ATTR_/; + my $cond_attr = $1 if $attrid =~ /^SAI_(\w+?)_ATTR_/; + + if ($main_attr ne $cond_attr) + { + LogError "conditional attribute $attr has condition from different object $attrid"; + return ""; + } + WriteSource "const sai_attr_condition_t metadata_condition_${attr}_$count = {"; if ($val eq "true" or $val eq "false") @@ -1154,6 +1235,15 @@ sub ProcessValidOnly my $attrid = $1; my $val = $2; + my $main_attr = $1 if $attr =~ /^SAI_(\w+?)_ATTR_/; + my $cond_attr = $1 if $attrid =~ /^SAI_(\w+?)_ATTR_/; + + if ($main_attr ne $cond_attr) + { + LogError "validonly attribute $attr has condition from different object $attrid"; + return ""; + } + WriteSource "const sai_attr_condition_t metadata_validonly_${attr}_$count = {"; if ($val eq "true" or $val eq "false") @@ -1235,6 +1325,24 @@ sub ProcessAttrName return "\"$attr\""; } +sub ProcessIsAclField +{ + my $attr = shift; + + return "true" if $attr =~ /^SAI_ACL_ENTRY_ATTR_FIELD_\w+$/; + + return "false"; +} + +sub ProcessIsAclAction +{ + my $attr = shift; + + return "true" if $attr =~ /^SAI_ACL_ENTRY_ATTR_ACTION_\w+$/; + + return "false"; +} + sub ProcessSingleObjectType { my ($typedef, $objecttype) = @_; @@ -1277,8 +1385,10 @@ sub ProcessSingleObjectType my $validonlytype = ProcessValidOnlyType($attr, $meta{validonly}); my $validonly = ProcessValidOnly($attr, $meta{validonly}, $meta{type}); my $validonlylen = ProcessValidOnlyLen($attr, $meta{validonly}); - my $isvlan = ProcessIsVlan($attr, $meta{isvlan}); + my $isvlan = ProcessIsVlan($attr, $meta{isvlan}, $meta{type}); my $getsave = ProcessGetSave($attr, $meta{getsave}); + my $isaclfield = ProcessIsAclField($attr); + my $isaclaction = ProcessIsAclAction($attr); WriteSource "const sai_attr_metadata_t metadata_attr_$attr = {"; @@ -1303,11 +1413,14 @@ sub ProcessSingleObjectType WriteSource " .conditiontype = $conditiontype,"; WriteSource " .conditions = $conditions,"; WriteSource " .conditionslength = $conditionslen,"; + WriteSource " .isconditional = ($conditionslen != 0),"; WriteSource " .validonlytype = $validonlytype,"; WriteSource " .validonly = $validonly,"; WriteSource " .validonlylength = $validonlylen,"; WriteSource " .getsave = $getsave,"; WriteSource " .isvlan = $isvlan,"; + WriteSource " .isaclfield = $isaclfield,"; + WriteSource " .isaclaction = $isaclaction,"; WriteSource "};"; @@ -1362,6 +1475,7 @@ sub WriteMetaDataFiles WriteFile("saimetadata.h", $HEADER_CONTENT); WriteFile("saimetadata.c", $SOURCE_CONTENT); + WriteFile("saimetadatatest.c", $TEST_CONTENT); } sub ProcessAttrValueType @@ -1527,7 +1641,6 @@ sub ProcessStructObjects return "NULL" if not $type eq "sai_object_id_t"; - WriteSource "const sai_object_type_t metadata_struct_member_sai_${rawname}_t_${key}_allowed_objects[] = {"; my $objects = $struct->{objects}; @@ -1557,6 +1670,59 @@ sub ProcessStructObjectLen return $count; } +sub ProcessStructEnumData +{ + my $type = shift; + + return "&metadata_enum_$type" if $type =~ /^sai_\w+_type_t$/; # enum + + return "NULL"; +} + +sub ProcessStructIsEnum +{ + my $type = shift; + + return "true" if $type =~ /^sai_\w+_type_t$/; # enum + + return "false"; +} + +sub ProcessStructGetOid +{ + my ($type, $key, $rawname) = @_; + + return "NULL" if $type ne "sai_object_id_t"; + + my $fname = "struct_member_get_sai_${rawname}_t_${key}"; + + WriteSource "sai_object_id_t $fname("; + WriteSource " _In_ const sai_object_meta_key_t *object_meta_key)"; + WriteSource "{"; + WriteSource " return object_meta_key->objectkey.key.${rawname}.${key};"; + WriteSource "}"; + + return $fname; +} + +sub ProcessStructSetOid +{ + my ($type, $key, $rawname) = @_; + + return "NULL" if $type ne "sai_object_id_t"; + + my $fname = "struct_member_set_sai_${rawname}_t_${key}"; + + WriteSource "void $fname("; + WriteSource " _Inout_ sai_object_meta_key_t *object_meta_key,"; + WriteSource " _In_ sai_object_id_t oid)"; + WriteSource "{"; + WriteSource " object_meta_key->objectkey.key.${rawname}.${key} = oid;"; + WriteSource "}"; + + return $fname; +} + sub ProcessStructMembers { my ($struct, $ot, $rawname) = @_; @@ -1571,6 +1737,10 @@ sub ProcessStructMembers my $isvlan = ProcessStructIsVlan($struct->{$key}{type}); my $objects = ProcessStructObjects($rawname, $key, $struct->{$key}); my $objectlen = ProcessStructObjectLen($rawname, $key, $struct->{$key}); + my $isenum = ProcessStructIsEnum($struct->{$key}{type}); + my $enumdata = ProcessStructEnumData($struct->{$key}{type}); + my $getoid = ProcessStructGetOid($struct->{$key}{type}, $key, $rawname); + my $setoid = ProcessStructSetOid($struct->{$key}{type}, $key, $rawname); WriteSource "const sai_struct_member_info_t struct_member_sai_${rawname}_t_$key = {"; @@ -1579,8 +1749,11 @@ sub ProcessStructMembers WriteSource " .isvlan = $isvlan,"; WriteSource " .allowedobjecttypes = $objects,"; WriteSource " .allowedobjecttypeslength = $objectlen,"; + WriteSource " .isenum = $isenum,"; + WriteSource " .enummetadata = $enumdata,"; + WriteSource " .getoid = $getoid,"; + WriteSource " .setoid = $setoid,"; - # TODO add enum type is value is enum # TODO allow null WriteSource "};"; @@ -1611,50 +1784,91 @@ sub ProcessStructMembersCount return $count; } -sub CreateObjectInfo +sub ProcessRevGraph { - my @objects = @{ $SAI_ENUMS{sai_object_type_t}{values} }; + # + # Purpose of this method is to generate metadata where current object type + # is used since currentrly if we have attribute metadata we can easly scan + # attributes with oids values and extract information of object being used + # on that attribute, scanning all attributes of that object type we have + # dependency graph + # + # but what we create here is reverse dependency graph it will tell us on + # which object and which attrubute current object type is used + # + # we can of course create both graphs right at the same time + # - for my $ot (@objects) + my %REVGRAPH = GetReverseDependencyGraph(); + + my $objectType = shift; + + if (not defined $REVGRAPH{$objectType}) { - if (not $ot =~ /^SAI_OBJECT_TYPE_(\w+)$/) - { - LogError "invalid obejct type '$ot'"; - next; - } + # some objects are not used, so they will be not defined + return "NULL"; + } - next if $1 eq "NULL" or $1 eq "MAX"; + my @dep = @{ $REVGRAPH{$objectType} }; - my $type = "sai_" . lc($1) . "_attr_t"; + @dep = sort @dep; - my $start = "SAI_" . uc($1) . "_ATTR_START"; - my $end = "SAI_" . uc($1) . "_ATTR_END"; + my $index = 0; - my $enum = "&metadata_enum_${type}"; + my @membernames = ();; - my $struct = $STRUCTS{$ot}; + for my $dep (@dep) + { + my ($depObjectType, $attrId) = split/,/,$dep; - my $isnonobjectid = ProcessIsNonObjectId($struct, $ot); - my $structmembers = ProcessStructMembers($struct, $ot ,lc($1)); - my $structmemberscount = ProcessStructMembersCount($struct, $ot); + my $membername = "metadata_${objectType}_rev_graph_member_$index"; - WriteHeader "extern const sai_object_type_info_t sai_object_type_info_$ot;"; + push@membernames,$membername; + + WriteSource "const sai_rev_graph_member_t $membername = {"; + + WriteSource " .objecttype = $objectType,"; + WriteSource " .depobjecttype = $depObjectType,"; + + if ($attrId =~ /^SAI_\w+_ATTR_\w+/) + { + # this is attribute + + WriteSource " .attrmetadata = &metadata_attr_$attrId,"; + WriteSource " .structmember = NULL,"; + } + else + { + # this is struct member inside non object id struct + + my $DEPOT = lc ($1) if $depObjectType =~ /SAI_OBJECT_TYPE_(\w+)/; + + WriteSource " .attrmetadata = NULL,"; + WriteSource " .structmember = &struct_member_sai_${DEPOT}_t_$attrId,"; + } - WriteSource "const sai_object_type_info_t sai_object_type_info_$ot = {"; - WriteSource " .objecttype = $ot,"; - WriteSource " .attridstart = $start,"; - WriteSource " .attridend = $end,"; - WriteSource " .enummetadata = $enum,"; - WriteSource " .attrmetadata = metadata_object_type_$type,"; - WriteSource " .isnonobjectid = $isnonobjectid,"; - WriteSource " .structmembers = $structmembers,"; - WriteSource " .structmemberscount = $structmemberscount,"; WriteSource "};"; + + $index++; } - WriteHeader "extern const sai_object_type_info_t* sai_all_object_type_infos[];"; + WriteSource "const sai_rev_graph_member_t* metadata_${objectType}_rev_graph_members[] = {"; - WriteSource "const sai_object_type_info_t* sai_all_object_type_infos[] = {"; + for my $mn (@membernames) + { + WriteSource " &$mn,"; + } + + WriteSource " NULL,"; + + WriteSource "};"; + + return "metadata_${objectType}_rev_graph_members"; +} + +sub CreateStructNonObjectId +{ + my @objects = @{ $SAI_ENUMS{sai_object_type_t}{values} }; for my $ot (@objects) { @@ -1664,118 +1878,408 @@ sub CreateObjectInfo next; } - if ($1 eq "NULL" or $1 eq "MAX") - { - WriteSource " NULL,"; - next; - } + next if $1 eq "NULL" or $1 eq "MAX"; - WriteSource " &sai_object_type_info_$ot,"; - } + my $type = "sai_" . lc($1) . "_attr_t"; - WriteSource " NULL"; - WriteSource "};"; -} + my $enum = "&metadata_enum_${type}"; -sub GetHeaderFiles -{ - opendir(my $dh, $INCLUDEDIR) || die "Can't opendir $INCLUDEDIR: $!"; - my @headers = grep { /^sai\S+\.h$/ && -f "$INCLUDEDIR/$_" } readdir($dh); - closedir $dh; + my $struct = $STRUCTS{$ot}; - return @headers; + my $structmembers = ProcessStructMembers($struct, $ot ,lc($1)); + } } -sub ReadHeaderFile +sub ProcessStructMembersName { - my $filename = shift; - local $/ = undef; - open FILE, "$INCLUDEDIR/$filename" or die "Couldn't open file $INCLUDEDIR/$filename: $!"; - binmode FILE; - my $string = ; - close FILE; + my ($struct, $ot, $rawname) = @_; - return $string; + return "NULL" if not defined $struct; + + return "struct_members_sai_${rawname}_t"; } -sub GetNonObjectIdStructNames +sub ProcessCreate { - my %structs; + my $struct = shift; + my $ot = shift; - my @headers = GetHeaderFiles(); + my $small = lc($1) if $ot =~ /SAI_OBJECT_TYPE_(\w+)/; - for my $header (@headers) - { - my $data = ReadHeaderFile($header); + my $api = $OBJTOAPIMAP{$ot}; - # TODO there should be better way to extract those + WriteSource "sai_status_t sai_meta_generic_create_$ot("; + WriteSource " _Inout_ sai_object_meta_key_t *meta_key,"; + WriteSource " _In_ sai_object_id_t switch_id,"; + WriteSource " _In_ uint32_t attr_count,"; + WriteSource " _In_ const sai_attribute_t *attr_list)"; + WriteSource "{"; - while ($data =~ /sai_(?:create|set)_\S+.+?\n.+const\s+(sai_(\w+)_t)/gim) + if (not defined $struct) + { + if ($small eq "switch") { - my $name = $1; - my $rawname = $2; - - $structs{$name} = $rawname; - - if (not $name =~ /_entry_t$/) - { - LogError "non object id struct name '$name'; should end on _entry_t"; - next; - } + WriteSource " return sai_metadata_sai_${api}_api->create_$small(&meta_key->objectkey.key.object_id, attr_count, attr_list);"; + } + else + { + WriteSource " return sai_metadata_sai_${api}_api->create_$small(&meta_key->objectkey.key.object_id, switch_id, attr_count, attr_list);"; } } + else + { + WriteSource " return sai_metadata_sai_${api}_api->create_$small(&meta_key->objectkey.key.$small, attr_count, attr_list);"; + } - return values %structs; + WriteSource "}"; + + return "sai_meta_generic_create_$ot"; } -sub CreateNonObjectIdTest +sub ProcessRemove { - WriteSource "void non_object_id_test(void)"; - WriteSource "{"; + my $struct = shift; + my $ot = shift; - WriteSource " sai_object_key_t ok;"; - WriteSource " void *p;"; + my $small = lc($1) if $ot =~ /SAI_OBJECT_TYPE_(\w+)/; - my @rawnames = GetNonObjectIdStructNames(); + my $api = $OBJTOAPIMAP{$ot}; - WriteSource " p = &ok.key.object_id;"; - WriteSource " printf(\"%p\",p);"; + WriteSource "sai_status_t sai_meta_generic_remove_$ot("; + WriteSource " _In_ const sai_object_meta_key_t *meta_key)"; + WriteSource "{"; - for my $rawname (@rawnames) + if (not defined $struct) { - WriteSource " p = &ok.key.$rawname;"; - WriteSource " printf(\"%p\",p);"; + WriteSource " return sai_metadata_sai_${api}_api->remove_$small(meta_key->objectkey.key.object_id);"; + } + else + { + WriteSource " return sai_metadata_sai_${api}_api->remove_$small(&meta_key->objectkey.key.$small);"; } WriteSource "}"; + + return "sai_meta_generic_remove_$ot"; } -sub ExtractStructInfo +sub ProcessSet { my $struct = shift; + my $ot = shift; - my %S = (); + my $small = lc($1) if $ot =~ /SAI_OBJECT_TYPE_(\w+)/; - my $filename = "struct_${struct}.xml"; + my $api = $OBJTOAPIMAP{$ot}; - $filename =~ s/_/__/g; + WriteSource "sai_status_t sai_meta_generic_set_$ot("; + WriteSource " _In_ const sai_object_meta_key_t *meta_key,"; + WriteSource " _In_ const sai_attribute_t *attr)"; + WriteSource "{"; - my $file = "$XMLDIR/$filename"; # example: xml/struct__sai__fdb__entry__t.xml + if (not defined $struct) + { + WriteSource " return sai_metadata_sai_${api}_api->set_${small}_attribute(meta_key->objectkey.key.object_id, attr);"; + } + else + { + WriteSource " return sai_metadata_sai_${api}_api->set_${small}_attribute(&meta_key->objectkey.key.$small, attr);"; + } - # read xml, we need to get each struct field and it's type and description + WriteSource "}"; - my $xs = XML::Simple->new(); + return "sai_meta_generic_set_$ot"; +} - my $ref = $xs->XMLin($file, KeyAttr => { }, ForceArray => 1); +sub ProcessGet +{ + my $struct = shift; + my $ot = shift; - my @sections = @{ $ref->{compounddef}[0]->{sectiondef} }; + my $small = lc($1) if $ot =~ /SAI_OBJECT_TYPE_(\w+)/; - my $count = @sections; + my $api = $OBJTOAPIMAP{$ot}; - if ($count != 1) + WriteSource "sai_status_t sai_meta_generic_get_$ot("; + WriteSource " _In_ const sai_object_meta_key_t *meta_key,"; + WriteSource " _In_ uint32_t attr_count,"; + WriteSource " _Inout_ sai_attribute_t *attr_list)"; + WriteSource "{"; + + if (not defined $struct) { - LogError "expected only 1 section in $file for $struct"; - return %S; + WriteSource " return sai_metadata_sai_${api}_api->get_${small}_attribute(meta_key->objectkey.key.object_id, attr_count, attr_list);"; + } + else + { + WriteSource " return sai_metadata_sai_${api}_api->get_${small}_attribute(&meta_key->objectkey.key.$small, attr_count, attr_list);"; + } + + WriteSource "}"; + + return "sai_meta_generic_get_$ot"; +} + +sub CreateApis +{ + for my $key(sort keys %APITOOBJMAP) + { + WriteSource "sai_${key}_api_t *sai_metadata_sai_${key}_api = NULL;"; + WriteHeader "extern sai_${key}_api_t *sai_metadata_sai_${key}_api;"; + } +} + +sub CreateApisQuery +{ + WriteHeader "typedef sai_status_t (*sai_api_query_fn)("; + WriteHeader " _In_ sai_api_t sai_api_id,"; + WriteHeader " _Out_ void** api_method_table);"; + + WriteSource "int sai_meta_apis_query("; + WriteSource " _In_ const sai_api_query_fn api_query)"; + WriteSource "{"; + WriteSource " sai_status_t status = SAI_STATUS_SUCCESS;"; + WriteSource " int count = 0;"; + + WriteSource " if (api_query == NULL)"; + WriteSource " {"; + + for my $key(sort keys %APITOOBJMAP) + { + WriteSource " sai_metadata_sai_${key}_api = NULL;"; + } + + WriteSource " return count;"; + WriteSource " }"; + + for my $key(sort keys %APITOOBJMAP) + { + my $api = uc("SAI_API_${key}"); + + WriteSource " status = api_query($api, (void**)&sai_metadata_sai_${key}_api);"; + WriteSource " if (status != SAI_STATUS_SUCCESS) { count++; SAI_META_LOG_ERROR(\"failed to query api $api\"); }"; + } + + WriteSource " return count; /* number of unsuccesfull apis */"; + + WriteSource "}"; + + WriteHeader "extern int sai_meta_apis_query("; + WriteHeader " _In_ const sai_api_query_fn api_query);"; +} + +sub CreateObjectInfo +{ + my @objects = @{ $SAI_ENUMS{sai_object_type_t}{values} }; + + for my $ot (@objects) + { + if (not $ot =~ /^SAI_OBJECT_TYPE_(\w+)$/) + { + LogError "invalid obejct type '$ot'"; + next; + } + + next if $1 eq "NULL" or $1 eq "MAX"; + + my $type = "sai_" . lc($1) . "_attr_t"; + + my $start = "SAI_" . uc($1) . "_ATTR_START"; + my $end = "SAI_" . uc($1) . "_ATTR_END"; + + my $enum = "&metadata_enum_${type}"; + + my $struct = $STRUCTS{$ot}; + + # + # here we need to only generate struct member names + # since we use those members in rev graph entries + # so struct members must be generated previously + # + + my $isnonobjectid = ProcessIsNonObjectId($struct, $ot); + my $structmembers = ProcessStructMembersName($struct, $ot ,lc($1)); + my $structmemberscount = ProcessStructMembersCount($struct, $ot); + my $revgraph = ProcessRevGraph($ot); + my $create = "NULL"; + my $remove = "NULL"; + my $set = "NULL"; + my $get = "NULL"; + + if ($ot eq "SAI_OBJECT_TYPE_FDB_FLUSH" or $ot eq "SAI_OBJECT_TYPE_HOSTIF_PACKET") + { + # ok + } + else + { + $create = ProcessCreate($struct, $ot); + $remove = ProcessRemove($struct, $ot); + $set = ProcessSet($struct, $ot); + $get = ProcessGet($struct, $ot); + } + + WriteHeader "extern const sai_object_type_info_t sai_object_type_info_$ot;"; + + WriteSource "const sai_object_type_info_t sai_object_type_info_$ot = {"; + WriteSource " .objecttype = $ot,"; + WriteSource " .objecttypename = \"$ot\","; + WriteSource " .attridstart = $start,"; + WriteSource " .attridend = $end,"; + WriteSource " .enummetadata = $enum,"; + WriteSource " .attrmetadata = metadata_object_type_$type,"; + WriteSource " .isnonobjectid = $isnonobjectid,"; + WriteSource " .structmembers = $structmembers,"; + WriteSource " .structmemberscount = $structmemberscount,"; + WriteSource " .revgraphmembers = $revgraph,"; + WriteSource " .create = $create,"; + WriteSource " .remove = $remove,"; + WriteSource " .set = $set,"; + WriteSource " .get = $get,"; + WriteSource "};"; + } + + WriteHeader "extern const sai_object_type_info_t* sai_all_object_type_infos[];"; + + WriteSource "const sai_object_type_info_t* sai_all_object_type_infos[] = {"; + + for my $ot (@objects) + { + if (not $ot =~ /^SAI_OBJECT_TYPE_(\w+)$/) + { + LogError "invalid obejct type '$ot'"; + next; + } + + if ($1 eq "NULL" or $1 eq "MAX") + { + WriteSource " NULL,"; + next; + } + + WriteSource " &sai_object_type_info_$ot,"; + } + + WriteSource " NULL"; + WriteSource "};"; +} + +sub GetHeaderFiles +{ + opendir(my $dh, $INCLUDEDIR) || die "Can't opendir $INCLUDEDIR: $!"; + my @headers = grep { /^sai\S*\.h$/ and -f "$INCLUDEDIR/$_" } readdir($dh); + closedir $dh; + + return @headers; +} + +sub ReadHeaderFile +{ + my $filename = shift; + local $/ = undef; + open FILE, "$INCLUDEDIR/$filename" or die "Couldn't open file $INCLUDEDIR/$filename: $!"; + binmode FILE; + my $string = ; + close FILE; + + return $string; +} + +sub GetNonObjectIdStructNames +{ + my %structs; + + my @headers = GetHeaderFiles(); + + for my $header (@headers) + { + my $data = ReadHeaderFile($header); + + # TODO there should be better way to extract those + + while ($data =~ /sai_(?:create|set)_\S+.+?\n.+const\s+(sai_(\w+)_t)/gim) + { + my $name = $1; + my $rawname = $2; + + $structs{$name} = $rawname; + + if (not $name =~ /_entry_t$/) + { + LogError "non object id struct name '$name'; should end on _entry_t"; + next; + } + } + } + + return values %structs; +} + +sub DefineTestName +{ + my $name = shift; + + push @TESTNAMES,$name; + + WriteTest "void $name(void)"; +} + +sub CreateNonObjectIdTest +{ + DefineTestName "non_object_id_test"; + + WriteTest "{"; + + WriteTest " sai_object_key_t ok;"; + WriteTest " volatile void *p;"; + + my @rawnames = GetNonObjectIdStructNames(); + + # add object id since it should be in the struct also + + push @rawnames, "object_id"; + + for my $rawname (@rawnames) + { + # we are getting pointers for each member of non object id + # to make sure its declared in the struct, if its not then + # it will fail to compile + + WriteTest " p = &ok.key.$rawname;"; + WriteTest " printf(\"$rawname: \"); PP(p);"; + + WriteTest " TEST_ASSERT_TRUE(&ok.key == (void*)&ok.key.$rawname, \"member $rawname don't start at union begin! Standard C fail\");"; + } + + WriteTest "}"; +} + +sub ExtractStructInfo +{ + my $struct = shift; + my $prefix = shift; + + my %S = (); + + my $filename = "${prefix}${struct}.xml"; + + $filename =~ s/_/__/g; + + my $file = "$XMLDIR/$filename"; # example: xml/struct__sai__fdb__entry__t.xml + + # read xml, we need to get each struct field and it's type and description + + my $xs = XML::Simple->new(); + + my $ref = $xs->XMLin($file, KeyAttr => { }, ForceArray => 1); + + my @sections = @{ $ref->{compounddef}[0]->{sectiondef} }; + + my $count = @sections; + + if ($count != 1) + { + LogError "expected only 1 section in $file for $struct"; + return %S; } my @members = @{ $sections[0]->{memberdef} }; @@ -1841,7 +2345,7 @@ sub ProcessSingleNonObjectId return undef; } - my %struct = ExtractStructInfo($structname); + my %struct = ExtractStructInfo($structname, "struct_"); for my $member (keys %struct) { @@ -1964,7 +2468,472 @@ sub CheckWhiteSpaceInHeaders { LogError "line contains non ascii characters $header $n: $line"; } + + if ($line =~ /typedef .+?\(\s*\*\s*(\w+)\s*\)/) + { + my $fname = $1; + + if (not $fname =~ /^sai_\w+_fn$/) + { + LogError "all function declarations should be in format sai_\\w+_fn $header $n: $line"; + } + } + } + } +} + +sub CheckApiStructNames +{ + # + # purpose of this check is to find out + # whether sai_api_t enums match actual + # struct of api declarations + # + + my @values = @{ $SAI_ENUMS{"sai_api_t"}{values} }; + + for my $value (@values) + { + next if $value eq "SAI_API_UNSPECIFIED"; + + if (not $value =~ /^SAI_API_(\S+)$/) + { + LogError "invalie api name $value"; + next; + } + + my $api = lc($1); + + my $structName = "sai_${api}_api_t"; + + my $structFile = "struct_$structName.xml"; + + # doxygen doubles underscores + + $structFile =~ s/_/__/g; + + my $file = "$XMLDIR/$structFile"; + + if (not -e $file) + { + LogError "there is no struct $structName corresponding to api name $value"; + } + } +} + +sub CheckApiDefines +{ + # + # purpose of this check is to check whether + # all enum entries defined in sai_api_t + # have corresponding structs defined for each + # defined object like sai_fdb_api_t + # + + my @apis = @{ $SAI_ENUMS{sai_api_t}{values} }; + + for my $api (@apis) + { + my $short = lc($1) if $api =~/SAI_API_(\w+)/; + + next if $short eq "unspecified"; + + if (not defined $APITOOBJMAP{$short}) + { + LogError "$api is defined in sai.h but no corresponding struct for objects found"; + } + } +} + +sub CheckHeadersStyle +{ + # + # Purpose of this check is to find out + # whether header files are correctly formated + # + # Wrong formating includes: + # - multiple empty lines + # - double spaces + # - wrong spacing idient + # + + my @headers = GetHeaderFiles(); + + for my $header (@headers) + { + my $data = ReadHeaderFile($header); + + my @lines = split/\n/,$data; + + my $n = 0; + + my $empty = 0; + my $emptydoxy = 0; + + for my $line (@lines) + { + $n++; + + # detect multiple empty lines + + if ($line =~ /^$/) + { + $empty++; + + if ($empty > 1) + { + LogWarning "header contains two empty lines one after another $header $n"; + } + } + else { $empty = 0 } + + # detect multiple empty lines in doxygen comments + + if ($line =~ /^\s+\*\s*$/) + { + $emptydoxy++; + + if ($emptydoxy > 1) + { + LogWarning "header contains two empty lines in doxygen $header $n"; + } + } + else { $emptydoxy = 0 } + + if ($line =~ /^\s+\* / and not $line =~ /\*( {4}| {8}| )[^ ]/) + { + LogWarning "not expected number of spaces after * (1,4,8) $header $n:$line"; + } + + if ($line =~ /\*\s+[^ ].* / and not $line =~ /\* \@(brief|file)/) + { + LogWarning "too many spaces after *\\s+ $header $n:$line"; + } + + if ($line =~ /(typedef|{|}|_In\w+|_Out\w+)( [^ ].* | )/ and not $line =~ /typedef\s+u?int/i) + { + LogWarning "too many spaces $header $n:$line"; + } + + if ($line =~ m!/\*\*! and not $line =~ m!/\*\*\s*$! and not $line =~ m!/\*\*.+\*/!) + { + LogWarning "multiline doxygen comment should start '/**' $header $n:$line"; + } + + if ($line =~ m![^ ]\*/!) + { + LogWarning "coment is ending without space $header $n:$line"; + } + + if ($line =~ /^\s*sai_(\w+)_fn\s+(\w+);/) + { + # make struct function members to follow convention + + LogWarning "$1 should be equal to $2" if (($1 ne $2) and not($1 =~ /^bulk/)) + } + + next if $line =~ /^ \*/; # doxygen comment + next if $line =~ /^$/; # empty line + next if $line =~ /^typedef /; # type definition + next if $line =~ /^sai_status/; # return codes + next if $line =~ /^sai_object/; # return codes + next if $line =~ /^[{}#\/]/; # start end of struct, define, start of comment + next if $line =~ /^ {8}(_In|_Out)/; # function arguments + next if $line =~ /^ {4}(sai_)/i; # sai struct entry or SAI enum + next if $line =~ /^ {4}\/\*/; # doxygen start + next if $line =~ /^ {5}\*/; # doxygen comment continue + next if $line =~ /^ {8}sai_/; # union entry + next if $line =~ /^ {4}union/; # union + next if $line =~ /^ {4}[{}]/; # start or end of union + next if $line =~ /^ {4}(u?int)/; # union entries + next if $line =~ /^ {4}(char|bool)/; # union entries + next if $line =~ /^ {8}bool booldata/; # union bool + next if $line =~ /^ {4}(true|false)/; # bool definition + + LogWarning "header don't meet style requirements (most likely ident is not 4 or 8 spaces) $header $n:$line"; + } + } +} + +sub ExtractApiToObjectMap +{ + # + # Purpose is to get which object type + # maps to which API, since multiple object types like acl + # can map to one api structure + # + + my @headers = GetHeaderFiles(); + + for my $header (@headers) + { + my $data = ReadHeaderFile($header); + + my @lines = split/\n/,$data; + + my $n = 0; + + my $empty = 0; + my $emptydoxy = 0; + + my @objects = (); + my $api = undef; + + for my $line (@lines) + { + $n++; + + if ($line =~ /typedef\s+enum\s+_sai_(\w+)_attr_t/) + { + push@objects,uc("SAI_OBJECT_TYPE_$1"); + } + + if ($line =~ /typedef\s+struct\s+_sai_(\w+)_api_t/) + { + $api = $1; + last; + } + } + + if (not defined $api) + { + my $len = @objects; + + if ($len > 0) + { + LogError "api struct was not found in file $header, but objects are defined @objects"; + next; + } + + next; + } + + my $shortapi = $api; + + $shortapi =~ s/_//g; + + my $correct = "sai$shortapi.h"; + + if ($header ne $correct) + { + LogWarning "File $header should be named $correct"; + } + + for my $obj(@objects) + { + $OBJTOAPIMAP{$obj} = $api; } + + $APITOOBJMAP{$api} = \@objects; + } +} + +sub GetReverseDependencyGraph +{ + # + # Purpose of this method is to generate reverse + # dependency graph of where object ID are used + # + + my %REVGRAPH = (); + + my @objects = @{ $SAI_ENUMS{sai_object_type_t}{values} }; + + for my $ot (@objects) + { + if (not $ot =~ /^SAI_OBJECT_TYPE_(\w+)$/) + { + LogError "invalid obejct type '$ot'"; + next; + } + + my $otname = $1; + + my $typedef = lc("sai_${otname}_attr_t"); + + next if $ot =~ /^SAI_OBJECT_TYPE_(MAX|NULL)$/; + + # for each objec types we need to scann all objects + # also non object id structs + + my $enum = $SAI_ENUMS{$typedef}; + + my @values = @{ $enum->{values} }; + + for my $attr (@values) + { + # metadata of single attribute of this object type + + my %meta = %{ $METADATA{$typedef}{$attr} }; + + next if not defined $meta{objects}; + + # we will also include RO attributes + + my @objects = @{ $meta{objects} }; + + my $attrid = $meta{attrid}; + + for my $usedot (@objects) + { + if (not defined $REVGRAPH{$usedot}) + { + my @arr = (); + $REVGRAPH{$usedot} = \@arr; + } + + push$REVGRAPH{$usedot},"$ot,$attrid"; + } + } + + next if not defined $STRUCTS{$ot}; + + # handle non object id types + + my %struct = %{ $STRUCTS{$ot} }; + + for my $key(keys %struct) + { + next if not defined $struct{$key}{objects}; + + my @objs = @{ $struct{$key}{objects} }; + + for my $usedot (@objs) + { + if (not defined $REVGRAPH{$usedot}) + { + my @arr = (); + $REVGRAPH{$usedot} = \@arr; + } + + push$REVGRAPH{$usedot},"$ot,$key"; + } + + } + } + + return %REVGRAPH; +} + +sub WriteTestHeader +{ + # + # Purpose is to write saimedatatest.c header + # + + WriteTest "#include "; + WriteTest "#include "; + WriteTest "#include \"saimetadata.h\""; + WriteTest "#define PP(x) printf(\"%p\\n\", (x));"; + WriteTest "#define TEST_ASSERT_TRUE(x,msg) if (!(x)){ fprintf(stderr, \"ASSERT TRUE FAILED(%d): %s: %s\\n\", __LINE__, #x, msg); exit(1);}"; +} + +sub WriteTestMain +{ + # + # Purpose is to write saimedatatest.c main funcion + # and all test names + # + + WriteTest "int main()"; + WriteTest "{"; + + my $count = @TESTNAMES; + + my $n = 0; + + for my $name (@TESTNAMES) + { + $n++; + + WriteTest " printf(\"Executing Test [$n/$count]: $name\\n\");"; + WriteTest " $name();"; + } + + WriteTest " return 0;"; + WriteTest "}"; +} + +sub WriteLoggerVariables +{ + # + # logger requires 2 variables + # - log level + # - log function + # + # we can extract this to another source file saimetadatalogger.c + # but now seems to be unnecessary + # + + WriteSource "volatile sai_log_level_t sai_meta_log_level = SAI_LOG_LEVEL_NOTICE;"; + WriteSource "volatile sai_meta_log_fn sai_meta_log = NULL;"; +} + +my %ProcessedItems = (); + +sub ProcessStructItem +{ + my $type = shift; + my $struct = shift; + + $type = $1 if $type =~/^(\w+)\*$/; # handle pointers + + return if defined $ProcessedItems{$type}; + + return if defined $SAI_ENUMS{$type}; # struct entry is enum + + return if $type eq "union"; # union is special, but all union members are flattened anyway + return if $type eq "bool"; + + return if $type =~/^sai_(u?int\d+|ip[46]|mac|cos|vlan_id|queue_index)_t/; # primitives, we could get that from defines + return if $type =~/^u?int\d+_t/; + return if $type =~/^sai_[su]\d+_list_t/; + + if ($type eq "sai_object_id_t" or $type eq "sai_object_list_t") + { + # NOTE: don't change that, we can't have object id's inside complicated structures + + LogError "type $type in $struct can't be used, please convert struct to new object type and this item to an attribute"; + return; + } + + my %S = ExtractStructInfo($type, "struct_"); + + for my $key (keys %S) + { + my $item = $S{$key}{type}; + + ProcessStructItem($item, $type); + + $ProcessedItems{$item} = 1; + } +} + +sub CheckAttributeValueUnion +{ + # + # purpose of this test is to find out if attribute + # union contains complex structures members that also contain + # object id, all object ids should be simple object id member oid + # or object list objlist, other complext structures containing + # objects are NOT supported since it will be VERY HARD to track + # object dependencies via metadata and comparison logic + # + + my %Union = ExtractStructInfo("sai_attribute_value_t", "union"); + + my @primitives = qw/sai_acl_action_data_t sai_acl_field_data_t sai_pointer_t sai_object_id_t sai_object_list_t char/; + + for my $key (keys %Union) + { + my $type = $Union{$key}{type}; + + next if $type =~/sai_u?int\d+_t/; + next if $type =~/sai_[su]\d+_list_t/; + + next if grep(/^$type$/, @primitives); + + ProcessStructItem($type, "sai_attribute_value_t"); } } @@ -1972,6 +2941,10 @@ sub CheckWhiteSpaceInHeaders # MAIN # +CheckHeadersStyle(); + +ExtractApiToObjectMap(); + for my $file (GetXmlFiles($XMLDIR)) { LogInfo "Processing $file"; @@ -1993,16 +2966,36 @@ sub CheckWhiteSpaceInHeaders CreateEnumHelperMethods(); -CreateNonObjectIdTest(); - ProcessNonObjectIdObjects(); +CreateStructNonObjectId(); + +CreateApis(); + +CreateApisQuery(); + CreateObjectInfo(); CreateListOfAllAttributes(); CheckWhiteSpaceInHeaders(); +CheckApiStructNames(); + +CheckApiDefines(); + +CheckAttributeValueUnion(); + WriteHeader "#endif /* __SAI_METADATA_H__ */"; +# Test Section + +WriteTestHeader(); + +CreateNonObjectIdTest(); + +WriteTestMain(); + +WriteLoggerVariables(); + WriteMetaDataFiles(); diff --git a/meta/saimetadatalogger.h b/meta/saimetadatalogger.h new file mode 100644 index 000000000..0e67458fc --- /dev/null +++ b/meta/saimetadatalogger.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2014 Microsoft Open Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc + * + * @file saimetadatatypes.h + * + * @brief This module defines SAI Metadata Types + */ + +#ifndef __SAI_METADATA_LOGGER_H__ +#define __SAI_METADATA_LOGGER_H__ + +/** + * @defgroup SAIMETADATALOGGER SAI Metadata Types Definitions + * + * @{ + */ + +/** + * @brief Log level function definition. + * + * User can sepcify his own function thah will be called when message log level + * will be greater or equal to #sai_meta_log_level. + */ +typedef void (*sai_meta_log_fn)( + _In_ sai_log_level_t log_level, + _In_ const char *file, + _In_ int line, + _In_ const char *func, + _In_ const char *format, + ...); + +/** + * @brief User specified log function. + * + * TODO: add a set function to update this? + */ +extern volatile sai_meta_log_fn sai_meta_log; + +/** + * @brief Log level for sai metadat macros. + * + * Log level can be changed by user at any time. + * + * TODO: add a set function to update this? + */ +extern volatile sai_log_level_t sai_meta_log_level; + +/** + * @brief Helper log macro definition + * + * If logger function is NULL, stderr is used to print messages. Also fprintf + * function will validate parameters at compilation time. + */ +#define SAI_META_LOG(loglevel,format,...)\ + if (loglevel >= sai_meta_log_level)\ +{\ + if (sai_meta_log == NULL) /* or syslog? */ \ + fprintf(stderr, "%s:%d %s: " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);\ + else\ + sai_meta_log(loglevel, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__);\ +} + +/* + * Helper macros. + */ + +#define SAI_META_LOG_ENTER() SAI_META_LOG(SAI_LOG_LEVEL_DEBUG, ":> enter"); +#define SAI_META_LOG_DEBUG(format,...) SAI_META_LOG(SAI_LOG_LEVEL_DEBUG, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_INFO(format,...) SAI_META_LOG(SAI_LOG_LEVEL_INFO, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_NOTICE(format,...) SAI_META_LOG(SAI_LOG_LEVEL_NOTICE, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_WARN(format,...) SAI_META_LOG(SAI_LOG_LEVEL_WARN, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_ERROR(format,...) SAI_META_LOG(SAI_LOG_LEVEL_ERROR, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_CRITICAL(format,...) SAI_META_LOG(SAI_LOG_LEVEL_CRITICAL, ":- " format, ##__VA_ARGS__) +#define SAI_META_LOG_EXIT() SAI_META_LOG(SAI_LOG_LEVEL_DEBUG, ":< exit"); + +/** + * @} + */ +#endif /** __SAI_METADATA_LOGGER_H__ */ diff --git a/meta/saimetadatatypes.h b/meta/saimetadatatypes.h index f863463ef..a89952c25 100644 --- a/meta/saimetadatatypes.h +++ b/meta/saimetadatatypes.h @@ -134,6 +134,11 @@ typedef enum _sai_attr_value_type_t { */ SAI_ATTR_VALUE_TYPE_IP_ADDRESS, + /** + * @brief Attribute value is ip prefix + */ + SAI_ATTR_VALUE_TYPE_IP_PREFIX, + /** * @brief Attribute value is object id. */ @@ -324,11 +329,6 @@ typedef enum _sai_attr_value_type_t { */ SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY, - /** - * @brief Attribute value is ip prefix - */ - SAI_ATTR_VALUE_TYPE_IP_PREFIX, - } sai_attr_value_type_t; /** @@ -742,6 +742,11 @@ typedef struct _sai_attr_metadata_t */ size_t conditionslength; + /** + * @brief Indicates wheter attribute is conditional. + */ + bool isconditional; + /** * @brief Specifies valid only type of attribute. * @@ -790,8 +795,48 @@ typedef struct _sai_attr_metadata_t */ bool isvlan; + /** + * @brief Determines whether attribute is ACL field + * + * This will become handy for fast detrmination whether + * default value is present. + */ + bool isaclfield; + + /* + * @brief Determines whether attribute is ACL action + * + * This will become handy for fast detrmination whether + * default value is present. + */ + bool isaclaction; + } sai_attr_metadata_t; +/* + * TODO since non object id members can have different type and can be localed + * at different object_key union position, we need to find a way to extract + * those for automatic serialize/deserialize for example extracting value as + * sai_attribute_value_t and pointing to right serialize/deserialize functions. + * Also a automatic generated functions for serialize/deserialize for those non + * object id structs must be generated, we don't want to update them manually. + */ + +/** + * @brief Function definition for getting OID from non obeject + * id struct member. + */ +typedef sai_object_id_t (*sai_meta_get_struct_member_oid_fn)( + _In_ const sai_object_meta_key_t *object_meta_key); + +/** + * @brief Function definition for setting OID from non obeject + * id struct member. + */ +typedef void (*sai_meta_set_struct_member_oid_fn)( + _Inout_ sai_object_meta_key_t *object_meta_key, + _In_ sai_object_id_t oid); + /** * @brief Defines struct member info for * non object id object type @@ -801,17 +846,17 @@ typedef struct _sai_struct_member_info_t /** * @brief Member vlaue type */ - sai_attr_value_type_t membervaluetype; + sai_attr_value_type_t membervaluetype; /** * @brief Member name */ - const char* membername; + const char* membername; /** * @brief Indicates whether field is vlan */ - bool isvlan; + bool isvlan; /** * @brief Specified allowed object types. @@ -819,15 +864,116 @@ typedef struct _sai_struct_member_info_t * If object attr value type is OBJECT_ID * this list specifies what object type can be used. */ - const sai_object_type_t* const allowedobjecttypes; + const sai_object_type_t* const allowedobjecttypes; /** * @brief Length of allowed object types. */ - size_t allowedobjecttypeslength; + size_t allowedobjecttypeslength; + + /** + * @brief Indicates wheter member is enum value. + * + * Type must be set as INT32. + * + * @note Could be deduced from enum type string or + * enum vector values and attr value type. + */ + bool isenum; + + /** + * @brief Provides enum metadata if member is enum + */ + const sai_enum_metadata_t* const enummetadata; + + /** + * @brief If struct member is OID this function + * will get it's value. + */ + const sai_meta_get_struct_member_oid_fn getoid; + + /** + * @brief If struct member is OID this function + * will set it's value. + */ + const sai_meta_set_struct_member_oid_fn setoid; } sai_struct_member_info_t; +/** + * @brief SAI reverse graph member + */ +typedef struct _sai_rev_graph_member_t +{ + /** + * @brief Defines main object type which is used + * by dependency object type. + */ + sai_object_type_t objecttype; + + /** + * @brief Defines dependency object type on which + * is object type defined above is used. + */ + sai_object_type_t depobjecttype; + + /** + * @brief Defines attribute metadata for object type + * + * This can be NULL if dependency objec type + * is non object id type and dependency is on + * defined struct. + */ + const sai_attr_metadata_t* const attrmetadata; + + /** + * @brief Defines struct member for non object + * id object type. + * + * This member can be NULL if dependency object type + * is object attribute, and is not NULL id object + * dependency is non object id struct member. + */ + const sai_struct_member_info_t* const structmember; + +} sai_rev_graph_member_t; + +/* + * Generic QUAD api definitions. All apis can be called using this quad genric + * functions. + * + * When creating switch object or non object id switch_id parameter is ignored, + * and can be NULL. Currently objecttype inside sai_object_meta_key_t is + * ignored and can be skipped. + * + * This generic quad api will help us later to call any api, without doind any + * switch cases for calling differen signature functions including non object + * id structs. Also later we will generate automatic serialize and deserialize + * methods for non object id which will deserialize data to object union in + * sai_object_meta_key_t to right place. + * + * TODO add medatada init function which will populate global api function + * pointers which will be used when calling each api. + */ + +typedef sai_status_t (*sai_meta_generic_create_fn)( + _Inout_ sai_object_meta_key_t *meta_key, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +typedef sai_status_t (*sai_meta_generic_remove_fn)( + _In_ const sai_object_meta_key_t *meta_key); + +typedef sai_status_t (*sai_meta_generic_set_fn)( + _In_ const sai_object_meta_key_t *meta_key, + _In_ const sai_attribute_t *attr); + +typedef sai_status_t (*sai_meta_generic_get_fn)( + _In_ const sai_object_meta_key_t *meta_key, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + /** * @brief SAI object type information */ @@ -838,6 +984,11 @@ typedef struct _sai_object_type_info_t */ sai_object_type_t objecttype; + /** + * @brief Object Type name + */ + const char* objecttypename; + /** * @brief Start of attributes *_START */ @@ -875,6 +1026,31 @@ typedef struct _sai_object_type_info_t */ size_t structmemberscount; + /** + * @brief Defines reverse dependency graph members + */ + const sai_rev_graph_member_t** const revgraphmembers; + + /** + * @brief Create function pointer. + */ + const sai_meta_generic_create_fn create; + + /** + * @brief Remove function pointer. + */ + const sai_meta_generic_remove_fn remove; + + /** + * @brief Set function pointer. + */ + const sai_meta_generic_set_fn set; + + /** + * @brief Get function pointer + */ + const sai_meta_generic_get_fn get; + } sai_object_type_info_t; /** diff --git a/meta/saimetadatautils.c b/meta/saimetadatautils.c index 6a1bd8d11..a5eaea973 100644 --- a/meta/saimetadatautils.c +++ b/meta/saimetadatautils.c @@ -160,3 +160,26 @@ const char* sai_metadata_get_enum_value_name( return NULL; } + +const sai_attribute_t* sai_metadata_get_attr_by_id( + _In_ sai_attr_id_t id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + if (attr_list == NULL) + { + return NULL; + } + + uint32_t i = 0; + + for (; i < attr_count; ++i) + { + if (attr_list[i].id == id) + { + return &attr_list[i]; + } + } + + return NULL; +} diff --git a/meta/saimetadatautils.h b/meta/saimetadatautils.h index 84e19dc8f..97343c837 100644 --- a/meta/saimetadatautils.h +++ b/meta/saimetadatautils.h @@ -41,7 +41,7 @@ * * @return True if object is allowed on on this attribute, false otherwise */ -extern bool sai_meta_is_allowed_object_type( +extern bool sai_metadata_is_allowed_object_type( _In_ const sai_attr_metadata_t* metadata, _In_ sai_object_type_t object_type); @@ -53,7 +53,7 @@ extern bool sai_meta_is_allowed_object_type( * * @return True if enum value is allowed on this attribute, false otherwise */ -extern bool sai_meta_is_allowed_enum_value( +extern bool sai_metadata_is_allowed_enum_value( _In_ const sai_attr_metadata_t* metadata, _In_ int value); @@ -64,7 +64,7 @@ extern bool sai_meta_is_allowed_enum_value( * * @return True if is ACL field or action, false otherwise */ -bool sai_metadata_is_acl_field_or_action( +extern bool sai_metadata_is_acl_field_or_action( _In_ const sai_attr_metadata_t* metadata); /** @@ -101,6 +101,20 @@ extern const char* sai_metadata_get_enum_value_name( _In_ const sai_enum_metadata_t* metadata, _In_ int value); +/** + * @brief Gets attribute from attribute list by attribyte id + * + * @param[in] id Attribute id to be found + * @param[in] attr_count Total number of attributes + * @param[in] attr_list List of attributest to search + * + * @return Attriute pointer with requested ID or NULL if not found + */ +extern const sai_attribute_t* sai_metadata_get_attr_by_id( + _In_ sai_attr_id_t id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + /** * @} */ diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c index 76fc14bb8..34dd1457c 100644 --- a/meta/saisanitycheck.c +++ b/meta/saisanitycheck.c @@ -4,6 +4,7 @@ #include #include "saimetadatautils.h" #include "saimetadata.h" +#include "saimetadatalogger.h" typedef struct _defined_attr_t { @@ -107,6 +108,8 @@ void check_all_enums_name_pointers() bool is_flag_enum(const sai_enum_metadata_t* emd) { + META_LOG_ENTER(); + const char* flagenums[] = { "sai_acl_entry_attr_t", "sai_acl_table_attr_t", @@ -249,7 +252,7 @@ void check_attr_by_object_type() { META_LOG_ENTER(); - META_ASSERT_TRUE(metadata_attr_by_object_type_count == SAI_OBJECT_TYPE_MAX + 1, "invalid object type count in metadata"); + META_ASSERT_TRUE(metadata_attr_by_object_type_count == SAI_OBJECT_TYPE_MAX, "invalid object type count in metadata"); size_t i = 0; @@ -277,7 +280,7 @@ void check_attr_by_object_type() index++; } - META_LOG_INFO("attr index %3zu for %s", index, sai_metadata_get_object_type_name((sai_object_type_t)i)); + META_LOG_INFO("attr index %zu for %s", index, sai_metadata_get_object_type_name((sai_object_type_t)i)); } META_ASSERT_NULL(metadata_attr_by_object_type[i]); @@ -286,6 +289,8 @@ void check_attr_by_object_type() void check_attr_object_type( _In_ const sai_attr_metadata_t* md) { + META_LOG_ENTER(); + if ((md->objecttype <= SAI_OBJECT_TYPE_NULL) || (md->objecttype >= SAI_OBJECT_TYPE_MAX)) { @@ -312,23 +317,29 @@ void check_attr_flags( case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY: case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: - if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_UINT32 && - md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_ATTR_RANGE) + if (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) { - break; + META_ASSERT_FAIL(md, "valid only attribute can't be mandatory on create, use condition"); } + /* + * Currently we don't use RANGE type so this check can be disabled. + * Range idea was introduces so attribute can be in specific range + * of other MIN/MAX attributes. This is not supported yet. + * + * if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_UINT32 && + * md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_ATTR_RANGE) + * { + * break; + * } + */ + if (md->defaultvaluetype != SAI_DEFAULT_VALUE_TYPE_NONE) { META_ASSERT_FAIL(md, "no default value expected, but type provided: %s", sai_metadata_get_default_value_type_name(md->defaultvaluetype)); } - if (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) - { - META_ASSERT_FAIL(md, "valid only attribute can't be mandatory on create, use condition"); - } - break; case SAI_ATTR_FLAGS_CREATE_ONLY: @@ -336,26 +347,25 @@ void check_attr_flags( if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_NONE) { - if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) - { - /* - * Object id's may not provide default value, which will mean it can - * be NULL or assigned by switch by default. - */ - break; - } + /* + * Default value of object id can be internal or NULL and it + * needs to be specified explicitly. + */ - if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_POINTER) + /* + * Default value for pointer must be specified and must be NULL. + */ + + if (sai_metadata_is_acl_field_or_action(md)) { /* - * Pointer may not provide default value, - * which will mean it can be NULL. + * Default value for acl field or action is not provided + * since by default they are disabled, but as TODO we can + * add this support and provide default value inside + * metadata with disabled parameter and remove this check + * here. */ - break; - } - if (sai_metadata_is_acl_field_or_action(md)) - { break; } @@ -366,14 +376,25 @@ void check_attr_flags( case SAI_ATTR_FLAGS_READ_ONLY: + if (md->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE) + { + META_ASSERT_FAIL(md, "read only attribute can't be conditional"); + } + + if (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) + { + META_ASSERT_FAIL(md, "read only attribute can't be valid only"); + } + if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_SWITCH_INTERNAL) { if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID || md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_LIST) { /* - * Read only object id/list can be marked as internal - * like default virtual router, cpu port id, etc. + * Read only object id/list can be marked as internal like + * default virtual router, cpu port id, default queues on + * ports, etc. */ break; @@ -386,16 +407,6 @@ void check_attr_flags( sai_metadata_get_default_value_type_name(md->defaultvaluetype)); } - if (md->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE) - { - META_ASSERT_FAIL(md, "read only attribute can't be conditional"); - } - - if (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) - { - META_ASSERT_FAIL(md, "read only attribute can't be valid only"); - } - break; default: @@ -411,7 +422,12 @@ void check_attr_object_id_allownull( if (md->attrvaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID) { - /* we don't care about ACL entry data/field */ + /* + * We don't care about ACL entry data/field, in that when we set NULL + * as object id on acl data/field it should mean as disable, or it + * should be not allowed at all. + */ + return; } @@ -434,6 +450,7 @@ void check_attr_object_id_allownull( * since attribute require default value and default value is * set to SAI_NULL_OBJECT_ID then allownull should be true */ + META_ASSERT_FAIL(md, "allow null object id should be set to true since default value is required"); } @@ -468,6 +485,7 @@ void check_attr_object_type_provided( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + if (md->allowedobjecttypes == NULL) { META_ASSERT_FAIL(md, "object types list is required but it's empty"); @@ -489,6 +507,7 @@ void check_attr_object_type_provided( case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_POINTER: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: + case SAI_ATTR_VALUE_TYPE_IP_PREFIX: case SAI_ATTR_VALUE_TYPE_CHARDATA: case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: case SAI_ATTR_VALUE_TYPE_UINT32_LIST: @@ -526,7 +545,7 @@ void check_attr_object_type_provided( break; default: - META_ASSERT_FAIL(md, "attr value type is not supported)"); + META_ASSERT_FAIL(md, "attr value type is not supported, FIXME"); } } @@ -615,8 +634,19 @@ void check_attr_default_required( if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_NONE) { + /* + * If default value type is NONE, then default value must be NULL. + */ + + META_ASSERT_NULL(md->defaultvalue); + if (sai_metadata_is_acl_field_or_action(md)) { + /* + * By default we assume that default acl field or action is + * disabled and default value is not provided. + */ + return; } @@ -627,16 +657,25 @@ void check_attr_default_required( { case SAI_DEFAULT_VALUE_TYPE_CONST: - if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_UINT8_LIST) + if (md->objecttype == SAI_OBJECT_TYPE_UDF && md->attrid == SAI_UDF_ATTR_HASH_MASK) { - /* const on list */ - break; + if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_UINT8_LIST) + { + /* + * Const on list, this is exception for UDF object since + * it's default value is 2 bytes 0xFF,0xFF and it's special + * calse. + */ + + break; + } } if (md->defaultvalue == NULL) { META_ASSERT_FAIL(md, "default value type is provided, but default value pointer is NULL"); } + break; case SAI_DEFAULT_VALUE_TYPE_ATTR_VALUE: @@ -647,11 +686,13 @@ void check_attr_default_required( if (md->defaultvalue != NULL) { - META_ASSERT_FAIL(md, "default value type is provided, but default value pointer is NULL"); + META_ASSERT_FAIL(md, "default value type is provided, but default value pointer is not NULL"); } + break; default: + META_ASSERT_FAIL(md, "unknown default value type %d", md->defaultvaluetype); } @@ -659,7 +700,6 @@ void check_attr_default_required( switch (md->attrvaluetype) { - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_BOOL: case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8: case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: @@ -692,7 +732,9 @@ void check_attr_default_required( case SAI_ATTR_VALUE_TYPE_UINT64: case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: + case SAI_ATTR_VALUE_TYPE_IP_PREFIX: break; + case SAI_ATTR_VALUE_TYPE_INT8_LIST: case SAI_ATTR_VALUE_TYPE_UINT32_LIST: case SAI_ATTR_VALUE_TYPE_INT32_LIST: @@ -700,6 +742,7 @@ void check_attr_default_required( case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8_LIST: + if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_EMPTY_LIST) { break; @@ -716,9 +759,17 @@ void check_attr_default_required( break; } - if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_CONST) + if (md->objecttype == SAI_OBJECT_TYPE_UDF && md->attrid == SAI_UDF_ATTR_HASH_MASK) { - break; + if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_CONST) + { + /* + * Again this is exception only for this one UDF attribute + * to support CONST on list. + */ + + break; + } } META_ASSERT_FAIL(md, "default value list is needed on this attr value type but list is NULL"); @@ -751,7 +802,6 @@ void check_attr_enums( default: META_ASSERT_FAIL(md, "attribute is marked as enum, but attr value type is not enum compatible"); } - } if (md->isenum && md->isenumlist) @@ -783,6 +833,11 @@ void check_attr_enums( { if (sai_metadata_is_acl_field_or_action(md)) { + /* + * Default value on acl field or action is by default disabled + * so we just skip it here. + */ + return; } @@ -831,7 +886,7 @@ void check_attr_default_value_type( if (md->attrvaluetype != def->attrvaluetype) { - META_ASSERT_FAIL(md, "attr value attribute value value type is different"); + META_ASSERT_FAIL(md, "default attr value type is different"); } break; @@ -848,6 +903,7 @@ void check_attr_default_value_type( } META_ASSERT_FAIL(md, "attr value attribute value range not supported yet"); + break; } @@ -881,6 +937,11 @@ void check_attr_default_value_type( default: + /* + * Vendor specific attribute should be used only on + * primitive types and not on object id types (OIDs). + */ + META_ASSERT_FAIL(md, "vendor specific not allowed on this type"); } @@ -895,6 +956,11 @@ void check_attr_default_value_type( if (md->objecttype != SAI_OBJECT_TYPE_SWITCH) { + /* + * This can be later relaxed to be set on PORTs since they have + * by default queues created. + */ + META_ASSERT_FAIL(md, "default internal can be only set on switch object type"); } @@ -942,9 +1008,12 @@ void check_attr_conditions( if (!conditional) { + META_ASSERT_FALSE(md->isconditional, "marked conditional but is not"); return; } + META_ASSERT_TRUE(md->isconditional, "marked not conditional but is"); + if (md->conditions == NULL) { META_ASSERT_FAIL(md, "marked as conditional but no conditions specified"); @@ -954,7 +1023,12 @@ void check_attr_conditions( { case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY: - case SAI_ATTR_FLAGS_CREATE_ONLY: /* will require default value, on some cases may be dynamic */ + + /* + * If attribute is marked as conditional then it must have flags + * mandatory on create, otherwise use validonly condition. + */ + break; default: @@ -1016,17 +1090,7 @@ void check_attr_conditions( if (cmd->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE) { - /* this is provieded for SAI_TUNNEL_ATTR_ENCAP_GRE_KEY and needs to be converted to validonly */ - - if (cmd->flags == SAI_ATTR_FLAGS_CREATE_ONLY && - cmd->attrvaluetype == SAI_ATTR_VALUE_TYPE_BOOL) - { - /* ok, that means there is default value (it may be depending on switch intenal) */ - } - else - { - META_ASSERT_FAIL(md, "conditional attibute is also conditional, not allowed"); - } + META_ASSERT_FAIL(md, "conditional attibute is also conditional, not allowed"); } switch ((int)cmd->flags) @@ -1034,11 +1098,13 @@ void check_attr_conditions( case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY | SAI_ATTR_FLAGS_KEY: case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY: case SAI_ATTR_FLAGS_CREATE_ONLY: + /* - * condition attribute must be create only since - * if it could change then other object may be required to pass - * on creation time that was not passed + * Condition attribute must be create only since if it could + * change then other object may be required to pass on creation + * time that was not passed. */ + break; default: @@ -1091,8 +1157,23 @@ void check_attr_validonly( break; case SAI_ATTR_FLAGS_CREATE_ONLY: + + /* + * In generral valid only attribute should be used only on + * CREATE_AND_SET flags, since when attribute is CREATE_ONLY it has + * default value and it can't be changed anywa, and entire purpose + * of valid only attribute is to allow change during runtime. + * + * Wthen attribute CREATE_ONLY is marked as valid only is more like + * indication that this value will be used in that specific case + * but you won't be able to change it anyway. + */ + + META_WARN(md, "marked as valid only, on flags CREATE_ONLY, default value is present, should this be CREATE_AND_SET?"); + case SAI_ATTR_FLAGS_CREATE_AND_SET: + /* ok */ break; @@ -1107,9 +1188,14 @@ void check_attr_validonly( META_ASSERT_FAIL(md, "marked as validonly, but invalid creation flags: 0x%u", md->flags); } - if ((md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_NONE) || - (md->defaultvalue == NULL)) + if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_NONE) { + /* + * In struct defaultvalue member can be NULL for some other default + * value types like empty list or internal etc. Default value is + * provided for CONST only. + */ + META_ASSERT_FAIL(md, "expected default value on vlaid only attribute, but none provided"); } @@ -1171,7 +1257,19 @@ void check_attr_validonly( if (cmd->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) { - META_ASSERT_FAIL(md, "validonly attibute is also validonly attribute, not allowed"); + if (md->objecttype == SAI_OBJECT_TYPE_TUNNEL && md->attrid == SAI_TUNNEL_ATTR_ENCAP_GRE_KEY) + { + /* + * For this case GRE_KEY is depending on GRE_KEY_VALID which is + * also valid only for other cases we don't allow valid only to + * be depending on valid only but maybe this is false + * assumption. + */ + } + else + { + META_ASSERT_FAIL(md, "validonly attibute is also validonly attribute, not allowed"); + } } if (cmd->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE) @@ -1186,11 +1284,14 @@ void check_attr_validonly( case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: case SAI_ATTR_FLAGS_CREATE_ONLY: case SAI_ATTR_FLAGS_CREATE_AND_SET: + /* - * valid only attribute can be create_only or create_and_set + * Valid only attribute can be create_only or create_and_set * conditional attribute can change during runtime and it may - * have impact on valid only attribute (it may or may not be used) + * have impact on valid only attribute (it may or may not be + * used). */ + break; default: @@ -1239,6 +1340,11 @@ void check_attr_enum_list_validonly( if (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE) { + /* + * This restriction can be removed if necessary so far i don't see + * any enum list that are marked as valid only. + */ + META_ASSERT_FAIL(md, "validonly enum list not supported yet"); } } @@ -1247,6 +1353,8 @@ void check_attr_enum_list_validonly( void check_attr_allow_flags( _In_ const sai_attr_metadata_t* md) { + META_LOG_ENTER(); + if (md->allownullobjectid) { switch (md->attrvaluetype) @@ -1256,7 +1364,7 @@ void check_attr_allow_flags( case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_OBJECT_ID: - case SAI_ATTR_VALUE_TYPE_POINTER: + break; default: @@ -1264,6 +1372,11 @@ void check_attr_allow_flags( META_ASSERT_FAIL(md, "allow null object is set but attr value type is wrong"); } + /* + * Object SAI_ATTR_VALUE_TYPE_POINTER should be allowed null pointer by + * default pointers received from SAI should be only via query api. + */ + if (md->allowedobjecttypeslength == 0) { META_ASSERT_FAIL(md, "allow null object is set but allowed object types is empty"); @@ -1338,14 +1451,28 @@ void check_attr_key( if (md->objecttype == SAI_OBJECT_TYPE_PORT && md->attrid == SAI_PORT_ATTR_HW_LANE_LIST) { + /* + * This is special case when HW_LANE_LIST is actual KEY for + * port, and it's more complicated because order don't + * matter and same lane can't be used on different port if + * some ports are splitted. + */ + break; } META_ASSERT_FAIL(md, "marked as key, but have invalid attr value type (list)"); case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + if (md->objecttype == SAI_OBJECT_TYPE_QUEUE && md->attrid == SAI_QUEUE_ATTR_PORT) { + /* + * This is also special case, OBJECT_ID at should not be a + * KEY in any attribute, this is TODO action to get rid of + * this kind of dependency. + */ + break; } @@ -1384,16 +1511,43 @@ void check_attr_acl_fields( case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8_LIST: - if (md->objecttype != SAI_OBJECT_TYPE_ACL_ENTRY || - md->attrid < SAI_ACL_ENTRY_ATTR_FIELD_START || - md->attrid > SAI_ACL_ENTRY_ATTR_FIELD_END) + if (md->objecttype == SAI_OBJECT_TYPE_ACL_ENTRY && + md->attrid >= SAI_ACL_ENTRY_ATTR_FIELD_START && + md->attrid <= SAI_ACL_ENTRY_ATTR_FIELD_END) + { + break; + + } + + if (md->objecttype == SAI_OBJECT_TYPE_UDF_MATCH) { - if (md->objecttype != SAI_OBJECT_TYPE_UDF_MATCH) + /* + * This is special case, object for UDF MATCH can use acl field + * attribute values since it's easier to maintain since this + * match also need a mask parameter. But restriction is that + * only primitive types can be used, no object id; + */ + + switch (md->attrvaluetype) { - META_ASSERT_FAIL(md, "acl field may only be set on acl field and udf match"); + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT16: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT32: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT32: + break; + + default: + + META_ASSERT_FAIL(md, "acl field data used on udf match can be only primitive type"); } + + break; } + META_ASSERT_FAIL(md, "acl field may only be set on acl field and udf match"); + break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT8: @@ -1480,128 +1634,514 @@ void check_attr_vlan( if (md->isvlan) { - if (md->attrvaluetype != SAI_ATTR_VALUE_TYPE_UINT16) + if (md->attrvaluetype != SAI_ATTR_VALUE_TYPE_UINT16 && + md->attrvaluetype != SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT16 && + md->attrvaluetype != SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT16) { META_ASSERT_FAIL(md, "marked as vlan, but fiels has wrong attr value type"); } } } -void check_if_attr_was_already_defined( - _In_ const sai_attr_metadata_t* md) +void check_condition_in_range( + _In_ const sai_attr_metadata_t* md, + _In_ size_t length, + _In_ const sai_attr_condition_t **conditions, + _In_ sai_attr_id_t start, + _In_ sai_attr_id_t end) { META_LOG_ENTER(); - const defined_attr_t *p = defined_attributes; + size_t index = 0; - while (p) + for (; index < length; ++index) { - if (p->metadata != NULL) + const sai_attr_condition_t* c = conditions[index]; + + if (c->attrid < start || c->attrid > end) { - if (p->metadata->objecttype == md->objecttype && - p->metadata->attrid == md->attrid) - { - META_ASSERT_FAIL(md, "attribute was already declared"); - } + continue; } - p = p->next; + META_ASSERT_FAIL(md, "has condition depending on acl field / action, not allowed"); } } -void define_attr( +void check_attr_acl_conditions( _In_ const sai_attr_metadata_t* md) { META_LOG_ENTER(); - defined_attr_t *p = (defined_attr_t*)malloc(sizeof(defined_attr_t)); - - p->metadata = md; - p->next = defined_attributes; + /* + * Purpose of this check is to find out if there is any condition in + * attributes that depends on acl entry object field or actions since such + * dependency has no sense. + */ - defined_attributes = p; -} + if (md->objecttype == SAI_OBJECT_TYPE_ACL_TABLE) + { + check_condition_in_range(md, md->validonlylength, md->validonly, + SAI_ACL_TABLE_ATTR_FIELD_START, SAI_ACL_TABLE_ATTR_FIELD_END); -void check_single_attribute( - _In_ const sai_attr_metadata_t* md) -{ - META_LOG_ENTER(); + check_condition_in_range(md, md->conditionslength, md->conditions, + SAI_ACL_TABLE_ATTR_FIELD_START, SAI_ACL_TABLE_ATTR_FIELD_END); - META_LOG_INFO("performing metadata sanity check: object type %d, attr id: %d", md->objecttype, md->attrid); + if (md->attrid >= SAI_ACL_TABLE_ATTR_FIELD_START && + md->attrid >= SAI_ACL_TABLE_ATTR_FIELD_END) + { + if (md->conditionslength != 0 || md->validonlylength != 0) + { + META_ASSERT_FAIL(md, "acl table field has conditions, not allowed"); + } + } + } - META_ASSERT_NOT_NULL(md->attridname); + if (md->objecttype == SAI_OBJECT_TYPE_ACL_ENTRY) + { + check_condition_in_range(md, md->validonlylength, md->validonly, + SAI_ACL_ENTRY_ATTR_FIELD_START, SAI_ACL_ENTRY_ATTR_FIELD_END); - check_if_attr_was_already_defined(md); - check_attr_object_type(md); - check_attr_value_type_range(md); - check_attr_flags(md); - check_attr_object_type_provided(md); - check_attr_allowed_object_types(md); - check_attr_default_required(md); - check_attr_enums(md); - check_attr_default_value_type(md); - check_attr_conditions(md); - check_attr_enum_list_condition(md); - check_attr_validonly(md); - check_attr_enum_list_validonly(md); - check_attr_allow_flags(md); - check_attr_get_save(md); - check_attr_key(md); - check_attr_acl_fields(md); - check_attr_vlan(md); - check_attr_object_id_allownull(md); + check_condition_in_range(md, md->conditionslength, md->conditions, + SAI_ACL_ENTRY_ATTR_FIELD_START, SAI_ACL_ENTRY_ATTR_FIELD_END); - define_attr(md); -} + check_condition_in_range(md, md->validonlylength, md->validonly, + SAI_ACL_ENTRY_ATTR_ACTION_START, SAI_ACL_ENTRY_ATTR_ACTION_END); -void check_single_object_type_attributes( - _In_ const sai_attr_metadata_t** attributes) -{ - META_LOG_ENTER(); + check_condition_in_range(md, md->conditionslength, md->conditions, + SAI_ACL_ENTRY_ATTR_ACTION_START, SAI_ACL_ENTRY_ATTR_ACTION_END); - size_t index = 0; + if (md->attrid >= SAI_ACL_ENTRY_ATTR_FIELD_START && + md->attrid >= SAI_ACL_ENTRY_ATTR_FIELD_END) + { + if (md->conditionslength != 0 || md->validonlylength != 0) + { + META_ASSERT_FAIL(md, "acl entry field has conditions, not allowed"); + } + } - for (; attributes[index] != NULL; ++index) - { - check_single_attribute(attributes[index]); + if (md->attrid >= SAI_ACL_ENTRY_ATTR_ACTION_START && + md->attrid >= SAI_ACL_ENTRY_ATTR_ACTION_END) + { + if (md->conditionslength != 0 || md->validonlylength != 0) + { + META_ASSERT_FAIL(md, "acl entry action has conditions, not allowed"); + } + } } } -void check_object_infos() +void check_attr_reverse_graph( + _In_ const sai_attr_metadata_t* md) { META_LOG_ENTER(); - size_t i = SAI_OBJECT_TYPE_NULL; + /* + * Purpose of this method is to check whether any defined attribute with is + * object id type is defined in reverse graph correctly. Read only objects + * are also included. + */ - for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + size_t index = 0; + + for (; index < md->allowedobjecttypeslength; index++) { - const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + /* + * for each defined object id on that list we need to check + * if its defined correctly in reverse graph + */ - if (info == NULL) - { - continue; - } + sai_object_type_t depobjecttype = md->allowedobjecttypes[index]; - META_ASSERT_TRUE(info->objecttype == i, "object type mismatch"); + const sai_object_type_info_t *oi = sai_all_object_type_infos[depobjecttype]; - META_LOG_INFO("processing object type: %s", sai_metadata_get_object_type_name((sai_object_type_t)i)); + META_ASSERT_NOT_NULL(oi->revgraphmembers); - META_ASSERT_TRUE(info->attridstart == 0, "attribute enum start should be zero"); - META_ASSERT_TRUE(info->attridend > 0, "attribute enum end must be > 0"); + size_t revidx = 0; - const sai_attr_metadata_t** const meta = info->attrmetadata; + bool defined = false; - META_ASSERT_NOT_NULL(meta); + for (; oi->revgraphmembers[revidx] != NULL; revidx++) + { + /* + * now let's search for graph member which defines + * this object and the same attribute value + */ - size_t index = 0; + const sai_rev_graph_member_t *rm = oi->revgraphmembers[revidx]; - int last = -1; + META_ASSERT_TRUE(rm->objecttype == depobjecttype, "invalid objecttype definition"); - /* check all listed attributes under this object type */ + if (rm->depobjecttype != md->objecttype) + { + /* + * this is not the member we are looking for + */ - for (; meta[index] != NULL; ++index) - { - const sai_attr_metadata_t* am = meta[index]; + continue; + } + + if (rm->attrmetadata == NULL) + { + META_ASSERT_NOT_NULL(rm->structmember); + + /* + * object is defined on non object id, + * this will require different method to check + */ + + META_ASSERT_FAIL(md, "This is attribute, it can't be defined in struct member"); + } + else + { + /* + * object is attribute + */ + + META_ASSERT_NOT_NULL(rm->attrmetadata); + META_ASSERT_NULL(rm->structmember); + + size_t i = 0; + + for (; i < rm->attrmetadata->allowedobjecttypeslength; i++) + { + /* + * Object type of graph member must match and also + * attribute id must match. + */ + + if (rm->attrmetadata->allowedobjecttypes[i] == depobjecttype && + rm->attrmetadata->attrid == md->attrid) + { + META_LOG_INFO("dep %s ot %s attr %s\n", + metadata_enum_sai_object_type_t.valuesnames[depobjecttype], + metadata_enum_sai_object_type_t.valuesnames[md->objecttype], + md->attridname); + + defined = true; + break; + } + } + + if (defined) + { + break; + } + } + } + + META_ASSERT_TRUE(defined, "reverse graph object is not defined anywhere"); + } +} + +void check_if_attr_was_already_defined( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + const defined_attr_t *p = defined_attributes; + + while (p) + { + if (p->metadata != NULL) + { + if (p->metadata->objecttype == md->objecttype && + p->metadata->attrid == md->attrid) + { + META_ASSERT_FAIL(md, "attribute was already declared"); + } + } + + p = p->next; + } +} + +void check_attr_acl_capability( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + if (md->attrvaluetype != SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY) + { + return; + } + + if (md->flags != SAI_ATTR_FLAGS_READ_ONLY) + { + META_ASSERT_FAIL(md, "attribute marked as acl capability should be READ_ONLY"); + } +} + +void define_attr( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + defined_attr_t *p = (defined_attr_t*)malloc(sizeof(defined_attr_t)); + + p->metadata = md; + p->next = defined_attributes; + + defined_attributes = p; +} + +void check_attr_acl_field_or_action( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + /* + * Purpose of this test is to check if respective flags are set to true on + * acl field or action. + */ + + if ((md->isaclfield | md->isaclaction) != sai_metadata_is_acl_field_or_action(md)) + { + META_ASSERT_FAIL(md, "isaclfield or isaclaction don't match utils method"); + } + + if (md->objecttype != SAI_OBJECT_TYPE_ACL_ENTRY) + { + META_ASSERT_FALSE(md->isaclfield, "field should be not marked as acl field"); + META_ASSERT_FALSE(md->isaclaction, "field should be not marked as acl action"); + + return; + } + + if (md->attrid >= SAI_ACL_ENTRY_ATTR_FIELD_START && + md->attrid <= SAI_ACL_ENTRY_ATTR_FIELD_END) + { + META_ASSERT_TRUE(md->isaclfield, "field should be marked as acl field"); + META_ASSERT_FALSE(md->isaclaction, "field should be not marked as acl action"); + } + + if (md->attrid >= SAI_ACL_ENTRY_ATTR_ACTION_START && + md->attrid <= SAI_ACL_ENTRY_ATTR_ACTION_END) + { + META_ASSERT_FALSE(md->isaclfield, "field should not be marked as acl field"); + META_ASSERT_TRUE(md->isaclaction, "field should be marked as acl action"); + } +} + +void check_attr_existing_objects( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + /* + * Purpose of this test it to find attributes on objects exisring already + * on the switch with attributes that are mandatory on create and create + * and set. Those attributes can be changed by user fro previous value, + * and this causes problem for comparison logic to bring those objects to + * default value. We need to store those initial values of created objects + * somewhere. + */ + + if (sai_all_object_type_infos[md->objecttype]->isnonobjectid) + { + return; + } + + switch (md->objecttype) + { + /* + * Those objects are not existing on the switch by default user needs + * to crete them. + */ + + case SAI_OBJECT_TYPE_SAMPLEPACKET: + case SAI_OBJECT_TYPE_HOSTIF_TRAP: + case SAI_OBJECT_TYPE_MIRROR_SESSION: + return; + + /* + * Those objects are objects which exist already on the switch, to bring + * back them to default state by comparison logic, we should not have any + * MANDATORY_ON_CREATE attributes on them. + */ + + case SAI_OBJECT_TYPE_VLAN_MEMBER: + case SAI_OBJECT_TYPE_VLAN: + case SAI_OBJECT_TYPE_HASH: + case SAI_OBJECT_TYPE_STP: + case SAI_OBJECT_TYPE_VIRTUAL_ROUTER: + case SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP: + case SAI_OBJECT_TYPE_SWITCH: + case SAI_OBJECT_TYPE_PORT: + case SAI_OBJECT_TYPE_QUEUE: + case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP: + case SAI_OBJECT_TYPE_SCHEDULER_GROUP: + default: + break; + } + + if (!HAS_FLAG_MANDATORY_ON_CREATE(md->flags) || !HAS_FLAG_CREATE_AND_SET(md->flags)) + { + return; + } + + /* + * If attribute is mandatory on create and create and set then there is no + * default value on created object, and user can change it's value so in + * comparison logic we will need to mantain this state somewhere as + * default. + */ + + /* + * Currently we are limiting value types on existing objects that are + * mandatory on create to primitive values. + */ + + switch (md->attrvaluetype) + { + case SAI_ATTR_VALUE_TYPE_UINT32: + case SAI_ATTR_VALUE_TYPE_INT32: + case SAI_ATTR_VALUE_TYPE_INT8: + + /* + * Primitives we can skip for now, just left as was set by user + * with warning in syslog. + */ + + break; + + case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + + if (md->allownullobjectid) + { + /* + * If object allows NULL object id then we assume that this can + * be used as default value. + */ + + return; + } + + /* + * When type is object id we need to store it's previous value + * since we will not be albe to bring it to default. + */ + + META_WARN_LOG("Default value needs to be stored %s", md->attridname); + + break; + + default: + + META_ASSERT_FAIL(md, "not supported attr value type on existing object"); + } + + /* TODO there is default .1Q Bridge present */ +} + +void check_attr_sai_pointer( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + /* + * Purpose of this test is to check whether sai_pointer_t + * is only used on SAI_OBJECT_TYPE_SWITCH. + */ + + if (md->objecttype == SAI_OBJECT_TYPE_SWITCH) + { + return; + } + + if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_POINTER) + { + META_ASSERT_FAIL(md, "attribute value pointer is only allowed on SAI_OBJECT_TYPE_SWITCH"); + } +} + +void check_single_attribute( + _In_ const sai_attr_metadata_t* md) +{ + META_LOG_ENTER(); + + META_LOG_INFO("performing metadata sanity check: object type %d, attr id: %d", md->objecttype, md->attrid); + + META_ASSERT_NOT_NULL(md->attridname); + + check_if_attr_was_already_defined(md); + check_attr_object_type(md); + check_attr_value_type_range(md); + check_attr_flags(md); + check_attr_object_type_provided(md); + check_attr_allowed_object_types(md); + check_attr_default_required(md); + check_attr_enums(md); + check_attr_default_value_type(md); + check_attr_conditions(md); + check_attr_enum_list_condition(md); + check_attr_validonly(md); + check_attr_enum_list_validonly(md); + check_attr_allow_flags(md); + check_attr_get_save(md); + check_attr_key(md); + check_attr_acl_fields(md); + check_attr_vlan(md); + check_attr_object_id_allownull(md); + check_attr_acl_capability(md); + check_attr_reverse_graph(md); + check_attr_acl_conditions(md); + check_attr_acl_field_or_action(md); + check_attr_existing_objects(md); + check_attr_sai_pointer(md); + + define_attr(md); +} + +void check_single_object_type_attributes( + _In_ const sai_attr_metadata_t** attributes) +{ + META_LOG_ENTER(); + + size_t index = 0; + + for (; attributes[index] != NULL; ++index) + { + check_single_attribute(attributes[index]); + } +} + +void check_object_infos() +{ + META_LOG_ENTER(); + + size_t i = SAI_OBJECT_TYPE_NULL; + + for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + { + const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + + if (info == NULL) + { + continue; + } + + META_ASSERT_TRUE(info->objecttype == i, "object type mismatch"); + + META_ASSERT_NOT_NULL(info->objecttypename); + + META_LOG_INFO("processing object type: %s", sai_metadata_get_object_type_name((sai_object_type_t)i)); + + META_ASSERT_TRUE(info->attridstart == 0, "attribute enum start should be zero"); + META_ASSERT_TRUE(info->attridend > 0, "attribute enum end must be > 0"); + + const sai_attr_metadata_t** const meta = info->attrmetadata; + + META_ASSERT_NOT_NULL(meta); + + size_t index = 0; + + int last = -1; + + /* check all listed attributes under this object type */ + + for (; meta[index] != NULL; ++index) + { + const sai_attr_metadata_t* am = meta[index]; META_ASSERT_TRUE((int)am->attrid >= 0, "attribute must be non negative"); META_ASSERT_TRUE(last < (int)am->attrid, "attributes are not incresing"); @@ -1623,36 +2163,479 @@ void check_object_infos() continue; } - if (info->objecttype == SAI_OBJECT_TYPE_ACL_ENTRY || - info->objecttype == SAI_OBJECT_TYPE_ACL_TABLE) + META_ASSERT_FAIL(am, "attr is is not in start .. end range"); + } + + META_ASSERT_NOT_NULL(info->enummetadata); + + if (index != info->attridend) + { + if (is_flag_enum(info->enummetadata)) + { + /* ok, flags */ + } + else + { + META_ENUM_ASSERT_FAIL(info->enummetadata, "end of attributes don't match attr count on %s", + sai_metadata_get_object_type_name((sai_object_type_t)i)); + } + } + } +} + +void check_non_object_id_object_types() +{ + META_LOG_ENTER(); + + size_t i = SAI_OBJECT_TYPE_NULL; + + for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + { + const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + + if (info == NULL) + { + continue; + } + + if (!info->isnonobjectid) + { + if (info->structmemberscount != 0 || + info->structmembers != NULL) + { + META_FAIL("object type %zu is non object id but struct members defined", i); + } + + continue; + } + + META_ASSERT_TRUE(info->structmemberscount != 0, "non object id should have members defined"); + META_ASSERT_NOT_NULL(info->structmembers); + + /* check each member of the struct */ + + size_t j = 0; + + int member_supports_switch_id = 0; + + for (; j < info->structmemberscount; ++j) + { + META_ASSERT_NOT_NULL(info->structmembers[j]); + + const sai_struct_member_info_t *m = info->structmembers[j]; + + META_ASSERT_NOT_NULL(m->membername); + + switch (m->membervaluetype) + { + case SAI_ATTR_VALUE_TYPE_MAC: + case SAI_ATTR_VALUE_TYPE_INT32: + case SAI_ATTR_VALUE_TYPE_UINT16: + case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: + case SAI_ATTR_VALUE_TYPE_IP_PREFIX: + case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + break; + + default: + + /* + * On struct members only primitive types should be + * supported so no other structs or lists. + */ + + META_FAIL("struct member %s have invalid value type %d", m->membername, m->membervaluetype); + } + + if (m->isenum) + { + META_ASSERT_NOT_NULL(m->enummetadata); + + META_ASSERT_TRUE(m->membervaluetype == SAI_ATTR_VALUE_TYPE_INT32, + "when enum is defined in struct member non objectid its type must be INT32"); + } + else + { + META_ASSERT_NULL(m->enummetadata); + } + + if (m->isvlan) + { + META_ASSERT_TRUE(m->membervaluetype == SAI_ATTR_VALUE_TYPE_UINT16, "member marked as vlan, but wrong type specified"); + } + + if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) + { + META_ASSERT_NOT_NULL(m->getoid); + META_ASSERT_NOT_NULL(m->setoid); + META_ASSERT_NOT_NULL(m->allowedobjecttypes); + META_ASSERT_TRUE(m->allowedobjecttypeslength > 0, "struct member object id, should specify some object types"); + + /* + * this check can be relaxed in the future, but currently + * supporting only one object type in non object id make sense + */ + + META_ASSERT_TRUE(m->allowedobjecttypeslength == 1, "currently struct member object id, should specify only one object type"); + + size_t k = 0; + + for (; k < m->allowedobjecttypeslength; k++) + { + sai_object_type_t ot = m->allowedobjecttypes[k]; + + if (ot >= SAI_OBJECT_TYPE_NULL && ot <= SAI_OBJECT_TYPE_MAX) + { + if (ot == SAI_OBJECT_TYPE_SWITCH) + { + /* + * to make struct object type complete, at least + * one struct member should be type of switch + */ + + member_supports_switch_id++; + } + + /* non object id struct can't contain object id which is also non object id */ + + const sai_object_type_info_t* sinfo = sai_all_object_type_infos[ot]; + + META_ASSERT_NOT_NULL(sinfo); + + if (sinfo->isnonobjectid) + { + META_FAIL("struct member %s of non object id type can't be used as object id in non object id struct: %s", + m->membername, + sai_metadata_get_object_type_name(ot)); + } + + continue; + } + + META_FAIL("invalid object type specified on file %s: %d", m->membername, ot); + } + } + else + { + META_ASSERT_NULL(m->getoid); + META_ASSERT_NULL(m->setoid); + META_ASSERT_NULL(m->allowedobjecttypes); + META_ASSERT_TRUE(m->allowedobjecttypeslength == 0, "member is not object id, should not specify object types"); + } + } + + META_ASSERT_TRUE(member_supports_switch_id == 1, "there should be only one struct member that support switch id object type"); + + META_ASSERT_NULL(info->structmembers[j]); + } +} + +void check_non_object_id_object_attrs() +{ + META_LOG_ENTER(); + + size_t i = SAI_OBJECT_TYPE_NULL; + + for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + { + const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + + if (info == NULL || !info->isnonobjectid) + { + continue; + } + + const sai_attr_metadata_t** meta = info->attrmetadata; + + META_ASSERT_NOT_NULL(meta); + + size_t idx = 0; + + /* iterate all attributes on non object id type */ + + for (; meta[idx] != NULL; ++idx) + { + const sai_attr_metadata_t* m = meta[idx]; + + META_ASSERT_NOT_NULL(m); + + switch ((int)m->flags) + { + case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: + case SAI_ATTR_FLAGS_CREATE_AND_SET: + break; + + default: + + META_ASSERT_FAIL(m, "non object id attribute has invalid flags: 0x%x (should be CREATE_AND_SET)", m->flags); + } + } + } +} + +void check_attr_sorted_by_id_name() +{ + META_LOG_ENTER(); + + size_t i = 0; + + const char *last = "AAA"; + + META_ASSERT_TRUE(metadata_attr_sorted_by_id_name_count > 500, + "there should be at least 500 attributes in total"); + + for (; i < metadata_attr_sorted_by_id_name_count; ++i) + { + const sai_attr_metadata_t *am = metadata_attr_sorted_by_id_name[i]; + + META_ASSERT_NOT_NULL(am); + + const char *name = am->attridname; + + if (strcmp(last, name) >= 0) + { + META_ASSERT_FAIL(am, "attribute id name in not sorted alphabetical"); + } + + META_ASSERT_TRUE(strncmp(name, "SAI_", 4) == 0, "all attributes should start with SAI_"); + + last = name; + } + + META_ASSERT_NULL(metadata_attr_sorted_by_id_name[i]); + + /* check search */ + + for (i = 0; i < metadata_attr_sorted_by_id_name_count; ++i) + { + const sai_attr_metadata_t *am = metadata_attr_sorted_by_id_name[i]; + + META_LOG_INFO("search for %s", am->attridname); + + const sai_attr_metadata_t *found = sai_metadata_get_attr_metadata_by_attr_id_name(am->attridname); + + META_ASSERT_NOT_NULL(found); + + META_ASSERT_TRUE(strcmp(found->attridname, am->attridname) == 0, "search attr by id name failed to find"); + } + + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name(NULL)); /* null pointer */ + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("AAA")); /* before all attr names */ + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_B")); /* in the middle of attr names */ + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_P")); /* in the middle of attr names */ + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_W")); /* in the middle of attr names */ + META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("ZZZ")); /* after all attr names */ +} + +void list_loop( + _In_ const sai_object_type_info_t* info, + _In_ const sai_object_type_t *visited, + _In_ const uint32_t *attributes, + _In_ int levelidx, + _In_ int level) +{ + META_LOG_ENTER(); + + META_WARN_LOG("LOOP DETECTED on object type: %s", + metadata_enum_sai_object_type_t.valuesnames[info->objecttype]); + + for (; levelidx < level; ++levelidx) + { + sai_object_type_t ot = visited[levelidx]; + + const char* ot_name = metadata_enum_sai_object_type_t.valuesnames[ot]; + + const sai_attr_metadata_t* m = sai_metadata_get_attr_metadata(ot, attributes[levelidx]); + + META_WARN_LOG(" %s: %s", ot_name, m->attridname); + } + + META_WARN_LOG(" -> %s", metadata_enum_sai_object_type_t.valuesnames[info->objecttype]); + + if (level >= 0) + { + META_FAIL("LOOP is detected, we can't have loops in graph, please fix attributes"); + } +} + +void check_objects_for_loops_recursive( + _In_ const sai_object_type_info_t* info, + _Inout_ sai_object_type_t *visited, + _Inout_ uint32_t *attributes, + _In_ int level) +{ + META_LOG_ENTER(); + + visited[level] = info->objecttype; + + int levelidx = 0; + + for (; levelidx < level; ++levelidx) + { + if (visited[levelidx] == info->objecttype) + { + /* object type is already defined, so we have a loop */ + + list_loop(info, visited, attributes, levelidx, level); + + return; + } + } + + const sai_attr_metadata_t** meta = info->attrmetadata; + + META_ASSERT_NOT_NULL(meta); + + size_t idx = 0; + + /* iterate all attributes on non object id type */ + + for (; meta[idx] != NULL; ++idx) + { + const sai_attr_metadata_t* m = meta[idx]; + + META_ASSERT_NOT_NULL(m); + + if (HAS_FLAG_READ_ONLY(m->flags)) + { + /* skip read only attributes since with those we will have loops for sure */ + + continue; + } + + /* skip known loops */ + + if (m->objecttype == SAI_OBJECT_TYPE_PORT) + { + if (m->attrid == SAI_PORT_ATTR_EGRESS_MIRROR_SESSION || + m->attrid == SAI_PORT_ATTR_INGRESS_MIRROR_SESSION || + m->attrid == SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST) + { + continue; + } + } + + if (m->objecttype == SAI_OBJECT_TYPE_SCHEDULER_GROUP && + m->attrid == SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE) + { + continue; + } + + attributes[level] = m->attrid; + + switch (m->attrvaluetype) + { + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + + { + size_t j = 0; + + for (; j < m->allowedobjecttypeslength; ++j) + { + const sai_object_type_info_t* next = sai_all_object_type_infos[ m->allowedobjecttypes[j] ]; + + check_objects_for_loops_recursive(next, visited, attributes, level + 1); + } + } + + break; + + default: + break; + } + } + + /* iterate for struct members on non object id object types */ + + if (info->isnonobjectid) + { + size_t j = 0; + + for (; j < info->structmemberscount; ++j) + { + const sai_struct_member_info_t *m = info->structmembers[j]; + + if (m->membervaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID) { continue; } - META_ASSERT_FAIL(am, "attr is is not in start .. end range"); + size_t k = 0; + + for (; k < m->allowedobjecttypeslength; k++) + { + const sai_object_type_info_t* next = sai_all_object_type_infos[ m->allowedobjecttypes[k] ]; + + check_objects_for_loops_recursive(next, visited, attributes, level + 1); + } + } + } + + /* clear level on exit */ + + visited[level] = SAI_OBJECT_TYPE_NULL; + attributes[level] = 0; +} + +void check_objects_for_loops() +{ + META_LOG_ENTER(); + + sai_object_type_t visited_objects[SAI_OBJECT_TYPE_MAX]; + uint32_t visited_attributes[SAI_OBJECT_TYPE_MAX]; + + size_t i = SAI_OBJECT_TYPE_NULL; + + for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + { + const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + + if (info == NULL) + { + continue; } - META_ASSERT_NOT_NULL(info->enummetadata); + memset(visited_objects, 0, SAI_OBJECT_TYPE_MAX * sizeof(sai_object_type_t)); + memset(visited_attributes, 0, SAI_OBJECT_TYPE_MAX * sizeof(uint32_t)); - if (index != info->attridend) - { - if (is_flag_enum(info->enummetadata)) - { - /* ok, flags */ - } - else - { - META_ENUM_ASSERT_FAIL(info->enummetadata, "end of attributes don't match attr count on %s", - sai_metadata_get_object_type_name((sai_object_type_t)i)); - } - } + check_objects_for_loops_recursive(info, visited_objects, visited_attributes, 0); } } -void check_non_object_id_object_types() +void check_null_object_id() +{ + META_LOG_ENTER(); + + /* + * Purpose of this check is to make sure that + * SAI_NULL_OBJECT_ID is always ZERO. + */ + + META_ASSERT_TRUE(SAI_NULL_OBJECT_ID == 0, "SAI_NULL_OBJECT_ID must be zero"); +} + +void check_read_only_attributes() { META_LOG_ENTER(); + /* + * Purpose of this check is to find out if there is any + * object that has only READ_ONLY attributes. + * + * If given object has only read only attributes + * there should be no purpose of such object. + * With only read only attributes there is no + * way to compare 2 objects of the same type + * sine we don't track read only attributes. + * + * As additional check we will also check if given + * object type defines at least 1 attribute. + */ + size_t i = SAI_OBJECT_TYPE_NULL; for (; i <= SAI_OBJECT_TYPE_MAX; ++i) @@ -1664,104 +2647,475 @@ void check_non_object_id_object_types() continue; } - if (!info->isnonobjectid) + size_t index = 0; + + /* check all listed attributes under this object type */ + + int non_read_only_count = 0; + + const sai_attr_metadata_t** const meta = info->attrmetadata; + + for (; meta[index] != NULL; ++index) { - if (info->structmemberscount != 0 || - info->structmembers != NULL) + const sai_attr_metadata_t* m = meta[index]; + + if (!HAS_FLAG_READ_ONLY(m->flags)) { - META_FAIL("object type %zu is non object id but struct members defined", i); + non_read_only_count++; } + } - continue; + if (index < 1) + { + META_FAIL("object %s must define at least 1 attribute", + sai_metadata_get_object_type_name((sai_object_type_t)i)); } - META_ASSERT_TRUE(info->structmemberscount != 0, "non object id should have members defined"); - META_ASSERT_NOT_NULL(info->structmembers); + if (non_read_only_count == 0) + { + /* + * currently we have some objects with only read only + * attributes, we for now we just warn here until this + * issue will be resolved. + */ + + META_WARN_LOG("object %s has only READ_ONLY attributes", + metadata_enum_sai_object_type_t.valuesnames[i]); + } + } +} - /* check each member of the struct */ +void check_mixed_object_list_types() +{ + META_LOG_ENTER(); - size_t j = 0; + /* + * Purpose of this check is to find out if any of object id lists supports + * multiple object types at the same time. For now this abbility will not + * be supported. + */ - bool member_supports_switch_id = false; + META_ASSERT_TRUE(metadata_attr_sorted_by_id_name_count > 500, "there should be at least 500 attributes in total"); - for (; j < info->structmemberscount; ++j) + size_t idx = 0; + + for (; idx < metadata_attr_sorted_by_id_name_count; ++idx) + { + const sai_attr_metadata_t* meta = metadata_attr_sorted_by_id_name[idx]; + + switch (meta->attrvaluetype) { - META_ASSERT_NOT_NULL(info->structmembers[j]); + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: - const sai_struct_member_info_t *m = info->structmembers[j]; + META_ASSERT_TRUE(meta->allowedobjecttypeslength > 0, "allowed object types on list can't be zero"); - META_ASSERT_NOT_NULL(m->membername); + if (meta->allowedobjecttypeslength == 1) + { + continue; + } - switch (m->membervaluetype) - { - case SAI_ATTR_VALUE_TYPE_MAC: - case SAI_ATTR_VALUE_TYPE_INT32: - case SAI_ATTR_VALUE_TYPE_UINT16: - case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: - case SAI_ATTR_VALUE_TYPE_IP_PREFIX: - case SAI_ATTR_VALUE_TYPE_OBJECT_ID: - break; + if (meta->flags == SAI_ATTR_FLAGS_READ_ONLY) + { + /* + * If attribute flag is READ_ONLY, then object can support + * mixed object types returned on list, for example + * SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST when it returns + * schedulers and queues. + */ + } + else + { + /* + * For non read only attributes, there should be a good + * reason why object list should support mixed object + * types on that list. Then this restriction can be + * relaxed and description should be added why mixed + * object types should be possible. + */ - default: + META_ASSERT_FAIL(meta, "allowed object types on object id list is more then 1, not supported yet"); + } - META_FAIL("struct member %s have invalid value type %d", m->membername, m->membervaluetype); - } + break; - if (m->isvlan) - { - META_ASSERT_TRUE(m->membervaluetype == SAI_ATTR_VALUE_TYPE_UINT16, "member marked as vlan, but wrong type specified"); - } + default: - if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) + META_ASSERT_FALSE(meta->allowmixedobjecttypes, "allow mixed object types should be false on non object id list"); + break; + } + } +} + +/* + * Below are defined all generic methods needed for api name check + */ + +typedef sai_status_t (*generic_create_fn)( + _Out_ sai_object_id_t *object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +typedef sai_status_t (*generic_remove_fn)( + _In_ sai_object_id_t object_id); + +typedef sai_status_t (*generic_set_fn)( + _In_ sai_object_id_t object_id, + _In_ const sai_attribute_t *attr); + +typedef sai_status_t (*generic_get_fn)( + _In_ sai_object_id_t object_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +typedef sai_status_t(*switch_create_fn)( + _Out_ sai_object_id_t* switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +void check_api_names() +{ + META_LOG_ENTER(); + + /* + * Purpose of this check is to find out if all api names correspond to + * actual object names and follow convention name and the same signature + * except some special objects. Currently this test is performed here + * manually, but it could be coverted to automatic generated test using + * parse.pl script. + * + * NOTE: Currently all new objects needs to be added here manually. + */ + + sai_object_type_t checked[SAI_OBJECT_TYPE_MAX]; + + memset(checked, 0, SAI_OBJECT_TYPE_MAX * sizeof(sai_object_type_t)); + + void *dummy = NULL; + +#define CHECK_API(apiname, short_object_type, object_type)\ + {\ + sai_ ## apiname ## _api_t apiname ## _api;\ + checked[(int)object_type] = object_type;\ + \ + generic_create_fn create = apiname ## _api.create_ ## short_object_type;\ + generic_remove_fn remove = apiname ## _api.remove_ ## short_object_type;\ + generic_set_fn set = apiname ## _api.set_ ## short_object_type ## _attribute;\ + generic_get_fn get = apiname ## _api.get_ ## short_object_type ## _attribute;\ + sai_create_ ## short_object_type ## _fn cr = NULL;\ + sai_remove_ ## short_object_type ## _fn re = NULL;\ + sai_set_ ## short_object_type ## _attribute_fn se = NULL;\ + sai_get_ ## short_object_type ## _attribute_fn ge = NULL;\ + dummy = &create;\ + dummy = &remove;\ + dummy = &set;\ + dummy = &get;\ + dummy = &cr;\ + dummy = &re;\ + dummy = &se;\ + dummy = ≥\ + } + + /* + * Rule here is that SECOND parameter should be exact match for object name + * but lower case, for example: CHECK_API(foo, xyz, SAI_OBJECT_TYPE_XYZ); + */ + + CHECK_API(port, port, SAI_OBJECT_TYPE_PORT); + CHECK_API(lag, lag, SAI_OBJECT_TYPE_LAG); + CHECK_API(virtual_router, virtual_router, SAI_OBJECT_TYPE_VIRTUAL_ROUTER); + CHECK_API(next_hop, next_hop, SAI_OBJECT_TYPE_NEXT_HOP); + CHECK_API(router_interface, router_interface, SAI_OBJECT_TYPE_ROUTER_INTERFACE); + CHECK_API(acl, acl_table, SAI_OBJECT_TYPE_ACL_TABLE); + CHECK_API(acl, acl_entry, SAI_OBJECT_TYPE_ACL_ENTRY); + CHECK_API(acl, acl_counter, SAI_OBJECT_TYPE_ACL_COUNTER); + CHECK_API(acl, acl_range, SAI_OBJECT_TYPE_ACL_RANGE); + CHECK_API(acl, acl_table_group, SAI_OBJECT_TYPE_ACL_TABLE_GROUP); + CHECK_API(acl, acl_table_group_member, SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER); + CHECK_API(hostif, hostif, SAI_OBJECT_TYPE_HOSTIF); + CHECK_API(mirror, mirror_session, SAI_OBJECT_TYPE_MIRROR_SESSION); + CHECK_API(samplepacket, samplepacket, SAI_OBJECT_TYPE_SAMPLEPACKET); + CHECK_API(stp, stp, SAI_OBJECT_TYPE_STP); + CHECK_API(hostif, hostif_trap_group, SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP); + CHECK_API(policer, policer, SAI_OBJECT_TYPE_POLICER); + CHECK_API(wred, wred, SAI_OBJECT_TYPE_WRED); + CHECK_API(qos_map, qos_map, SAI_OBJECT_TYPE_QOS_MAP); + CHECK_API(queue, queue, SAI_OBJECT_TYPE_QUEUE); + CHECK_API(scheduler, scheduler, SAI_OBJECT_TYPE_SCHEDULER); + CHECK_API(scheduler_group, scheduler_group, SAI_OBJECT_TYPE_SCHEDULER_GROUP); + CHECK_API(buffer, buffer_pool, SAI_OBJECT_TYPE_BUFFER_POOL); + CHECK_API(buffer, buffer_profile, SAI_OBJECT_TYPE_BUFFER_PROFILE); + CHECK_API(buffer, ingress_priority_group, SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP); + CHECK_API(lag, lag_member, SAI_OBJECT_TYPE_LAG_MEMBER); + CHECK_API(hash, hash, SAI_OBJECT_TYPE_HASH); + CHECK_API(udf, udf, SAI_OBJECT_TYPE_UDF); + CHECK_API(udf, udf_match, SAI_OBJECT_TYPE_UDF_MATCH); + CHECK_API(udf, udf_group, SAI_OBJECT_TYPE_UDF_GROUP); + CHECK_API(hostif, hostif_trap, SAI_OBJECT_TYPE_HOSTIF_TRAP); + CHECK_API(hostif, hostif_table_entry, SAI_OBJECT_TYPE_HOSTIF_TABLE_ENTRY); + CHECK_API(vlan, vlan, SAI_OBJECT_TYPE_VLAN); + CHECK_API(vlan, vlan_member, SAI_OBJECT_TYPE_VLAN_MEMBER); + + /* + * hostif packet is special since its not a real object but represents + * attruibutes received from host interface. + */ + + checked[(int)SAI_OBJECT_TYPE_HOSTIF_PACKET] = SAI_OBJECT_TYPE_HOSTIF_PACKET; + + CHECK_API(tunnel, tunnel_map, SAI_OBJECT_TYPE_TUNNEL_MAP); + CHECK_API(tunnel, tunnel, SAI_OBJECT_TYPE_TUNNEL); + CHECK_API(tunnel, tunnel_term_table_entry, SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY); + + /* + * fdb flush is special since its not a real object but represents + * attruibutes that are passed when flushng fdb entries + */ + + checked[(int)SAI_OBJECT_TYPE_FDB_FLUSH] = SAI_OBJECT_TYPE_FDB_FLUSH; + + CHECK_API(next_hop_group, next_hop_group, SAI_OBJECT_TYPE_NEXT_HOP_GROUP); + CHECK_API(next_hop_group, next_hop_group_member, SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER); + CHECK_API(stp, stp_port, SAI_OBJECT_TYPE_STP_PORT); + CHECK_API(rpf_group, rpf_group, SAI_OBJECT_TYPE_RPF_GROUP); + CHECK_API(rpf_group, rpf_group_member, SAI_OBJECT_TYPE_RPF_GROUP_MEMBER); + CHECK_API(l2mc_group, l2mc_group, SAI_OBJECT_TYPE_L2MC_GROUP); + CHECK_API(l2mc_group, l2mc_group_member, SAI_OBJECT_TYPE_L2MC_GROUP_MEMBER); + CHECK_API(ipmc_group, ipmc_group, SAI_OBJECT_TYPE_IPMC_GROUP); + CHECK_API(ipmc_group, ipmc_group_member, SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER); + CHECK_API(hostif, hostif_user_defined_trap, SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP); + CHECK_API(bridge, bridge, SAI_OBJECT_TYPE_BRIDGE); + CHECK_API(bridge, bridge_port, SAI_OBJECT_TYPE_BRIDGE_PORT); + CHECK_API(tunnel, tunnel_map_entry, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY); + +#define CHECK_ENTRY_API(apiname, entry_name, object_type)\ + {\ + typedef sai_status_t (*entry_name ## _create_fn)(\ + _In_ const sai_ ## entry_name ## _t *entry_name,\ + _In_ uint32_t attr_count,\ + _In_ const sai_attribute_t *attr_list);\ + typedef sai_status_t (*entry_name ## _remove_fn)(\ + _In_ const sai_ ## entry_name ## _t *entry_name);\ + typedef sai_status_t (*entry_name ## _set_fn)(\ + _In_ const sai_ ## entry_name ## _t *entry_name,\ + _In_ const sai_attribute_t *attr);\ + typedef sai_status_t (*entry_name ## _get_fn)(\ + _In_ const sai_ ## entry_name ## _t *entry_name,\ + _In_ uint32_t attr_count,\ + _Inout_ sai_attribute_t *attr_list);\ + \ + sai_ ## apiname ## _api_t apiname ## _api;\ + checked[(int)object_type] = object_type;\ + \ + entry_name ## _create_fn create = apiname ## _api.create_ ## entry_name;\ + entry_name ## _remove_fn remove = apiname ## _api.remove_ ## entry_name;\ + entry_name ## _set_fn set = apiname ## _api.set_ ## entry_name ## _attribute;\ + entry_name ## _get_fn get = apiname ## _api.get_ ## entry_name ## _attribute;\ + sai_create_ ## entry_name ## _fn cr = NULL;\ + sai_remove_ ## entry_name ## _fn re = NULL;\ + sai_set_ ## entry_name ## _attribute_fn se = NULL;\ + sai_get_ ## entry_name ## _attribute_fn ge = NULL;\ + dummy = &create;\ + dummy = &remove;\ + dummy = &set;\ + dummy = &get;\ + dummy = &cr;\ + dummy = &re;\ + dummy = &se;\ + dummy = ≥\ + } + + /* + * Those are objects with non object id, so we need to generate api + * definitions on the fly. + */ + + CHECK_ENTRY_API(fdb, fdb_entry, SAI_OBJECT_TYPE_FDB_ENTRY); + CHECK_ENTRY_API(neighbor, neighbor_entry, SAI_OBJECT_TYPE_NEIGHBOR_ENTRY); + CHECK_ENTRY_API(route, route_entry, SAI_OBJECT_TYPE_ROUTE_ENTRY); + CHECK_ENTRY_API(l2mc, l2mc_entry, SAI_OBJECT_TYPE_L2MC_ENTRY); + CHECK_ENTRY_API(ipmc, ipmc_entry, SAI_OBJECT_TYPE_IPMC_ENTRY); + CHECK_ENTRY_API(mcast_fdb, mcast_fdb_entry, SAI_OBJECT_TYPE_MCAST_FDB_ENTRY); + + { + /* + * Switch object is special since it create function + * don't have switch_id as input parameter + */ + + checked[(int)SAI_OBJECT_TYPE_SWITCH] = SAI_OBJECT_TYPE_SWITCH; + + sai_switch_api_t switch_api; + + switch_create_fn create = switch_api.create_switch; + generic_remove_fn remove = switch_api.remove_switch; + generic_set_fn set = switch_api.set_switch_attribute; + generic_get_fn get = switch_api.get_switch_attribute; + sai_create_switch_fn cr = NULL; + sai_remove_switch_fn re = NULL; + sai_set_switch_attribute_fn se = NULL; + sai_get_switch_attribute_fn ge = NULL; + dummy = &create; + dummy = &remove; + dummy = &set; + dummy = &get; + dummy = &cr; + dummy = &re; + dummy = &se; + dummy = ≥ + } + + if (debug) + { + /* + * to prevent warnings on not used variable + */ + printf("dummy pointer: %p", dummy); + } + + int index = SAI_OBJECT_TYPE_NULL; + + /* + * check if all objects were processed + */ + + for (; index < SAI_OBJECT_TYPE_MAX; ++index) + { + if (checked[index] != (sai_object_type_t)index) + { + META_FAIL("object %s (%d) was not added to check", + metadata_enum_sai_object_type_t.valuesnames[index], index); + } + } +} + +void check_single_non_object_id_for_rev_graph( + _In_ const sai_struct_member_info_t *sm, + _In_ sai_object_type_t objecttype, + _In_ sai_object_type_t depobjecttype) +{ + META_LOG_ENTER(); + + /* + * This method checks single non object id struct + * member. + */ + + const sai_object_type_info_t *oi = sai_all_object_type_infos[depobjecttype]; + + META_ASSERT_NOT_NULL(oi->revgraphmembers); + + size_t revidx = 0; + + bool defined = false; + + for (; oi->revgraphmembers[revidx] != NULL; revidx++) + { + /* + * now let's search for graph member which defines + * this object and the same attribute value + */ + + const sai_rev_graph_member_t *rm = oi->revgraphmembers[revidx]; + + META_ASSERT_TRUE(rm->objecttype == depobjecttype, "invalid objecttype definition"); + + if (rm->depobjecttype != objecttype) + { + /* + * this is not the member we are looking for + */ + + continue; + } + + if (rm->attrmetadata == NULL) + { + META_ASSERT_NOT_NULL(rm->structmember); + + /* + * This graph entry is struct memner, maybe this i the + * one we are looking for, since graph can have multiple + * entries for the same object. + */ + + if (strcmp(rm->structmember->membername, sm->membername) != 0) { - META_ASSERT_NOT_NULL(m->allowedobjecttypes); - META_ASSERT_TRUE(m->allowedobjecttypeslength > 0, "member is object id, should specify some object types"); + /* this is the member we are not looking for */ - size_t k = 0; + continue; + } - for (; k < m->allowedobjecttypeslength; k++) - { - sai_object_type_t ot = m->allowedobjecttypes[k]; + /* + * We found out member name, so our object must be on the object list + */ - if (ot >= SAI_OBJECT_TYPE_NULL && ot <= SAI_OBJECT_TYPE_MAX) - { - if (ot == SAI_OBJECT_TYPE_SWITCH) - { - /* - * to make struct object type complete, at least - * one struct member should be type of switch - */ + size_t i = 0; - member_supports_switch_id = true; - } + for (; i < rm->structmember->allowedobjecttypeslength; i++) + { + /* + * Object type of graph member must match and also + * attribute id must match. + */ - continue; - } + if (rm->structmember->allowedobjecttypes[i] == depobjecttype) + { + META_LOG_INFO("dep %s ot %s attr %s\n", + metadata_enum_sai_object_type_t.valuesnames[depobjecttype], + metadata_enum_sai_object_type_t.valuesnames[objecttype], + sm->membername); - META_FAIL("invalid object type specified on file %s: %d", m->membername, ot); + defined = true; + break; } } - else + + if (defined) { - META_ASSERT_NULL(m->allowedobjecttypes); - META_ASSERT_TRUE(m->allowedobjecttypeslength == 0, "member is not object id, should not specify object types"); + break; } + } + else + { + /* + * object is attribute + */ - META_ASSERT_TRUE(member_supports_switch_id, "none of struct members support switch id object type"); + META_ASSERT_NOT_NULL(rm->attrmetadata); + META_ASSERT_NULL(rm->structmember); - META_ASSERT_NULL(info->structmembers[j]); + /* + * we are not looking for attribute object + * we are looking for struct member + */ + + continue; + } } + + META_ASSERT_TRUE(defined, "reverse graph object is not defined anywhere"); } -void check_non_object_id_object_attrs() +void check_reverse_graph_for_non_object_id() { META_LOG_ENTER(); + /* + * Purpose of this check is to find out whether non object id structmembers + * which are object id are well defined inside reverse graph. Attribute + * values are checked during standard loop of attribute above. + */ + size_t i = SAI_OBJECT_TYPE_NULL; for (; i <= SAI_OBJECT_TYPE_MAX; ++i) { + sai_object_type_t objecttype = (sai_object_type_t)i; + const sai_object_type_info_t* info = sai_all_object_type_infos[i]; if (info == NULL || !info->isnonobjectid) @@ -1769,279 +3123,397 @@ void check_non_object_id_object_attrs() continue; } - const sai_attr_metadata_t** meta = info->attrmetadata; + /* + * This is non object id and they can't have graph members + * since non object id can't be used as any object id. + */ - META_ASSERT_NOT_NULL(meta); + META_ASSERT_NULL(info->revgraphmembers); - size_t idx = 0; + /* + * Now for each struct member check if it's object id member + * and process it. + */ - /* iterate all attributes on non object id type */ + size_t j = 0; - for (; meta[idx] != NULL; ++idx) + for (; j < info->structmemberscount; ++j) { - const sai_attr_metadata_t* m = meta[idx]; + const sai_struct_member_info_t *m = info->structmembers[j]; - META_ASSERT_NOT_NULL(m); + if (m->membervaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID) + { + continue; + } - switch ((int)m->flags) + size_t k = 0; + + for (; k < m->allowedobjecttypeslength; k++) { - case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: - case SAI_ATTR_FLAGS_CREATE_AND_SET: - break; + /* + * For each object type check it's location in graph + */ - default: + sai_object_type_t depobjecttype = m->allowedobjecttypes[k]; - META_WARN(m, "non object id attribute has invalid flags: 0x%x (should be CREATE_AND_SET)", m->flags); + check_single_non_object_id_for_rev_graph(m, objecttype, depobjecttype); } } } } -void check_attr_sorted_by_id_name() +void check_vlan_attributes() { META_LOG_ENTER(); - size_t i = 0; - - const char *last = "AAA"; + /* + * Purpose of this check is to make sure there in vlan object there is only + * one attribute marked as a KEY and it's a VLAN_ID and it's value type is + * UINT16. This will be helpful later on on comparison logic since we can + * have so many vlan's then searching them in hash will be much faster than + * iterating each time. + */ - META_ASSERT_TRUE(metadata_attr_sorted_by_id_name_count > 500, - "there should be at least 500 attributes in total"); + const sai_attr_metadata_t** const meta = sai_object_type_info_SAI_OBJECT_TYPE_VLAN.attrmetadata; - for (; i < metadata_attr_sorted_by_id_name_count; ++i) - { - const sai_attr_metadata_t *am = metadata_attr_sorted_by_id_name[i]; + size_t index = 0; - META_ASSERT_NOT_NULL(am); + int keys = 0; - const char *name = am->attridname; + for (; meta[index] != NULL; index++) + { + const sai_attr_metadata_t *md = meta[index]; - if (strcmp(last, name) >= 0) + if (HAS_FLAG_KEY(md->flags)) { - META_ASSERT_FAIL(am, "attribute id name in not sorted alphabetical"); + keys++; } - META_ASSERT_TRUE(strncmp(name, "SAI_", 4) == 0, "all attributes should start with SAI_"); - - last = name; - } - - META_ASSERT_NULL(metadata_attr_sorted_by_id_name[i]); - - /* check search */ - - for (i = 0; i < metadata_attr_sorted_by_id_name_count; ++i) - { - const sai_attr_metadata_t *am = metadata_attr_sorted_by_id_name[i]; - - META_LOG_INFO("search for %s", am->attridname); - - const sai_attr_metadata_t *found = sai_metadata_get_attr_metadata_by_attr_id_name(am->attridname); + if (md->attrid == SAI_VLAN_ATTR_VLAN_ID) + { + int expected_flags = (SAI_ATTR_FLAGS_MANDATORY_ON_CREATE|SAI_ATTR_FLAGS_CREATE_ONLY|SAI_ATTR_FLAGS_KEY); - META_ASSERT_NOT_NULL(found); + if ((int)md->flags != expected_flags) + { + META_ASSERT_FAIL(md, "vlan id should have flags MANDATORY_ON_CREATE | CREATE_ONLY | KEY, but has: %d", md->flags); + } - META_ASSERT_TRUE(strcmp(found->attridname, am->attridname) == 0, "search attr by id name failed to find"); + META_ASSERT_TRUE(md->attrvaluetype == SAI_ATTR_VALUE_TYPE_UINT16, "VLAN_ID should be UINT16"); + } } - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name(NULL)); /* null pointer */ - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("AAA")); /* before all attr names */ - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_B")); /* in the middle of attr names */ - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_P")); /* in the middle of attr names */ - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("SAI_W")); /* in the middle of attr names */ - META_ASSERT_NULL(sai_metadata_get_attr_metadata_by_attr_id_name("ZZZ")); /* after all attr names */ + META_ASSERT_TRUE(keys == 1, "vlan object type should have only 1 attribute marked as key which is vlan id"); } -void list_loop( - _In_ const sai_object_type_info_t* info, - _In_ const sai_object_type_t *visited, - _In_ const uint32_t *attributes, - _In_ int levelidx, - _In_ int level) +void check_acl_table_fields_and_acl_entry_fields() { META_LOG_ENTER(); - META_WARN_LOG("LOOP DETECTED on object type: %s", - metadata_enum_sai_object_type_t.valuesnames[info->objecttype]); - - for (; levelidx < level; ++levelidx) - { - sai_object_type_t ot = visited[levelidx]; + /* + * Purpose of this check is to find out if acl table fields and acl entry + * fields correspond to each other. We also make check if they have the + * same attribute id which is not required but it is nice to have. We also + * check if those attributes have right flags and right attribute values. + */ - const char* ot_name = metadata_enum_sai_object_type_t.valuesnames[ot]; + META_ASSERT_TRUE(SAI_ACL_ENTRY_ATTR_FIELD_START == 0x1000, "acl entry field start value should be 0x1000"); + META_ASSERT_TRUE(SAI_ACL_TABLE_ATTR_FIELD_START == 0x1000, "acl table field start value should be 0x1000"); - const sai_attr_metadata_t* m = sai_metadata_get_attr_metadata(ot, attributes[levelidx]); + META_ASSERT_TRUE((int)SAI_ACL_ENTRY_ATTR_FIELD_START == (int)SAI_ACL_TABLE_ATTR_FIELD_START, + "acl entry and table fields start should be the same"); - META_WARN_LOG(" %s: %s", ot_name, m->attridname); - } + /* + * We are using volatile here since if we use enum directly and values are + * different, compiler will optimize this to true and throw error on + * candidate for non return which in this case is confusing. + */ - META_WARN_LOG(" -> %s", metadata_enum_sai_object_type_t.valuesnames[info->objecttype]); + volatile int table_end = SAI_ACL_TABLE_ATTR_FIELD_END; + volatile int entry_end = SAI_ACL_ENTRY_ATTR_FIELD_END; - if (level >= 0) + if (table_end != entry_end) { - META_FAIL("LOOP is detected, we can't have loops in graph, please fix attributes"); + META_FAIL("SAI_ACL_TABLE_ATTR_FIELD_END 0x%x is not equal to SAI_ACL_ENTRY_ATTR_FIELD_END 0x%x", + SAI_ACL_TABLE_ATTR_FIELD_END, SAI_ACL_ENTRY_ATTR_FIELD_END); } -} -void check_objects_for_loops_recursive( - _In_ const sai_object_type_info_t* info, - _Inout_ sai_object_type_t *visited, - _Inout_ uint32_t *attributes, - _In_ int level) -{ - META_LOG_ENTER(); + /* + * find both attribute fields start for entry and table + */ - visited[level] = info->objecttype; + const sai_attr_metadata_t **meta_acl_table = sai_object_type_info_SAI_OBJECT_TYPE_ACL_TABLE.attrmetadata; + const sai_attr_metadata_t **meta_acl_entry = sai_object_type_info_SAI_OBJECT_TYPE_ACL_ENTRY.attrmetadata; - int levelidx = 0; + int acl_table_field_index = 0; - for (; levelidx < level; ++levelidx) + for (; meta_acl_table[acl_table_field_index] != NULL; acl_table_field_index++) { - if (visited[levelidx] == info->objecttype) + if (meta_acl_table[acl_table_field_index]->attrid == SAI_ACL_TABLE_ATTR_FIELD_START) { - /* object type is already defined, so we have a loop */ - - list_loop(info, visited, attributes, levelidx, level); - - return; + break; } } - const sai_attr_metadata_t** meta = info->attrmetadata; + META_ASSERT_NOT_NULL(meta_acl_table[acl_table_field_index]); - META_ASSERT_NOT_NULL(meta); + int acl_entry_field_index = 0; - size_t idx = 0; + for (; meta_acl_entry[acl_entry_field_index] != NULL; acl_entry_field_index++) + { + if (meta_acl_entry[acl_entry_field_index]->attrid == SAI_ACL_ENTRY_ATTR_FIELD_START) + { + break; + } + } - /* iterate all attributes on non object id type */ + META_ASSERT_NOT_NULL(meta_acl_entry[acl_entry_field_index]); - for (; meta[idx] != NULL; ++idx) - { - const sai_attr_metadata_t* m = meta[idx]; + /* + * we found our attribute indexes, now let's compare attributes + */ - META_ASSERT_NOT_NULL(m); + while (true) + { + const sai_attr_metadata_t *mtable = meta_acl_table[acl_table_field_index]; + const sai_attr_metadata_t *mentry = meta_acl_entry[acl_entry_field_index]; - if (HAS_FLAG_READ_ONLY(m->flags)) + if (mentry == NULL || mtable == NULL) { - /* skip read only attributes since with those we will have loops for sure */ + break; + } - continue; + if (mtable->attrid > SAI_ACL_TABLE_ATTR_FIELD_END || + mentry->attrid > SAI_ACL_ENTRY_ATTR_FIELD_END) + { + break; } - /* skip known loops */ + META_LOG_INFO("processing acl fields: %s %s", mtable->attridname, mentry->attridname); - if (m->objecttype == SAI_OBJECT_TYPE_PORT) + /* + * check acl table flags and attr value type + */ + + if (mtable->attrid == SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE) { - if (m->attrid == SAI_PORT_ATTR_EGRESS_MIRROR_SESSION || - m->attrid == SAI_PORT_ATTR_INGRESS_MIRROR_SESSION || - m->attrid == SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST) + /* + * This field is exception, it's not bool, it's a list and it's + * designed in this way to save resources on device to not support + * all ranges on each acl table when it's not necessary. + */ + } + else + { + if (mtable->flags != SAI_ATTR_FLAGS_CREATE_ONLY) { - continue; + META_ASSERT_FAIL(mtable, "acl table field flags should be CREATE_ONLY"); + } + + if (mtable->attrvaluetype != SAI_ATTR_VALUE_TYPE_BOOL) + { + META_ASSERT_FAIL(mtable, "acl table attr value type should be bool"); } } - if (m->objecttype == SAI_OBJECT_TYPE_SCHEDULER_GROUP && - m->attrid == SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE) + /* + * check acl entry flags + */ + + if (mentry->flags != SAI_ATTR_FLAGS_CREATE_AND_SET) { - continue; + META_ASSERT_FAIL(mentry, "acl entry field flags should be CREATE_AND_SET"); } - attributes[level] = m->attrid; + if (mentry->attrid != mtable->attrid) + { + META_ASSERT_FAIL(mentry, "acl entry attr id %d is different than acl table field %d", mentry->attrid, mtable->attrid); + } - switch (m->attrvaluetype) + /* + * check acl fields attribute if endings are the same + */ + + const char * attr_table_pos = strstr(mtable->attridname, "_ATTR_"); + + META_ASSERT_NOT_NULL(attr_table_pos); + + const char * attr_entry_pos = strstr(mentry->attridname, "_ATTR_"); + + META_ASSERT_NOT_NULL(attr_entry_pos); + + if (strcmp(attr_table_pos, attr_entry_pos) != 0) { - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: - case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: - case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + META_FAIL("attr entry field name %s is not ending at the same name as acl table field %s", + mentry->attridname, mtable->attridname); + } - { - size_t j = 0; + acl_table_field_index++; + acl_entry_field_index++; + } +} - for (; j < m->allowedobjecttypeslength; ++j) - { - const sai_object_type_info_t* next = sai_all_object_type_infos[ m->allowedobjecttypes[j] ]; +void check_acl_entry_actions() +{ + META_LOG_ENTER(); - check_objects_for_loops_recursive(next, visited, attributes, level + 1); - } - } + /* + * Purpose of this check is to find out if acl entry actions correspond to + * sai_acl_action_type_t enum type and contain all actions in the same + * order. + */ - break; + META_ASSERT_TRUE(SAI_ACL_ENTRY_ATTR_ACTION_START == 0x2000, "acl entry action start value should be 0x2000"); - default: - break; + /* + * find both attribute fields start for entry and table + */ + + const sai_attr_metadata_t **meta_acl_entry = sai_object_type_info_SAI_OBJECT_TYPE_ACL_ENTRY.attrmetadata; + + size_t index = 0; + + for (; meta_acl_entry[index] != NULL; index++) + { + if (meta_acl_entry[index]->attrid == SAI_ACL_ENTRY_ATTR_ACTION_START) + { + break; } } - /* iterate for struct members on non object id object types */ + META_ASSERT_NOT_NULL(meta_acl_entry[index]); - if (info->isnonobjectid) + /* + * lets compare all action attributes with enum names + */ + + size_t enum_index = 0; + + while (true) { - size_t j = 0; + const sai_attr_metadata_t *meta = meta_acl_entry[index]; - for (; j < info->structmemberscount; ++j) + if (meta == NULL) { - const sai_struct_member_info_t *m = info->structmembers[j]; + break; + } - if (m->membervaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID) - { - continue; - } + if (meta->attrid > SAI_ACL_ENTRY_ATTR_ACTION_END) + { + break; + } - size_t k = 0; + if (meta->flags != SAI_ATTR_FLAGS_CREATE_AND_SET) + { + META_ASSERT_FAIL(meta, "acl entry action flags should be CREATE_AND_SET"); + } - for (; k < m->allowedobjecttypeslength; k++) - { - const sai_object_type_info_t* next = sai_all_object_type_infos[ m->allowedobjecttypes[k] ]; + const char* enum_name = metadata_enum_sai_acl_action_type_t.valuesnames[enum_index]; - check_objects_for_loops_recursive(next, visited, attributes, level + 1); - } + META_ASSERT_NOT_NULL(enum_name); + + META_LOG_INFO("processing acl action: %s %s", meta->attridname, enum_name); + + /* + * check acl fields attribute if endings are the same + */ + + const char * enum_name_pos = strstr(enum_name, "_ACTION_TYPE_"); + + META_ASSERT_NOT_NULL(enum_name_pos); + + const char * attr_entry_pos = strstr(meta->attridname, "_ATTR_ACTION_"); + + META_ASSERT_NOT_NULL(attr_entry_pos); + + if (strcmp(enum_name_pos + strlen("_ACTION_TYPE_"), attr_entry_pos + strlen("_ATTR_ACTION_")) != 0) + { + META_FAIL("attr entry action name %s is not ending at the same enum name %s", + meta->attridname, enum_name); } - } - /* clear level on exit */ + index++; + enum_index++; + } - visited[level] = SAI_OBJECT_TYPE_NULL; - attributes[level] = 0; + META_ASSERT_TRUE(enum_index == metadata_enum_sai_acl_action_type_t.valuescount, + "number of acl entry action mismatch vs number of enums in sai_acl_action_type_t"); } -void check_objects_for_loops() +void check_switch_create_only_objects() { META_LOG_ENTER(); - sai_object_type_t visited_objects[SAI_OBJECT_TYPE_MAX]; - uint32_t visited_attributes[SAI_OBJECT_TYPE_MAX]; + /* + * Purpose of this check is to find out whether switch object has some + * attributes that are object id type and are marked as CREATE_ONLY. Such + * attribute has no sense since, you need first switch_id to create any + * other object so setting that object on create will be impossible. + */ - size_t i = SAI_OBJECT_TYPE_NULL; + const sai_attr_metadata_t** const meta = sai_object_type_info_SAI_OBJECT_TYPE_SWITCH.attrmetadata; - for (; i <= SAI_OBJECT_TYPE_MAX; ++i) + size_t index = 0; + + for (; meta[index] != NULL; index++) { - const sai_object_type_info_t* info = sai_all_object_type_infos[i]; + const sai_attr_metadata_t *md = meta[index]; - if (info == NULL) + if (HAS_FLAG_CREATE_ONLY(md->flags) && md->allowedobjecttypeslength > 0) { - continue; + META_ASSERT_FAIL(md, "attribute is create_only and it's an object id, this is not allowed"); } + } +} - memset(visited_objects, 0, SAI_OBJECT_TYPE_MAX * sizeof(sai_object_type_t)); - memset(visited_attributes, 0, SAI_OBJECT_TYPE_MAX * sizeof(uint32_t)); +void check_quad_api_pointers( + _In_ const sai_object_type_info_t *oi) +{ + META_LOG_ENTER(); - check_objects_for_loops_recursive(info, visited_objects, visited_attributes, 0); + /* + * Check if quad api pointers are not NULL except hostif packet and fdb + * flush which are special. + */ + + if (oi->objecttype == SAI_OBJECT_TYPE_HOSTIF_PACKET || + oi->objecttype == SAI_OBJECT_TYPE_FDB_FLUSH) + { + META_ASSERT_NULL(oi->create); + META_ASSERT_NULL(oi->remove); + META_ASSERT_NULL(oi->set); + META_ASSERT_NULL(oi->get); + } + else + { + META_ASSERT_NOT_NULL(oi->create); + META_ASSERT_NOT_NULL(oi->remove); + META_ASSERT_NOT_NULL(oi->set); + META_ASSERT_NOT_NULL(oi->get); } } -void check_null_object_id() +void check_single_object_info( + _In_ const sai_object_type_info_t *oi) { META_LOG_ENTER(); - META_ASSERT_TRUE(SAI_NULL_OBJECT_ID == 0, "SAI_NULL_OBJECT_ID must be zero"); + check_quad_api_pointers(oi); +} + +void check_api_max() +{ + META_LOG_ENTER(); + + META_ASSERT_TRUE(metadata_enum_sai_api_t.valuescount == SAI_API_MAX, + "SAI_API_MAX should be equal to number of SAI_API*"); } int main(int argc, char **argv) { debug = (argc > 1); + SAI_META_LOG_ENTER(); + check_all_enums_name_pointers(); check_all_enums_values(); check_sai_status(); @@ -2061,8 +3533,28 @@ int main(int argc, char **argv) check_non_object_id_object_attrs(); check_objects_for_loops(); check_null_object_id(); + check_read_only_attributes(); + check_mixed_object_list_types(); + check_vlan_attributes(); + check_api_names(); + check_switch_create_only_objects(); + check_reverse_graph_for_non_object_id(); + check_acl_table_fields_and_acl_entry_fields(); + check_acl_entry_actions(); + check_api_max(); + + i = SAI_OBJECT_TYPE_NULL + 1; + + for (; i < SAI_OBJECT_TYPE_MAX; ++i) + { + check_single_object_info(sai_all_object_type_infos[i]); + } + + SAI_META_LOG_DEBUG("log test"); + + printf("\n [ %s ]\n\n", sai_metadata_get_status_name(SAI_STATUS_SUCCESS)); - printf("\n [ %s ]\n\n", sai_metadata_get_status_name(SAI_STATUS_SUCCESS)); + SAI_META_LOG_EXIT(); return 0; } diff --git a/stub/src/stub_sai_host_interface.c b/stub/src/stub_sai_host_interface.c index 41b4ea61c..2b413ea75 100644 --- a/stub/src/stub_sai_host_interface.c +++ b/stub/src/stub_sai_host_interface.c @@ -341,7 +341,7 @@ sai_status_t stub_host_interface_name_set(_In_ const sai_object_key_t *key, return SAI_STATUS_SUCCESS; } -sai_status_t stub_set_host_interface_trap_attribute(_In_ sai_hostif_trap_id_t hostif_trapid, +sai_status_t stub_set_host_interface_trap_attribute(_In_ sai_hostif_trap_type_t hostif_trapid, _In_ const sai_attribute_t *attr) { STUB_LOG_ENTER(); diff --git a/test/Makefile b/test/Makefile index f5ac3373c..a47b3afba 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,7 +22,7 @@ LDIR = ./lib MKDIR_P = mkdir -p USER_ODIR = obj USER_BDIR = bin -OUT_DIRS = $(USER_BDIR) $(USER_ODIR) +OUT_DIRS = $(USER_BDIR) $(USER_ODIR) $(LDIR) TESTS = $(USER_BDIR)/basic_router ########################################################### @@ -66,7 +66,7 @@ $(USER_ODIR)/gtest_main.o : $(GTEST_SRCS_) $(CXX) $(GTEST_FLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ $(GTEST_DIR)/src/gtest_main.cc -o $@ -$(LDIR)/gtest.a : $(USER_DIR)/gtest-all.o +$(LDIR)/gtest.a : $(USER_ODIR)/gtest-all.o $(AR) $(ARFLAGS) -o $@ $^ $(LDIR)/gtest_main.a : $(USER_ODIR)/gtest-all.o $(USER_ODIR)/gtest_main.o diff --git a/test/sai_ut/Makefile b/test/sai_ut/Makefile index 0fdceb2db..737134d4b 100644 --- a/test/sai_ut/Makefile +++ b/test/sai_ut/Makefile @@ -26,6 +26,11 @@ nhg_SRCS = $(l3_util_SRCS) ./routing/sai_l3_nexthopgroup_unit_test.cpp nbr_SRCS = $(l3_util_SRCS) ./routing/sai_l3_neighbor_unit_test.cpp route_SRCS = $(l3_util_SRCS) ./routing/sai_l3_route_unit_test.cpp +fdb_SRCS = ./switching/sai_fdb_unit_test.cpp +vlan_SRCS = ./switching/sai_vlan_unit_test.cpp +lag_SRCS = ./switching/sai_lag_unit_test.cpp +stp_SRCS = ./switching/sai_stp_unit_test.cpp + ### platform specific Linker/LD Flags # add pointers to SAI library # by adding -l and -L directives @@ -42,8 +47,12 @@ nh_EXEC = sai_ut_nh nhg_EXEC = sai_ut_nhg nbr_EXEC = sai_ut_nbr route_EXEC = sai_ut_route +fdb_EXEC = sai_ut_fdb +vlan_EXEC = sai_ut_vlan +lag_EXEC = sai_ut_lag +stp_EXEC = sai_ut_stp -EXEC_ALL = $(BDIR)/$(vr_EXEC) $(BDIR)/$(rif_EXEC) $(BDIR)/$(nh_EXEC) $(BDIR)/$(nhg_EXEC) $(BDIR)/$(nbr_EXEC) $(BDIR)/$(route_EXEC) +EXEC_ALL = $(BDIR)/$(vr_EXEC) $(BDIR)/$(rif_EXEC) $(BDIR)/$(nh_EXEC) $(BDIR)/$(nhg_EXEC) $(BDIR)/$(nbr_EXEC) $(BDIR)/$(route_EXEC) $(BDIR)/$(fdb_EXEC) $(BDIR)/$(vlan_EXEC) $(BDIR)/$(lag_EXEC) $(BDIR)/$(stp_EXEC) # what to use for compiling CXX=g++ @@ -62,9 +71,12 @@ nh_OBJS = $(nh_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a nhg_OBJS = $(nhg_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a nbr_OBJS = $(nbr_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a route_OBJS = $(route_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a +fdb_OBJS = $(fdb_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a +vlan_OBJS = $(vlan_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a +lag_OBJS = $(lag_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a +stp_OBJS = $(stp_SRCS:%.cpp=%.o) $(LDIR)/gtest_main.a -all : $(vr_SRCS) $(rif_SRCS) $(nh_SRCS) $(nhg_SRCS) $(nbr_SRCS) $(route_SRCS) $(EXEC_ALL) - +all : $(vr_SRCS) $(rif_SRCS) $(nh_SRCS) $(nhg_SRCS) $(nbr_SRCS) $(route_SRCS) $(fdb_SRCS) $(vlan_SRCS) $(lag_SRCS) $(stp_SRCS) $(EXEC_ALL) # rule for execs $(BDIR)/$(vr_EXEC): $(vr_OBJS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(vr_OBJS) -o $@ $(LDFLAGS) @@ -84,10 +96,22 @@ $(BDIR)/$(nbr_EXEC): $(nbr_OBJS) $(BDIR)/$(route_EXEC): $(route_OBJS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(route_OBJS) -o $@ $(LDFLAGS) +$(BDIR)/$(fdb_EXEC): $(fdb_OBJS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(fdb_OBJS) -o $@ $(LDFLAGS) + +$(BDIR)/$(vlan_EXEC): $(vlan_OBJS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(vlan_OBJS) -o $@ $(LDFLAGS) + +$(BDIR)/$(lag_EXEC): $(lag_OBJS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(lag_OBJS) -o $@ $(LDFLAGS) + +$(BDIR)/$(stp_EXEC): $(stp_OBJS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(stp_OBJS) -o $@ $(LDFLAGS) + .cpp.o: $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDEFLAGS) -o $@ -c $< clean : - rm -f $(EXEC_ALL) *.o routing/*.o + rm -f $(EXEC_ALL) *.o routing/*.o switching/*.o diff --git a/test/sai_ut/routing/sai_l3_nexthopgroup_unit_test.cpp b/test/sai_ut/routing/sai_l3_nexthopgroup_unit_test.cpp index f24ef68a1..6d265508e 100644 --- a/test/sai_ut/routing/sai_l3_nexthopgroup_unit_test.cpp +++ b/test/sai_ut/routing/sai_l3_nexthopgroup_unit_test.cpp @@ -151,7 +151,7 @@ void saiL3NextHopGroupTest::TearDownTestCase (void) EXPECT_EQ (SAI_STATUS_SUCCESS, status); /* Reset the Max ECMP Paths attribute to its old value */ - attr.id = SAI_SWITCH_ATTR_ECMP_MAX_PATHS; + attr.id = SAI_SWITCH_ATTR_ECMP_MEMBERS; attr.value.u32 = prev_max_ecmp_paths_value; status = saiL3Test::switch_api_tbl_get()->set_switch_attribute ( @@ -169,7 +169,7 @@ void saiL3NextHopGroupTest::sai_test_setup_max_ecmp_paths (void) memset (&attr, 0, sizeof (sai_attribute_t)); - attr.id = SAI_SWITCH_ATTR_ECMP_MAX_PATHS; + attr.id = SAI_SWITCH_ATTR_ECMP_MEMBERS; /* Retrieve and store the current Max ECMP Paths value */ status = saiL3Test::switch_api_tbl_get()->get_switch_attribute (1, &attr); @@ -179,7 +179,7 @@ void saiL3NextHopGroupTest::sai_test_setup_max_ecmp_paths (void) prev_max_ecmp_paths_value = attr.value.u32; /* Set the default Max ECMP Paths value */ - attr.id = SAI_SWITCH_ATTR_ECMP_MAX_PATHS; + attr.id = SAI_SWITCH_ATTR_ECMP_MEMBERS; attr.value.u32 = max_ecmp_paths; status = saiL3Test::switch_api_tbl_get()->set_switch_attribute ( @@ -189,7 +189,7 @@ void saiL3NextHopGroupTest::sai_test_setup_max_ecmp_paths (void) /* Verify the Max ECMP Paths attribute */ memset (&attr, 0, sizeof (sai_attribute_t)); - attr.id = SAI_SWITCH_ATTR_ECMP_MAX_PATHS; + attr.id = SAI_SWITCH_ATTR_ECMP_MEMBERS; status = saiL3Test::switch_api_tbl_get()->get_switch_attribute (1, &attr); diff --git a/test/sai_ut/routing/sai_l3_rif_unit_test.cpp b/test/sai_ut/routing/sai_l3_rif_unit_test.cpp index 09ef6a178..262b5ef0f 100644 --- a/test/sai_ut/routing/sai_l3_rif_unit_test.cpp +++ b/test/sai_ut/routing/sai_l3_rif_unit_test.cpp @@ -55,6 +55,8 @@ class saiL3RifTest : public saiL3Test { bool v4_admin_state, bool v6_admin_state); static void sai_test_rif_mtu_attr_verify (sai_object_id_t rif, uint32_t mtu); + static sai_object_id_t sai_test_rif_add_lag_member ( + sai_object_id_t lag_id, sai_object_id_t port_id); static const unsigned int test_port = 0; static const unsigned int test_vlan_id = 1000; @@ -294,6 +296,33 @@ void saiL3RifTest ::sai_test_rif_mtu_attr_verify (sai_object_id_t rif_id, EXPECT_EQ (mtu, mtu_attr.value.u32); } +/* + * Helper function to add LAG member ports. + */ +sai_object_id_t saiL3RifTest ::sai_test_rif_add_lag_member ( + sai_object_id_t lag_id, sai_object_id_t port_id) +{ + unsigned int count = 0; + sai_object_id_t member_id; + sai_attribute_t attr_list [2]; + sai_status_t sai_rc = SAI_STATUS_SUCCESS; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_LAG_ID; + attr_list [count].value.oid = lag_id; + count++; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_PORT_ID; + attr_list [count].value.oid = port_id; + count++; + + sai_rc = sai_lag_api_table->create_lag_member (&member_id, count, + attr_list); + + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + + return member_id; +} + /* * Validate Router Interface creation and removal for a port interface. * Port RIF created without any optional attributes. @@ -1184,9 +1213,11 @@ TEST_F (saiL3RifTest, create_rif_on_active_lag) const unsigned int member_count = 2; sai_object_id_t lag_id; sai_object_id_t port_arr[member_count]; - sai_object_list_t lag_port_list; sai_attribute_t attr; sai_vlan_port_t vlan_port[member_count]; + unsigned int port_id_index = 2; + unsigned int index; + sai_object_id_t member_arr[member_count]; ASSERT_TRUE(sai_lag_api_table != NULL); ASSERT_TRUE(sai_vlan_api_table != NULL); @@ -1204,14 +1235,18 @@ TEST_F (saiL3RifTest, create_rif_on_active_lag) (const sai_vlan_port_t*)vlan_port)); /* Create the LAG object with port members */ - lag_port_list.count = member_count; - lag_port_list.list = port_arr; + sai_rc = sai_lag_api_table->create_lag (&lag_id, 0, &attr); + ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); - attr.id = SAI_LAG_ATTR_PORT_LIST; - attr.value.objlist = lag_port_list; + for (index = 0; index < member_count; index++) { - sai_rc = sai_lag_api_table->create_lag (&lag_id, 1, &attr); - ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); + member_arr [index] = sai_test_rif_add_lag_member (lag_id, + sai_l3_port_id_get (port_id_index)); + + EXPECT_NE (member_arr [index], SAI_NULL_OBJECT_ID); + + port_id_index++; + } /* Create RIF with LAG object id */ sai_rc = sai_test_rif_create (&rif_id, 3, @@ -1239,6 +1274,14 @@ TEST_F (saiL3RifTest, create_rif_on_active_lag) sai_rc = sai_test_rif_remove (rif_id); EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + /* Remove the LAG members */ + for (index = 0; index < member_count; index++) { + + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [index]); + + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + } + /* Remove the LAG */ sai_rc = sai_lag_api_table->remove_lag (lag_id); EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); @@ -1258,11 +1301,12 @@ TEST_F (saiL3RifTest, rif_lag_member_update) sai_status_t sai_rc = SAI_STATUS_SUCCESS; sai_object_id_t rif_id; sai_object_id_t lag_id; - sai_object_id_t port_arr[2]; - sai_object_list_t lag_port_list; sai_attribute_t attr; const unsigned int member_count = 4; sai_vlan_port_t vlan_port[member_count]; + sai_object_id_t member_arr[member_count]; + unsigned int port_id_index = 2; + unsigned int index; vlan_port[0].port_id = sai_l3_port_id_get (2); vlan_port[1].port_id = sai_l3_port_id_get (3); @@ -1281,16 +1325,18 @@ TEST_F (saiL3RifTest, rif_lag_member_update) (const sai_vlan_port_t*)vlan_port)); /* Create the LAG object with first two port members */ - port_arr[0] = sai_l3_port_id_get (2); - port_arr[1] = sai_l3_port_id_get (3); - lag_port_list.count = 2; - lag_port_list.list = port_arr; + sai_rc = sai_lag_api_table->create_lag (&lag_id, 0, &attr); + ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); - attr.id = SAI_LAG_ATTR_PORT_LIST; - attr.value.objlist = lag_port_list; + for (index = 0; index < 2; index++) { - sai_rc = sai_lag_api_table->create_lag (&lag_id, 1, &attr); - ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); + member_arr [index] = sai_test_rif_add_lag_member (lag_id, + sai_l3_port_id_get (port_id_index)); + + EXPECT_NE (member_arr [index], SAI_NULL_OBJECT_ID); + + port_id_index++; + } /* Create RIF with LAG object id */ sai_rc = sai_test_rif_create (&rif_id, 3, @@ -1304,27 +1350,34 @@ TEST_F (saiL3RifTest, rif_lag_member_update) ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); /* Add two new members to the LAG */ - lag_port_list.count = 2; - port_arr[0] = sai_l3_port_id_get (4); - port_arr[1] = sai_l3_port_id_get (5); + for (; index < 4; index++) { - lag_port_list.list = port_arr; - sai_rc = sai_lag_api_table->add_ports_to_lag (lag_id, &lag_port_list); - EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + member_arr [index] = sai_test_rif_add_lag_member (lag_id, + sai_l3_port_id_get (port_id_index)); + + EXPECT_NE (member_arr [index], SAI_NULL_OBJECT_ID); + + port_id_index++; + } /* Remove two members from the LAG */ - lag_port_list.count = 2; - port_arr[0] = sai_l3_port_id_get (3); - port_arr[1] = sai_l3_port_id_get (5); + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [1]); + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); - lag_port_list.list = port_arr; - sai_rc = sai_lag_api_table->remove_ports_from_lag (lag_id, &lag_port_list); + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [3]); EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); /* Remove the port RIF. */ sai_rc = sai_test_rif_remove (rif_id); EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + /* Remove the LAG members */ + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [0]); + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [2]); + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + /* Remove the LAG */ sai_rc = sai_lag_api_table->remove_lag (lag_id); EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); diff --git a/test/sai_ut/routing/sai_l3_route_unit_test.cpp b/test/sai_ut/routing/sai_l3_route_unit_test.cpp index aaeeb8762..3ae4e19e3 100644 --- a/test/sai_ut/routing/sai_l3_route_unit_test.cpp +++ b/test/sai_ut/routing/sai_l3_route_unit_test.cpp @@ -929,8 +929,7 @@ TEST_F (saiL3RouteTest, route_next_hop_on_lag_id) sai_object_id_t rif_id; sai_object_id_t nh_id; sai_lag_api_t* sai_lag_api_table; - sai_object_list_t lag_port_list; - sai_attribute_t attr; + sai_attribute_t attr_list[2]; const char *ip_str = "21.1.1.1"; const char *prefix_str = "100.0.0.0"; unsigned int prefix_len = 8; @@ -938,6 +937,9 @@ TEST_F (saiL3RouteTest, route_next_hop_on_lag_id) const unsigned int member_count = 2; sai_object_id_t port_arr[member_count]; sai_vlan_port_t vlan_port[member_count]; + sai_object_id_t member_arr[member_count]; + unsigned int index; + const unsigned int attr_count = 2; EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query (SAI_API_LAG, (static_cast @@ -959,14 +961,20 @@ TEST_F (saiL3RouteTest, route_next_hop_on_lag_id) (const sai_vlan_port_t*)vlan_port)); /* Create the LAG object with port members */ - lag_port_list.count = member_count; - lag_port_list.list = port_arr; + sai_rc = sai_lag_api_table->create_lag (&lag_id, 0, attr_list); + ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); - attr.id = SAI_LAG_ATTR_PORT_LIST; - attr.value.objlist = lag_port_list; + for (index = 0; index < member_count; index++) { + attr_list [0].id = SAI_LAG_MEMBER_ATTR_LAG_ID; + attr_list [0].value.oid = lag_id; - sai_rc = sai_lag_api_table->create_lag (&lag_id, 1, &attr); - ASSERT_EQ (SAI_STATUS_SUCCESS, sai_rc); + attr_list [1].id = SAI_LAG_MEMBER_ATTR_PORT_ID; + attr_list [1].value.oid = port_arr [index]; + + sai_rc = sai_lag_api_table->create_lag_member (&member_arr [index], + attr_count, attr_list); + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + } /* Create RIF with LAG object id */ sai_rc = sai_test_rif_create (&rif_id, default_rif_attr_count, @@ -1027,6 +1035,14 @@ TEST_F (saiL3RouteTest, route_next_hop_on_lag_id) EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + /* Remove the LAG members */ + for (index = 0; index < member_count; index++) { + + sai_rc = sai_lag_api_table->remove_lag_member (member_arr [index]); + + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_rc); + } + /* Remove the LAG */ sai_rc = sai_lag_api_table->remove_lag (lag_id); diff --git a/test/sai_ut/routing/sai_l3_vr_unit_test.cpp b/test/sai_ut/routing/sai_l3_vr_unit_test.cpp index 5aa16dc9a..29138e0e6 100644 --- a/test/sai_ut/routing/sai_l3_vr_unit_test.cpp +++ b/test/sai_ut/routing/sai_l3_vr_unit_test.cpp @@ -914,7 +914,7 @@ TEST_F(saiL3VrfTest, max_ecmp_paths_switch_attr_set) memset (&attr, 0, sizeof (sai_attribute_t)); /* Set the Max ECMP Paths value */ - attr.id = SAI_SWITCH_ATTR_ECMP_MAX_PATHS; + attr.id = SAI_SWITCH_ATTR_ECMP_MEMBERS; attr.value.u32 = max_paths; status = saiL3Test::switch_api_tbl_get()->set_switch_attribute ( diff --git a/test/sai_ut/switching/sai_fdb_unit_test.cpp b/test/sai_ut/switching/sai_fdb_unit_test.cpp new file mode 100644 index 000000000..068bc337c --- /dev/null +++ b/test/sai_ut/switching/sai_fdb_unit_test.cpp @@ -0,0 +1,421 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_fdb_unit_test.cpp +* +* Abstract: +* +* This file contains APIS for testing the SAI FDB module +* +*************************************************************************/ + +#include +#include +#include +#include +#include "gtest/gtest.h" +#include "inttypes.h" + +extern "C" { +#include "sai.h" +#include "saifdb.h" +#include "saitypes.h" +#include "saiswitch.h" +#include "sai_l2_unit_test_defs.h" +} + +#define SAI_MAX_PORTS 256 +#define SAI_MAX_FDB_ATTRIBUTES 3 + +static uint32_t port_count = 0; +static sai_object_id_t port_list[SAI_MAX_PORTS] = {0}; + +static inline void sai_port_evt_callback (uint32_t count, + sai_port_event_notification_t *data) +{ + uint32_t port_idx = 0; + sai_object_id_t port_id = 0; + sai_port_event_t port_event; + + for(port_idx = 0; port_idx < count; port_idx++) { + port_id = data[port_idx].port_id; + port_event = data[port_idx].port_event; + + if(port_event == SAI_PORT_EVENT_ADD) { + if(port_count < SAI_MAX_PORTS) { + port_list[port_count] = port_id; + port_count++; + } + + printf("PORT ADD EVENT FOR port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else if(port_event == SAI_PORT_EVENT_DELETE) { + + printf("PORT DELETE EVENT for port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else { + printf("Invalid PORT EVENT for port %"PRIu64" \r\n", port_id); + } + } +} + +static inline void sai_set_test_fdb_entry(sai_fdb_entry_t* fdb_entry) +{ + memset(fdb_entry,0, sizeof(sai_fdb_entry_t)); + fdb_entry->mac_address[5] = 0xa; + fdb_entry->vlan_id = SAI_GTEST_VLAN; +} + +/* + * API query is done while running the first test case and + * the method table is stored in sai_fdb_api_table so + * that its available for the rest of the test cases which + * use the method table + */ +class fdbInit : public ::testing::Test +{ + public: + void sai_fdb_entry_create(void); + protected: + static void SetUpTestCase() + { + sai_switch_api_t *p_sai_switch_api_tbl = NULL; + sai_switch_notification_t notification; + memset (¬ification, 0, sizeof(sai_switch_notification_t)); + + /* + * Query and populate the SAI Switch API Table. + */ + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_SWITCH, (static_cast + (static_cast(&p_sai_switch_api_tbl))))); + + ASSERT_TRUE (p_sai_switch_api_tbl != NULL); + + /* + * Switch Initialization. + * Fill in notification callback routines with stubs. + */ + notification.on_switch_state_change = sai_switch_operstate_callback; + notification.on_fdb_event = sai_fdb_evt_callback; + notification.on_port_state_change = sai_port_state_evt_callback; + notification.on_switch_shutdown_request = sai_switch_shutdown_callback; + notification.on_port_event = sai_port_evt_callback; + notification.on_packet_event = sai_packet_event_callback; + + ASSERT_TRUE(p_sai_switch_api_tbl->initialize_switch != NULL); + + EXPECT_EQ (SAI_STATUS_SUCCESS, + (p_sai_switch_api_tbl->initialize_switch (0, NULL, NULL, + ¬ification))); + + ASSERT_EQ(NULL,sai_api_query(SAI_API_FDB, + (static_cast(static_cast(&sai_fdb_api_table))))); + + ASSERT_TRUE(sai_fdb_api_table != NULL); + + EXPECT_TRUE(sai_fdb_api_table->create_fdb_entry != NULL); + EXPECT_TRUE(sai_fdb_api_table->remove_fdb_entry != NULL); + EXPECT_TRUE(sai_fdb_api_table->get_fdb_entry_attribute != NULL); + EXPECT_TRUE(sai_fdb_api_table->set_fdb_entry_attribute != NULL); + EXPECT_TRUE(sai_fdb_api_table->flush_fdb_entries != NULL); + + port_id_1 = port_list[0]; + port_id_2 = port_list[port_count-1]; + } + static sai_fdb_api_t* sai_fdb_api_table; + static sai_object_id_t port_id_1; + static sai_object_id_t port_id_2; +}; + +sai_fdb_api_t* fdbInit ::sai_fdb_api_table = NULL; +sai_object_id_t fdbInit ::port_id_1 = 0; +sai_object_id_t fdbInit ::port_id_2 = 0; + +void fdbInit ::sai_fdb_entry_create(void) +{ + + sai_fdb_entry_t fdb_entry; + sai_attribute_t attr_list[SAI_MAX_FDB_ATTRIBUTES]; + + sai_set_test_fdb_entry(&fdb_entry); + + memset(attr_list,0, sizeof(attr_list)); + attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + attr_list[0].value.s32 = SAI_FDB_ENTRY_DYNAMIC; + + attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + attr_list[1].value.oid = port_id_1; + + attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + attr_list[2].value.s32 = SAI_PACKET_ACTION_FORWARD; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->create_fdb_entry( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + (const sai_attribute_t*)attr_list)); +} + +/* + * FDB Create and Get FDB Entry + */ +TEST_F(fdbInit, create_fdb_entry) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + memset(get_attr_list,0, sizeof(get_attr_list)); + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); + + ASSERT_EQ(SAI_FDB_ENTRY_DYNAMIC, get_attr_list[0].value.s32); + ASSERT_EQ(port_id_1, get_attr_list[1].value.oid); + ASSERT_EQ(SAI_PACKET_ACTION_FORWARD, get_attr_list[2].value.s32); + +} + +/* + * FDB Create and Get FDB Entry + */ +TEST_F(fdbInit, remove_fdb_entry) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + + sai_set_test_fdb_entry(&fdb_entry); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->remove_fdb_entry( + (const sai_fdb_entry_t*)&fdb_entry)); + memset(get_attr_list,0, sizeof(get_attr_list)); + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_ADDR_NOT_FOUND, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); + +} +TEST_F(fdbInit, flush_all_fdb_entries_by_port) +{ + + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + sai_attribute_t flush_attr[2]; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + memset(get_attr_list,0, sizeof(get_attr_list)); + memset(flush_attr,0, sizeof(flush_attr)); + + flush_attr[0].id = SAI_FDB_FLUSH_ATTR_PORT_ID; + flush_attr[0].value.oid = port_id_1; + + flush_attr[1].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + flush_attr[1].value.s32 = SAI_FDB_FLUSH_ENTRY_DYNAMIC; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->flush_fdb_entries(2, + (const sai_attribute_t*)flush_attr)); + + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_ADDR_NOT_FOUND, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); +} + +TEST_F(fdbInit, flush_all_fdb_entries_by_vlan) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + sai_attribute_t flush_attr[2]; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + memset(get_attr_list,0, sizeof(get_attr_list)); + memset(flush_attr,0, sizeof(flush_attr)); + + flush_attr[0].id = SAI_FDB_FLUSH_ATTR_VLAN_ID; + flush_attr[0].value.u16 = SAI_GTEST_VLAN; + + flush_attr[1].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + flush_attr[1].value.s32 = SAI_FDB_FLUSH_ENTRY_DYNAMIC; + + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->flush_fdb_entries(2, + (const sai_attribute_t*)flush_attr)); + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_ADDR_NOT_FOUND, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); +} +TEST_F(fdbInit, flush_all_fdb_entries_by_port_vlan) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + sai_attribute_t flush_attr[3]; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + memset(get_attr_list,0, sizeof(get_attr_list)); + memset(flush_attr,0, sizeof(flush_attr)); + + flush_attr[0].id = SAI_FDB_FLUSH_ATTR_VLAN_ID; + flush_attr[0].value.u16 = SAI_GTEST_VLAN; + + flush_attr[1].id = SAI_FDB_FLUSH_ATTR_PORT_ID; + flush_attr[1].value.oid = port_id_1; + + flush_attr[2].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + flush_attr[2].value.s32 = SAI_FDB_FLUSH_ENTRY_DYNAMIC; + + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->flush_fdb_entries(3, + (const sai_attribute_t*)flush_attr)); + + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_ADDR_NOT_FOUND, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); +} +TEST_F(fdbInit, flush_all_fdb_entries) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr_list[SAI_MAX_FDB_ATTRIBUTES]; + sai_attribute_t flush_attr[1]; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + memset(get_attr_list,0, sizeof(get_attr_list)); + memset(flush_attr,0, sizeof(flush_attr)); + + flush_attr[0].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + flush_attr[0].value.s32 = SAI_FDB_FLUSH_ENTRY_DYNAMIC; + + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->flush_fdb_entries(1, + (const sai_attribute_t*)flush_attr)); + + get_attr_list[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + get_attr_list[1].id = SAI_FDB_ENTRY_ATTR_PORT_ID; + get_attr_list[2].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + + ASSERT_EQ(SAI_STATUS_ADDR_NOT_FOUND, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + SAI_MAX_FDB_ATTRIBUTES, + get_attr_list)); +} +/* + * FDB Create and Get FDB Entry + */ +TEST_F(fdbInit, set_fdb_entry) +{ + sai_fdb_entry_t fdb_entry; + sai_attribute_t get_attr; + sai_attribute_t set_attr; + + sai_fdb_entry_create(); + sai_set_test_fdb_entry(&fdb_entry); + + /*Changing type*/ + memset(&set_attr,0, sizeof(set_attr)); + set_attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + set_attr.value.s32 = SAI_FDB_ENTRY_STATIC; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->set_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + (const sai_attribute_t*)&set_attr)); + + memset(&get_attr,0, sizeof(get_attr)); + get_attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + 1, &get_attr)); + EXPECT_EQ(SAI_FDB_ENTRY_STATIC, get_attr.value.s32); + + /*Changing action*/ + memset(&set_attr,0, sizeof(set_attr)); + set_attr.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + set_attr.value.s32 = SAI_PACKET_ACTION_DROP; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->set_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + (const sai_attribute_t*)&set_attr)); + + memset(&get_attr,0, sizeof(get_attr)); + get_attr.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + 1, &get_attr)); + EXPECT_EQ(SAI_PACKET_ACTION_DROP, get_attr.value.s32); + + /*Changing port*/ + memset(&set_attr,0, sizeof(set_attr)); + set_attr.id = SAI_FDB_ENTRY_ATTR_PORT_ID; + set_attr.value.oid = port_id_2; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->set_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + (const sai_attribute_t*)&set_attr)); + + memset(&get_attr,0, sizeof(get_attr)); + get_attr.id = SAI_FDB_ENTRY_ATTR_PORT_ID; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_fdb_api_table->get_fdb_entry_attribute( + (const sai_fdb_entry_t*)&fdb_entry, + 1, &get_attr)); + EXPECT_EQ(port_id_2, get_attr.value.oid); + +} diff --git a/test/sai_ut/switching/sai_fdb_unit_test.o b/test/sai_ut/switching/sai_fdb_unit_test.o new file mode 100644 index 000000000..7eb49bd67 Binary files /dev/null and b/test/sai_ut/switching/sai_fdb_unit_test.o differ diff --git a/test/sai_ut/switching/sai_l2_unit_test_defs.h b/test/sai_ut/switching/sai_l2_unit_test_defs.h new file mode 100644 index 000000000..0c1dbc84c --- /dev/null +++ b/test/sai_ut/switching/sai_l2_unit_test_defs.h @@ -0,0 +1,63 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_l2_unit_test_defs.h +* +* Abstract: +* +* This file contains declarations to be used by all L2 testing utilities +* +*************************************************************************/ + +#include "saitypes.h" +#include "saifdb.h" + +#define SAI_GTEST_VLAN 10 +#define SAI_GTEST_INVALID_VLAN_ID 4096 + +/* + * Stubs for Callback functions to be passed from adaptor host/application + * upon switch initialization API call. + */ +inline void sai_port_state_evt_callback (uint32_t count, + sai_port_oper_status_notification_t *data) +{ +} + +inline void sai_fdb_evt_callback(uint32_t count, sai_fdb_event_notification_data_t *data) +{ +} + +inline void sai_switch_operstate_callback (sai_switch_oper_status_t + switchstate) +{ +} + +/* Packet event callback + */ +static inline void sai_packet_event_callback (const void *buffer, + sai_size_t buffer_size, + uint32_t attr_count, + const sai_attribute_t *attr_list) +{ +} + +inline void sai_switch_shutdown_callback (void) +{ +} diff --git a/test/sai_ut/switching/sai_lag_unit_test.cpp b/test/sai_ut/switching/sai_lag_unit_test.cpp new file mode 100644 index 000000000..bff310dce --- /dev/null +++ b/test/sai_ut/switching/sai_lag_unit_test.cpp @@ -0,0 +1,467 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_lag_unit_test.cpp +* +* Abstract: +* +* This file contains APIS for testing the SAI LAG module +* +*************************************************************************/ + +#include +#include +#include +#include +#include "gtest/gtest.h" +#include + +extern "C" { +#include "sai.h" +#include "sailag.h" +#include "saitypes.h" +#include "sai_l2_unit_test_defs.h" +} + +#define SAI_MAX_PORTS 256 +#define SAI_LAG_UT_DEFAULT_VLAN 1 + +uint32_t port_count = 0; +sai_object_id_t port_list[SAI_MAX_PORTS] = {0}; + +#include "sai_lag_unit_test.h" + +sai_lag_api_t* lagInit ::sai_lag_api_table = NULL; +sai_object_id_t lagInit ::port_id_1 = 0; +sai_object_id_t lagInit ::port_id_2 = 0; +sai_object_id_t lagInit ::port_id_l3 = 0; +sai_object_id_t lagInit ::port_id_invalid = 0; + +void sai_port_evt_callback (uint32_t count, sai_port_event_notification_t *data) +{ + uint32_t port_idx = 0; + sai_object_id_t port_id = 0; + sai_port_event_t port_event; + + for(port_idx = 0; port_idx < count; port_idx++) { + port_id = data[port_idx].port_id; + port_event = data[port_idx].port_event; + + if(port_event == SAI_PORT_EVENT_ADD) { + if(port_count < SAI_MAX_PORTS) { + port_list[port_count] = port_id; + port_count++; + } + + printf("PORT ADD EVENT FOR port 0x%"PRIx64" and total ports count is %d \r\n", + port_id, port_count); + } else if(port_event == SAI_PORT_EVENT_DELETE) { + + printf("PORT DELETE EVENT for port 0x%"PRIx64" and total ports count is %d \r\n", + port_id, port_count); + } else { + printf("Invalid PORT EVENT for port 0x%"PRIx64" \r\n", port_id); + } + } +} + +sai_status_t sai_lag_ut_add_port_to_lag (sai_lag_api_t *lag_api, + sai_object_id_t *member_id, + sai_object_id_t lag_id, + sai_object_id_t port_id, + bool is_ing_disable_present, + bool ing_disable, + bool is_egr_disable_present, + bool egr_disable) +{ + sai_attribute_t attr_list [4]; + uint32_t count = 0; + + memset (attr_list, 0, sizeof (attr_list)); + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_LAG_ID; + attr_list [count].value.oid = lag_id; + count++; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_PORT_ID; + attr_list [count].value.oid = port_id; + count++; + + if (is_ing_disable_present) { + attr_list [count].id = SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE; + attr_list [count].value.booldata = ing_disable; + count++; + } + + if (is_egr_disable_present) { + attr_list [count].id = SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE; + attr_list [count].value.booldata = egr_disable; + count++; + } + + return lag_api->create_lag_member (member_id, count, attr_list); +} + +sai_status_t sai_lag_ut_get_lag_attr (sai_lag_api_t *lag_api, + sai_object_id_t member_id, + bool *ing_disable, + bool *egr_disable) +{ + sai_status_t rc; + sai_attribute_t attr_list [4]; + uint32_t count = 0; + + memset (attr_list, 0, sizeof (attr_list)); + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE; + attr_list [count].value.booldata = ing_disable; + count++; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE; + attr_list [count].value.booldata = egr_disable; + count++; + + rc = lag_api->get_lag_member_attribute (member_id, count, attr_list); + + *ing_disable = attr_list [0].value.booldata; + *egr_disable = attr_list [1].value.booldata; + + return rc; +} + +sai_status_t sai_lag_ut_set_lag_attr (sai_lag_api_t *lag_api, + sai_object_id_t member_id, + bool is_ing_disable_present, + bool ing_disable, + bool is_egr_disable_present, + bool egr_disable) +{ + sai_status_t rc; + sai_attribute_t attr; + + memset (&attr, 0, sizeof (attr)); + + if (is_ing_disable_present) { + attr.id = SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE; + attr.value.booldata = ing_disable; + + rc = lag_api->set_lag_member_attribute (member_id, &attr); + + if (rc != SAI_STATUS_SUCCESS) { + return rc; + } + } + + if (is_egr_disable_present) { + attr.id = SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE; + attr.value.booldata = egr_disable; + + rc = lag_api->set_lag_member_attribute (member_id, &attr); + + if (rc != SAI_STATUS_SUCCESS) { + return rc; + } + } + + return SAI_STATUS_SUCCESS; +} + +sai_status_t sai_lag_ut_remove_port_from_lag (sai_lag_api_t *lag_api, + sai_object_id_t member_id) +{ + return lag_api->remove_lag_member (member_id); +} + +/* + * LAG create and delete + */ +TEST_F(lagInit, create_remove_lag) +{ + sai_object_id_t lag_id = 0; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag(&lag_id, 0, NULL)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->remove_lag(lag_id)); + + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_api_table->remove_lag(lag_id)); + +} + + +/* + * LAG port priority tag testing + */ +TEST_F(lagInit, lag_attribute_test) +{ + sai_object_id_t lag_id = 0; + sai_object_id_t port_arr[2]; + sai_object_id_t get_port_arr[2]; + sai_object_list_t lag_port_list; + sai_object_list_t get_lag_port_list; + sai_object_id_t member_id_1 = 0; + sai_object_id_t member_id_2 = 0; + sai_attribute_t attr; + sai_attribute_t get_attr; + + lag_port_list.count = 2; + port_arr[0] = port_id_1; + port_arr[1] = port_id_2; + lag_port_list.list = port_arr; + + memset(&attr, 0, sizeof(attr)); + attr.id = SAI_LAG_ATTR_PORT_LIST; + attr.value.objlist = lag_port_list; + + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag(&lag_id, 0, NULL)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_1, + lag_id, port_id_1, + false, false, false, false)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_2, + lag_id, port_id_2, + false, false, false, false)); + + memset(&get_attr, 0, sizeof(get_attr)); + memset(get_port_arr, 0, sizeof(get_port_arr)); + memset(&get_lag_port_list, 0, sizeof(get_lag_port_list)); + get_lag_port_list.count = 2; + get_lag_port_list.list = get_port_arr; + get_attr.id = SAI_LAG_ATTR_PORT_LIST; + get_attr.value.objlist = get_lag_port_list; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->get_lag_attribute(lag_id, 1, &get_attr)); + EXPECT_EQ(port_arr[0], get_port_arr[0]); + EXPECT_EQ(port_arr[1], get_port_arr[1]); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->remove_lag(lag_id)); +} + +TEST_F(lagInit, lag_member_new_api_test) +{ + sai_object_id_t lag_id_1 = 0; + sai_object_id_t lag_id_2 = 0; + sai_object_id_t member_id_1 = 0; + sai_object_id_t member_id_2 = 0; + sai_object_id_t tmp_member_id = 0; + sai_attribute_t attr_list [4]; + uint32_t count; + + /* Create Lag lag_id_1 and add port_id_1 and port_id_2 as members */ + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag(&lag_id_1, 0, NULL)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_1, + lag_id_1, port_id_1, + false, false, false, false)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_2, + lag_id_1, port_id_2, + false, false, true, true)); + + /* Check if same port cannot be added to two lags */ + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag (&lag_id_2, 0, NULL)); + + ASSERT_EQ(SAI_STATUS_INVALID_PORT_MEMBER, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &tmp_member_id, + lag_id_2, port_id_1, + false, false, false, false)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->remove_lag(lag_id_2)); + + /* Check if the addition of a lag member fails if it is already a member */ + ASSERT_EQ(SAI_STATUS_ITEM_ALREADY_EXISTS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &tmp_member_id, + lag_id_1, port_id_1, + false, false, false, false)); + + /* Check if invalid port is not allowed to be added to the lag */ + ASSERT_EQ(SAI_STATUS_INVALID_PARAMETER, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &tmp_member_id, + lag_id_1, port_id_invalid, + false, false, false, false)); + + /* Check if member removal with an invalid member_id fails */ + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_ut_remove_port_from_lag (sai_lag_api_table, 0)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_remove_port_from_lag (sai_lag_api_table, member_id_1)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_ut_remove_port_from_lag (sai_lag_api_table, member_id_2)); + + /* Check if member removal fails, if it is not a member of the lag */ + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_ut_remove_port_from_lag (sai_lag_api_table, member_id_1)); + + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_ut_remove_port_from_lag (sai_lag_api_table, member_id_2)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->remove_lag(lag_id_1)); + + /* Check if member addition fails if the lag is not created. */ + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &tmp_member_id, + lag_id_1, port_id_1, + false, false, false, false)); + + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &tmp_member_id, + lag_id_1, port_id_2, + false, false, false, false)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag (&lag_id_1, 0, NULL)); + + /* Check if member addition fails, if mandatory arguments are not present */ + memset (attr_list, 0, sizeof (attr_list)); + count = 0; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_LAG_ID; + attr_list [count].value.oid = lag_id_1; + count++; + + ASSERT_EQ (SAI_MANDATORY_ATTRIBUTE_MISSING, + sai_lag_api_table->create_lag_member (&tmp_member_id, + count, attr_list)); + + count = 0; + attr_list [count].id = SAI_LAG_MEMBER_ATTR_PORT_ID; + attr_list [count].value.oid = port_id_1; + count++; + + ASSERT_EQ (SAI_MANDATORY_ATTRIBUTE_MISSING, + sai_lag_api_table->create_lag_member (&tmp_member_id, + count, attr_list)); + + count = 0; + attr_list [count].id = SAI_LAG_MEMBER_ATTR_LAG_ID; + attr_list [count].value.oid = lag_id_1; + count++; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_PORT_ID; + attr_list [count].value.oid = port_id_1; + count++; + + attr_list [count].id = SAI_LAG_MEMBER_ATTR_CUSTOM_RANGE_BASE + 1000; + attr_list [count].value.oid = 0; + count++; + + /* Check if member addition fails if unknown attribute is present. */ + ASSERT_EQ (SAI_STATUS_UNKNOWN_ATTRIBUTE_0, + sai_lag_api_table->create_lag_member (&tmp_member_id, + count, attr_list)); + +} + +TEST_F(lagInit, lag_member_attribute_new_api_test) +{ + sai_object_id_t lag_id_1 = 0; + sai_object_id_t member_id_1 = 0; + sai_object_id_t member_id_2 = 0; + bool ing_disable; + bool egr_disable; + + /* + * Create a lag with members assigned default ingress/egress disable + * attribute values. + */ + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_api_table->create_lag (&lag_id_1, 0, NULL)); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_1, + lag_id_1, port_id_1, + false, false, false, false)); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_add_port_to_lag (sai_lag_api_table, &member_id_2, + lag_id_1, port_id_2, + false, false, false, false)); + + /* + * Check if the get attribute returns correct values for ingress/egress + * disable attributes. + */ + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_get_lag_attr (sai_lag_api_table, member_id_1, + &ing_disable, &egr_disable)); + ASSERT_FALSE (ing_disable); + ASSERT_FALSE (egr_disable); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_get_lag_attr (sai_lag_api_table, member_id_2, + &ing_disable, &egr_disable)); + ASSERT_FALSE (ing_disable); + ASSERT_FALSE (egr_disable); + + /* + * Modify the attributes and check if the get attribute returns + * correct values for ingress/egress disable attributes. + */ + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_set_lag_attr (sai_lag_api_table, member_id_1, + true, true, true, false)); + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_get_lag_attr (sai_lag_api_table, member_id_1, + &ing_disable, &egr_disable)); + ASSERT_TRUE (ing_disable); + ASSERT_FALSE (egr_disable); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_set_lag_attr (sai_lag_api_table, member_id_2, + false, false, true, true)); + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_get_lag_attr (sai_lag_api_table, member_id_2, + &ing_disable, &egr_disable)); + ASSERT_FALSE (ing_disable); + ASSERT_TRUE (egr_disable); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_set_lag_attr (sai_lag_api_table, member_id_2, + false, false, true, true)); + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_get_lag_attr (sai_lag_api_table, member_id_2, + &ing_disable, &egr_disable)); + ASSERT_FALSE (ing_disable); + ASSERT_TRUE (egr_disable); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_remove_port_from_lag(sai_lag_api_table, member_id_1)); + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_ut_remove_port_from_lag(sai_lag_api_table, member_id_2)); + + ASSERT_EQ (SAI_STATUS_SUCCESS, + sai_lag_api_table->remove_lag (lag_id_1)); +} diff --git a/test/sai_ut/switching/sai_lag_unit_test.h b/test/sai_ut/switching/sai_lag_unit_test.h new file mode 100644 index 000000000..2e13349ac --- /dev/null +++ b/test/sai_ut/switching/sai_lag_unit_test.h @@ -0,0 +1,142 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_lag_unit_test.h +* +* Abstract: +* +* This file contains definition of APIs used by the SAI LAG unit test module +* +*************************************************************************/ + +#ifndef __SAI_LAG_UNIT_TEST_H__ +#define __SAI_LAG_UNIT_TEST_H__ + +#include "gtest/gtest.h" + +extern "C" { +#include "saiswitch.h" +#include "saistp.h" +#include "saitypes.h" + +void sai_port_evt_callback (uint32_t count, + sai_port_event_notification_t *data); + +sai_status_t sai_lag_ut_add_port_to_lag (sai_lag_api_t *lag_api, + sai_object_id_t *member_id, + sai_object_id_t lag_id, + sai_object_id_t port_id, + bool is_ing_disable_present, + bool ing_disable, + bool is_egr_disable_present, + bool egr_disable); + +sai_status_t sai_lag_ut_remove_port_from_lag (sai_lag_api_t *lag_api, + sai_object_id_t member_id); +sai_status_t sai_lag_ut_get_lag_attr (sai_lag_api_t *lag_api, + sai_object_id_t member_id, + bool *ing_disable, + bool *egr_disable); + +sai_status_t sai_lag_ut_set_lag_attr (sai_lag_api_t *lag_api, + sai_object_id_t member_id, + bool is_ing_disable_present, + bool ing_disable, + bool is_egr_disable_present, + bool egr_disable); +} + +#define SAI_MAX_PORTS 256 +#define SAI_LAG_UT_DEFAULT_VLAN 1 + +extern uint32_t port_count; +extern sai_object_id_t port_list[SAI_MAX_PORTS]; + +/* + * API query is done while running the first test case and + * the method table is stored in sai_lag_api_table so + * that its available for the rest of the test cases which + * use the method table + */ +class lagInit : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + sai_switch_api_t *p_sai_switch_api_tbl = NULL; + sai_switch_notification_t notification; + + /* + * Query and populate the SAI Switch API Table. + */ + memset(¬ification, 0, sizeof(notification)); + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_SWITCH, (static_cast + (static_cast(&p_sai_switch_api_tbl))))); + + ASSERT_TRUE (p_sai_switch_api_tbl != NULL); + + /* + * Switch Initialization. + * Fill in notification callback routines with stubs. + */ + notification.on_switch_state_change = sai_switch_operstate_callback; + notification.on_fdb_event = sai_fdb_evt_callback; + notification.on_port_state_change = sai_port_state_evt_callback; + notification.on_switch_shutdown_request = sai_switch_shutdown_callback; + notification.on_packet_event = sai_packet_event_callback; + notification.on_port_event = sai_port_evt_callback; + + ASSERT_TRUE(p_sai_switch_api_tbl->initialize_switch != NULL); + + EXPECT_EQ (SAI_STATUS_SUCCESS, + (p_sai_switch_api_tbl->initialize_switch (0, NULL, NULL, + ¬ification))); + + ASSERT_EQ(NULL,sai_api_query(SAI_API_LAG, + (static_cast(static_cast(&sai_lag_api_table))))); + + ASSERT_TRUE(sai_lag_api_table != NULL); + + EXPECT_TRUE(sai_lag_api_table->create_lag != NULL); + EXPECT_TRUE(sai_lag_api_table->remove_lag != NULL); + EXPECT_TRUE(sai_lag_api_table->set_lag_attribute != NULL); + EXPECT_TRUE(sai_lag_api_table->get_lag_attribute != NULL); + EXPECT_TRUE(sai_lag_api_table->create_lag_member != NULL); + EXPECT_TRUE(sai_lag_api_table->remove_lag_member != NULL); + EXPECT_TRUE(sai_lag_api_table->set_lag_member_attribute != NULL); + EXPECT_TRUE(sai_lag_api_table->get_lag_member_attribute != NULL); + + ASSERT_TRUE(port_count!=0); + port_id_1 = port_list[0]; + port_id_2 = port_list[port_count-1]; + port_id_l3 = port_list [1]; + port_id_invalid = port_id_2 + 1; + } + + static sai_lag_api_t* sai_lag_api_table; + static sai_object_id_t port_id_1; + static sai_object_id_t port_id_2; + static sai_object_id_t port_id_l3; + static sai_object_id_t port_id_invalid; + + public: + sai_lag_api_t *sai_lag_ut_get_lag_api () {return sai_lag_api_table;} +}; +#endif /* __SAI_LAG_UNIT_TEST_H__ */ diff --git a/test/sai_ut/switching/sai_stp_unit_test.cpp b/test/sai_ut/switching/sai_stp_unit_test.cpp new file mode 100644 index 000000000..5e2144a6a --- /dev/null +++ b/test/sai_ut/switching/sai_stp_unit_test.cpp @@ -0,0 +1,422 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_stp_unit_test.cpp +* +* Abstract: +* +* This file contains APIS for testing the SAI STP module +* +*************************************************************************/ + +#include "gtest/gtest.h" +#include "sai_stp_unit_test.h" + +extern "C" { +#include "sai.h" +#include "saistatus.h" +#include "saitypes.h" +#include "saiswitch.h" +#include "saistp.h" +#include +#include +#include +#include +#include +#include "stdarg.h" +} + +#define SAI_STP_NO_OF_ATTRIB 1 +#define SAI_STP_DEF_VLAN 1 +#define SAI_STP_VLAN_2 2 +#define SAI_STP_VLAN_3 3 +#define SAI_STP_VLAN_10 10 +#define SAI_MAX_PORTS 106 + +static uint32_t port_count = 0; + +static sai_object_id_t port_list[SAI_MAX_PORTS] = {0}; + +sai_object_id_t stpTest ::sai_stp_port_id_get (uint32_t port_index) +{ + if(port_index >= port_count) { + return 0; + } + + return port_list [port_index]; +} + +sai_object_id_t stpTest ::sai_stp_invalid_port_id_get () +{ + return (port_list[port_count-1] + 1); +} + +/* + * Stubs for Callback functions to be passed from adaptor host/application + * upon switch initialization API call. + */ +static inline void sai_port_evt_callback (uint32_t count, + sai_port_event_notification_t *data) +{ + uint32_t port_idx = 0; + sai_object_id_t port_id = 0; + sai_port_event_t port_event; + + for(port_idx = 0; port_idx < count; port_idx++) { + port_id = data[port_idx].port_id; + port_event = data[port_idx].port_event; + + if(port_event == SAI_PORT_EVENT_ADD) { + if(port_count < SAI_MAX_PORTS) { + port_list[port_count] = port_id; + port_count++; + } + + printf("PORT ADD EVENT FOR port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else if(port_event == SAI_PORT_EVENT_DELETE) { + + printf("PORT DELETE EVENT for port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else { + printf("Invalid PORT EVENT for port %"PRIu64" \r\n", port_id); + } + } +} + +static inline void sai_port_state_evt_callback (uint32_t count, + sai_port_oper_status_notification_t *data) +{ +} + +static inline void sai_fdb_evt_callback (uint32_t count, sai_fdb_event_notification_data_t *data) +{ +} + +static inline void sai_switch_operstate_callback (sai_switch_oper_status_t + switchstate) { +} + +/* Packet event callback + */ +static inline void sai_packet_event_callback (const void *buffer, + sai_size_t buffer_size, + uint32_t attr_count, + const sai_attribute_t *attr_list) +{ +} + +static inline void sai_switch_shutdown_callback (void) { +} + + +void stpTest ::SetUpTestCase (void) { + sai_switch_notification_t notification; + memset (¬ification, 0, sizeof(sai_switch_notification_t)); + + memset(¬ification, 0, sizeof(sai_switch_notification_t)); + /* + * Query and populate the SAI Switch API Table. + */ + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_SWITCH, (static_cast + (static_cast(&p_sai_switch_api_tbl))))); + + ASSERT_TRUE (p_sai_switch_api_tbl != NULL); + + /* + * Switch Initialization. + */ + ASSERT_TRUE(p_sai_switch_api_tbl->initialize_switch != NULL); + + /* + * Fill in notification callback routines with stubs. + */ + notification.on_switch_state_change = sai_switch_operstate_callback; + notification.on_fdb_event = sai_fdb_evt_callback; + notification.on_port_state_change = sai_port_state_evt_callback; + notification.on_switch_shutdown_request = sai_switch_shutdown_callback; + notification.on_packet_event = sai_packet_event_callback; + notification.on_port_event = sai_port_evt_callback; + + EXPECT_EQ (SAI_STATUS_SUCCESS, + (p_sai_switch_api_tbl->initialize_switch (0, NULL, NULL, + ¬ification))); + /* + * Query and populate the SAI Virtual Router API Table. + */ + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_VLAN, (static_cast + (static_cast + (&p_sai_vlan_api_tbl))))); + + ASSERT_TRUE (p_sai_vlan_api_tbl != NULL); + + /* + * Query and populate the SAI Virtual Router API Table. + */ + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_STP, (static_cast + (static_cast + (&p_sai_stp_api_tbl))))); + + ASSERT_TRUE (p_sai_stp_api_tbl != NULL); + + sai_port_id_1 = sai_stp_port_id_get (0); +} + +sai_switch_api_t* stpTest ::p_sai_switch_api_tbl = NULL; +sai_vlan_api_t* stpTest ::p_sai_vlan_api_tbl = NULL; +sai_stp_api_t* stpTest ::p_sai_stp_api_tbl = NULL; +sai_object_id_t stpTest ::sai_port_id_1 = 0; + + + +TEST_F(stpTest, def_stp_get) +{ + sai_attribute_t attr[SAI_STP_NO_OF_ATTRIB] = {0}; + sai_object_id_t def_stp_id = 0; + sai_vlan_id_t vlan_id = SAI_STP_VLAN_10; + + attr[0].id = SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID; + attr[0].value.u16 = 0; + + EXPECT_EQ(SAI_STATUS_INVALID_ATTRIBUTE_0,p_sai_switch_api_tbl-> + set_switch_attribute(attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_switch_api_tbl-> + get_switch_attribute(SAI_STP_NO_OF_ATTRIB, attr)); + + def_stp_id = attr[0].value.oid; + + attr[0].id = SAI_STP_ATTR_VLAN_LIST; + attr[0].value.vlanlist.vlan_count = 1; + attr[0].value.vlanlist.vlan_list = &vlan_id; + + EXPECT_EQ(SAI_STATUS_INVALID_ATTRIBUTE_0,p_sai_stp_api_tbl-> + set_stp_attribute(def_stp_id, attr)); + + attr[0].value.vlanlist.vlan_count = 1; + attr[0].value.vlanlist.vlan_list = (sai_vlan_id_t *) calloc (attr[0].value.vlanlist.vlan_count, + sizeof(sai_vlan_id_t)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_stp_api_tbl-> + get_stp_attribute(def_stp_id, SAI_STP_NO_OF_ATTRIB, attr)); + + EXPECT_EQ (attr[0].value.objlist.count, 1); + EXPECT_EQ (attr[0].value.objlist.list[0], SAI_STP_DEF_VLAN); + + free (attr[0].value.vlanlist.vlan_list); +} + +TEST_F(stpTest, create_stp_group) +{ + sai_attribute_t attr[SAI_STP_NO_OF_ATTRIB] = {0}; + sai_object_id_t stp_id = 0; + sai_object_id_t def_inst_id = 0; + + attr[SAI_STP_NO_OF_ATTRIB - 1].id = SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID; + + EXPECT_EQ(SAI_STATUS_INVALID_ATTRIBUTE_0,p_sai_switch_api_tbl-> + set_switch_attribute(attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_switch_api_tbl-> + get_switch_attribute(SAI_STP_NO_OF_ATTRIB, attr)); + + def_inst_id = attr[0].value.oid; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_stp_api_tbl-> + create_stp(&stp_id,0,attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + create_vlan(SAI_STP_VLAN_2)); + + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + attr[0].value.oid = stp_id; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + set_vlan_attribute(SAI_STP_VLAN_2,attr)); + + EXPECT_EQ(SAI_STATUS_OBJECT_IN_USE, p_sai_stp_api_tbl-> + remove_stp(stp_id)); + + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + attr[0].value.oid = def_inst_id; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + set_vlan_attribute(SAI_STP_VLAN_2,attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + remove_stp(stp_id)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + remove_vlan(SAI_STP_VLAN_2)); +} + +TEST_F(stpTest, stp_port_state) +{ + sai_attribute_t attr[SAI_STP_NO_OF_ATTRIB] = {0}; + sai_object_id_t stp_id = 0; + sai_port_stp_port_state_t port_state; + sai_object_id_t port_id = sai_port_id_1; + sai_object_id_t invalid_port_id = sai_stp_invalid_port_id_get(); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_stp_api_tbl-> + create_stp(&stp_id,0,attr)); + + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_ID, p_sai_stp_api_tbl-> + set_stp_port_state (stp_id, invalid_port_id, SAI_PORT_STP_STATE_FORWARDING)); + + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_TYPE, p_sai_stp_api_tbl-> + set_stp_port_state (10, port_id, SAI_PORT_STP_STATE_FORWARDING)); + + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_TYPE, p_sai_stp_api_tbl-> + get_stp_port_state (10, port_id, &port_state)); + + /* Set to some random number */ + port_state = SAI_PORT_STP_STATE_LEARNING; + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_ID, p_sai_stp_api_tbl-> + get_stp_port_state (stp_id, invalid_port_id, &port_state)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + set_stp_port_state (stp_id, port_id, SAI_PORT_STP_STATE_FORWARDING)); + + /* Set to some random number */ + port_state = SAI_PORT_STP_STATE_LEARNING; + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + get_stp_port_state (stp_id, port_id, &port_state)); + + EXPECT_EQ(SAI_PORT_STP_STATE_FORWARDING, port_state); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + set_stp_port_state (stp_id, port_id, SAI_PORT_STP_STATE_LEARNING)); + + /* Set to some random number */ + port_state = SAI_PORT_STP_STATE_BLOCKING; + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + get_stp_port_state (stp_id, port_id, &port_state)); + + EXPECT_EQ(SAI_PORT_STP_STATE_LEARNING, port_state); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + set_stp_port_state (stp_id, port_id, SAI_PORT_STP_STATE_BLOCKING)); + + /* Set to some random number */ + port_state = SAI_PORT_STP_STATE_LEARNING; + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + get_stp_port_state (stp_id, port_id, &port_state)); + + EXPECT_EQ(SAI_PORT_STP_STATE_BLOCKING, port_state); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + remove_stp(stp_id)); +} + +TEST_F(stpTest, delet_vlan) +{ + sai_attribute_t attr[SAI_STP_NO_OF_ATTRIB] = {0}; + sai_object_id_t stp_id = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_stp_api_tbl-> + create_stp(&stp_id,0,attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + create_vlan(SAI_STP_VLAN_2)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + create_vlan(SAI_STP_VLAN_3)); + + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + attr[0].value.oid = stp_id; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + set_vlan_attribute(SAI_STP_VLAN_3,attr)); + + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + attr[0].value.oid = 10; + + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_ID, p_sai_vlan_api_tbl-> + set_vlan_attribute(SAI_STP_VLAN_2, attr)); + + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + attr[0].value.oid = stp_id; + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_vlan_api_tbl-> + set_vlan_attribute(SAI_STP_VLAN_2, attr)); + + memset (attr, 0, sizeof(attr)); + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + get_vlan_attribute(SAI_STP_VLAN_3, SAI_STP_NO_OF_ATTRIB, attr)); + + EXPECT_EQ (attr->value.oid, stp_id); + + memset (attr, 0, sizeof(attr)); + attr[0].id = SAI_VLAN_ATTR_STP_INSTANCE; + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + get_vlan_attribute(SAI_STP_VLAN_2, SAI_STP_NO_OF_ATTRIB, attr)); + + EXPECT_EQ (attr->value.oid, stp_id); + + memset (attr, 0, sizeof(attr)); + attr[0].id = SAI_STP_ATTR_VLAN_LIST; + attr[0].value.vlanlist.vlan_count = 1; + attr[0].value.vlanlist.vlan_list = (sai_vlan_id_t *) calloc (attr[0].value.vlanlist.vlan_count, + sizeof(sai_vlan_id_t)); + + EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, p_sai_stp_api_tbl-> + get_stp_attribute(stp_id, SAI_STP_NO_OF_ATTRIB, attr)); + + EXPECT_EQ (attr->value.vlanlist.vlan_count, SAI_STP_VLAN_2); + + attr[0].id = SAI_STP_ATTR_VLAN_LIST; + attr[0].value.vlanlist.vlan_list = (sai_vlan_id_t *) realloc (attr[0].value.vlanlist.vlan_list, + sizeof(sai_vlan_id_t)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + get_stp_attribute(stp_id, SAI_STP_NO_OF_ATTRIB, attr)); + + EXPECT_EQ (attr->value.vlanlist.vlan_count, 2); + EXPECT_EQ (attr->value.vlanlist.vlan_list[0], SAI_STP_VLAN_2); + EXPECT_EQ (attr->value.vlanlist.vlan_list[1], SAI_STP_VLAN_3); + + free (attr[0].value.vlanlist.vlan_list); + + EXPECT_EQ(SAI_STATUS_OBJECT_IN_USE, p_sai_stp_api_tbl-> + remove_stp(stp_id)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + remove_vlan(SAI_STP_VLAN_3)); + + EXPECT_EQ(SAI_STATUS_SUCCESS,p_sai_vlan_api_tbl-> + remove_vlan(SAI_STP_VLAN_2)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, p_sai_stp_api_tbl-> + remove_stp(stp_id)); + + EXPECT_EQ(SAI_STATUS_INVALID_OBJECT_ID, p_sai_stp_api_tbl-> + remove_stp(stp_id)); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/sai_ut/switching/sai_stp_unit_test.h b/test/sai_ut/switching/sai_stp_unit_test.h new file mode 100755 index 000000000..67229fe36 --- /dev/null +++ b/test/sai_ut/switching/sai_stp_unit_test.h @@ -0,0 +1,55 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_stp_unit_test.h +* +* Abstract: +* +* This file contains declarations to be used to STP testing module +* +*************************************************************************/ + +#ifndef __SAI_STP_UNIT_TEST_H__ +#define __SAI_STP_UNIT_TEST_H__ + +#include "gtest/gtest.h" + +extern "C" { +#include "saiswitch.h" +#include "saivlan.h" +#include "saistp.h" +#include "saitypes.h" +} + +class stpTest : public ::testing::Test +{ + public: + static void SetUpTestCase(); + + static sai_object_id_t sai_stp_port_id_get (uint32_t port_index); + static sai_object_id_t sai_stp_invalid_port_id_get (); + + static sai_switch_api_t *p_sai_switch_api_tbl; + static sai_stp_api_t *p_sai_stp_api_tbl; + static sai_vlan_api_t *p_sai_vlan_api_tbl; + static sai_object_id_t sai_port_id_1; + static sai_object_id_t sai_invalid_port_id; + +}; +#endif /* __SAI_STP_UNIT_TEST_H__ */ diff --git a/test/sai_ut/switching/sai_vlan_unit_test.cpp b/test/sai_ut/switching/sai_vlan_unit_test.cpp new file mode 100644 index 000000000..feccd4349 --- /dev/null +++ b/test/sai_ut/switching/sai_vlan_unit_test.cpp @@ -0,0 +1,485 @@ +/************************************************************************ +* Copyright (c) 2015 Dell Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); you may +* not use this file except in compliance with the License. You may obtain +* a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +* FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +* +* See the Apache Version 2.0 License for specific language governing +* permissions and limitations under the License. +* +* +* +* Module Name: +* +* sai_vlan_unit_test.cpp +* +* Abstract: +* +* This file contains APIS for testing the SAI VLAN module +* +*************************************************************************/ + +#include +#include +#include +#include +#include "gtest/gtest.h" +#include "inttypes.h" + +extern "C" { +#include "sai.h" +#include "saivlan.h" +#include "saitypes.h" +#include "sai_l2_unit_test_defs.h" +} + +#define SAI_MAX_PORTS 256 + +static uint32_t port_count = 0; +static sai_object_id_t port_list[SAI_MAX_PORTS] = {0}; + +static inline void sai_port_evt_callback (uint32_t count, + sai_port_event_notification_t *data) +{ + uint32_t port_idx = 0; + sai_object_id_t port_id = 0; + sai_port_event_t port_event; + + for(port_idx = 0; port_idx < count; port_idx++) { + port_id = data[port_idx].port_id; + port_event = data[port_idx].port_event; + + if(port_event == SAI_PORT_EVENT_ADD) { + if(port_count < SAI_MAX_PORTS) { + port_list[port_count] = port_id; + port_count++; + } + + printf("PORT ADD EVENT FOR port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else if(port_event == SAI_PORT_EVENT_DELETE) { + + printf("PORT DELETE EVENT for port %"PRIu64" and total ports count is %d \r\n", + port_id, port_count); + } else { + printf("Invalid PORT EVENT for port %"PRIu64" \r\n", port_id); + } + } +} + +/* + * API query is done while running the first test case and + * the method table is stored in sai_vlan_api_table so + * that its available for the rest of the test cases which + * use the method table + */ +class vlanInit : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + sai_switch_api_t *p_sai_switch_api_tbl = NULL; + sai_switch_notification_t notification; + memset (¬ification, 0, sizeof(sai_switch_notification_t)); + + /* + * Query and populate the SAI Switch API Table. + */ + EXPECT_EQ (SAI_STATUS_SUCCESS, sai_api_query + (SAI_API_SWITCH, (static_cast + (static_cast(&p_sai_switch_api_tbl))))); + + ASSERT_TRUE (p_sai_switch_api_tbl != NULL); + + /* + * Switch Initialization. + * Fill in notification callback routines with stubs. + */ + notification.on_switch_state_change = sai_switch_operstate_callback; + notification.on_fdb_event = sai_fdb_evt_callback; + notification.on_port_state_change = sai_port_state_evt_callback; + notification.on_switch_shutdown_request = sai_switch_shutdown_callback; + notification.on_packet_event = sai_packet_event_callback; + notification.on_port_event = sai_port_evt_callback; + + ASSERT_TRUE(p_sai_switch_api_tbl->initialize_switch != NULL); + + EXPECT_EQ (SAI_STATUS_SUCCESS, + (p_sai_switch_api_tbl->initialize_switch (0, NULL, NULL, + ¬ification))); + + ASSERT_EQ(NULL,sai_api_query(SAI_API_VLAN, + (static_cast(static_cast(&sai_vlan_api_table))))); + + ASSERT_TRUE(sai_vlan_api_table != NULL); + + EXPECT_TRUE(sai_vlan_api_table->create_vlan != NULL); + EXPECT_TRUE(sai_vlan_api_table->remove_vlan != NULL); + EXPECT_TRUE(sai_vlan_api_table->set_vlan_attribute != NULL); + EXPECT_TRUE(sai_vlan_api_table->get_vlan_attribute != NULL); + EXPECT_TRUE(sai_vlan_api_table->add_ports_to_vlan != NULL); + EXPECT_TRUE(sai_vlan_api_table->remove_ports_from_vlan != NULL); + EXPECT_TRUE(sai_vlan_api_table->remove_all_vlans != NULL); + EXPECT_TRUE(sai_vlan_api_table->get_vlan_stats != NULL); + + port_id_1 = port_list[0]; + port_id_2 = port_list[port_count-1]; + port_id_invalid = port_id_2 + 1; + } + + static sai_vlan_api_t* sai_vlan_api_table; + static sai_object_id_t port_id_1; + static sai_object_id_t port_id_2; + static sai_object_id_t port_id_invalid; +}; + +sai_vlan_api_t* vlanInit ::sai_vlan_api_table = NULL; +sai_object_id_t vlanInit ::port_id_1 = 0; +sai_object_id_t vlanInit ::port_id_2 = 0; +sai_object_id_t vlanInit ::port_id_invalid = 0; + +/* + * VLAN create and delete + */ +TEST_F(vlanInit, create_remove_vlan) +{ + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + ASSERT_EQ(SAI_STATUS_ITEM_ALREADY_EXISTS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); + + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); + + ASSERT_EQ(SAI_STATUS_INVALID_VLAN_ID, + sai_vlan_api_table->create_vlan(SAI_GTEST_INVALID_VLAN_ID)); + + ASSERT_EQ(SAI_STATUS_INVALID_VLAN_ID, + sai_vlan_api_table->remove_vlan(SAI_GTEST_INVALID_VLAN_ID)); +} +TEST_F(vlanInit, remove_all_vlans) +{ + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_all_vlans()); + + ASSERT_EQ(SAI_STATUS_ITEM_NOT_FOUND, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN add port and remove port + */ +TEST_F(vlanInit, vlan_port_test) +{ + sai_vlan_port_t vlan_port[2]; + sai_vlan_port_t invalid_vlan_port[2]; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + memset(vlan_port, 0, sizeof(vlan_port)); + + vlan_port[0].port_id = port_id_1; + vlan_port[0].tagging_mode = SAI_VLAN_PORT_UNTAGGED; + vlan_port[1].port_id = port_id_2; + vlan_port[1].tagging_mode = SAI_VLAN_PORT_TAGGED; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->add_ports_to_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + vlan_port)); + invalid_vlan_port[0].port_id = port_id_1; + invalid_vlan_port[0].tagging_mode = SAI_VLAN_PORT_TAGGED; + invalid_vlan_port[1].port_id = port_id_2; + invalid_vlan_port[1].tagging_mode = SAI_VLAN_PORT_TAGGED; + + ASSERT_EQ(SAI_STATUS_INVALID_PORT_MEMBER, + sai_vlan_api_table->add_ports_to_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + invalid_vlan_port)); + + ASSERT_EQ(SAI_STATUS_INVALID_PORT_MEMBER, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + invalid_vlan_port)); + + invalid_vlan_port[0].port_id = port_id_invalid; + invalid_vlan_port[0].tagging_mode = SAI_VLAN_PORT_TAGGED; + invalid_vlan_port[1].port_id = port_id_2; + invalid_vlan_port[1].tagging_mode = SAI_VLAN_PORT_TAGGED; + + ASSERT_EQ(SAI_STATUS_INVALID_OBJECT_ID, + sai_vlan_api_table->add_ports_to_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + invalid_vlan_port)); + + ASSERT_EQ(SAI_STATUS_INVALID_OBJECT_ID, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + invalid_vlan_port)); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + vlan_port)); + + ASSERT_EQ(SAI_STATUS_INVALID_PORT_MEMBER, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + vlan_port)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN get port test + */ +TEST_F(vlanInit, vlan_get_port) +{ + sai_vlan_port_t vlan_port[2]; + sai_attribute_t attr; + sai_vlan_port_list_t vplist; + sai_vlan_port_t get_vlan_port[2]; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + memset(vlan_port, 0, sizeof(vlan_port)); + + vlan_port[0].port_id = port_id_1; + vlan_port[0].tagging_mode = SAI_VLAN_PORT_UNTAGGED; + vlan_port[1].port_id = port_id_2; + vlan_port[1].tagging_mode = SAI_VLAN_PORT_TAGGED; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->add_ports_to_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + vlan_port)); + + memset(&attr, 0, sizeof(attr)); + memset(&vplist, 0, sizeof(vplist)); + memset(get_vlan_port, 0, sizeof(get_vlan_port)); + vplist.count = 2; + vplist.list = get_vlan_port; + + attr.id = SAI_VLAN_ATTR_PORT_LIST; + attr.value.vlanportlist = vplist; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_attribute(SAI_GTEST_VLAN, 1, &attr)); + + EXPECT_EQ(vlan_port[0].port_id, get_vlan_port[0].port_id); + EXPECT_EQ(vlan_port[1].port_id, get_vlan_port[1].port_id); + EXPECT_EQ(vlan_port[0].tagging_mode, get_vlan_port[0].tagging_mode); + EXPECT_EQ(vlan_port[1].tagging_mode, get_vlan_port[1].tagging_mode); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 2, + (const sai_vlan_port_t*) + vlan_port)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN port priority tag testing + */ +TEST_F(vlanInit, vlan_port_priority_tag_test) +{ + sai_vlan_port_t vlan_port; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + memset(&vlan_port, 0, sizeof(vlan_port)); + + vlan_port.port_id = port_id_1; + vlan_port.tagging_mode = SAI_VLAN_PORT_PRIORITY_TAGGED; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->add_ports_to_vlan(SAI_GTEST_VLAN, + 1, + (const sai_vlan_port_t*) + &vlan_port)); + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 1, + (const sai_vlan_port_t*) + &vlan_port)); + EXPECT_EQ(SAI_STATUS_INVALID_PORT_MEMBER, + sai_vlan_api_table->remove_ports_from_vlan(SAI_GTEST_VLAN, + 1, + (const sai_vlan_port_t*) + &vlan_port)); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN test MAX learnt MAC address + */ +TEST_F(vlanInit, test_max_learnt_mac_address) +{ + sai_attribute_t set_attr; + sai_attribute_t get_attr; + + + memset(&set_attr, 0, sizeof(sai_attribute_t)); + memset(&get_attr, 0, sizeof(sai_attribute_t)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + set_attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + set_attr.value.u32 = 100; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->set_vlan_attribute(SAI_GTEST_VLAN, + (const sai_attribute_t*)&set_attr)); + get_attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_attribute(SAI_GTEST_VLAN,1, + &get_attr)); + EXPECT_EQ(set_attr.value.u32,get_attr.value.u32); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN test learn disable + */ +TEST_F(vlanInit, test_vlan_learn_disable) +{ + sai_attribute_t set_attr; + sai_attribute_t get_attr; + + + memset(&set_attr, 0, sizeof(sai_attribute_t)); + memset(&get_attr, 0, sizeof(sai_attribute_t)); + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + set_attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + set_attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->set_vlan_attribute(SAI_GTEST_VLAN, + (const sai_attribute_t*)&set_attr)); + get_attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_attribute(SAI_GTEST_VLAN,1, + &get_attr)); + EXPECT_EQ(set_attr.value.booldata,get_attr.value.booldata); + set_attr.value.booldata = false; + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->set_vlan_attribute(SAI_GTEST_VLAN, + (const sai_attribute_t*)&set_attr)); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} +/* + * VLAN test get statistics + */ +TEST_F(vlanInit, vlan_get_stats) +{ + sai_vlan_stat_counter_t id = SAI_VLAN_STAT_IN_OCTETS; + uint64_t counter_val = 0; + + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->create_vlan(SAI_GTEST_VLAN)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + id = SAI_VLAN_STAT_IN_UCAST_PKTS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_IN_NON_UCAST_PKTS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_IN_DISCARDS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_IN_ERRORS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + + id = SAI_VLAN_STAT_IN_UNKNOWN_PROTOS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_OCTETS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_UCAST_PKTS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_NON_UCAST_PKTS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_DISCARDS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_ERRORS; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + + id = SAI_VLAN_STAT_OUT_QLEN; + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->get_vlan_stats(SAI_GTEST_VLAN, + (const sai_vlan_stat_counter_t*)&id,1, + &counter_val)); + ASSERT_EQ(SAI_STATUS_SUCCESS, + sai_vlan_api_table->remove_vlan(SAI_GTEST_VLAN)); +} diff --git a/test/saithrift/src/saiserver.cpp b/test/saithrift/src/saiserver.cpp index c5014c69b..0103bf9bb 100644 --- a/test/saithrift/src/saiserver.cpp +++ b/test/saithrift/src/saiserver.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -36,7 +37,10 @@ sai_switch_api_t* sai_switch_api; std::map gProfileMap; std::map, std::string> gPortMap; -void on_switch_state_change(_In_ sai_switch_oper_status_t switch_oper_status) +sai_object_id_t gSwitchId; ///< SAI switch global object ID. + +void on_switch_state_change(_In_ sai_object_id_t switch_id, + _In_ sai_switch_oper_status_t switch_oper_status)// { } @@ -50,31 +54,18 @@ void on_port_state_change(_In_ uint32_t count, { } -void on_port_event(_In_ uint32_t count, - _In_ sai_port_event_notification_t *data) -{ -} - -void on_shutdown_request() +void on_shutdown_request(_In_ sai_object_id_t switch_id)// { } -void on_packet_event(_In_ const void *buffer, +void on_packet_event(_In_ sai_object_id_t switch_id, + _In_ const void *buffer, _In_ sai_size_t buffer_size, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list) { } -sai_switch_notification_t switch_notifications = { - on_switch_state_change, - on_fdb_event, - on_port_state_change, - on_port_event, - on_shutdown_request, - on_packet_event -}; - // Profile services /* Get variable value given its name */ const char* test_profile_get_value( @@ -155,7 +146,7 @@ void sai_diag_shell() sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_SWITCH_SHELL_ENABLE; attr.value.booldata = true; - status = sai_switch_api->set_switch_attribute(&attr); + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); if (status != SAI_STATUS_SUCCESS) { return; @@ -290,7 +281,10 @@ void handlePortMap(const std::string& portMapFile) std::string fp_value = line.substr(0, pos); std::string lanes = line.substr(pos + 1); - lanes.erase(lanes.begin(), std::find_if(lanes.begin(), lanes.end(), std::not1(std::ptr_fun(std::isspace)))); + + // ::isspace : C-Style white space predicate. Locale independent. + lanes.erase(std::remove_if(lanes.begin(), lanes.end(), ::isspace), lanes.end()); + std::istringstream iss(lanes); std::string lane_str; std::set lane_set; @@ -327,7 +321,30 @@ main(int argc, char* argv[]) sai_api_initialize(0, (service_method_table_t *)&test_services); sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - sai_status_t status = sai_switch_api->initialize_switch(0, (char *)"", (char *)"", &switch_notifications); + constexpr std::uint32_t attrSz = 6; + + sai_attribute_t attr[attrSz]; + std::memset(attr, '\0', sizeof(attr)); + + attr[0].id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr[0].value.booldata = true; + + attr[1].id = SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY; + attr[1].value.ptr = reinterpret_cast(&on_switch_state_change); + + attr[2].id = SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY; + attr[2].value.ptr = reinterpret_cast(&on_shutdown_request); + + attr[3].id = SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY; + attr[3].value.ptr = reinterpret_cast(&on_fdb_event); + + attr[4].id = SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY; + attr[4].value.ptr = reinterpret_cast(&on_port_state_change); + + attr[5].id = SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY; + attr[5].value.ptr = reinterpret_cast(&on_packet_event); + + sai_status_t status = sai_switch_api->create_switch(&gSwitchId, attrSz, attr); if (status != SAI_STATUS_SUCCESS) { exit(EXIT_FAILURE); @@ -342,23 +359,23 @@ main(int argc, char* argv[]) start_sai_thrift_rpc_server(SWITCH_SAI_THRIFT_RPC_SERVER_PORT); - sai_log_set(SAI_API_SWITCH, SAI_LOG_NOTICE); - sai_log_set(SAI_API_FDB, SAI_LOG_NOTICE); - sai_log_set(SAI_API_PORT, SAI_LOG_NOTICE); - sai_log_set(SAI_API_VLAN, SAI_LOG_NOTICE); - sai_log_set(SAI_API_ROUTE, SAI_LOG_NOTICE); - sai_log_set(SAI_API_VIRTUAL_ROUTER, SAI_LOG_NOTICE); - sai_log_set(SAI_API_ROUTER_INTERFACE, SAI_LOG_NOTICE); - sai_log_set(SAI_API_NEXT_HOP, SAI_LOG_NOTICE); - sai_log_set(SAI_API_NEXT_HOP_GROUP, SAI_LOG_NOTICE); - sai_log_set(SAI_API_NEIGHBOR, SAI_LOG_NOTICE); - sai_log_set(SAI_API_ACL, SAI_LOG_NOTICE); - sai_log_set(SAI_API_MIRROR, SAI_LOG_NOTICE); - sai_log_set(SAI_API_LAG, SAI_LOG_NOTICE); - sai_log_set(SAI_API_BUFFERS, SAI_LOG_NOTICE); - sai_log_set(SAI_API_POLICER, SAI_LOG_NOTICE); - sai_log_set(SAI_API_WRED, SAI_LOG_NOTICE); - sai_log_set(SAI_API_QOS_MAPS, SAI_LOG_NOTICE); + sai_log_set(SAI_API_SWITCH, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_FDB, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_PORT, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_VLAN, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_ROUTE, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_VIRTUAL_ROUTER, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_ROUTER_INTERFACE, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_NEXT_HOP, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_NEXT_HOP_GROUP, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_NEIGHBOR, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_ACL, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_MIRROR, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_LAG, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_BUFFER, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_POLICER, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_WRED, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_QOS_MAP, SAI_LOG_LEVEL_NOTICE); while (1) pause(); diff --git a/test/saithrift/src/switch_sai.thrift b/test/saithrift/src/switch_sai.thrift index e7d426f98..b27e110f9 100644 --- a/test/saithrift/src/switch_sai.thrift +++ b/test/saithrift/src/switch_sai.thrift @@ -34,6 +34,16 @@ typedef i32 sai_thrift_port_stat_counter_t typedef i32 sai_thrift_queue_stat_counter_t typedef i32 sai_thrift_pg_stat_counter_t +union sai_thrift_result_data_t { + 1: sai_thrift_object_id_t oid; + 2: i16 u16; +} + +struct sai_thrift_result_t { + 1: sai_thrift_result_data_t data; + 2: sai_thrift_status_t status; +} + struct sai_thrift_fdb_entry_t { 1: sai_thrift_mac_t mac_address; 2: sai_thrift_vlan_id_t vlan_id; @@ -70,6 +80,11 @@ struct sai_thrift_vlan_list_t { 2: list vlan_list; } +struct sai_thrift_s32_list_t { + 1: i32 count; + 2: list s32list; +} + union sai_thrift_acl_mask_t { 1: byte u8; 2: byte s8; @@ -167,7 +182,8 @@ union sai_thrift_attribute_value_t { 18: sai_thrift_acl_field_data_t aclfield; 19: sai_thrift_acl_action_data_t aclaction; 20: sai_thrift_u32_list_t u32list; - 21: sai_thrift_qos_map_list_t qosmap; + 21: sai_thrift_s32_list_t s32list; + 22: sai_thrift_qos_map_list_t qosmap; } struct sai_thrift_attribute_t { @@ -175,7 +191,7 @@ struct sai_thrift_attribute_t { 2: sai_thrift_attribute_value_t value; } -struct sai_thrift_unicast_route_entry_t { +struct sai_thrift_route_entry_t { 1: sai_thrift_object_id_t vr_id; 2: sai_thrift_ip_prefix_t destination; } @@ -206,8 +222,8 @@ service switch_sai_rpc { sai_thrift_status_t sai_thrift_flush_fdb_entries(1: list thrift_attr_list); //vlan API - sai_thrift_status_t sai_thrift_create_vlan(1: sai_thrift_vlan_id_t vlan_id); - sai_thrift_status_t sai_thrift_delete_vlan(1: sai_thrift_vlan_id_t vlan_id); + sai_thrift_object_id_t sai_thrift_create_vlan(1: list thrift_attr_list); + sai_thrift_status_t sai_thrift_remove_vlan(1: sai_thrift_object_id_t vlan_oid); list sai_thrift_get_vlan_stats( 1: sai_thrift_vlan_id_t vlan_id, 2: list counter_ids, @@ -215,28 +231,30 @@ service switch_sai_rpc { sai_thrift_object_id_t sai_thrift_create_vlan_member(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_vlan_member(1: sai_thrift_object_id_t vlan_member_id); sai_thrift_attribute_list_t sai_thrift_get_vlan_attribute(1: sai_thrift_object_id_t vlan_id); + sai_thrift_result_t sai_thrift_get_vlan_id(1: sai_thrift_object_id_t vlan_id); //virtual router API sai_thrift_object_id_t sai_thrift_create_virtual_router(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_virtual_router(1: sai_thrift_object_id_t vr_id); //route API - sai_thrift_status_t sai_thrift_create_route(1: sai_thrift_unicast_route_entry_t thrift_unicast_route_entry, 2: list thrift_attr_list); - sai_thrift_status_t sai_thrift_remove_route(1: sai_thrift_unicast_route_entry_t thrift_unicast_route_entry); + sai_thrift_status_t sai_thrift_create_route(1: sai_thrift_route_entry_t thrift_route_entry, 2: list thrift_attr_list); + sai_thrift_status_t sai_thrift_remove_route(1: sai_thrift_route_entry_t thrift_route_entry); //router interface API sai_thrift_object_id_t sai_thrift_create_router_interface(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_router_interface(1: sai_thrift_object_id_t rif_id); + sai_thrift_status_t sai_thrift_set_router_interface_attribute(1: sai_thrift_object_id_t rif_id, 2: sai_thrift_attribute_t thrift_attr); //next hop API sai_thrift_object_id_t sai_thrift_create_next_hop(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_next_hop(1: sai_thrift_object_id_t next_hop_id); - //next hop group API + // Next Hop Group API. sai_thrift_object_id_t sai_thrift_create_next_hop_group(1: list thrift_attr_list); - sai_thrift_status_t sai_thrift_remove_next_hop_group(1: sai_thrift_object_id_t next_hop_group_id); - sai_thrift_status_t sai_thrift_add_next_hop_to_group(1: sai_thrift_object_id_t next_hop_group_id, 2: list thrift_nexthops); - sai_thrift_status_t sai_thrift_remove_next_hop_from_group(1: sai_thrift_object_id_t next_hop_group_id, 2: list thrift_nexthops); + sai_thrift_status_t sai_thrift_remove_next_hop_group(1: sai_thrift_object_id_t nhop_group_oid); + sai_thrift_object_id_t sai_thrift_create_next_hop_group_member(1: list thrift_attr_list); + sai_thrift_status_t sai_thrift_remove_next_hop_group_member(1: sai_thrift_object_id_t nhop_group_member_oid); //lag API sai_thrift_object_id_t sai_thrift_create_lag(1: list thrift_attr_list); @@ -260,6 +278,7 @@ service switch_sai_rpc { sai_thrift_object_id_t sai_thrift_get_cpu_port_id(); sai_thrift_object_id_t sai_thrift_get_default_trap_group(); sai_thrift_object_id_t sai_thrift_get_default_router_id(); + sai_thrift_result_t sai_thrift_get_default_vlan_id(); sai_thrift_object_id_t sai_thrift_get_port_id_by_front_port(1: string port_name); sai_thrift_status_t sai_thrift_set_switch_attribute(1: sai_thrift_attribute_t attribute); @@ -270,18 +289,24 @@ service switch_sai_rpc { sai_thrift_status_t sai_thrift_remove_hostif_trap_group(1: sai_thrift_object_id_t trap_group_id); sai_thrift_status_t sai_thrift_create_hostif_trap(1: list thrift_attr_list); sai_thrift_status_t sai_thrift_remove_hostif_trap(1: sai_thrift_hostif_trap_id_t trap_id); - sai_thrift_status_t sai_thrift_set_hostif_trap(1: sai_thrift_hostif_trap_id_t trap_id, 2: sai_thrift_attribute_t thrift_attr); + sai_thrift_status_t sai_thrift_set_hostif_trap(1: sai_thrift_object_id_t trap_id, 2: sai_thrift_attribute_t thrift_attr); sai_thrift_status_t sai_thrift_set_hostif_trap_group(1: sai_thrift_object_id_t trap_group_id, 2: sai_thrift_attribute_t thrift_attr); // ACL API sai_thrift_object_id_t sai_thrift_create_acl_table(1: list thrift_attr_list); - sai_thrift_status_t sai_thrift_delete_acl_table(1: sai_thrift_object_id_t acl_table_id); + sai_thrift_status_t sai_thrift_remove_acl_table(1: sai_thrift_object_id_t acl_table_id); sai_thrift_object_id_t sai_thrift_create_acl_entry(1: list thrift_attr_list); - sai_thrift_status_t sai_thrift_delete_acl_entry(1: sai_thrift_object_id_t acl_entry); + sai_thrift_status_t sai_thrift_remove_acl_entry(1: sai_thrift_object_id_t acl_entry); + + sai_thrift_object_id_t sai_thrift_create_acl_table_group(1: list thrift_attr_list); + sai_thrift_status_t sai_thrift_remove_acl_table_group(1: sai_thrift_object_id_t acl_table_group_id); + + sai_thrift_object_id_t sai_thrift_create_acl_table_group_member(1: list thrift_attr_list); + sai_thrift_status_t sai_thrift_remove_acl_table_group_member(1: sai_thrift_object_id_t acl_table_group_member_id); sai_thrift_object_id_t sai_thrift_create_acl_counter(1: list thrift_attr_list); - sai_thrift_status_t sai_thrift_delete_acl_counter(1: sai_thrift_object_id_t acl_counter_id); + sai_thrift_status_t sai_thrift_remove_acl_counter(1: sai_thrift_object_id_t acl_counter_id); list sai_thrift_get_acl_counter_attribute( 1: sai_thrift_object_id_t acl_counter_id, 2: list thrift_attr_ids); diff --git a/test/saithrift/src/switch_sai_rpc_server.cpp b/test/saithrift/src/switch_sai_rpc_server.cpp index 307c6f1b8..12da301a5 100644 --- a/test/saithrift/src/switch_sai_rpc_server.cpp +++ b/test/saithrift/src/switch_sai_rpc_server.cpp @@ -17,6 +17,20 @@ limitations under the License. // This autogenerated skeleton file illustrates how to build a server. // You should copy it to another filename to avoid overwriting it. +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + #include #include #include "switch_sai_rpc.h" @@ -45,6 +59,14 @@ extern "C" { #include "arpa/inet.h" +#define SAI_THRIFT_LOG_DBG(msg, ...) sai_thrift_timestamp_print(); \ + printf("SAI THRIFT DEBUG: %s(): " msg "\n", __FUNCTION__, ##__VA_ARGS__); + +#define SAI_THRIFT_LOG_ERR(msg, ...) sai_thrift_timestamp_print(); \ + printf("SAI THRIFT ERROR: %s(): " msg "\n", __FUNCTION__, ##__VA_ARGS__); + +#define SAI_THRIFT_FUNC_LOG() SAI_THRIFT_LOG_DBG("Called.") + using namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; @@ -52,13 +74,26 @@ using namespace ::apache::thrift::server; using boost::shared_ptr; -using namespace ::switch_sai; +using namespace ::switch_sai; + +extern sai_object_id_t gSwitchId; + +typedef std::vector std_sai_thrift_attr_vctr_t; class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { - public: - switch_sai_rpcHandler() { - // Your initialization goes here - } +public: + switch_sai_rpcHandler() noexcept + { + // Your initialization goes here + } + + inline void sai_thrift_timestamp_print() const noexcept + { + const auto ltime = std::time(nullptr); + const auto tm = std::localtime(<ime); + + std::printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); + } unsigned int sai_thrift_string_to_mac(const std::string s, unsigned char *m) { unsigned int i, j=0; @@ -100,6 +135,12 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return; } + inline void sai_thrift_alloc_attr(sai_attribute_t* &attr, const sai_uint32_t &size) const noexcept + { attr = new (std::nothrow) sai_attribute_t[size]; } + + inline void sai_thrift_free_attr(sai_attribute_t* &attr) const noexcept + { delete[] attr; attr = nullptr; } + void sai_thrift_parse_object_id_list(const std::vector & thrift_object_id_list, sai_object_id_t *object_id_list) { std::vector::const_iterator it = thrift_object_id_list.begin(); for(uint32_t i = 0; i < thrift_object_id_list.size(); i++, it++) { @@ -139,12 +180,14 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_thrift_string_to_mac(thrift_fdb_entry.mac_address, fdb_entry->mac_address); } - void sai_thrift_parse_unicast_route_entry(const sai_thrift_unicast_route_entry_t &thrift_unicast_route_entry, sai_unicast_route_entry_t *unicast_route_entry) { - unicast_route_entry->vr_id = (sai_object_id_t) thrift_unicast_route_entry.vr_id; - sai_thrift_parse_ip_prefix(thrift_unicast_route_entry.destination, &unicast_route_entry->destination); + void sai_thrift_parse_route_entry(const sai_thrift_route_entry_t &thrift_route_entry, sai_route_entry_t *route_entry) { + route_entry->switch_id = gSwitchId; + route_entry->vr_id = (sai_object_id_t) thrift_route_entry.vr_id; + sai_thrift_parse_ip_prefix(thrift_route_entry.destination, &route_entry->destination); } void sai_thrift_parse_neighbor_entry(const sai_thrift_neighbor_entry_t &thrift_neighbor_entry, sai_neighbor_entry_t *neighbor_entry) { + neighbor_entry->switch_id = gSwitchId; neighbor_entry->rif_id = (sai_object_id_t) thrift_neighbor_entry.rif_id; sai_thrift_parse_ip_address(thrift_neighbor_entry.ip_address, &neighbor_entry->ip_address); } @@ -168,7 +211,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_PORT_ATTR_QOS_DEFAULT_TC: attr_list[i].value.u8 = attribute.value.u8; break; - case SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST: + case SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST: case SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST: { *buffer_profile_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count); @@ -179,7 +222,19 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attr_list[i].value.objlist.count = attribute.value.objlist.count; attr_list[i].value.objlist.list = *buffer_profile_list; break; + } + case SAI_PORT_ATTR_INGRESS_MIRROR_SESSION: + case SAI_PORT_ATTR_EGRESS_MIRROR_SESSION: + { + *buffer_profile_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count); + std::vector::const_iterator it2 = attribute.value.objlist.object_id_list.begin(); + for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++) { + *buffer_profile_list[j] = (sai_object_id_t) *it2; } + attr_list[i].value.objlist.count = attribute.value.objlist.count; + attr_list[i].value.objlist.list=*buffer_profile_list; + break; + } case SAI_PORT_ATTR_QOS_SCHEDULER_PROFILE_ID: case SAI_PORT_ATTR_QOS_WRED_PROFILE_ID: case SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP: @@ -192,8 +247,10 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_PORT_ATTR_QOS_TC_TO_PRIORITY_GROUP_MAP: case SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP: case SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_QUEUE_MAP: + case SAI_PORT_ATTR_INGRESS_ACL: attr_list[i].value.oid = attribute.value.oid; break; + default: break; } @@ -210,7 +267,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_FDB_ENTRY_ATTR_TYPE: attr_list[i].value.s32 = attribute.value.s32; break; - case SAI_FDB_ENTRY_ATTR_PORT_ID: + case SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID: attr_list[i].value.oid = attribute.value.oid; break; case SAI_FDB_ENTRY_ATTR_PACKET_ACTION: @@ -229,7 +286,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attribute = (sai_thrift_attribute_t)*it; attr_list[i].id = attribute.id; switch (attribute.id) { - case SAI_FDB_FLUSH_ATTR_PORT_ID: + case SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID: attr_list[i].value.oid = (sai_object_id_t) attribute.value.oid; break; case SAI_FDB_FLUSH_ATTR_VLAN_ID: @@ -267,10 +324,10 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attribute = (sai_thrift_attribute_t)*it; attr_list[i].id = attribute.id; switch (attribute.id) { - case SAI_ROUTE_ATTR_NEXT_HOP_ID: + case SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID: attr_list[i].value.oid = attribute.value.oid; break; - case SAI_ROUTE_ATTR_PACKET_ACTION: + case SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION: attr_list[i].value.s32 = attribute.value.s32; break; default: @@ -288,14 +345,12 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { switch (attribute.id) { case SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID: case SAI_ROUTER_INTERFACE_ATTR_PORT_ID: + case SAI_ROUTER_INTERFACE_ATTR_VLAN_ID: attr_list[i].value.oid = attribute.value.oid; break; case SAI_ROUTER_INTERFACE_ATTR_TYPE: attr_list[i].value.s32 = attribute.value.s32; break; - case SAI_ROUTER_INTERFACE_ATTR_VLAN_ID: - attr_list[i].value.u16 = attribute.value.u16; - break; case SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS: sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac); break; @@ -303,6 +358,8 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE: attr_list[i].value.booldata = attribute.value.booldata; break; + case SAI_ROUTER_INTERFACE_ATTR_INGRESS_ACL: + attr_list[i].value.oid = attribute.value.oid; default: break; } @@ -329,32 +386,6 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { } } - void sai_thrift_parse_next_hop_group_attributes(const std::vector &thrift_attr_list, sai_attribute_t *attr_list, sai_object_id_t **nhop_list) { - std::vector::const_iterator it1 = thrift_attr_list.begin(); - sai_thrift_attribute_t attribute; - for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it1++) { - attribute = (sai_thrift_attribute_t)*it1; - attr_list[i].id = attribute.id; - switch (attribute.id) { - case SAI_NEXT_HOP_GROUP_ATTR_TYPE: - attr_list[i].value.s32 = attribute.value.s32; - break; - case SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_COUNT: - attr_list[i].value.u32 = attribute.value.u32; - break; - case SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_LIST: - *nhop_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count); - std::vector::const_iterator it2 = attribute.value.objlist.object_id_list.begin(); - for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++) { - (*nhop_list)[j] = (sai_object_id_t) *it2; - } - attr_list[i].value.objlist.count = attribute.value.objlist.count; - attr_list[i].value.objlist.list = *nhop_list; - break; - } - } - } - void sai_thrift_parse_lag_member_attributes(const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { std::vector::const_iterator it1 = thrift_attr_list.begin(); sai_thrift_attribute_t attribute; @@ -403,7 +434,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attribute = (sai_thrift_attribute_t)*it1; attr_list[i].id = attribute.id; switch (attribute.id) { - case SAI_NEIGHBOR_ATTR_DST_MAC_ADDRESS: + case SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS: sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac); break; } @@ -420,7 +451,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_HOSTIF_ATTR_TYPE: attr_list[i].value.s32 = attribute.value.s32; break; - case SAI_HOSTIF_ATTR_RIF_OR_PORT_ID: + case SAI_HOSTIF_ATTR_OBJ_ID: attr_list[i].value.oid = attribute.value.oid; break; case SAI_HOSTIF_ATTR_NAME: @@ -460,9 +491,6 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY: attr_list[i].value.u32 = attribute.value.u32; break; - case SAI_HOSTIF_TRAP_ATTR_TRAP_CHANNEL: - attr_list[i].value.u32 = attribute.value.u32; - break; case SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP: attr_list[i].value.oid = attribute.value.oid; break; @@ -481,9 +509,6 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { case SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY: attr->value.u32 = thrift_attr.value.u32; break; - case SAI_HOSTIF_TRAP_ATTR_TRAP_CHANNEL: - attr->value.s32 = thrift_attr.value.s32; - break; case SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP: attr->value.oid = thrift_attr.value.oid; break; @@ -506,10 +531,32 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t attr; sai_thrift_parse_port_attributes(thrift_attr_list, &attr, &buffer_profile_list); status = port_api->set_port_attribute((sai_object_id_t)port_id, &attr); + if (status != SAI_STATUS_SUCCESS) { + SAI_THRIFT_LOG_ERR("Failed to set port attributes."); + } if (buffer_profile_list) free(buffer_profile_list); return status; } + sai_thrift_status_t sai_thrift_set_router_interface_attribute(const sai_thrift_object_id_t rif_id, const sai_thrift_attribute_t &thrift_attr) { + printf("sai_thrift_set_router_interface\n"); + sai_status_t status = SAI_STATUS_SUCCESS; + sai_router_interface_api_t *rif_api; + status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + std::vector thrift_attr_list; + thrift_attr_list.push_back(thrift_attr); + sai_attribute_t attr; + sai_thrift_parse_router_interface_attributes(thrift_attr_list, &attr); + status = rif_api->set_router_interface_attribute((sai_object_id_t)rif_id, &attr); + if (status != SAI_STATUS_SUCCESS) { + SAI_THRIFT_LOG_ERR("Failed to set router interface attributes."); + } + return status; + } + sai_thrift_status_t sai_thrift_create_fdb_entry(const sai_thrift_fdb_entry_t& thrift_fdb_entry, const std::vector & thrift_attr_list) { printf("sai_thrift_create_fdb_entry\n"); sai_status_t status = SAI_STATUS_SUCCESS; @@ -553,24 +600,60 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_fdb_flush_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = fdb_api->flush_fdb_entries(attr_count, attr_list); + status = fdb_api->flush_fdb_entries(gSwitchId, attr_count, attr_list); free(attr_list); return status; } - sai_thrift_status_t sai_thrift_create_vlan(const sai_thrift_vlan_id_t vlan_id) { - printf("sai_thrift_create_vlan\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_vlan_api_t *vlan_api; - status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api); - if (status != SAI_STATUS_SUCCESS) { - return status; + void sai_thrift_parse_vlan_attributes(const std_sai_thrift_attr_vctr_t &thrift_attr_list, sai_attribute_t *attr_list) { + SAI_THRIFT_LOG_DBG("Called."); + + std_sai_thrift_attr_vctr_t::const_iterator cit = thrift_attr_list.begin(); + + for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++) + { + sai_thrift_attribute_t attribute = *cit; + attr_list[i].id = attribute.id; + + switch (attribute.id) + { + case SAI_VLAN_ATTR_VLAN_ID: + attr_list[i].value.u16 = attribute.value.u16; + break; + + default: + SAI_THRIFT_LOG_ERR("Failed to parse VLAN attributes."); + break; + } } - status = vlan_api->create_vlan((sai_vlan_id_t) vlan_id); - return status; } - sai_thrift_status_t sai_thrift_delete_vlan(const sai_thrift_vlan_id_t vlan_id) { + sai_thrift_object_id_t sai_thrift_create_vlan(const std_sai_thrift_attr_vctr_t &thrift_attr_list) { + SAI_THRIFT_LOG_DBG("Called."); + + sai_vlan_api_t *vlan_api = nullptr; + auto status = sai_api_query(SAI_API_VLAN, reinterpret_cast(&vlan_api)); + + if (status != SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_ERR("Failed to get VLAN API."); return SAI_NULL_OBJECT_ID; } + + sai_attribute_t *attr_list = nullptr; + sai_uint32_t attr_size = thrift_attr_list.size(); + sai_thrift_alloc_attr(attr_list, attr_size); + sai_thrift_parse_vlan_attributes(thrift_attr_list, attr_list); + + sai_object_id_t vlanObjId = 0; + status = vlan_api->create_vlan(&vlanObjId, gSwitchId, attr_size, attr_list); + sai_thrift_free_attr(attr_list); + + if (status == SAI_STATUS_SUCCESS) { return vlanObjId; } + + SAI_THRIFT_LOG_ERR("Failed to create VLAN."); + + return SAI_NULL_OBJECT_ID; + } + + sai_thrift_status_t sai_thrift_remove_vlan(const sai_thrift_object_id_t vlan_oid) { printf("sai_thrift_delete_vlan\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_vlan_api_t *vlan_api; @@ -578,42 +661,41 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { if (status != SAI_STATUS_SUCCESS) { return status; } - status = vlan_api->remove_vlan((sai_vlan_id_t) vlan_id); + status = vlan_api->remove_vlan(vlan_oid); return status; } - void sai_thrift_get_vlan_stats( - std::vector & thrift_counters, - const sai_thrift_vlan_id_t vlan_id, - const std::vector & thrift_counter_ids, - const int32_t number_of_counters) { - printf("sai_thrift_get_vlan_stats\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_vlan_api_t *vlan_api; - status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api); - if (status != SAI_STATUS_SUCCESS) { - return; - } - sai_vlan_stat_counter_t *counter_ids = (sai_vlan_stat_counter_t *) malloc(sizeof(sai_vlan_stat_counter_t) * thrift_counter_ids.size()); - std::vector::const_iterator it = thrift_counter_ids.begin(); - uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); - for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_vlan_stat_counter_t) *it; - } + void sai_thrift_get_vlan_stats(std::vector &thrift_counters, + const sai_thrift_vlan_id_t vlan_id, + const std::vector &thrift_counter_ids, + const int32_t number_of_counters) + { + printf("sai_thrift_get_vlan_stats\n"); + sai_status_t status = SAI_STATUS_SUCCESS; + sai_vlan_api_t *vlan_api; + status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api); - status = vlan_api->get_vlan_stats( - (sai_vlan_id_t) vlan_id, - counter_ids, - number_of_counters, - counters); + if (status != SAI_STATUS_SUCCESS) { return; } - for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { - thrift_counters.push_back(counters[i]); - } - free(counter_ids); - free(counters); - return; - } + sai_vlan_stat_t *counter_ids = (sai_vlan_stat_t *) malloc(sizeof(sai_vlan_stat_t) * thrift_counter_ids.size()); + std::vector::const_iterator it = thrift_counter_ids.begin(); + uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); + + for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) + { counter_ids[i] = (sai_vlan_stat_t) *it; } + + status = vlan_api->get_vlan_stats((sai_vlan_id_t) vlan_id, + counter_ids, + number_of_counters, + counters); + + for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); } + + free(counter_ids); + free(counters); + + return; + } void sai_thrift_get_vlan_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t vlan_id) { printf("sai_thrift_get_vlan_attribute\n"); @@ -657,7 +739,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_vlan_member_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - vlan_api->create_vlan_member(&vlan_member_id, attr_count, attr_list); + vlan_api->create_vlan_member(&vlan_member_id, gSwitchId, attr_count, attr_list); return vlan_member_id; } @@ -669,12 +751,12 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { attr_list[i].id = attribute.id; switch (attribute.id) { case SAI_VLAN_MEMBER_ATTR_VLAN_ID: - attr_list[i].value.s32 = attribute.value.s32; + attr_list[i].value.oid = attribute.value.oid; break; - case SAI_VLAN_MEMBER_ATTR_PORT_ID: + case SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID: attr_list[i].value.oid = attribute.value.oid; break; - case SAI_VLAN_MEMBER_ATTR_TAGGING_MODE: + case SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE: attr_list[i].value.s32 = attribute.value.s32; break; } @@ -693,6 +775,28 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return status; } + void sai_thrift_get_vlan_id(sai_thrift_result_t &ret, sai_thrift_object_id_t vlan_id) + { + sai_attribute_t vlan_attr; + sai_vlan_api_t *vlan_api; + + SAI_THRIFT_FUNC_LOG(); + + ret.status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api); + if (ret.status != SAI_STATUS_SUCCESS) { + SAI_THRIFT_LOG_ERR("failed to obtain vlan_api, status:%d", ret.status); + return; + } + + vlan_attr.id = SAI_VLAN_ATTR_VLAN_ID; + ret.status = vlan_api->get_vlan_attribute((sai_object_id_t)vlan_id, 1, &vlan_attr); + if (ret.status != SAI_STATUS_SUCCESS) { + SAI_THRIFT_LOG_ERR("failed to get vlan ID, status:%d", ret.status); + return; + } + + ret.data.u16 = vlan_attr.value.u16; + } sai_thrift_object_id_t sai_thrift_create_virtual_router(const std::vector & thrift_attr_list) { printf("sai_thrift_create_virtual_router\n"); @@ -706,7 +810,8 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_vr_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - vr_api->create_virtual_router(&vr_id, attr_count, attr_list); + vr_api->create_virtual_router(&vr_id, gSwitchId, attr_count, attr_list); + free(attr_list); return vr_id; } @@ -722,35 +827,37 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return status; } - sai_thrift_status_t sai_thrift_create_route(const sai_thrift_unicast_route_entry_t& thrift_unicast_route_entry, const std::vector & thrift_attr_list) { + sai_thrift_status_t sai_thrift_create_route(const sai_thrift_route_entry_t &thrift_route_entry, const std::vector & thrift_attr_list) + { printf("sai_thrift_create_route\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_route_api_t *route_api; - sai_unicast_route_entry_t unicast_route_entry; + sai_route_entry_t route_entry; status = sai_api_query(SAI_API_ROUTE, (void **) &route_api); if (status != SAI_STATUS_SUCCESS) { return status; } - sai_thrift_parse_unicast_route_entry(thrift_unicast_route_entry, &unicast_route_entry); + sai_thrift_parse_route_entry(thrift_route_entry, &route_entry); sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_route_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = route_api->create_route(&unicast_route_entry, attr_count, attr_list); + status = route_api->create_route_entry(&route_entry, attr_count, attr_list); free(attr_list); + SAI_THRIFT_LOG_DBG("Exit."); return status; } - sai_thrift_status_t sai_thrift_remove_route(const sai_thrift_unicast_route_entry_t& thrift_unicast_route_entry) { + sai_thrift_status_t sai_thrift_remove_route(const sai_thrift_route_entry_t &thrift_route_entry) { printf("sai_thrift_remove_route\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_route_api_t *route_api; - sai_unicast_route_entry_t unicast_route_entry; + sai_route_entry_t route_entry; status = sai_api_query(SAI_API_ROUTE, (void **) &route_api); if (status != SAI_STATUS_SUCCESS) { return status; } - sai_thrift_parse_unicast_route_entry(thrift_unicast_route_entry, &unicast_route_entry); - status = route_api->remove_route(&unicast_route_entry); + sai_thrift_parse_route_entry(thrift_route_entry, &route_entry); + status = route_api->remove_route_entry(&route_entry); return status; } @@ -766,7 +873,8 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_router_interface_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = rif_api->create_router_interface(&rif_id, attr_count, attr_list); + status = rif_api->create_router_interface(&rif_id, gSwitchId, attr_count, attr_list); + free(attr_list); return rif_id; } @@ -794,7 +902,8 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_next_hop_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = nhop_api->create_next_hop(&nhop_id, attr_count, attr_list); + status = nhop_api->create_next_hop(&nhop_id, gSwitchId, attr_count, attr_list); + free(attr_list); return nhop_id; } @@ -810,71 +919,6 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return status; } - sai_thrift_object_id_t sai_thrift_create_next_hop_group(const std::vector & thrift_attr_list) { - printf("sai_thrift_create_next_hop_group\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_next_hop_group_api_t *nhop_group_api; - sai_object_id_t nhop_group_id = 0; - sai_object_id_t *nhop_list; - status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api); - if (status != SAI_STATUS_SUCCESS) { - return status; - } - sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); - sai_thrift_parse_next_hop_group_attributes(thrift_attr_list, attr_list, &nhop_list); - uint32_t attr_count = thrift_attr_list.size(); - status = nhop_group_api->create_next_hop_group(&nhop_group_id, attr_count, attr_list); - if (nhop_list) free(nhop_list); - free(attr_list); - return nhop_group_id; - } - - sai_thrift_status_t sai_thrift_remove_next_hop_group(const sai_thrift_object_id_t next_hop_group_id) { - printf("sai_thrift_remove_next_hop_group\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_next_hop_group_api_t *nhop_group_api; - status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api); - if (status != SAI_STATUS_SUCCESS) { - return status; - } - status = nhop_group_api->remove_next_hop_group(next_hop_group_id); - return status; - } - - sai_thrift_status_t sai_thrift_add_next_hop_to_group(const sai_thrift_object_id_t next_hop_group_id, const std::vector & thrift_nexthops) { - printf("sai_thrift_add_next_hop_to_group\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_next_hop_group_api_t *nhop_group_api; - sai_object_id_t *nhop_list; - status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api); - if (status != SAI_STATUS_SUCCESS) { - return status; - } - nhop_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * thrift_nexthops.size()); - sai_thrift_parse_object_id_list(thrift_nexthops, nhop_list); - uint32_t nhop_count = thrift_nexthops.size(); - status = nhop_group_api->add_next_hop_to_group(next_hop_group_id, nhop_count, nhop_list); - free(nhop_list); - return status; - } - - sai_thrift_status_t sai_thrift_remove_next_hop_from_group(const sai_thrift_object_id_t next_hop_group_id, const std::vector & thrift_nexthops) { - printf("sai_thrift_remove_next_hop_from_group\n"); - sai_status_t status = SAI_STATUS_SUCCESS; - sai_next_hop_group_api_t *nhop_group_api; - sai_object_id_t *nhop_list; - status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api); - if (status != SAI_STATUS_SUCCESS) { - return status; - } - nhop_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * thrift_nexthops.size()); - sai_thrift_parse_object_id_list(thrift_nexthops, nhop_list); - uint32_t nhop_count = thrift_nexthops.size(); - status = nhop_group_api->remove_next_hop_from_group(next_hop_group_id, nhop_count, nhop_list); - free(nhop_list); - return status; - } - sai_thrift_object_id_t sai_thrift_create_lag(const std::vector & thrift_attr_list) { printf("sai_thrift_create_lag\n"); sai_status_t status = SAI_STATUS_SUCCESS; @@ -886,7 +930,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return status; } - status = lag_api->create_lag(&lag_id, 0, NULL); + status = lag_api->create_lag(&lag_id, gSwitchId, 0, nullptr); return lag_id; } @@ -914,7 +958,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_lag_member_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = lag_api->create_lag_member(&lag_member_id, attr_count, attr_list); + status = lag_api->create_lag_member(&lag_member_id, gSwitchId, attr_count, attr_list); return lag_member_id; } @@ -943,7 +987,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_stp_attributes(thrift_attr_list, attr_list, &vlan_list); uint32_t attr_count = thrift_attr_list.size(); - status = (sai_object_id_t) stp_api->create_stp(&stp_id, attr_count, attr_list); + status = (sai_object_id_t) stp_api->create_stp(&stp_id, gSwitchId, attr_count, attr_list); if (vlan_list) free(vlan_list); free(attr_list); return stp_id; @@ -969,9 +1013,11 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { if (status != SAI_STATUS_SUCCESS) { return status; } - status = stp_api->set_stp_port_state((sai_object_id_t) stp_id, - (sai_object_id_t) port_id, - (sai_port_stp_port_state_t) stp_port_state); + sai_attribute_t attr[1]; + std::memset(attr, '\0', sizeof(attr)); + attr[0].id = SAI_STP_PORT_ATTR_STATE; + attr[0].value.s32 = stp_port_state; + status = stp_api->set_stp_port_attribute(port_id, attr); return status; } @@ -980,14 +1026,14 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { sai_status_t status = SAI_STATUS_SUCCESS; sai_stp_api_t *stp_api; status = sai_api_query(SAI_API_STP, (void **) &stp_api); - sai_port_stp_port_state_t stp_port_state; if (status != SAI_STATUS_SUCCESS) { return status; } - status = stp_api->get_stp_port_state((sai_object_id_t) stp_id, - (sai_object_id_t) port_id, - &stp_port_state); - return (sai_thrift_port_stp_port_state_t) stp_port_state; + sai_attribute_t attr[1]; + std::memset(attr, '\0', sizeof(attr)); + attr[0].id = SAI_STP_PORT_ATTR_STATE; + status = stp_api->get_stp_port_attribute(port_id, 1, attr); + return (sai_thrift_port_stp_port_state_t) attr[0].value.s32; } sai_thrift_status_t sai_thrift_create_neighbor_entry(const sai_thrift_neighbor_entry_t& thrift_neighbor_entry, const std::vector & thrift_attr_list) { @@ -1022,7 +1068,7 @@ class switch_sai_rpcHandler : virtual public switch_sai_rpcIf { return status; } -sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { + sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_status_t status; sai_attribute_t attr; sai_switch_api_t *switch_api; @@ -1035,7 +1081,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return SAI_NULL_OBJECT_ID; } attr.id = SAI_SWITCH_ATTR_CPU_PORT; - status = switch_api->get_switch_attribute(1, &attr); + status = switch_api->get_switch_attribute(gSwitchId, 1, &attr); if (status != SAI_STATUS_SUCCESS) { printf("%s failed, status:%d\n", f_name, status); @@ -1058,7 +1104,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return SAI_NULL_OBJECT_ID; } attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; - status = switch_api->get_switch_attribute(1, &attr); + status = switch_api->get_switch_attribute(gSwitchId, 1, &attr); if (status != SAI_STATUS_SUCCESS) { printf("%s. Failed to get switch virtual router ID, status %d", f_name, status); @@ -1068,6 +1114,29 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return default_router_id; } + void sai_thrift_get_default_vlan_id(sai_thrift_result_t &ret) { + sai_switch_api_t *switch_api; + sai_attribute_t attr; + + SAI_THRIFT_FUNC_LOG(); + + ret.status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api); + if (ret.status != SAI_STATUS_SUCCESS) { + SAI_THRIFT_LOG_ERR("failed to obtain switch_api, status:%d", ret.status); + return; + } + + attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID; + ret.status = switch_api->get_switch_attribute(gSwitchId, 1, &attr); + if (ret.status != SAI_STATUS_SUCCESS) + { + SAI_THRIFT_LOG_ERR("failed to get switch default vlan ID, status:%d", ret.status); + return; + } + + ret.data.oid = (sai_thrift_object_id_t)attr.value.oid; + } + sai_thrift_object_id_t sai_thrift_get_default_trap_group() { sai_status_t status; sai_attribute_t attr; @@ -1081,7 +1150,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return SAI_NULL_OBJECT_ID; } attr.id = SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP; - status = switch_api->get_switch_attribute(1, &attr); + status = switch_api->get_switch_attribute(gSwitchId, 1, &attr); if (status != SAI_STATUS_SUCCESS) { printf("%s. Failed to get switch default trap group, status %d", f_name, status); @@ -1107,12 +1176,12 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER; - switch_api->get_switch_attribute(1, &max_port_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute); max_ports = max_port_attribute.value.u32; port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST; port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports); port_list_object_attribute.value.objlist.count = max_ports; - switch_api->get_switch_attribute(1, &port_list_object_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute); thrift_attr_list.attr_count = 1; std::vector& attr_list = thrift_attr_list.attr_list; @@ -1140,7 +1209,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_thrift_parse_switch_attribute(thrift_attr, &attr); - status = switch_api->set_switch_attribute(&attr); + status = switch_api->set_switch_attribute(gSwitchId, &attr); return status; } @@ -1152,9 +1221,9 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_thrift_string_to_mac(thrift_attr.value.mac, attr->value.mac); break; - case SAI_SWITCH_ATTR_FDB_UNICAST_MISS_ACTION: - case SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_ACTION: - case SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_ACTION: + case SAI_SWITCH_ATTR_FDB_UNICAST_MISS_PACKET_ACTION: + case SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_PACKET_ACTION: + case SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION: attr->value.s32 = thrift_attr.value.s32; break; } @@ -1187,12 +1256,12 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER; - switch_api->get_switch_attribute(1, &max_port_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute); max_ports = max_port_attribute.value.u32; port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST; port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports); port_list_object_attribute.value.objlist.count = max_ports; - switch_api->get_switch_attribute(1, &port_list_object_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute); std::map front_to_sai_map; for (int i=0 ; iget_switch_attribute(1, &max_port_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute); max_ports = max_port_attribute.value.u32; port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST; port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports); port_list_object_attribute.value.objlist.count = max_ports; - switch_api->get_switch_attribute(1, &port_list_object_attribute); + switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute); for (int i=0 ; icreate_hostif(&hif_id, attr_count, attr_list); + status = hostif_api->create_hostif(&hif_id, gSwitchId, attr_count, attr_list); free(attr_list); return hif_id; } @@ -1330,7 +1399,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { printf("sai_thrift_remove_hostif\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_hostif_api_t *hostif_api; - status = sai_api_query(SAI_API_HOST_INTERFACE, (void **) &hostif_api); + status = sai_api_query(SAI_API_HOSTIF, (void **) &hostif_api); if (status != SAI_STATUS_SUCCESS) { return status; } @@ -1343,14 +1412,14 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_status_t status = SAI_STATUS_SUCCESS; sai_hostif_api_t *hostif_api; sai_object_id_t hif_trap_group_id; - status = sai_api_query(SAI_API_HOST_INTERFACE, (void **) &hostif_api); + status = sai_api_query(SAI_API_HOSTIF, (void **) &hostif_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_hostif_trap_group_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = hostif_api->create_hostif_trap_group(&hif_trap_group_id, attr_count, attr_list); + status = hostif_api->create_hostif_trap_group(&hif_trap_group_id, gSwitchId, attr_count, attr_list); free(attr_list); return hif_trap_group_id; } @@ -1359,7 +1428,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { printf("sai_thrift_remove_hostif_trap_group\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_hostif_api_t *hostif_api; - status = sai_api_query(SAI_API_HOST_INTERFACE, (void **) &hostif_api); + status = sai_api_query(SAI_API_HOSTIF, (void **) &hostif_api); if (status != SAI_STATUS_SUCCESS) { return status; } @@ -1377,17 +1446,17 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return 0; } - sai_thrift_status_t sai_thrift_set_hostif_trap(const sai_thrift_hostif_trap_id_t trap_id, const sai_thrift_attribute_t& thrift_attr) { + sai_thrift_status_t sai_thrift_set_hostif_trap(const sai_thrift_object_id_t trap_id, const sai_thrift_attribute_t& thrift_attr) { printf("sai_thrift_set_hostif_trap\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_hostif_api_t *hostif_api; sai_attribute_t attr; - status = sai_api_query(SAI_API_HOST_INTERFACE, (void **) &hostif_api); + status = sai_api_query(SAI_API_HOSTIF, (void **) &hostif_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_thrift_parse_hostif_trap_attribute(thrift_attr, &attr); - status = hostif_api->set_trap_attribute((sai_hostif_trap_id_t) trap_id, &attr); + status = hostif_api->set_hostif_trap_attribute((sai_object_id_t) trap_id, &attr); return status; } @@ -1407,12 +1476,12 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_status_t status = SAI_STATUS_SUCCESS; sai_hostif_api_t *hostif_api; sai_attribute_t attr; - status = sai_api_query(SAI_API_HOST_INTERFACE, (void **) &hostif_api); + status = sai_api_query(SAI_API_HOSTIF, (void **) &hostif_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_thrift_parse_hostif_trap_group_attribute(thrift_attr, &attr); - status = hostif_api->set_trap_group_attribute((sai_object_id_t) trap_group_id, &attr); + status = hostif_api->set_hostif_trap_group_attribute((sai_object_id_t) trap_group_id, &attr); return status; } @@ -1423,12 +1492,23 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { attribute = (sai_thrift_attribute_t)*it; attr_list[i].id = attribute.id; switch (attribute.id) { - case SAI_ACL_TABLE_ATTR_STAGE: - case SAI_ACL_TABLE_ATTR_PRIORITY: - attr_list[i].value.u32 = attribute.value.u32; + case SAI_ACL_TABLE_ATTR_ACL_STAGE: + attr_list[i].value.s32 = attribute.value.s32; break; - case SAI_ACL_TABLE_ATTR_FIELD_SRC_IPv6: - case SAI_ACL_TABLE_ATTR_FIELD_DST_IPv6: + case SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST: + { + int count = attribute.value.s32list.s32list.size(); + sai_int32_t *aclbp_list = NULL; + std::vector::const_iterator it = attribute.value.s32list.s32list.begin(); + aclbp_list = (sai_int32_t *) malloc(sizeof(sai_int32_t) * count); + for(int j = 0; j < count; j++, it++) + *(aclbp_list + j) = (sai_int32_t) *it; + attr_list[i].value.s32list.list = aclbp_list; + attr_list[i].value.s32list.count = count; + } + break; + case SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6: + case SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6: case SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC: case SAI_ACL_TABLE_ATTR_FIELD_DST_MAC: case SAI_ACL_TABLE_ATTR_FIELD_SRC_IP: @@ -1453,9 +1533,9 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_ACL_TABLE_ATTR_FIELD_TOS: case SAI_ACL_TABLE_ATTR_FIELD_IP_FLAGS: case SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS: - case SAI_ACL_TABLE_ATTR_FIELD_IP_TYPE: - case SAI_ACL_TABLE_ATTR_FIELD_IP_FRAG: - case SAI_ACL_TABLE_ATTR_FIELD_IPv6_FLOW_LABEL: + case SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE: + case SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_FRAG: + case SAI_ACL_TABLE_ATTR_FIELD_IPV6_FLOW_LABEL: case SAI_ACL_TABLE_ATTR_FIELD_TC: attr_list[i].value.booldata = attribute.value.booldata; break; @@ -1481,8 +1561,8 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_ACL_ENTRY_ATTR_ADMIN_STATE: attr_list[i].value.u8 = attribute.value.u8; break; - case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPv6: - case SAI_ACL_ENTRY_ATTR_FIELD_DST_IPv6: + case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6: + case SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6: sai_thrift_string_to_v6_ip(attribute.value.aclfield.data.ip6, attr_list[i].value.aclfield.data.ip6); sai_thrift_string_to_v6_ip(attribute.value.aclfield.mask.ip6, attr_list[i].value.aclfield.mask.ip6); break; @@ -1535,15 +1615,15 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_ACL_ENTRY_ATTR_FIELD_ECN: case SAI_ACL_ENTRY_ATTR_FIELD_TTL: case SAI_ACL_ENTRY_ATTR_FIELD_TOS: -// case SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS: + case SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS: case SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS: -// case SAI_ACL_ENTRY_ATTR_FIELD_IP_TYPE: -// case SAI_ACL_ENTRY_ATTR_FIELD_IP_FRAG: + case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE: + case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_FRAG: case SAI_ACL_ENTRY_ATTR_FIELD_TC: attr_list[i].value.aclfield.data.u8 = attribute.value.aclfield.data.u8; attr_list[i].value.aclfield.mask.u8 = attribute.value.aclfield.mask.u8; break; - case SAI_ACL_ENTRY_ATTR_FIELD_IPv6_FLOW_LABEL: + case SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL: attr_list[i].value.aclfield.data.u16 = attribute.value.aclfield.data.u16; attr_list[i].value.aclfield.mask.u16 = attribute.value.aclfield.mask.u16; break; @@ -1559,7 +1639,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_ACL_ENTRY_ATTR_ACTION_COUNTER: attr_list[i].value.aclfield.data.oid = attribute.value.aclfield.data.oid; break; - case SAI_ACL_ENTRY_ATTR_PACKET_ACTION: + case SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION: attr_list[i].value.aclaction.parameter.u32 = attribute.value.aclaction.parameter.u32; break; default: @@ -1568,6 +1648,59 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } } + void sai_thrift_parse_acl_table_group_attributes(const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { + std::vector::const_iterator it = thrift_attr_list.begin(); + sai_thrift_attribute_t attribute; + for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) { + attribute = (sai_thrift_attribute_t)*it; + attr_list[i].id = attribute.id; + switch (attribute.id) { + case SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE: + attr_list[i].value.s32 = attribute.value.s32; + break; + case SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST: + { + int count = attribute.value.s32list.s32list.size(); + sai_int32_t *s32_list = NULL; + std::vector::const_iterator it = attribute.value.s32list.s32list.begin(); + s32_list = (sai_int32_t *) malloc(sizeof(sai_int32_t) * count); + for(int j = 0; j < count; j++, it++) + *(s32_list + j) = (sai_int32_t) *it; + attr_list[i].value.s32list.list = s32_list; + attr_list[i].value.s32list.count = count; + } + break; + case SAI_ACL_TABLE_GROUP_ATTR_TYPE: + attr_list[i].value.s32 = attribute.value.s32; + break; + default: + break; + } + } + } + + void sai_thrift_parse_acl_table_group_member_attributes(const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { + std::vector::const_iterator it = thrift_attr_list.begin(); + sai_thrift_attribute_t attribute; + for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) { + attribute = (sai_thrift_attribute_t)*it; + attr_list[i].id = attribute.id; + switch (attribute.id) { + case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID: + attr_list[i].value.oid = attribute.value.oid; + break; + case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID: + attr_list[i].value.oid = attribute.value.oid; + break; + case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY: + attr_list[i].value.u32 = attribute.value.u32; + break; + default: + break; + } + } + } + void sai_thrift_convert_to_acl_counter_attributes( const std::vector &thrift_attr_list, sai_attribute_t *attr_list) { @@ -1637,19 +1770,19 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_acl_table_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = acl_api->create_acl_table(&acl_table, attr_count, attr_list); + status = acl_api->create_acl_table(&acl_table, gSwitchId, attr_count, attr_list); free(attr_list); return acl_table; } - sai_thrift_status_t sai_thrift_delete_acl_table(const sai_thrift_object_id_t acl_table_id) { + sai_thrift_status_t sai_thrift_remove_acl_table(const sai_thrift_object_id_t acl_table_id) { sai_status_t status = SAI_STATUS_SUCCESS; sai_acl_api_t *acl_api; status = sai_api_query(SAI_API_ACL, (void **) &acl_api); if (status != SAI_STATUS_SUCCESS) { return status; } - status = acl_api->delete_acl_table(acl_table_id); + status = acl_api->remove_acl_table(acl_table_id); return status; } @@ -1665,19 +1798,75 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_acl_entry_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = acl_api->create_acl_entry(&acl_entry, attr_count, attr_list); + status = acl_api->create_acl_entry(&acl_entry, gSwitchId, attr_count, attr_list); free(attr_list); return acl_entry; } - sai_thrift_status_t sai_thrift_delete_acl_entry(const sai_thrift_object_id_t acl_entry) { + sai_thrift_status_t sai_thrift_remove_acl_entry(const sai_thrift_object_id_t acl_entry) { + sai_status_t status = SAI_STATUS_SUCCESS; + sai_acl_api_t *acl_api; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + status = acl_api->remove_acl_entry(acl_entry); + return status; + } + + sai_thrift_object_id_t sai_thrift_create_acl_table_group(const std::vector & thrift_attr_list) { + sai_object_id_t acl_table_group_id = 0ULL; + sai_acl_api_t *acl_api; + sai_status_t status = SAI_STATUS_SUCCESS; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + + sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); + sai_thrift_parse_acl_table_group_attributes(thrift_attr_list, attr_list); + uint32_t attr_count = thrift_attr_list.size(); + status = acl_api->create_acl_table_group(&acl_table_group_id, gSwitchId, attr_count, attr_list); + free(attr_list); + return acl_table_group_id; + } + + sai_thrift_status_t sai_thrift_remove_acl_table_group(const sai_thrift_object_id_t acl_table_group_id) { sai_status_t status = SAI_STATUS_SUCCESS; sai_acl_api_t *acl_api; status = sai_api_query(SAI_API_ACL, (void **) &acl_api); if (status != SAI_STATUS_SUCCESS) { return status; } - status = acl_api->delete_acl_entry(acl_entry); + status = acl_api->remove_acl_table_group(acl_table_group_id); + return status; + } + + sai_thrift_object_id_t sai_thrift_create_acl_table_group_member(const std::vector & thrift_attr_list) { + sai_object_id_t acl_table_group_member_id = 0ULL; + sai_acl_api_t *acl_api; + sai_status_t status = SAI_STATUS_SUCCESS; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + + sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); + sai_thrift_parse_acl_table_group_member_attributes(thrift_attr_list, attr_list); + uint32_t attr_count = thrift_attr_list.size(); + status = acl_api->create_acl_table_group_member(&acl_table_group_member_id, gSwitchId, attr_count, attr_list); + free(attr_list); + return acl_table_group_member_id; + } + + sai_thrift_status_t sai_thrift_remove_acl_table_group_member(const sai_thrift_object_id_t acl_table_group_member_id) { + sai_status_t status = SAI_STATUS_SUCCESS; + sai_acl_api_t *acl_api; + status = sai_api_query(SAI_API_ACL, (void **) &acl_api); + if (status != SAI_STATUS_SUCCESS) { + return status; + } + status = acl_api->remove_acl_table_group_member(acl_table_group_member_id); return status; } @@ -1692,12 +1881,12 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_convert_to_acl_counter_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - status = acl_api->create_acl_counter(&acl_counter_id, attr_count, attr_list); + status = acl_api->create_acl_counter(&acl_counter_id, gSwitchId, attr_count, attr_list); free(attr_list); return acl_counter_id; } - sai_thrift_status_t sai_thrift_delete_acl_counter(const sai_thrift_object_id_t acl_counter_id) { + sai_thrift_status_t sai_thrift_remove_acl_counter(const sai_thrift_object_id_t acl_counter_id) { sai_object_id_t acl_entry = 0ULL; sai_acl_api_t *acl_api; sai_status_t status = SAI_STATUS_SUCCESS; @@ -1705,7 +1894,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return status; } - status = acl_api->delete_acl_counter(acl_counter_id); + status = acl_api->remove_acl_counter(acl_counter_id); return status; } @@ -1725,10 +1914,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size()); memset(attr_list, 0x0, sizeof(sizeof(sai_attribute_t) * thrift_attr_ids.size())); sai_thrift_parse_attribute_ids(thrift_attr_ids, attr_list); - status = acl_api->get_acl_counter_attribute( - acl_counter_id, - attr_count, - attr_list); + status = acl_api->get_acl_counter_attribute(acl_counter_id, attr_count, attr_list); if (status != SAI_STATUS_SUCCESS) { return; } @@ -1765,8 +1951,8 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_MIRROR_SESSION_ATTR_VLAN_PRI: attr_list[i].value.u8 = attribute.value.u8; break; - case SAI_MIRROR_SESSION_ATTR_ENCAP_TYPE: - attr_list[i].value.u8 = attribute.value.u8; + case SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE: + attr_list[i].value.s32 = attribute.value.s32; break; case SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION: attr_list[i].value.u8 = attribute.value.u8; @@ -1810,7 +1996,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_mirror_session_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - mirror_api->create_mirror_session(&session_id, attr_count, attr_list); + mirror_api->create_mirror_session(&session_id, gSwitchId, attr_count, attr_list); return session_id; } @@ -1879,7 +2065,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_policer_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - policer_api->create_policer(&policer_id, attr_count, attr_list); + policer_api->create_policer(&policer_id, gSwitchId, attr_count, attr_list); return policer_id; } @@ -1895,10 +2081,9 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return status; } - void sai_thrift_get_policer_stats( - std::vector & thrift_counters, - const sai_thrift_object_id_t policer_id, - const std::vector & thrift_counter_ids) { + void sai_thrift_get_policer_stats(std::vector & thrift_counters, + const sai_thrift_object_id_t policer_id, + const std::vector & thrift_counter_ids) { printf("sai_thrift_get_policer_stats\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_policer_api_t *policer_api; @@ -1906,15 +2091,15 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return; } - sai_policer_stat_counter_t *counter_ids = (sai_policer_stat_counter_t *) malloc(sizeof(sai_policer_stat_counter_t) * thrift_counter_ids.size()); + _sai_policer_stat_t *counter_ids = (_sai_policer_stat_t *) malloc(sizeof(_sai_policer_stat_t) * thrift_counter_ids.size()); std::vector::const_iterator it = thrift_counter_ids.begin(); uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_policer_stat_counter_t) *it; + counter_ids[i] = (_sai_policer_stat_t) *it; } int32_t number_of_counters = thrift_counter_ids.size(); - status = policer_api->get_policer_statistics( + status = policer_api->get_policer_stats( (sai_object_id_t) policer_id, counter_ids, number_of_counters, @@ -1940,7 +2125,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_scheduler_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - scheduler_api->create_scheduler_profile(&scheduler_id, attr_count, attr_list); + scheduler_api->create_scheduler(&scheduler_id, gSwitchId, attr_count, attr_list); free (attr_list); return scheduler_id; } @@ -1953,7 +2138,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return status; } - status = scheduler_api->remove_scheduler_profile((sai_object_id_t) scheduler_id); + status = scheduler_api->remove_scheduler((sai_object_id_t) scheduler_id); return status; } @@ -1964,15 +2149,9 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { attribute = (sai_thrift_attribute_t)*it; attr_list[i].id = attribute.id; switch (attribute.id) { - case SAI_SCHEDULER_ATTR_SCHEDULING_ALGORITHM: - attr_list[i].value.s32 = attribute.value.s32; - break; case SAI_SCHEDULER_ATTR_SCHEDULING_WEIGHT: attr_list[i].value.u8 = attribute.value.u8; break; - case SAI_SCHEDULER_ATTR_SHAPER_TYPE: - attr_list[i].value.s32 = attribute.value.s32; - break; case SAI_SCHEDULER_ATTR_MIN_BANDWIDTH_RATE: attr_list[i].value.u64 = attribute.value.u64; break; @@ -1989,11 +2168,10 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } } - void sai_thrift_get_port_stats( - std::vector & thrift_counters, - const sai_thrift_object_id_t port_id, - const std::vector & thrift_counter_ids, - const int32_t number_of_counters) { + void sai_thrift_get_port_stats(std::vector & thrift_counters, + const sai_thrift_object_id_t port_id, + const std::vector & thrift_counter_ids, + const int32_t number_of_counters) { printf("sai_thrift_get_port_stats\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_port_api_t *port_api; @@ -2001,18 +2179,17 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return; } - sai_port_stat_counter_t *counter_ids = (sai_port_stat_counter_t *) malloc(sizeof(sai_port_stat_counter_t) * thrift_counter_ids.size()); + sai_port_stat_t *counter_ids = (sai_port_stat_t *) malloc(sizeof(sai_port_stat_t) * thrift_counter_ids.size()); std::vector::const_iterator it = thrift_counter_ids.begin(); uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_port_stat_counter_t) *it; + counter_ids[i] = (sai_port_stat_t) *it; } - status = port_api->get_port_stats( - (sai_object_id_t) port_id, - counter_ids, - number_of_counters, - counters); + status = port_api->get_port_stats((sai_object_id_t) port_id, + counter_ids, + number_of_counters, + counters); for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); @@ -2074,16 +2251,16 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_object_list_t *pg_list_object; int max_pg = 0; - max_pg_attribute.id = SAI_PORT_ATTR_NUMBER_OF_PRIORITY_GROUPS; + max_pg_attribute.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS; port_api->get_port_attribute(port_id, 1, &max_pg_attribute); max_pg = max_pg_attribute.value.u32; - pg_list_object_attribute.id = SAI_PORT_ATTR_PRIORITY_GROUP_LIST; + pg_list_object_attribute.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; pg_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_pg); pg_list_object_attribute.value.objlist.count = max_pg; port_api->get_port_attribute(port_id, 1, &pg_list_object_attribute); thrift_attr_list.attr_count = 3; - thrift_pg_list_attribute.id = SAI_PORT_ATTR_PRIORITY_GROUP_LIST; + thrift_pg_list_attribute.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; thrift_pg_list_attribute.value.objlist.count = max_pg; std::vector& pg_list = thrift_pg_list_attribute.value.objlist.object_id_list; pg_list_object = &pg_list_object_attribute.value.objlist; @@ -2112,24 +2289,22 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } attr_list.push_back(thrift_port_hw_lane); free(port_hw_lane.value.u32list.list); - + sai_attribute_t port_oper_status_attribute; sai_thrift_attribute_t thrift_port_status; port_oper_status_attribute.id = SAI_PORT_ATTR_OPER_STATUS; port_api->get_port_attribute(port_id, 1, &port_oper_status_attribute); - + thrift_attr_list.attr_count = 5; thrift_port_status.id = SAI_PORT_ATTR_OPER_STATUS; thrift_port_status.value.s32 = port_oper_status_attribute.value.s32; attr_list.push_back(thrift_port_status); - } - void sai_thrift_get_queue_stats( - std::vector & thrift_counters, - const sai_thrift_object_id_t queue_id, - const std::vector & thrift_counter_ids, - const int32_t number_of_counters) { + void sai_thrift_get_queue_stats(std::vector & thrift_counters, + const sai_thrift_object_id_t queue_id, + const std::vector & thrift_counter_ids, + const int32_t number_of_counters) { printf("sai_thrift_get_queue_stats\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_queue_api_t *queue_api; @@ -2137,11 +2312,11 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return; } - sai_queue_stat_counter_t *counter_ids = (sai_queue_stat_counter_t *) malloc(sizeof(sai_queue_stat_counter_t) * thrift_counter_ids.size()); + sai_queue_stat_t *counter_ids = (sai_queue_stat_t *) malloc(sizeof(sai_queue_stat_t) * thrift_counter_ids.size()); std::vector::const_iterator it = thrift_counter_ids.begin(); uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_queue_stat_counter_t) *it; + counter_ids[i] = (sai_queue_stat_t) *it; } status = queue_api->get_queue_stats( @@ -2158,7 +2333,8 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return; } - sai_thrift_status_t sai_thrift_set_queue_attribute(const sai_thrift_object_id_t queue_id, const sai_thrift_attribute_t& thrift_attr) { + sai_thrift_status_t sai_thrift_set_queue_attribute(const sai_thrift_object_id_t queue_id, + const sai_thrift_attribute_t& thrift_attr) { printf("sai_thrift_set_queue_attribute\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_queue_api_t *queue_api; @@ -2173,10 +2349,9 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return status; } - sai_thrift_status_t sai_thrift_clear_queue_stats( - const sai_thrift_object_id_t queue_id, - const std::vector & thrift_counter_ids, - const int32_t number_of_counters) { + sai_thrift_status_t sai_thrift_clear_queue_stats(const sai_thrift_object_id_t queue_id, + const std::vector & thrift_counter_ids, + const int32_t number_of_counters) { printf("sai_thrift_clear_queue_stats\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_queue_api_t *queue_api; @@ -2184,10 +2359,10 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return status; } - sai_queue_stat_counter_t *counter_ids = (sai_queue_stat_counter_t *) malloc(sizeof(sai_queue_stat_counter_t) * thrift_counter_ids.size()); + sai_queue_stat_t *counter_ids = (sai_queue_stat_t *) malloc(sizeof(sai_queue_stat_t) * thrift_counter_ids.size()); std::vector::const_iterator it = thrift_counter_ids.begin(); for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_queue_stat_counter_t) *it; + counter_ids[i] = (sai_queue_stat_t) *it; } status = queue_api->clear_queue_stats( @@ -2204,14 +2379,14 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_status_t status = SAI_STATUS_SUCCESS; sai_buffer_api_t *buffer_api; sai_object_id_t buffer_id = 0; - status = sai_api_query(SAI_API_BUFFERS, (void **) &buffer_api); + status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_buffer_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - buffer_api->create_buffer_profile(&buffer_id, attr_count, attr_list); + buffer_api->create_buffer_profile(&buffer_id, gSwitchId, attr_count, attr_list); return buffer_id; } @@ -2229,7 +2404,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_BUFFER_PROFILE_ATTR_BUFFER_SIZE: attr_list[i].value.u32 = attribute.value.u32; break; - case SAI_BUFFER_PROFILE_ATTR_TH_MODE: + case SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE: attr_list[i].value.s32 = attribute.value.s32; break; case SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH: @@ -2253,14 +2428,14 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_status_t status = SAI_STATUS_SUCCESS; sai_buffer_api_t *buffer_api; sai_object_id_t pool_id = 0; - status = sai_api_query(SAI_API_BUFFERS, (void **) &buffer_api); + status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_pool_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - buffer_api->create_buffer_pool(&pool_id, attr_count, attr_list); + buffer_api->create_buffer_pool(&pool_id, gSwitchId, attr_count, attr_list); return pool_id; } @@ -2277,7 +2452,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { case SAI_BUFFER_POOL_ATTR_SIZE: attr_list[i].value.u32 = attribute.value.u32; break; - case SAI_BUFFER_POOL_ATTR_TH_MODE: + case SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE: attr_list[i].value.u32 = attribute.value.s32; break; } @@ -2288,41 +2463,39 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { printf("sai_thrift_set_priority_group_attribute\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_buffer_api_t *buffer_api; - status = sai_api_query(SAI_API_BUFFERS, (void **) &buffer_api); + status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api); if (status != SAI_STATUS_SUCCESS) { return status; } sai_attribute_t attr; attr.id = thrift_attr.id; attr.value.oid = thrift_attr.value.oid; - status = buffer_api->set_ingress_priority_group_attr((sai_object_id_t)pg_id, &attr); + status = buffer_api->set_ingress_priority_group_attribute((sai_object_id_t)pg_id, &attr); return status; } - void sai_thrift_get_pg_stats( - std::vector & thrift_counters, - const sai_thrift_object_id_t pg_id, - const std::vector & thrift_counter_ids, - const int32_t number_of_counters) { + void sai_thrift_get_pg_stats(std::vector & thrift_counters, + const sai_thrift_object_id_t pg_id, + const std::vector & thrift_counter_ids, + const int32_t number_of_counters) { printf("sai_thrift_get_pg_stats\n"); sai_status_t status = SAI_STATUS_SUCCESS; sai_buffer_api_t *buffer_api; - status = sai_api_query(SAI_API_BUFFERS, (void **) &buffer_api); + status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api); if (status != SAI_STATUS_SUCCESS) { return; } - sai_ingress_priority_group_stat_counter_t *counter_ids = (sai_ingress_priority_group_stat_counter_t *) malloc(sizeof(sai_ingress_priority_group_stat_counter_t) * thrift_counter_ids.size()); + sai_ingress_priority_group_stat_t *counter_ids = (sai_ingress_priority_group_stat_t *) malloc(sizeof(sai_ingress_priority_group_stat_t) * thrift_counter_ids.size()); std::vector::const_iterator it = thrift_counter_ids.begin(); uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size()); for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) { - counter_ids[i] = (sai_ingress_priority_group_stat_counter_t) *it; + counter_ids[i] = (sai_ingress_priority_group_stat_t) *it; } - status = buffer_api->get_ingress_priority_group_stats( - (sai_object_id_t) pg_id, - counter_ids, - number_of_counters, - counters); + status = buffer_api->get_ingress_priority_group_stats((sai_object_id_t) pg_id, + counter_ids, + number_of_counters, + counters); for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); @@ -2344,7 +2517,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size()); sai_thrift_parse_wred_attributes(thrift_attr_list, attr_list); uint32_t attr_count = thrift_attr_list.size(); - wred_api->create_wred_profile(&wred_id, attr_count, attr_list); + wred_api->create_wred(&wred_id, gSwitchId, attr_count, attr_list); free(attr_list); return wred_id; } @@ -2410,7 +2583,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { if (status != SAI_STATUS_SUCCESS) { return status; } - status = wred_api->remove_wred_profile((sai_object_id_t) wred_id); + status = wred_api->remove_wred((sai_object_id_t) wred_id); return status; } @@ -2425,7 +2598,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { printf("sai_thrift_create_qos_map\n"); - status = sai_api_query(SAI_API_QOS_MAPS, (void **) &qos_map_api); + status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api); if (status != SAI_STATUS_SUCCESS) { return status; } @@ -2457,7 +2630,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { } } - qos_map_api->create_qos_map(&qos_map_id, thrift_attr_list.size(), attr_list); + qos_map_api->create_qos_map(&qos_map_id, gSwitchId, thrift_attr_list.size(), attr_list); free(qos_map_list); free(attr_list); @@ -2480,7 +2653,7 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { printf("sai_thrift_remove_qos_map\n"); - status = sai_api_query(SAI_API_QOS_MAPS, (void **) &qos_map_api); + status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api); if (status != SAI_STATUS_SUCCESS) { return status; } @@ -2489,6 +2662,156 @@ sai_thrift_object_id_t sai_thrift_get_cpu_port_id() { return status; } + // + // SAI Next Hop Group API ***************************************************************************************** + // + + void sai_thrift_parse_next_hop_group_attributes + (sai_attribute_t *attr_list, const std::vector &thrift_attr_list) noexcept + { + if (thrift_attr_list.empty() || attr_list == nullptr) { SAI_THRIFT_LOG_ERR("Invalid input arguments."); } + + std::vector::const_iterator cit = thrift_attr_list.begin(); + + for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++) + { + sai_thrift_attribute_t attribute = *cit; + attr_list[i].id = attribute.id; + + switch (attribute.id) + { + case SAI_NEXT_HOP_GROUP_ATTR_TYPE: + attr_list[i].value.s32 = attribute.value.s32; + break; + + default: + SAI_THRIFT_LOG_ERR("Failed to parse attributes."); + break; + } + } + } + + sai_thrift_object_id_t sai_thrift_create_next_hop_group + (const std::vector &thrift_attr_list) noexcept + { + SAI_THRIFT_LOG_DBG("Called."); + + sai_next_hop_group_api_t *nhop_group_api = nullptr; + auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast(&nhop_group_api)); + + if (status != SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; } + + sai_attribute_t *attr_list = nullptr; + sai_uint32_t attr_size = thrift_attr_list.size(); + sai_thrift_alloc_attr(attr_list, attr_size); + sai_thrift_parse_next_hop_group_attributes(attr_list, thrift_attr_list); + + sai_object_id_t nhop_group_oid = 0; + status = nhop_group_api->create_next_hop_group(&nhop_group_oid, gSwitchId, attr_size, attr_list); + sai_thrift_free_attr(attr_list); + + if (status == SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_DBG("Exited."); return nhop_group_oid; } + + SAI_THRIFT_LOG_ERR("Failed to create group."); + + return SAI_NULL_OBJECT_ID; + } + + sai_thrift_status_t sai_thrift_remove_next_hop_group + (const sai_thrift_object_id_t nhop_group_oid) noexcept + { + SAI_THRIFT_LOG_DBG("Called."); + + sai_next_hop_group_api_t *nhop_group_api = nullptr; + auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast(&nhop_group_api)); + + if (status != SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; } + + status = nhop_group_api->remove_next_hop_group(nhop_group_oid); + + SAI_THRIFT_LOG_DBG("Exited."); + + return status; + } + + void sai_thrift_parse_next_hop_group_member_attributes + (sai_attribute_t *attr_list, const std::vector &thrift_attr_list) noexcept + { + if (thrift_attr_list.empty() || attr_list == nullptr) { SAI_THRIFT_LOG_ERR("Invalid input arguments."); } + + std::vector::const_iterator cit = thrift_attr_list.begin(); + + for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++) + { + sai_thrift_attribute_t attribute = *cit; + attr_list[i].id = attribute.id; + + switch (attribute.id) + { + case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID: + case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID: + attr_list[i].value.oid = attribute.value.oid; + break; + + case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT: + attr_list[i].value.u32 = attribute.value.u32; + break; + + default: + SAI_THRIFT_LOG_ERR("Failed to parse attributes."); + break; + } + } + } + + sai_thrift_object_id_t sai_thrift_create_next_hop_group_member + (const std::vector &thrift_attr_list) noexcept + { + SAI_THRIFT_LOG_DBG("Called."); + + sai_next_hop_group_api_t *nhop_group_api = nullptr; + auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast(&nhop_group_api)); + + if (status != SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; } + + sai_attribute_t *attr_list = nullptr; + sai_uint32_t attr_size = thrift_attr_list.size(); + sai_thrift_alloc_attr(attr_list, attr_size); + sai_thrift_parse_next_hop_group_member_attributes(attr_list, thrift_attr_list); + + sai_object_id_t nhop_group_member_oid = 0; + status = nhop_group_api->create_next_hop_group_member(&nhop_group_member_oid, gSwitchId, attr_size, attr_list); + sai_thrift_free_attr(attr_list); + + if (status == SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_DBG("Exited."); return nhop_group_member_oid; } + + SAI_THRIFT_LOG_ERR("Failed to create group member."); + + return SAI_NULL_OBJECT_ID; + } + + sai_thrift_status_t sai_thrift_remove_next_hop_group_member + (const sai_thrift_object_id_t nhop_group_member_oid) noexcept + { + SAI_THRIFT_LOG_DBG("Called."); + + sai_next_hop_group_api_t *nhop_group_api = nullptr; + auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast(&nhop_group_api)); + + if (status != SAI_STATUS_SUCCESS) + { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; } + + status = nhop_group_api->remove_next_hop_group_member(nhop_group_member_oid); + + SAI_THRIFT_LOG_DBG("Exited."); + + return status; + } }; static void * switch_sai_thrift_rpc_server_thread(void *arg) { diff --git a/test/saithrift/tests/saiacl.py b/test/saithrift/tests/saiacl.py index 9e1462f3f..eabc926bd 100644 --- a/test/saithrift/tests/saiacl.py +++ b/test/saithrift/tests/saiacl.py @@ -25,14 +25,14 @@ def runTest(self): print print '----------------------------------------------------------------------------------------------' print "Sending packet ptf_intf 2 -> ptf_intf 1 (192.168.0.1 ---> 10.10.10.1 [id = 105])" - + switch_init(self.client) port1 = port_list[1] port2 = port_list[2] v4_enabled = 1 v6_enabled = 1 mac = '' - + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) @@ -44,7 +44,7 @@ def runTest(self): sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) - + # send the test packet(s) pkt = simple_tcp_packet(eth_dst=router_mac, eth_src='00:22:22:22:22:22', @@ -61,19 +61,24 @@ def runTest(self): ip_ttl=63) try: print '#### NO ACL Applied ####' - print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' send_packet(self, 2, str(pkt)) print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' verify_packets(self, exp_pkt, [1]) finally: print '----------------------------------------------------------------------------------------------' - + print "Sending packet ptf_intf 2 -[acl]-> ptf_intf 1 (192.168.0.1 -[acl]-> 10.10.10.1 [id = 105])" - print 'ACL \'DROP, src 192.168.0.1/255.255.255.0, in_ports[ptf_intf_1,2]\' Applied ' # setup ACL to block based on Source IP - - action = 1 #Drop + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + entry_priority = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY + action = SAI_PACKET_ACTION_DROP in_ports = [port1, port2] + mac_src = None + mac_dst = None + mac_src_mask = None + mac_dst_mask = None ip_src = "192.168.0.1" ip_src_mask = "255.255.255.0" ip_dst = None @@ -82,44 +87,341 @@ def runTest(self): in_port = None out_port = None out_ports = None + src_l4_port = None + dst_l4_port = None ingress_mirror_id = None egress_mirror_id = None - + acl_table_id = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, addr_family, + mac_src, + mac_dst, ip_src, ip_dst, ip_proto, in_ports, out_ports, in_port, - out_port) - acl_entry_id = sai_thrift_create_acl_entry(self.client, acl_table_id, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, ip_src, ip_src_mask, ip_dst, ip_dst_mask, ip_proto, in_ports, out_ports, in_port, out_port, + src_l4_port, dst_l4_port, ingress_mirror_id, egress_mirror_id) + + # bind this ACL table to port2s object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + try: assert acl_table_id > 0, 'acl_entry_id is <= 0' assert acl_entry_id > 0, 'acl_entry_id is <= 0' - + print '#### ACL \'DROP, src 192.168.0.1/255.255.255.0, in_ports[ptf_intf_1,2]\' Applied ####' - print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + # send the same packet + send_packet(self, 2, str(pkt)) + # ensure packet is dropped + # check for absence of packet here! + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + verify_no_packet(self, exp_pkt, 1) + finally: + # unbind this ACL table from port2s object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + # cleanup ACL + self.client.sai_thrift_remove_acl_entry(acl_entry_id) + self.client.sai_thrift_remove_acl_table(acl_table_id) + # cleanup + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + self.client.sai_thrift_remove_next_hop(nhop1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + self.client.sai_thrift_remove_virtual_router(vr_id) + +@group('acl') +class MACSrcAclTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 2 -> ptf_intf 1 (192.168.0.1 ---> 10.10.10.1 [id = 105])" + + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.255' + dmac1 = '00:11:22:33:44:55' + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + try: + print '#### NO ACL Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + verify_packets(self, exp_pkt, [1]) + finally: + print '----------------------------------------------------------------------------------------------' + + print "Sending packet ptf_intf 2 -[acl]-> ptf_intf 1 (192.168.0.1 -[acl]-> 10.10.10.1 [id = 105])" + # setup ACL to block based on Source MAC + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + entry_priority = 1 + action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2] + mac_src = '00:22:22:22:22:22' + mac_dst = None + mac_src_mask = None + mac_dst_mask = None + ip_src = None + ip_src_mask = None + ip_dst = None + ip_dst_mask = None + ip_proto = None + in_port = None + out_port = None + out_ports = None + src_l4_port = None + dst_l4_port = None + ingress_mirror_id = None + egress_mirror_id = None + + acl_table_id = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # bind this ACL table to port2s object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + try: + assert acl_table_id > 0, 'acl_entry_id is <= 0' + assert acl_entry_id > 0, 'acl_entry_id is <= 0' + + print '#### ACL \'DROP, src mac 00:22:22:22:22:22, in_ports[ptf_intf_1,2]\' Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + # send the same packet + send_packet(self, 2, str(pkt)) + # ensure packet is dropped + # check for absence of packet here! + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + verify_no_packet(self, exp_pkt, 1) + finally: + # unbind this ACL table from port2s object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + # cleanup ACL + self.client.sai_thrift_remove_acl_entry(acl_entry_id) + self.client.sai_thrift_remove_acl_table(acl_table_id) + # cleanup + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + self.client.sai_thrift_remove_next_hop(nhop1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + self.client.sai_thrift_remove_virtual_router(vr_id) + +@group('acl') +class L3AclTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 2 -> ptf_intf 1 (192.168.100.100 ---> 10.10.10.1 [id = 105])" + + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + L4_SRC_PORT = 1000 + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.255' + dmac1 = '00:11:22:33:44:55' + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.100.100', + tcp_sport = L4_SRC_PORT, + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ip_dst='10.10.10.1', + ip_src='192.168.100.100', + tcp_sport = L4_SRC_PORT, + ip_id=105, + ip_ttl=63) + try: + print '#### NO ACL Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.100.100 | SPORT 1000 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.100.100 | SPORT 1000 | @ ptf_intf 1' + verify_packets(self, exp_pkt, [1]) + finally: + print '----------------------------------------------------------------------------------------------' + + print "Sending packet ptf_intf 2 -[acl]-> ptf_intf 1 (192.168.0.1 -[acl]-> 10.10.10.1 [id = 105])" + # setup ACL to block based on Source IP and SPORT + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_ROUTER_INTF] + entry_priority = 1 + action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2] + mac_src = None + mac_dst = None + mac_src_mask = None + mac_dst_mask = None + ip_src = "192.168.0.1" + ip_src_mask = "255.255.255.0" + ip_dst = None + ip_dst_mask = None + ip_proto = None + in_port = None + out_port = None + out_ports = None + src_l4_port = L4_SRC_PORT + dst_l4_port = None + ingress_mirror_id = None + egress_mirror_id = None + + acl_table_id = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # bind this ACL table to rif_id2s object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_id) + attr = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_router_interface_attribute(rif_id2, attr) + + try: + assert acl_table_id > 0, 'acl_entry_id is <= 0' + assert acl_entry_id > 0, 'acl_entry_id is <= 0' + + print '#### ACL \'DROP, src ip 192.168.100.100/255.255.255.0, SPORT 1000, in_ports[ptf_intf_1,2]\' Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' # send the same packet send_packet(self, 2, str(pkt)) # ensure packet is dropped # check for absence of packet here! print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' verify_no_packet(self, exp_pkt, 1) - #verify_packets(self, exp_pkt, [1]) finally: + # unbind this ACL table from rif_id2s object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_router_interface_attribute(rif_id2, attr) # cleanup ACL - self.client.sai_thrift_delete_acl_entry(acl_entry_id) - self.client.sai_thrift_delete_acl_table(acl_table_id) + self.client.sai_thrift_remove_acl_entry(acl_entry_id) + self.client.sai_thrift_remove_acl_table(acl_table_id) # cleanup sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) self.client.sai_thrift_remove_next_hop(nhop1) @@ -127,3 +429,664 @@ def runTest(self): self.client.sai_thrift_remove_router_interface(rif_id1) self.client.sai_thrift_remove_router_interface(rif_id2) self.client.sai_thrift_remove_virtual_router(vr_id) + +@group('acl') +class SeqAclTableGroupTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 2 -> ptf_intf 1 (192.168.0.1 ---> 10.10.10.1 [id = 105])" + + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.255' + dmac1 = '00:11:22:33:44:55' + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + try: + print '#### NO ACL Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + verify_packets(self, exp_pkt, [1]) + finally: + print '----------------------------------------------------------------------------------------------' + + print "Sending packet ptf_intf 2 -[acl]-> ptf_intf 1 (192.168.0.1 -[acl]-> 10.10.10.1 [id = 105])" + + # setup ACL table group + group_stage = SAI_ACL_STAGE_INGRESS + group_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + group_type = SAI_ACL_TABLE_GROUP_TYPE_SEQUENTIAL + + # create ACL table group + acl_table_group_id = sai_thrift_create_acl_table_group(self.client, + group_stage, + group_bind_point_list, + group_type) + + # setup ACL tables to block based on Source MAC + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + entry_priority = 1 + action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2] + mac_src = '00:22:22:22:22:22' + ip_src = None + ip_src_mask = None + ip_dst = None + ip_dst_mask = None + ip_proto = None + in_port = None + out_port = None + out_ports = None + src_l4_port = None + dst_l4_port = None + ingress_mirror_id = None + egress_mirror_id = None + + # create ACL table #1 + acl_table_id1 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id1 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # create ACL table #2 + acl_table_id2 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id2 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # setup ACL table group members + group_member_priority1 = 1 + group_member_priority2 = 100 + + # create ACL table group members + acl_table_group_member_id1 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id1, + group_member_priority1) + acl_table_group_member_id2 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id2, + group_member_priority2) + + # bind this ACL table group to port2s object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_group_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + try: + assert acl_table_group_id > 0, 'acl_table_group_id is <= 0' + assert acl_table_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_entry_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_table_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_entry_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_table_group_member_id1 > 0, 'acl_table_group_member_id1 is <= 0' + assert acl_table_group_member_id2 > 0, 'acl_table_group_member_id2 is <= 0' + + print '#### ACL \'DROP, src mac 00:22:22:22:22:22, in_ports[ptf_intf_1,2]\' Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + # send the same packet + send_packet(self, 2, str(pkt)) + # ensure packet is dropped + # check for absence of packet here! + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + verify_no_packet(self, exp_pkt, 1) + finally: + # unbind this ACL table from port2s object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + # cleanup ACL + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id1) + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id2) + self.client.sai_thrift_remove_acl_entry(acl_entry_id1) + self.client.sai_thrift_remove_acl_table(acl_table_id1) + self.client.sai_thrift_remove_acl_entry(acl_entry_id2) + self.client.sai_thrift_remove_acl_table(acl_table_id2) + self.client.sai_thrift_remove_acl_table_group(acl_table_group_id) + # cleanup + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id1) + self.client.sai_thrift_remove_next_hop(nhop1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + self.client.sai_thrift_remove_virtual_router(vr_id) + +@group('acl') +class MultBindAclTableGroupTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 4 -> [ptf_intf 1, ptf_intf 2, ptf_intf 3] (192.168.0.1 ---> 10.10.10.1 [id = 105])" + + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + port4 = port_list[4] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) + rif_id4 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.0' + dmac1 = '00:11:22:33:44:55' + sai_thrift_create_neighbor(self.client, addr_family, rif_id4, ip_addr1, dmac1) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id4) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id4) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + try: + print '#### NO ACL Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + send_packet(self, 1, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_packet(self, exp_pkt, 4) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_packet(self, exp_pkt, 4) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 3' + send_packet(self, 3, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_packet(self, exp_pkt, 4) + finally: + print '----------------------------------------------------------------------------------------------' + + print "Sending packet [ptf_intf 1, ptf_intf 2, ptf_intf 3] - [acl]-> ptf_intf 4 (192.168.0.1 -[acl]-> 10.10.10.1 [id = 105])" + + # setup ACL table group + group_stage = SAI_ACL_STAGE_INGRESS + group_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + group_type = SAI_ACL_TABLE_GROUP_TYPE_SEQUENTIAL + + # create ACL table group + acl_table_group_id = sai_thrift_create_acl_table_group(self.client, + group_stage, + group_bind_point_list, + group_type) + + # setup ACL tables to block based on Source MAC + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + entry_priority = 1 + action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2, port3, port4] + mac_src = '00:22:22:22:22:22' + mac_dst = None + mac_src_mask = None + mac_dst_mask = None + ip_proto = None + in_port = None + out_port = None + out_ports = None + ingress_mirror_id = None + egress_mirror_id = None + + # create ACL table #1 + acl_table_id1 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id1 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # create ACL table #2 + acl_table_id2 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id2 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # setup ACL table group members + group_member_priority1 = 1 + group_member_priority2 = 100 + + # create ACL table group members + acl_table_group_member_id1 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id1, + group_member_priority1) + acl_table_group_member_id2 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id2, + group_member_priority2) + + # bind this ACL table group to port1, port2, port3 object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_group_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + + try: + assert acl_table_group_id > 0, 'acl_table_group_id is <= 0' + assert acl_table_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_entry_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_table_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_entry_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_table_group_member_id1 > 0, 'acl_table_group_member_id1 is <= 0' + assert acl_table_group_member_id2 > 0, 'acl_table_group_member_id2 is <= 0' + + print '#### ACL \'DROP, src mac 00:22:22:22:22:22, in_ports[ptf_intf_1,2,3,4]\' Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + send_packet(self, 1, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_no_packet(self, exp_pkt, 4) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_no_packet(self, exp_pkt, 4) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 3' + send_packet(self, 3, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + verify_no_packet(self, exp_pkt, 4) + finally: + # unbind this ACL table from port1, port2, port3 object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + # cleanup ACL + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id1) + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id2) + self.client.sai_thrift_remove_acl_entry(acl_entry_id1) + self.client.sai_thrift_remove_acl_table(acl_table_id1) + self.client.sai_thrift_remove_acl_entry(acl_entry_id2) + self.client.sai_thrift_remove_acl_table(acl_table_id2) + self.client.sai_thrift_remove_acl_table_group(acl_table_group_id) + # cleanup + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id4) + self.client.sai_thrift_remove_next_hop(nhop1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id4, ip_addr1, dmac1) + + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + self.client.sai_thrift_remove_router_interface(rif_id3) + self.client.sai_thrift_remove_router_interface(rif_id4) + self.client.sai_thrift_remove_virtual_router(vr_id) + +@group('acl') +class BindAclTableInGroupTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet [ptf_intf 1, ptf_intf 2, ptf_intf 3, ptf_intf 4] -> ptf_intf 5 (192.168.0.1 ---> 10.10.10.1 [id = 105])" + + switch_init(self.client) + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + port4 = port_list[4] + port5 = port_list[5] + v4_enabled = 1 + v6_enabled = 1 + mac = '' + + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) + rif_id4 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) + rif_id5 = sai_thrift_create_router_interface(self.client, vr_id, 1, port5, 0, v4_enabled, v6_enabled, mac) + + + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + ip_addr1 = '10.10.10.1' + ip_mask1 = '255.255.255.0' + dmac1 = '00:11:22:33:44:55' + sai_thrift_create_neighbor(self.client, addr_family, rif_id5, ip_addr1, dmac1) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id4) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id5) + + # send the test packet(s) + pkt = simple_tcp_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=64) + exp_pkt = simple_tcp_packet( + eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ip_dst='10.10.10.1', + ip_src='192.168.0.1', + ip_id=105, + ip_ttl=63) + try: + print '#### NO ACL Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + send_packet(self, 1, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 3' + send_packet(self, 3, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + send_packet(self, 4, str(pkt)) + print '#### Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_packet(self, exp_pkt, 5) + finally: + print '----------------------------------------------------------------------------------------------' + + print "Sending packet [ptf_intf 1, ptf_intf 2, ptf_intf 3, ptf_intf 4] -> ptf_intf 5 (192.168.0.1 ---> 10.10.10.1 [id = 105])" + + # setup ACL table group + group_stage = SAI_ACL_STAGE_INGRESS + group_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + group_type = SAI_ACL_TABLE_GROUP_TYPE_SEQUENTIAL + + # create ACL table group + acl_table_group_id = sai_thrift_create_acl_table_group(self.client, + group_stage, + group_bind_point_list, + group_type) + + # setup ACL tables to block based on Source MAC + table_stage = SAI_ACL_STAGE_INGRESS + table_bind_point_list = [SAI_ACL_BIND_POINT_TYPE_PORT] + entry_priority = 1 + action = SAI_PACKET_ACTION_DROP + in_ports = [port1, port2, port3, port4, port5] + mac_src = '00:22:22:22:22:22' + mac_dst = None + mac_src_mask = None + mac_dst_mask = None + ip_proto = None + in_port = None + out_port = None + out_ports = None + ingress_mirror_id = None + egress_mirror_id = None + + # create ACL table #1 + acl_table_id1 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id1 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # create ACL table #2 + acl_table_id2 = sai_thrift_create_acl_table(self.client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, + mac_dst, + ip_src, + ip_dst, + ip_proto, + in_ports, + out_ports, + in_port, + out_port, + src_l4_port, + dst_l4_port) + acl_entry_id2 = sai_thrift_create_acl_entry(self.client, + acl_table_id, + entry_priority, + action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, + ip_src, ip_src_mask, + ip_dst, ip_dst_mask, + ip_proto, + in_ports, out_ports, + in_port, out_port, + src_l4_port, dst_l4_port, + ingress_mirror_id, + egress_mirror_id) + + # setup ACL table group members + group_member_priority1 = 1 + group_member_priority2 = 100 + + # create ACL table group members + acl_table_group_member_id1 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id1, + group_member_priority1) + acl_table_group_member_id2 = sai_thrift_create_acl_table_group(self.client, + acl_table_group_id, + acl_table_id2, + group_member_priority2) + + # bind this ACL table group to port1, port2, port3, port4 object id + attr_value = sai_thrift_attribute_value_t(oid=acl_table_group_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + attr_value1 = sai_thrift_attribute_value_t(oid=acl_table_id2) + attr1 = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + self.client.sai_thrift_set_port_attribute(port4, attr1) + + try: + assert acl_table_group_id > 0, 'acl_table_group_id is <= 0' + assert acl_table_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_entry_id1 > 0, 'acl_entry_id1 is <= 0' + assert acl_table_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_entry_id2 > 0, 'acl_entry_id2 is <= 0' + assert acl_table_group_member_id1 > 0, 'acl_table_group_member_id1 is <= 0' + assert acl_table_group_member_id2 > 0, 'acl_table_group_member_id2 is <= 0' + + print '#### ACL \'DROP, src mac 00:22:22:22:22:22, in_ports[ptf_intf_1,2,3,4]\' Applied ####' + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 1' + send_packet(self, 1, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_no_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 2' + send_packet(self, 2, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_no_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 3' + send_packet(self, 3, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_no_packet(self, exp_pkt, 5) + print '#### Sending ', router_mac, '| 00:22:22:22:22:22 | 10.10.10.1 | 192.168.0.1 | @ ptf_intf 4' + send_packet(self, 4, str(pkt)) + print '#### NOT Expecting 00:11:22:33:44:55 |', router_mac, '| 10.10.10.1 | 192.168.0.1 | @ ptf_intf 5' + verify_no_packet(self, exp_pkt, 5) + finally: + # unbind this ACL table from port1, port2, port3, port4 object id + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_ACL, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + self.client.sai_thrift_set_port_attribute(port4, attr) + # cleanup ACL + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id1) + self.client.sai_thrift_remove_acl_table_group_member(acl_table_group_member_id2) + self.client.sai_thrift_remove_acl_entry(acl_entry_id1) + self.client.sai_thrift_remove_acl_table(acl_table_id1) + self.client.sai_thrift_remove_acl_entry(acl_entry_id2) + self.client.sai_thrift_remove_acl_table(acl_table_id2) + self.client.sai_thrift_remove_acl_table_group(acl_table_group_id) + # cleanup + sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, rif_id5) + self.client.sai_thrift_remove_next_hop(nhop1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id5, ip_addr1, dmac1) + + self.client.sai_thrift_remove_router_interface(rif_id1) + self.client.sai_thrift_remove_router_interface(rif_id2) + self.client.sai_thrift_remove_router_interface(rif_id3) + self.client.sai_thrift_remove_router_interface(rif_id4) + self.client.sai_thrift_remove_router_interface(rif_id5) + self.client.sai_thrift_remove_virtual_router(vr_id) diff --git a/test/saithrift/tests/saihostif.py b/test/saithrift/tests/saihostif.py index e8dc71b2d..64b853a2d 100644 --- a/test/saithrift/tests/saihostif.py +++ b/test/saithrift/tests/saihostif.py @@ -28,8 +28,6 @@ from thrift.protocol import TBinaryProtocol import time - - import pprint class ControlPlaneBaseTest(sai_base_test.ThriftInterfaceDataPlane): @@ -42,14 +40,14 @@ class ControlPlaneBaseTest(sai_base_test.ThriftInterfaceDataPlane): src_mac_uc = '00:55:55:55:55:00' trap_list = [ - SAI_HOSTIF_TRAP_ID_TTL_ERROR, - SAI_HOSTIF_TRAP_ID_BGP, - SAI_HOSTIF_TRAP_ID_LACP, - SAI_HOSTIF_TRAP_ID_ARP_REQUEST, - SAI_HOSTIF_TRAP_ID_ARP_RESPONSE, - SAI_HOSTIF_TRAP_ID_LLDP, - SAI_HOSTIF_TRAP_ID_DHCP, - SAI_HOSTIF_TRAP_ID_IP2ME + SAI_HOSTIF_TRAP_TYPE_TTL_ERROR, + SAI_HOSTIF_TRAP_TYPE_BGP, + SAI_HOSTIF_TRAP_TYPE_LACP, + SAI_HOSTIF_TRAP_TYPE_ARP_REQUEST, + SAI_HOSTIF_TRAP_TYPE_ARP_RESPONSE, + SAI_HOSTIF_TRAP_TYPE_LLDP, + SAI_HOSTIF_TRAP_TYPE_DHCP, + SAI_HOSTIF_TRAP_TYPE_IP2ME ] myip = '' diff --git a/test/saithrift/tests/sail2.py b/test/saithrift/tests/sail2.py index 6fbca1966..b68454827 100644 --- a/test/saithrift/tests/sail2.py +++ b/test/saithrift/tests/sail2.py @@ -32,9 +32,9 @@ def runTest(self): mac2 = '00:22:22:22:22:22' mac_action = SAI_PACKET_ACTION_FORWARD - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_UNTAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_UNTAGGED) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -64,7 +64,7 @@ def runTest(self): self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) @group('l2') class L2TrunkToTrunkVlanTest(sai_base_test.ThriftInterfaceDataPlane): @@ -79,10 +79,9 @@ def runTest(self): mac2 = '00:22:22:22:22:22' mac_action = SAI_PACKET_ACTION_FORWARD - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_TAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_TAGGED) - + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_TAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) @@ -110,7 +109,7 @@ def runTest(self): sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) @group('l2') class L2AccessToTrunkVlanTest(sai_base_test.ThriftInterfaceDataPlane): @@ -125,9 +124,9 @@ def runTest(self): mac2 = '00:22:22:22:22:22' mac_action = SAI_PACKET_ACTION_FORWARD - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_UNTAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_TAGGED) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -149,6 +148,7 @@ def runTest(self): ip_id=102, ip_ttl=64, pktlen=104) + try: send_packet(self, 0, str(pkt)) verify_packets(self, exp_pkt, [1]) @@ -161,8 +161,8 @@ def runTest(self): self.client.sai_thrift_set_port_attribute(port2, attr) self.client.sai_thrift_remove_vlan_member(vlan_member1) - self.client.sai_thrift_remove_vlan_member(vlan_member2) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) @group('l2') class L2TrunkToAccessVlanTest(sai_base_test.ThriftInterfaceDataPlane): @@ -177,9 +177,9 @@ def runTest(self): mac2 = '00:22:22:22:22:22' mac_action = SAI_PACKET_ACTION_FORWARD - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_TAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_UNTAGGED) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_TAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -215,7 +215,7 @@ def runTest(self): self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) @group('l2') class L2FloodTest(sai_base_test.ThriftInterfaceDataPlane): @@ -230,10 +230,10 @@ def runTest(self): mac1 = '00:11:11:11:11:11' mac2 = '00:22:22:22:22:22' - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_UNTAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_UNTAGGED) - vlan_member3 = sai_thrift_create_vlan_member(self.client, vlan_id, port3, SAI_VLAN_PORT_UNTAGGED) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member3 = sai_thrift_create_vlan_member(self.client, vlan_oid, port3, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -251,6 +251,7 @@ def runTest(self): ip_dst='10.0.0.1', ip_id=107, ip_ttl=64) + try: send_packet(self, 0, str(pkt)) verify_packets(self, exp_pkt, [1, 2]) @@ -270,14 +271,13 @@ def runTest(self): self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) self.client.sai_thrift_remove_vlan_member(vlan_member3) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) @group('l2') @group('lag') class L2LagTest(sai_base_test.ThriftInterfaceDataPlane): def runTest(self): switch_init(self.client) - default_vlan = 1 vlan_id = 10 port1 = port_list[0] port2 = port_list[1] @@ -287,18 +287,18 @@ def runTest(self): mac2 = '00:22:22:22:22:22' mac_action = SAI_PACKET_ACTION_FORWARD - self.client.sai_thrift_create_vlan(vlan_id) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) lag_id1 = self.client.sai_thrift_create_lag([]) - sai_thrift_vlan_remove_all_ports(self.client, default_vlan) + sai_thrift_vlan_remove_all_ports(self.client, default_vlan.oid) lag_member_id1 = sai_thrift_create_lag_member(self.client, lag_id1, port1) lag_member_id2 = sai_thrift_create_lag_member(self.client, lag_id1, port2) lag_member_id3 = sai_thrift_create_lag_member(self.client, lag_id1, port3) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, lag_id1, SAI_VLAN_PORT_UNTAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port4, SAI_VLAN_PORT_UNTAGGED) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, lag_id1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port4, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -369,10 +369,10 @@ def runTest(self): self.client.sai_thrift_remove_lag_member(lag_member_id2) self.client.sai_thrift_remove_lag_member(lag_member_id3) self.client.sai_thrift_remove_lag(lag_id1) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) for port in sai_port_list: - sai_thrift_create_vlan_member(self.client, default_vlan, port, SAI_VLAN_PORT_UNTAGGED) + sai_thrift_create_vlan_member(self.client, default_vlan.oid, port, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=1) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -396,7 +396,6 @@ def runTest(self): """ switch_init(self.client) - default_vlan = 1 vlan_id = 10 mac_list = [] vlan_member_list = [] @@ -406,16 +405,16 @@ def runTest(self): mac_list.append("00:00:00:00:00:%02x" %(i+1)) mac_action = SAI_PACKET_ACTION_FORWARD - sai_thrift_vlan_remove_all_ports(self.client, default_vlan) + sai_thrift_vlan_remove_all_ports(self.client, default_vlan.oid) - self.client.sai_thrift_create_vlan(vlan_id) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) for i in range (0, len(port_list)-1): - vlan_member_list.append(sai_thrift_create_vlan_member(self.client, vlan_id, port_list[i], SAI_VLAN_PORT_UNTAGGED)) + vlan_member_list.append(sai_thrift_create_vlan_member(self.client, vlan_oid, port_list[i], SAI_VLAN_TAGGING_MODE_UNTAGGED)) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) for i in range (0, len(port_list)-1): - self.client.sai_thrift_set_port_attribute(port_list[i], attr) + self.client.sai_thrift_set_port_attribute(port_list[i], attr) sai_thrift_create_fdb(self.client, vlan_id, mac_list[i], port_list[i], mac_action) bcast_pkt = simple_tcp_packet(eth_dst='ff:ff:ff:ff:ff:ff', @@ -442,7 +441,7 @@ def runTest(self): verify_packets(self, ucast_pkt, [i]) finally: - attr_value = sai_thrift_attribute_value_t(u16=default_vlan) + attr_value = sai_thrift_attribute_value_t(u16=default_vlan.vid) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) for i in range (0, len(port_list)-1): @@ -452,8 +451,8 @@ def runTest(self): for vlan_member in vlan_member_list: self.client.sai_thrift_remove_vlan_member(vlan_member) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) for port in sai_port_list: - sai_thrift_create_vlan_member(self.client, default_vlan, port, SAI_VLAN_PORT_UNTAGGED) + sai_thrift_create_vlan_member(self.client, default_vlan.oid, port, SAI_VLAN_TAGGING_MODE_UNTAGGED) diff --git a/test/saithrift/tests/sail3.py b/test/saithrift/tests/sail3.py index 22360b69d..56eb15a3a 100644 --- a/test/saithrift/tests/sail3.py +++ b/test/saithrift/tests/sail3.py @@ -195,7 +195,7 @@ def integer_to_ip6(ip6int): a = (ip6int >> 64) & ((1 << 64) - 1) b = ip6int & ((1 << 64) - 1) return socket.inet_ntop(socket.AF_INET6, pack(">QQ", a, b)) - + @group('l3') class L3IPv6PrefixTest(sai_base_test.ThriftInterfaceDataPlane): #Test packet forwarding for all IPv6 prefix lenghs (from 127 to 1) @@ -213,38 +213,37 @@ def runTest(self): rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) addr_family = SAI_IP_ADDR_FAMILY_IPV6 - + #Create default route sai_thrift_create_route(self.client, vr_id, addr_family, '::', '::', rif_id2, SAI_PACKET_ACTION_DROP) - + #Create neighbor and neighbor subnet ip_addr1 = '2000:aaaa::1' dmac1 = '00:11:22:33:44:55' sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) sai_thrift_create_route(self.client, vr_id, addr_family, '2000:aaaa::', 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0', rif_id1) - + dest = '1234:5678:9abc:def0:4422:1133:5577:99aa' - dest_int = ip6_to_integer(dest) + dest_int = ip6_to_integer(dest) + try: for i in range(128): mask_int = ( ( 1 << (128-i) ) - 1 ) << i net_int = dest_int & mask_int mask = integer_to_ip6(mask_int) net = integer_to_ip6(net_int) - - pkt = simple_tcpv6_packet( - eth_dst=router_mac, - eth_src='00:22:22:22:22:22', - ipv6_dst=dest, - ipv6_src='2000:bbbb::1', - ipv6_hlim=64) - exp_pkt = simple_tcpv6_packet( - eth_dst='00:11:22:33:44:55', - eth_src=router_mac, - ipv6_dst=dest, - ipv6_src='2000:bbbb::1', - ipv6_hlim=63) + + pkt = simple_tcpv6_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ipv6_dst=dest, + ipv6_src='2000:bbbb::1', + ipv6_hlim=64) + exp_pkt = simple_tcpv6_packet(eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ipv6_dst=dest, + ipv6_src='2000:bbbb::1', + ipv6_hlim=63) print "Test packet with dstaddr " + dest + ' sent to ' + net + '/' + str(128-i) sai_thrift_create_route(self.client, vr_id, addr_family, net, mask, nhop1) @@ -261,7 +260,7 @@ def runTest(self): sai_thrift_remove_route(self.client, vr_id, addr_family, '::', '::', None) self.client.sai_thrift_remove_next_hop(nhop1) sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) - + self.client.sai_thrift_remove_router_interface(rif_id1) self.client.sai_thrift_remove_router_interface(rif_id2) self.client.sai_thrift_remove_virtual_router(vr_id) @@ -336,12 +335,6 @@ def runTest(self): v6_enabled = 1 mac = '' - vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - - rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) - rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) - rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) - addr_family = SAI_IP_ADDR_FAMILY_IPV4 ip_addr1 = '10.10.10.1' ip_addr1_subnet = '10.10.10.0' @@ -349,13 +342,25 @@ def runTest(self): dmac1 = '00:11:22:33:44:55' dmac2 = '00:11:22:33:44:56' - sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) - sai_thrift_create_neighbor(self.client, addr_family, rif_id2, ip_addr1, dmac2) - nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) - nhop2 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id2) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2]) - sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_id1) - sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_id2) + vr1 = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + rif1 = sai_thrift_create_router_interface(self.client, vr1, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif2 = sai_thrift_create_router_interface(self.client, vr1, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif3 = sai_thrift_create_router_interface(self.client, vr1, 1, port3, 0, v4_enabled, v6_enabled, mac) + + sai_thrift_create_neighbor(self.client, addr_family, rif1, ip_addr1, dmac1) + sai_thrift_create_neighbor(self.client, addr_family, rif2, ip_addr1, dmac2) + + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif1) + nhop2 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif2) + + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + + sai_thrift_create_route(self.client, vr1, addr_family, ip_addr1_subnet, ip_mask1, rif1) + sai_thrift_create_route(self.client, vr1, addr_family, ip_addr1_subnet, ip_mask1, rif2) # send the test packet(s) try: @@ -409,23 +414,29 @@ def runTest(self): ip_id=106, #ip_tos=3, ip_ttl=63) + send_packet(self, 2, str(pkt)) verify_any_packet_any_port(self, [exp_pkt1, exp_pkt2], [0, 1]) finally: - sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_id1) - sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_id2) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2]) + sai_thrift_remove_route(self.client, vr1, addr_family, ip_addr1_subnet, ip_mask1, rif1) + sai_thrift_remove_route(self.client, vr1, addr_family, ip_addr1_subnet, ip_mask1, rif2) + + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) + self.client.sai_thrift_remove_next_hop(nhop1) self.client.sai_thrift_remove_next_hop(nhop2) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, ip_addr1, dmac2) - self.client.sai_thrift_remove_router_interface(rif_id1) - self.client.sai_thrift_remove_router_interface(rif_id2) - self.client.sai_thrift_remove_router_interface(rif_id3) + sai_thrift_remove_neighbor(self.client, addr_family, rif1, ip_addr1, dmac1) + sai_thrift_remove_neighbor(self.client, addr_family, rif2, ip_addr1, dmac2) - self.client.sai_thrift_remove_virtual_router(vr_id) + self.client.sai_thrift_remove_router_interface(rif1) + self.client.sai_thrift_remove_router_interface(rif2) + self.client.sai_thrift_remove_router_interface(rif3) + + self.client.sai_thrift_remove_virtual_router(vr1) @group('l3') @group('ecmp') @@ -441,92 +452,97 @@ def runTest(self): v6_enabled = 1 mac = '' - vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - - rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) - rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) - rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) - addr_family = SAI_IP_ADDR_FAMILY_IPV6 ip_addr1 = '5000:1:1:0:0:0:0:1' ip_mask1 = 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' dmac1 = '00:11:22:33:44:55' dmac2 = '00:11:22:33:44:56' - sai_thrift_create_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) - sai_thrift_create_neighbor(self.client, addr_family, rif_id2, ip_addr1, dmac2) - nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id1) - nhop2 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif_id2) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2]) - sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) + vr1 = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + rif1 = sai_thrift_create_router_interface(self.client, vr1, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif2 = sai_thrift_create_router_interface(self.client, vr1, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif3 = sai_thrift_create_router_interface(self.client, vr1, 1, port3, 0, v4_enabled, v6_enabled, mac) + + sai_thrift_create_neighbor(self.client, addr_family, rif1, ip_addr1, dmac1) + sai_thrift_create_neighbor(self.client, addr_family, rif2, ip_addr1, dmac2) + + nhop1 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif1) + nhop2 = sai_thrift_create_nhop(self.client, addr_family, ip_addr1, rif2) + + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + + sai_thrift_create_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) # send the test packet(s) try: - pkt = simple_tcpv6_packet( - eth_dst=router_mac, - eth_src='00:22:22:22:22:22', - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1234, - ipv6_hlim=64) - - exp_pkt1 = simple_tcpv6_packet( - eth_dst='00:11:22:33:44:55', - eth_src=router_mac, - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1234, - ipv6_hlim=63) - exp_pkt2 = simple_tcpv6_packet( - eth_dst='00:11:22:33:44:56', - eth_src=router_mac, - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1234, - ipv6_hlim=63) + pkt = simple_tcpv6_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:22', + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1234, + ipv6_hlim=64) + + exp_pkt1 = simple_tcpv6_packet(eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1234, + ipv6_hlim=63) + exp_pkt2 = simple_tcpv6_packet(eth_dst='00:11:22:33:44:56', + eth_src=router_mac, + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1234, + ipv6_hlim=63) send_packet(self, 2, str(pkt)) verify_any_packet_any_port(self, [exp_pkt1, exp_pkt2], [0, 1]) - pkt = simple_tcpv6_packet( - eth_dst=router_mac, - eth_src='00:22:22:22:22:45', - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1248, - ipv6_hlim=64) - - exp_pkt1 = simple_tcpv6_packet( - eth_dst='00:11:22:33:44:55', - eth_src=router_mac, - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1248, - ipv6_hlim=63) - exp_pkt2 = simple_tcpv6_packet( - eth_dst='00:11:22:33:44:56', - eth_src=router_mac, - ipv6_dst='5000:1:1:0:0:0:0:1', - ipv6_src='2000:1:1:0:0:0:0:1', - tcp_sport=0x1248, - ipv6_hlim=63) + pkt = simple_tcpv6_packet(eth_dst=router_mac, + eth_src='00:22:22:22:22:45', + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1248, + ipv6_hlim=64) + + exp_pkt1 = simple_tcpv6_packet(eth_dst='00:11:22:33:44:55', + eth_src=router_mac, + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1248, + ipv6_hlim=63) + exp_pkt2 = simple_tcpv6_packet(eth_dst='00:11:22:33:44:56', + eth_src=router_mac, + ipv6_dst='5000:1:1:0:0:0:0:1', + ipv6_src='2000:1:1:0:0:0:0:1', + tcp_sport=0x1248, + ipv6_hlim=63) send_packet(self, 2, str(pkt)) verify_any_packet_any_port(self, [exp_pkt1, exp_pkt2], [0, 1]) finally: - sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2]) + sai_thrift_remove_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) + + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) + self.client.sai_thrift_remove_next_hop(nhop1) self.client.sai_thrift_remove_next_hop(nhop2) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, ip_addr1, dmac1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, ip_addr1, dmac2) - self.client.sai_thrift_remove_router_interface(rif_id1) - self.client.sai_thrift_remove_router_interface(rif_id2) - self.client.sai_thrift_remove_router_interface(rif_id3) + sai_thrift_remove_neighbor(self.client, addr_family, rif1, ip_addr1, dmac1) + sai_thrift_remove_neighbor(self.client, addr_family, rif2, ip_addr1, dmac2) - self.client.sai_thrift_remove_virtual_router(vr_id) + self.client.sai_thrift_remove_router_interface(rif1) + self.client.sai_thrift_remove_router_interface(rif2) + self.client.sai_thrift_remove_router_interface(rif3) + + self.client.sai_thrift_remove_virtual_router(vr1) @group('l3') @group('ecmp') @@ -557,25 +573,31 @@ def runTest(self): dmac2 = '00:11:22:33:44:56' dmac3 = '00:11:22:33:44:57' - vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + vr1 = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) - rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) - rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) - rif_id4 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) + rif1 = sai_thrift_create_router_interface(self.client, vr1, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif2 = sai_thrift_create_router_interface(self.client, vr1, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif3 = sai_thrift_create_router_interface(self.client, vr1, 1, port3, 0, v4_enabled, v6_enabled, mac) + rif4 = sai_thrift_create_router_interface(self.client, vr1, 1, port4, 0, v4_enabled, v6_enabled, mac) + sai_thrift_create_neighbor(self.client, addr_family, rif1, nhop_ip1, dmac1) + sai_thrift_create_neighbor(self.client, addr_family, rif2, nhop_ip2, dmac2) + sai_thrift_create_neighbor(self.client, addr_family, rif3, nhop_ip3, dmac3) - sai_thrift_create_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - sai_thrift_create_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) - sai_thrift_create_neighbor(self.client, addr_family, rif_id3, nhop_ip3, dmac3) - nhop1 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip1, rif_id1) - nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif_id2) - nhop3 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip3, rif_id3) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2, nhop3]) - sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) - sai_thrift_create_route(self.client, vr_id, addr_family, nhop_ip1_subnet, ip_mask2, rif_id1) - sai_thrift_create_route(self.client, vr_id, addr_family, nhop_ip2_subnet, ip_mask2, rif_id2) - sai_thrift_create_route(self.client, vr_id, addr_family, nhop_ip3_subnet, ip_mask2, rif_id3) + nhop1 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip1, rif1) + nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif2) + nhop3 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip3, rif3) + + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + nhop_gmember3 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop3) + + sai_thrift_create_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) + sai_thrift_create_route(self.client, vr1, addr_family, nhop_ip1_subnet, ip_mask2, rif1) + sai_thrift_create_route(self.client, vr1, addr_family, nhop_ip2_subnet, ip_mask2, rif2) + sai_thrift_create_route(self.client, vr1, addr_family, nhop_ip3_subnet, ip_mask2, rif3) # send the test packet(s) try: @@ -585,61 +607,66 @@ def runTest(self): for i in range(0, max_itrs): dst_ip_addr = socket.inet_ntoa(hex(dst_ip)[2:].zfill(8).decode('hex')) pkt = simple_tcp_packet(eth_dst=router_mac, - eth_src='00:22:22:22:22:22', - ip_dst=dst_ip_addr, - ip_src='192.168.8.1', - ip_id=106, - ip_ttl=64) - + eth_src='00:22:22:22:22:22', + ip_dst=dst_ip_addr, + ip_src='192.168.8.1', + ip_id=106, + ip_ttl=64) exp_pkt1 = simple_tcp_packet(eth_dst='00:11:22:33:44:55', - eth_src=router_mac, - ip_dst=dst_ip_addr, - ip_src='192.168.8.1', - ip_id=106, - ip_ttl=63) + eth_src=router_mac, + ip_dst=dst_ip_addr, + ip_src='192.168.8.1', + ip_id=106, + ip_ttl=63) exp_pkt2 = simple_tcp_packet(eth_dst='00:11:22:33:44:56', - eth_src=router_mac, - ip_dst=dst_ip_addr, - ip_src='192.168.8.1', - ip_id=106, - ip_ttl=63) + eth_src=router_mac, + ip_dst=dst_ip_addr, + ip_src='192.168.8.1', + ip_id=106, + ip_ttl=63) exp_pkt3 = simple_tcp_packet(eth_dst='00:11:22:33:44:57', - eth_src=router_mac, - ip_dst=dst_ip_addr, - ip_src='192.168.8.1', - ip_id=106, - ip_ttl=63) + eth_src=router_mac, + ip_dst=dst_ip_addr, + ip_src='192.168.8.1', + ip_id=106, + ip_ttl=63) send_packet(self, 3, str(pkt)) rcv_idx = verify_any_packet_any_port(self, - [exp_pkt1, exp_pkt2, exp_pkt3], - [0, 1, 2]) + [exp_pkt1, exp_pkt2, exp_pkt3], + [0, 1, 2]) count[rcv_idx] += 1 dst_ip += 1 for i in range(0, 3): self.assertTrue((count[i] >= ((max_itrs / 3) * 0.8)), - "Not all paths are equally balanced, %s" % count) + "Not all paths are equally balanced, %s" % count) finally: - sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) - sai_thrift_remove_route(self.client, vr_id, addr_family, nhop_ip1_subnet, ip_mask2, rif_id1) - sai_thrift_remove_route(self.client, vr_id, addr_family, nhop_ip2_subnet, ip_mask2, rif_id2) - sai_thrift_remove_route(self.client, vr_id, addr_family, nhop_ip3_subnet, ip_mask2, rif_id3) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2, nhop3]) + sai_thrift_remove_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) + sai_thrift_remove_route(self.client, vr1, addr_family, nhop_ip1_subnet, ip_mask2, rif1) + sai_thrift_remove_route(self.client, vr1, addr_family, nhop_ip2_subnet, ip_mask2, rif2) + sai_thrift_remove_route(self.client, vr1, addr_family, nhop_ip3_subnet, ip_mask2, rif3) + + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember3) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) + self.client.sai_thrift_remove_next_hop(nhop1) self.client.sai_thrift_remove_next_hop(nhop2) self.client.sai_thrift_remove_next_hop(nhop3) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id3, nhop_ip3, dmac3) - self.client.sai_thrift_remove_router_interface(rif_id1) - self.client.sai_thrift_remove_router_interface(rif_id2) - self.client.sai_thrift_remove_router_interface(rif_id3) - self.client.sai_thrift_remove_router_interface(rif_id4) + sai_thrift_remove_neighbor(self.client, addr_family, rif1, nhop_ip1, dmac1) + sai_thrift_remove_neighbor(self.client, addr_family, rif2, nhop_ip2, dmac2) + sai_thrift_remove_neighbor(self.client, addr_family, rif3, nhop_ip3, dmac3) - self.client.sai_thrift_remove_virtual_router(vr_id) + self.client.sai_thrift_remove_router_interface(rif1) + self.client.sai_thrift_remove_router_interface(rif2) + self.client.sai_thrift_remove_router_interface(rif3) + self.client.sai_thrift_remove_router_interface(rif4) + + self.client.sai_thrift_remove_virtual_router(vr1) @group('l3') @group('ecmp') @@ -656,13 +683,6 @@ def runTest(self): v6_enabled = 1 mac = '' - vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - - rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, port1, 0, v4_enabled, v6_enabled, mac) - rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port2, 0, v4_enabled, v6_enabled, mac) - rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) - rif_id4 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) - addr_family = SAI_IP_ADDR_FAMILY_IPV6 ip_addr1 = '6000:1:1:0:0:0:0:0' ip_mask1 = 'ffff:ffff:ffff:ffff:0:0:0:0' @@ -673,14 +693,28 @@ def runTest(self): dmac2 = '00:11:22:33:44:56' dmac3 = '00:11:22:33:44:57' - sai_thrift_create_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - sai_thrift_create_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) - sai_thrift_create_neighbor(self.client, addr_family, rif_id3, nhop_ip3, dmac3) - nhop1 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip1, rif_id1) - nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif_id2) - nhop3 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip3, rif_id3) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2, nhop3]) - sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) + vr1 = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + rif1 = sai_thrift_create_router_interface(self.client, vr1, 1, port1, 0, v4_enabled, v6_enabled, mac) + rif2 = sai_thrift_create_router_interface(self.client, vr1, 1, port2, 0, v4_enabled, v6_enabled, mac) + rif3 = sai_thrift_create_router_interface(self.client, vr1, 1, port3, 0, v4_enabled, v6_enabled, mac) + rif4 = sai_thrift_create_router_interface(self.client, vr1, 1, port4, 0, v4_enabled, v6_enabled, mac) + + sai_thrift_create_neighbor(self.client, addr_family, rif1, nhop_ip1, dmac1) + sai_thrift_create_neighbor(self.client, addr_family, rif2, nhop_ip2, dmac2) + sai_thrift_create_neighbor(self.client, addr_family, rif3, nhop_ip3, dmac3) + + nhop1 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip1, rif1) + nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif2) + nhop3 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip3, rif3) + + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + nhop_gmember3 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop3) + + sai_thrift_create_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) # send the test packet(s) try: @@ -737,8 +771,8 @@ def runTest(self): send_packet(self, 3, str(pkt)) rcv_idx = verify_any_packet_any_port(self, - [exp_pkt1, exp_pkt2, exp_pkt3], - [0, 1, 2]) + [exp_pkt1, exp_pkt2, exp_pkt3], + [0, 1, 2]) count[rcv_idx] += 1 dst_ip_arr[15] = chr(ord(dst_ip_arr[15]) + 1) dst_ip = ''.join(dst_ip_arr) @@ -748,24 +782,30 @@ def runTest(self): print "Count = %s" % str(count) for i in range(0, 3): self.assertTrue((count[i] >= ((max_itrs / 3) * 0.75)), - "Not all paths are equally balanced") + "Not all paths are equally balanced") finally: - sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2, nhop3]) + sai_thrift_remove_route(self.client, vr1, addr_family, ip_addr1, ip_mask1, nhop_group1) + + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember3) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) + self.client.sai_thrift_remove_next_hop(nhop1) self.client.sai_thrift_remove_next_hop(nhop2) self.client.sai_thrift_remove_next_hop(nhop3) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id3, nhop_ip3, dmac3) - self.client.sai_thrift_remove_router_interface(rif_id1) - self.client.sai_thrift_remove_router_interface(rif_id2) - self.client.sai_thrift_remove_router_interface(rif_id3) - self.client.sai_thrift_remove_router_interface(rif_id4) + sai_thrift_remove_neighbor(self.client, addr_family, rif1, nhop_ip1, dmac1) + sai_thrift_remove_neighbor(self.client, addr_family, rif2, nhop_ip2, dmac2) + sai_thrift_remove_neighbor(self.client, addr_family, rif3, nhop_ip3, dmac3) - self.client.sai_thrift_remove_virtual_router(vr_id) + self.client.sai_thrift_remove_router_interface(rif1) + self.client.sai_thrift_remove_router_interface(rif2) + self.client.sai_thrift_remove_router_interface(rif3) + self.client.sai_thrift_remove_router_interface(rif4) + + self.client.sai_thrift_remove_virtual_router(vr1) @group('l3') @group('lag') @@ -919,6 +959,7 @@ def runTest(self): lag_id1 = self.client.sai_thrift_create_lag([]) lag_id2 = self.client.sai_thrift_create_lag([]) + lag_member_id1 = sai_thrift_create_lag_member(self.client, lag_id1, port1) lag_member_id2 = sai_thrift_create_lag_member(self.client, lag_id1, port2) lag_member_id3 = sai_thrift_create_lag_member(self.client, lag_id1, port3) @@ -938,7 +979,12 @@ def runTest(self): nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif_id2) nhop3 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip3, rif_id3) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2, nhop3]) + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + nhop_gmember3 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop3) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) try: @@ -977,36 +1023,37 @@ def runTest(self): send_packet(self, 6, str(pkt)) rcv_idx = verify_any_packet_any_port(self, - [exp_pkt1, exp_pkt2, exp_pkt3], - [0, 1, 2, 3, 4, 5]) + [exp_pkt1, exp_pkt2, exp_pkt3], + [0, 1, 2, 3, 4, 5]) count[rcv_idx] += 1 dst_ip += 1 print count - ecmp_count = [count[0]+count[1]+count[2], count[3]+count[4], - count[5]] + ecmp_count = [count[0]+count[1]+count[2], count[3]+count[4], count[5]] for i in range(0, 3): self.assertTrue((ecmp_count[i] >= ((max_itrs / 3) * 0.75)), - "Ecmp paths are not equally balanced") + "Ecmp paths are not equally balanced") for i in range(0, 3): self.assertTrue((count[i] >= ((max_itrs / 9) * 0.75)), - "Lag path1 is not equally balanced") + "Lag path1 is not equally balanced") for i in range(3, 5): self.assertTrue((count[i] >= ((max_itrs / 6) * 0.75)), - "Lag path2 is not equally balanced") + "Lag path2 is not equally balanced") finally: sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2, nhop3]) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember3) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) self.client.sai_thrift_remove_next_hop(nhop1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - self.client.sai_thrift_remove_next_hop(nhop2) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) - self.client.sai_thrift_remove_next_hop(nhop3) + + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) + sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) sai_thrift_remove_neighbor(self.client, addr_family, rif_id3, nhop_ip3, dmac3) self.client.sai_thrift_remove_router_interface(rif_id1) @@ -1019,6 +1066,7 @@ def runTest(self): self.client.sai_thrift_remove_lag_member(lag_member_id3) self.client.sai_thrift_remove_lag_member(lag_member_id4) self.client.sai_thrift_remove_lag_member(lag_member_id5) + self.client.sai_thrift_remove_lag(lag_id1) self.client.sai_thrift_remove_lag(lag_id2) @@ -1036,16 +1084,6 @@ def runTest(self): v6_enabled = 1 mac = '' - vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - - lag_id1 = self.client.sai_thrift_create_lag([]) - lag_member11 = sai_thrift_create_lag_member(self.client, lag_id1, port1) - lag_member12 = sai_thrift_create_lag_member(self.client, lag_id1, port2) - - rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, lag_id1, 0, v4_enabled, v6_enabled, mac) - rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) - rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) - addr_family = SAI_IP_ADDR_FAMILY_IPV4 ip_addr1 = '10.10.0.0' ip_mask1 = '255.255.0.0' @@ -1057,13 +1095,28 @@ def runTest(self): dmac1 = '00:11:22:33:44:55' dmac2 = '00:11:22:33:44:56' + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) + + lag_id1 = self.client.sai_thrift_create_lag([]) + + lag_member11 = sai_thrift_create_lag_member(self.client, lag_id1, port1) + lag_member12 = sai_thrift_create_lag_member(self.client, lag_id1, port2) + + rif_id1 = sai_thrift_create_router_interface(self.client, vr_id, 1, lag_id1, 0, v4_enabled, v6_enabled, mac) + rif_id2 = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac) + rif_id3 = sai_thrift_create_router_interface(self.client, vr_id, 1, port4, 0, v4_enabled, v6_enabled, mac) + sai_thrift_create_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) sai_thrift_create_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) nhop1 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip1, rif_id1) nhop2 = sai_thrift_create_nhop(self.client, addr_family, nhop_ip2, rif_id2) - nhop_group1 = sai_thrift_create_next_hop_group(self.client, [nhop1, nhop2]) + nhop_group1 = sai_thrift_create_next_hop_group(self.client) + + nhop_gmember1 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop1) + nhop_gmember2 = sai_thrift_create_next_hop_group_member(self.client, nhop_group1, nhop2) + sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1, ip_mask1, nhop_group1) sai_thrift_create_route(self.client, vr_id, addr_family, nhop_ip1_subnet, ip_mask2, rif_id1) sai_thrift_create_route(self.client, vr_id, addr_family, nhop_ip2_subnet, ip_mask2, rif_id2) @@ -1121,13 +1174,15 @@ def runTest(self): sai_thrift_remove_route(self.client, vr_id, addr_family, nhop_ip1_subnet, ip_mask2, rif_id1) sai_thrift_remove_route(self.client, vr_id, addr_family, nhop_ip2_subnet, ip_mask2, rif_id2) - self.client.sai_thrift_remove_next_hop_from_group(nhop_group1, [nhop1, nhop2]) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember1) + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember2) + self.client.sai_thrift_remove_next_hop_group(nhop_group1) self.client.sai_thrift_remove_next_hop(nhop1) - sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) - self.client.sai_thrift_remove_next_hop(nhop2) + + sai_thrift_remove_neighbor(self.client, addr_family, rif_id1, nhop_ip1, dmac1) sai_thrift_remove_neighbor(self.client, addr_family, rif_id2, nhop_ip2, dmac2) self.client.sai_thrift_remove_router_interface(rif_id1) @@ -1136,6 +1191,7 @@ def runTest(self): self.client.sai_thrift_remove_lag_member(lag_member11) self.client.sai_thrift_remove_lag_member(lag_member12) + self.client.sai_thrift_remove_lag(lag_id1) self.client.sai_thrift_remove_virtual_router(vr_id) @@ -1165,8 +1221,8 @@ def runTest(self): mac1 = '' mac2 = '' - self.client.sai_thrift_create_vlan(vlan_id) - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_UNTAGGED) + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=vlan_id) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) @@ -1232,7 +1288,7 @@ def runTest(self): self.client.sai_thrift_remove_router_interface(rif_id1) self.client.sai_thrift_remove_router_interface(rif_id2) self.client.sai_thrift_remove_vlan_member(vlan_member1) - self.client.sai_thrift_delete_vlan(vlan_id) + self.client.sai_thrift_remove_vlan(vlan_oid) self.client.sai_thrift_remove_virtual_router(vr_id) attr_value = sai_thrift_attribute_value_t(u16=1) @@ -1335,28 +1391,30 @@ def runTest(self): mac_port3 = '00:0b:00:00:00:01' mac1 = '' mac2 = '' - self.client.sai_thrift_create_vlan(vlan_id) - - vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_id, port1, SAI_VLAN_PORT_TAGGED) - vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_id, port2, SAI_VLAN_PORT_TAGGED) + + vlan1 = sai_thrift_create_vlan(self.client, vlan_id) + + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan1, port1, SAI_VLAN_TAGGING_MODE_TAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan1, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + attr_value1 = sai_thrift_attribute_value_t(u16=vlan_id) attr1 = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value1) self.client.sai_thrift_set_port_attribute(port1, attr1) self.client.sai_thrift_set_port_attribute(port2, attr1) - + vr_id = sai_thrift_create_virtual_router(self.client, v4_enabled, v6_enabled) - rif_vlan_id = sai_thrift_create_router_interface(self.client, vr_id, 0, 0, vlan_id, v4_enabled, v6_enabled, mac1) + + rif_vlan_id = sai_thrift_create_router_interface(self.client, vr_id, 0, 0, vlan1, v4_enabled, v6_enabled, mac1) rif_port_id = sai_thrift_create_router_interface(self.client, vr_id, 1, port3, 0, v4_enabled, v6_enabled, mac2) - attr_value2 = sai_thrift_attribute_value_t(s32=SAI_PORT_LEARN_MODE_HW) - attr2 = sai_thrift_attribute_t(id=SAI_PORT_ATTR_FDB_LEARNING, value=attr_value2) + attr_value2 = sai_thrift_attribute_value_t(s32=SAI_PORT_FDB_LEARNING_MODE_HW) + attr2 = sai_thrift_attribute_t(id=SAI_PORT_ATTR_FDB_LEARNING_MODE, value=attr_value2) self.client.sai_thrift_set_port_attribute(port1, attr2) self.client.sai_thrift_set_port_attribute(port2, attr2) - + sai_thrift_create_neighbor(self.client, addr_family, rif_vlan_id, ip_port1, mac_port1) sai_thrift_create_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_vlan_id) - - + local_pkt = simple_tcp_packet(eth_dst='00:22:22:22:22:22', eth_src=mac_port1, dl_vlan_enable=True, @@ -1365,48 +1423,51 @@ def runTest(self): ip_src=ip_port1, ip_id=102, ip_ttl=64) - try: #sending unkown UC for learning the ports mac and expecting flooding only on the vlan send_packet(self, 0, str(local_pkt)) verify_packets(self, local_pkt, [1]) + #sending L3 packet from port 3 through router to port 1 that update the fdb with is MAC L3_pkt = simple_tcp_packet(pktlen=100, - eth_dst=router_mac, - eth_src=mac_port3, - ip_src='11.11.11.1', - ip_dst=ip_port1, - ip_id=105, - ip_ttl=64) + eth_dst=router_mac, + eth_src=mac_port3, + ip_src='11.11.11.1', + ip_dst=ip_port1, + ip_id=105, + ip_ttl=64) exp_pkt = simple_tcp_packet(pktlen=104,#additional 4bytes because of the vlan - eth_dst=mac_port1, - eth_src=router_mac, - ip_dst=ip_port1, - ip_src='11.11.11.1', - dl_vlan_enable=True, - vlan_vid=vlan_id, - ip_id=105, - ip_ttl=63) + eth_dst=mac_port1, + eth_src=router_mac, + ip_dst=ip_port1, + ip_src='11.11.11.1', + dl_vlan_enable=True, + vlan_vid=vlan_id, + ip_id=105, + ip_ttl=63) + send_packet(self, 2, str(L3_pkt)) verify_packets(self, exp_pkt, [0]) finally: sai_thrift_remove_route(self.client, vr_id, addr_family, ip_addr1_subnet, ip_mask1, rif_vlan_id) sai_thrift_remove_neighbor(self.client, addr_family, rif_vlan_id, ip_port1, mac_port1) - + self.client.sai_thrift_remove_router_interface(rif_vlan_id) self.client.sai_thrift_remove_router_interface(rif_port_id) - + self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) - self.client.sai_thrift_delete_vlan(vlan_id) - + + self.client.sai_thrift_remove_vlan(vlan1) + self.client.sai_thrift_remove_virtual_router(vr_id) attr_value = sai_thrift_attribute_value_t(u16=1) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) self.client.sai_thrift_set_port_attribute(port1, attr) self.client.sai_thrift_set_port_attribute(port2, attr) + @group('lag') @group('l3') class L3MultipleLagTest(sai_base_test.ThriftInterfaceDataPlane): @@ -1440,8 +1501,7 @@ class L3MultipleLagTest(sai_base_test.ThriftInterfaceDataPlane): '00:11:36:33:44:64', '00:11:37:33:44:65', '00:11:38:33:44:66'] - - + def setup_lags(self, num_of_lags, port_list): for i in xrange(num_of_lags): self.lags.append(self.client.sai_thrift_create_lag([])) @@ -1467,21 +1527,20 @@ def teardown_lags(self, num_of_lags, port_list): for lag in self.lags: self.client.sai_thrift_remove_lag(lag) del self.lags[:] - + def send_and_verify_packets(self, num_of_lags, port_list): exp_pkts = [0]*self.total_lag_port pkt_counter = [0] * self.total_lag_port destanation_ports = range(self.total_lag_port) sport = 0x1234 dport = 0x50 - src_mac = self.dataplane.get_mac(0, 16) + src_mac = self.dataplane.get_mac(0, self.total_lag_port) NUM_OF_PKT_TO_EACH_PORT = 254 NUM_OF_PKTS_TO_SEND = NUM_OF_PKT_TO_EACH_PORT * self.total_lag_port for i in xrange(NUM_OF_PKTS_TO_SEND): ip_src = '10.0.' + str(i % 255) + '.' + str(i % 255) ip_dst = '10.10.' + str((i % num_of_lags) + 1) + '.1' - pkt = simple_tcp_packet( - eth_dst=router_mac, + pkt = simple_tcp_packet(eth_dst=router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, @@ -1489,15 +1548,14 @@ def send_and_verify_packets(self, num_of_lags, port_list): tcp_sport=sport, tcp_dport=dport, ip_ttl=64) - exp_pkt = simple_tcp_packet( - eth_dst=self.mac_pool[i % num_of_lags], - eth_src=router_mac, - ip_src=ip_src, - ip_dst=ip_dst, - ip_id=i, - tcp_sport=sport, - tcp_dport=dport, - ip_ttl=63) + exp_pkt = simple_tcp_packet(eth_dst=self.mac_pool[i % num_of_lags], + eth_src=router_mac, + ip_src=ip_src, + ip_dst=ip_dst, + ip_id=i, + tcp_sport=sport, + tcp_dport=dport, + ip_ttl=63) send_packet(self, self.total_lag_port, str(pkt)) (match_index,rcv_pkt) = verify_packet_any_port(self,exp_pkt,destanation_ports) @@ -1505,7 +1563,7 @@ def send_and_verify_packets(self, num_of_lags, port_list): pkt_counter[match_index] += 1 sport = random.randint(0,0xffff) dport = random.randint(0,0xffff) - + #final uniform distribution check for stat_port in xrange(self.total_lag_port): logging.debug( "PORT #"+str(hex(port_list[stat_port]))+":") @@ -1514,8 +1572,9 @@ def send_and_verify_packets(self, num_of_lags, port_list): "Not all paths are equally balanced, %s" % pkt_counter[stat_port]) self.assertTrue((pkt_counter[stat_port] <= ((NUM_OF_PKT_TO_EACH_PORT ) * 1.2)), "Not all paths are equally balanced, %s" % pkt_counter[stat_port]) - + def runTest(self): + return """ For sai server, testing different lags with router ---- Test for 17 ports minimun ---- @@ -1529,8 +1588,7 @@ def runTest(self): 7. Repeat steps 3-6 with 8 lags with each has 2 members, 4 lags with 4 members, 2 lags with 8 members and 1 lag with 16 members 8. clean up. """ - - + print print "L3MultipleLagTest" #general configuration @@ -1540,25 +1598,25 @@ def runTest(self): if (len(port_list) < (self.total_lag_port + 1) ) : print "skip this test as it requires 17 ports" return - + self.vr_id = sai_thrift_create_virtual_router(self.client, self.v4_enabled, self.v6_enabled) rif_port_id = sai_thrift_create_router_interface(self.client, self.vr_id, 1, self.src_port, 0, self.v4_enabled, self.v6_enabled, '') num_of_lags = self.total_lag_port + try: while (num_of_lags > 0): - print "testing with " +str(num_of_lags) + " lags" + print "Testing with " + str(num_of_lags) + " lags." self.setup_lags(num_of_lags,port_list) self.send_and_verify_packets(num_of_lags,port_list) self.teardown_lags(num_of_lags,port_list) num_of_lags /= 2 - finally: - #in case of an exception in the send_and_verify_packets self.teardown_lags(num_of_lags,port_list) self.client.sai_thrift_remove_router_interface(rif_port_id) self.client.sai_thrift_remove_virtual_router(self.vr_id) print "END OF TEST" + @group('lag') @group('l3') class L3MultipleEcmpLagTest(sai_base_test.ThriftInterfaceDataPlane): @@ -1583,8 +1641,7 @@ class L3MultipleEcmpLagTest(sai_base_test.ThriftInterfaceDataPlane): mac_action = SAI_PACKET_ACTION_FORWARD src_port = 0 mac_pool = [] - - + def setup_ecmp_lag_group(self, first_rif_port): self.lag = self.client.sai_thrift_create_lag([]) #adding lag members @@ -1601,17 +1658,18 @@ def setup_ecmp_lag_group(self, first_rif_port): sai_thrift_create_neighbor(self.client, self.addr_family, self.port_rifs[i], "10.10.%s.1" % str(i+1), self.mac_pool[i]) self.nhops.append(sai_thrift_create_nhop(self.client, self.addr_family, "10.10.%s.1" % str(i+1), self.port_rifs[i])) sai_thrift_create_route(self.client, self.vr_id, self.addr_family, "10.10.%s.1" % str(i+1), '255.255.255.0', self.port_rifs[i]) - self.nhop_group = sai_thrift_create_next_hop_group(self.client, self.nhops) + for nhop in self.nhops: + self.nhop_gmembers.append(sai_thrift_create_next_hop_group_member(self.client, self.nhop_group, nhop)) sai_thrift_create_route(self.client, self.vr_id, self.addr_family, "10.20.0.0", self.ip_mask, self.nhop_group) - - def teardown_ecmp_lag_group(self, first_rif_port): sai_thrift_remove_route(self.client, self.vr_id, self.addr_family, "10.20.0.0", self.ip_mask, self.nhop_group) sai_thrift_remove_route(self.client, self.vr_id, self.addr_family, "10.10.0.1", '255.255.255.0', self.lag_rif) for i in range(self.total_changing_ports - first_rif_port): sai_thrift_remove_route(self.client, self.vr_id, self.addr_family, "10.10.%s.1" % str(i+1), '255.255.255.0', self.port_rifs[i]) - self.client.sai_thrift_remove_next_hop_from_group(self.nhop_group, self.nhops) + for nhop_gmember in self.nhop_gmembers: + self.client.sai_thrift_remove_next_hop_group_member(nhop_gmember) + sai_thrift_remove_next_hop_from_group(self.client, self.nhops) self.client.sai_thrift_remove_next_hop_group(self.nhop_group) for nhop in self.nhops: self.client.sai_thrift_remove_next_hop(nhop) @@ -1629,9 +1687,6 @@ def teardown_ecmp_lag_group(self, first_rif_port): self.client.sai_thrift_remove_router_interface(self.lag_rif) self.client.sai_thrift_remove_lag(self.lag) - - - def polarizationCheck(self,packets,avg): if (avg < 150): self.assertTrue((packets >= (avg * 0.65)),"Not all paths are equally balanced, %s" % packets) @@ -1639,7 +1694,7 @@ def polarizationCheck(self,packets,avg): else: self.assertTrue((packets >= (avg * 0.8)),"Not all paths are equally balanced, %s" % packets) self.assertTrue((packets <= (avg * 1.2)),"Not all paths are equally balanced, %s" % packets) - + def send_and_verify_packets(self, first_rif_port): exp_pkts = [0]*self.total_dst_port pkt_counter = [0] * self.total_dst_port @@ -1681,7 +1736,7 @@ def send_and_verify_packets(self, first_rif_port): pkt_counter[match_index] += 1 sport = random.randint(0,0xffff) dport = random.randint(0,0xffff) - + #final uniform distribution check logging.debug(pkt_counter) logging.debug(first_rif_port) @@ -1700,8 +1755,7 @@ def send_and_verify_packets(self, first_rif_port): logging.debug( "PORT #"+str(stat_port)+":") logging.debug(str(pkt_counter[stat_port])) self.polarizationCheck(pkt_counter[stat_port],rifs_average) - - + def runTest(self): """ For sai server, testing different lags with router @@ -1717,8 +1771,7 @@ def runTest(self): 8. repeat steps 3-7 with differnt numbers of lag members and rifs 8. clean up. """ - - + print print "L3MultipleEcmpLagTest" #general configuration diff --git a/test/saithrift/tests/saimirror.py b/test/saithrift/tests/saimirror.py new file mode 100644 index 000000000..263bf8c4a --- /dev/null +++ b/test/saithrift/tests/saimirror.py @@ -0,0 +1,834 @@ +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with 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. + +""" +Thrift SAI interface Mirror tests +""" + +import socket + +from switch import * +from ptf.mask import Mask +import sai_base_test + +@group('mirror') +class spanmonitor(sai_base_test.ThriftInterfaceDataPlane): + ''' + This performs Local mirroring + We set port2 traffic to be monitored(both ingress and egress) on port1 + We send a packet from port 2 to port 3 + We expect the same packet on port 1 which is a mirror packet + ''' + def runTest(self): + print + switch_init(self.client) + port1 = port_list[0] + port2 = port_list[1] + port3 = port_list[2] + monitor_port=port1 + source_port=port2 + mac3='00:00:00:00:00:33' + mac2='00:00:00:00:00:22' + mirror_type=SAI_MIRROR_TYPE_LOCAL + sai_thrift_create_fdb(self.client, 2, mac3, port3, 1) + sai_thrift_create_fdb(self.client, 2, mac2, port2, 1) + + # Put ports under test in VLAN 2 + self.client.sai_thrift_create_vlan(2) + vlan_member1 = sai_thrift_create_vlan_member(self.client, 2, port1, SAI_VLAN_PORT_TAGGED) + vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_TAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, 2, port2, SAI_VLAN_PORT_TAGGED) + vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_TAGGED) + vlan_member3 = sai_thrift_create_vlan_member(self.client, 2, port3, SAI_VLAN_PORT_TAGGED) + vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_TAGGED) + + # Remove ports from default VLAN + self.client.sai_thrift_remove_vlan_member(vlan_member1a) + self.client.sai_thrift_remove_vlan_member(vlan_member2a) + self.client.sai_thrift_remove_vlan_member(vlan_member3a) + + # Set PVID + attr_value = sai_thrift_attribute_value_t(u16=2) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + + spanid=sai_thrift_create_mirror_session(self.client,mirror_type=mirror_type,port=monitor_port,vlan=1,vlan_priority=0,vlan_tpid=0,src_mac=None,dst_mac=None,addr_family=0,src_ip=None,dst_ip=None,encap_type=0,protocol=0,ttl=0,tos=0,gre_type=0) + attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=1,object_id_list=[spanid])) + + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.0.0.1', + dl_vlan_enable=True, + vlan_vid=2, + ip_id=101, + ip_ttl=64) + + exp_pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.0.0.1', + dl_vlan_enable=True, + vlan_vid=2, + ip_id=101, + ip_ttl=64) + + pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', + eth_src='00:33:33:33:33:33', + ip_dst='10.0.0.1', + dl_vlan_enable=True, + vlan_vid=2, + ip_id=101, + ip_ttl=64, + pktlen=104) + + exp_pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', + eth_src='00:33:33:33:33:33', + ip_dst='10.0.0.1', + dl_vlan_enable=True, + vlan_vid=2,#use vlan_vid field if packets are expected to be monitored on client side otherwise not needed + ip_id=101, + ip_ttl=64, + pktlen=104) + + m=Mask(exp_pkt2) + m.set_do_not_care_scapy(ptf.packet.IP,'id') + m.set_do_not_care_scapy(ptf.packet.IP,'chksum') + try: + # in tuple: 0 is device number, 2 is port number + # this tuple uniquely identifies a port + # for ingress mirroring + print "Checking INGRESS Local Mirroring" + print "Sending packet port 2 -> port 3 (00:22:22:22:22:22 -> 00:00:00:00:00:33)" + send_packet(self, 1, pkt) + verify_packets(self, exp_pkt, ports=[0,2]) + # for egress mirroring + print "Checking EGRESS Local Mirroring" + print "Sending packet port 3 -> port 2 (00:33:33:33:33:33 -> 00:00:00:00:00:22)" + send_packet(self, 2, pkt2) + verify_each_packet_on_each_port(self, [m,pkt2], ports=[0,1]) + finally: + sai_thrift_delete_fdb(self.client, 2, mac3, port3) + sai_thrift_delete_fdb(self.client, 2, mac2, port2) + + # Remove ports from mirror destination + attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=0,object_id_list=[spanid])) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + # Now you can remove destination + self.client.sai_thrift_remove_mirror_session(spanid) + + # Remove ports from VLAN 2 + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan_member(vlan_member3) + self.client.sai_thrift_delete_vlan(2) + + # Add ports back to default VLAN + vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_UNTAGGED) + vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_UNTAGGED) + vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_UNTAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + + + +@group('mirror') +class erspanmonitor(sai_base_test.ThriftInterfaceDataPlane): + ''' + This test performs erspan monitoring + From port2(source port) we send traffic to port 3 + erspan mirror packets are expected on port 1(monitor port) + ''' + def runTest(self): + print + switch_init(self.client) + port1 = port_list[0] + port2 = port_list[1] + port3 = port_list[2] + mac3='00:00:00:00:00:33' + mac2='00:00:00:00:00:22' + monitor_port=port1 + source_port=port2 + mirror_type=SAI_MIRROR_TYPE_ENHANCED_REMOTE + vlan=0x2 + vlan_tpid=0x8100 + vlan_pri=0x6 + src_mac='00:00:00:00:11:22' + dst_mac='00:00:00:00:11:33' + encap_type=SAI_MIRROR_L3_GRE_TUNNEL + ip_version=0x4 + tos=0x3c + ttl=0xf0 + gre_type=0x88be + src_ip='17.18.19.0' + dst_ip='33.19.20.0' + addr_family=0 + + sai_thrift_create_fdb(self.client, 3, mac3, port3, 1) + sai_thrift_create_fdb(self.client, 3, mac2, port2, 1) + + # Put ports under test in VLAN 3 + self.client.sai_thrift_create_vlan(3) + vlan_member1 = sai_thrift_create_vlan_member(self.client, 3, port1, SAI_VLAN_PORT_TAGGED) + vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_TAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, 3, port2, SAI_VLAN_PORT_TAGGED) + vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_TAGGED) + vlan_member3 = sai_thrift_create_vlan_member(self.client, 3, port3, SAI_VLAN_PORT_TAGGED) + vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_TAGGED) + + # Remove ports from default VLAN + self.client.sai_thrift_remove_vlan_member(vlan_member1a) + self.client.sai_thrift_remove_vlan_member(vlan_member2a) + self.client.sai_thrift_remove_vlan_member(vlan_member3a) + + # Set PVID + attr_value = sai_thrift_attribute_value_t(u16=3) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + + erspanid=sai_thrift_create_mirror_session(self.client,mirror_type=mirror_type,port=monitor_port,vlan=vlan,vlan_priority=vlan_pri,vlan_tpid=vlan_tpid,src_mac=src_mac,dst_mac=dst_mac,addr_family=addr_family,src_ip=src_ip,dst_ip=dst_ip,encap_type=encap_type,protocol=ip_version,ttl=ttl,tos=tos,gre_type=gre_type) + + #attrb_value = sai_thrift_attribute_value_t(oid=erspanid) + attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=1,object_id_list=[erspanid])) + + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', + eth_src='00:22:22:22:22:22', + ip_dst='10.0.0.1', + dl_vlan_enable=True, + vlan_vid=3, + ip_id=101, + ip_ttl=64) + + pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', + eth_src='00:33:33:33:33:33', + dl_vlan_enable=True, + vlan_vid=3, + ip_dst='10.0.0.1', + ip_id=101, + ip_ttl=64) + + pkt3 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', + eth_src='00:33:33:33:33:33', + dl_vlan_enable=True, + vlan_vid=3, + ip_dst='10.0.0.1', + ip_id=101, + ip_ttl=64) + + exp_pkt1= simple_gre_packet(pktlen=142, + eth_dst='00:00:00:00:11:33', + eth_src='00:00:00:00:11:22', + dl_vlan_enable=True, + vlan_vid=2, + ip_id=0, + ip_ttl=240, + ip_tos=0x3c, + ip_ihl=5, + ip_src='17.18.19.0', + ip_dst='33.19.20.0', + inner_frame=pkt + ) + + exp_pkt2= simple_gre_packet(pktlen=142, + eth_dst='00:00:00:00:11:33', + eth_src='00:00:00:00:11:22', + dl_vlan_enable=True, + vlan_vid=2, + ip_id=0, + ip_ttl=240, + ip_tos=0x3c, + ip_ihl=5, + ip_src='17.18.19.0', + ip_dst='33.19.20.0', + inner_frame=pkt3 + ) + m1=Mask(exp_pkt1) + m2=Mask(exp_pkt2) + m1.set_do_not_care_scapy(ptf.packet.IP,'tos') + m1.set_do_not_care_scapy(ptf.packet.IP,'frag') + m1.set_do_not_care_scapy(ptf.packet.IP,'flags') + m1.set_do_not_care_scapy(ptf.packet.IP,'chksum') + m1.set_do_not_care_scapy(ptf.packet.GRE,'proto') + m2.set_do_not_care_scapy(ptf.packet.IP,'tos') + m2.set_do_not_care_scapy(ptf.packet.IP,'frag') + m2.set_do_not_care_scapy(ptf.packet.IP,'flags') + m2.set_do_not_care_scapy(ptf.packet.IP,'chksum') + m2.set_do_not_care_scapy(ptf.packet.GRE,'proto') + n=Mask(pkt2) + n.set_do_not_care_scapy(ptf.packet.IP,'len') + n.set_do_not_care_scapy(ptf.packet.IP,'chksum') + + try: + # in tuple: 0 is device number, 2 is port number + # this tuple uniquely identifies a port + # for ingress mirroring + print "Checking INGRESS ERSPAN Mirroring" + print "Sending packet port 2 -> port 3 (00:22:22:22:22:22 -> 00:00:00:00:00:33)" + send_packet(self, 1, pkt) + verify_each_packet_on_each_port(self, [m1,pkt], ports=[0,2])#FIXME need to properly implement + # for egress mirroring + print "Checking EGRESS ERSPAN Mirroring" + print "Sending packet port 3 -> port 2 (00:33:33:33:33:33 -> 00:00:00:00:00:22)" + send_packet(self, 2, pkt2) + verify_each_packet_on_each_port(self, [pkt2,m2], ports=[1,0])#FIXME need to properly implement + finally: + sai_thrift_delete_fdb(self.client, 3, mac2, port2) + sai_thrift_delete_fdb(self.client, 3, mac3, port3) + + # Remove ports from mirror destination + attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=0,object_id_list=[erspanid])) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + # Now you can remove destination + self.client.sai_thrift_remove_mirror_session(erspanid) + + # Remove ports from VLAN 3 + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan_member(vlan_member3) + self.client.sai_thrift_delete_vlan(3) + + # Add ports back to default VLAN + vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_UNTAGGED) + vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_UNTAGGED) + vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_UNTAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + self.client.sai_thrift_set_port_attribute(port3, attr) + +@group('mirror') +class IngressLocalMirrorTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 1 -> ptf_intf 2, ptf_intf 3 (local mirror)" + print "Sending packet ptf_intf 2 -> ptf_intf 1, ptf_intf 3 (local mirror)" + + switch_init(self.client) + vlan_id = 10 + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + mac1 = '00:11:11:11:11:11' + mac2 = '00:22:22:22:22:22' + mac_action = SAI_PACKET_ACTION_FORWARD + + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=vlan_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) + sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) + + # setup local mirror session + mirror_type = SAI_MIRROR_SESSION_TYPE_LOCAL + monitor_port = port3 + print "Create mirror session: mirror_type = SAI_MIRROR_TYPE_LOCAL, monitor_port = ptf_intf 3 " + ingress_mirror_id = sai_thrift_create_mirror_session(self.client, + mirror_type, + monitor_port, + None, None, None, + None, None, None, + None, None, None, + None, None, None) + print "ingress_mirror_id = %d" %ingress_mirror_id + + attr_value = sai_thrift_attribute_value_t(oid=ingress_mirror_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + + try: + assert ingress_mirror_id > 0, 'ingress_mirror_id is <= 0' + + pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64) + exp_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=10, + ip_id=102, + ip_ttl=64, + pktlen=104) + + print '#### Sending 00:22:22:22:22:22 | 00:11:11:11:11:11 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 1 ####' + send_packet(self, 1, str(pkt)) + verify_each_packet_on_each_port(self, [exp_pkt, pkt], [2, 3]) + + time.sleep(1) + + pkt = simple_tcp_packet(eth_dst=mac1, + eth_src=mac2, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + vlan_vid=10, + dl_vlan_enable=True, + ip_id=102, + ip_ttl=64, + pktlen=104) + exp_pkt = simple_tcp_packet(eth_dst=mac1, + eth_src=mac2, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64, + pktlen=100) + + print '#### Sending 00:11:11:11:11:11 | 00:22:22:22:22:22 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 2 ####' + send_packet(self, 2, str(pkt)) + verify_each_packet_on_each_port(self, [exp_pkt, pkt], [1, 3]) + + finally: + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_mirror_session(ingress_mirror_id) + + sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) + sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) + +@group('mirror') +class IngressRSpanMirrorTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 1 -> ptf_intf 2, ptf_intf 3 (rspan mirror)" + + switch_init(self.client) + vlan_id = 10 + vlan_remote_id = 110 + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + mac1 = '00:11:11:11:11:11' + mac2 = '00:22:22:22:22:22' + mac_action = SAI_PACKET_ACTION_FORWARD + + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_remote_oid = sai_thrift_create_vlan(self.client, vlan_remote_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=vlan_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) + sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) + + # setup remote mirror session + mirror_type = SAI_MIRROR_SESSION_TYPE_REMOTE + monitor_port = port3 + vlan = vlan_remote_id + print "Create mirror session: mirror_type = SAI_MIRROR_SESSION_TYPE_REMOTE, monitor_port = ptf_intf 3 " + ingress_mirror_id = sai_thrift_create_mirror_session(self.client, + mirror_type, + monitor_port, + vlan, None, None, + None, None, None, + None, None, None, + None, None, None) + print "ingress_mirror_id = %x" %ingress_mirror_id + + attr_value = sai_thrift_attribute_value_t(oid=ingress_mirror_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + try: + assert ingress_mirror_id > 0, 'ingress_mirror_id is <= 0' + + pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64) + exp_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=10, + ip_id=102, + ip_ttl=64, + pktlen=104) + exp_mirrored_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=110, + ip_id=102, + ip_ttl=64, + pktlen=104) + print '#### Sending 00:22:22:22:22:22 | 00:11:11:11:11:11 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 1 ####' + send_packet(self, 1, str(pkt)) + verify_each_packet_on_each_port(self, [exp_pkt, exp_mirrored_pkt], [2, 3]) + + finally: + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + self.client.sai_thrift_remove_mirror_session(ingress_mirror_id) + + sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) + sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) + self.client.sai_thrift_remove_vlan(vlan_remote_oid) + +@group('mirror') +class IngressERSpanMirrorTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 1 -> ptf_intf 2, ptf_intf 3 (erspan mirror)" + + switch_init(self.client) + vlan_id = 10 + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + mac1 = '00:11:11:11:11:11' + mac2 = '00:22:22:22:22:22' + mac_action = SAI_PACKET_ACTION_FORWARD + + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=vlan_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) + sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) + + # setup enhanced remote mirror session + mirror_type = SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE + monitor_port = port3 + vlan = vlan_id + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + tunnel_src_ip = "1.1.1.1" + tunnel_dst_ip = "1.1.1.2" + tunnel_src_mac = router_mac + tunnel_dst_mac = "00:33:33:33:33:33" + protocol = 47 + + print "Create mirror session: mirror_type = SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE, monitor_port = ptf_intf 3 " + ingress_mirror_id = sai_thrift_create_mirror_session(self.client, + mirror_type, + monitor_port, + vlan, None, None, + tunnel_src_mac, tunnel_dst_mac, + addr_family, tunnel_src_ip, tunnel_dst_ip, + None, protocol, None, None) + print "ingress_mirror_id = %d" %ingress_mirror_id + + attr_value = sai_thrift_attribute_value_t(oid=ingress_mirror_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + try: + assert ingress_mirror_id > 0, 'ingress_mirror_id is <= 0' + + pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64) + exp_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=10, + ip_id=102, + ip_ttl=64, + pktlen=104) + exp_mirrored_pkt = ipv4_erspan_pkt(eth_dst=tunnel_dst_mac, + eth_src=tunnel_src_mac, + ip_src=tunnel_src_ip, + ip_dst=tunnel_dst_ip, + ip_id=0, + ip_ttl=64, + version=2, + mirror_id=(ingress_mirror_id & 0x3FFFFFFF), + inner_frame=pkt); + print '#### Sending 00:22:22:22:22:22 | 00:11:11:11:11:11 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 1 ####' + send_packet(self, 1, str(pkt)) + verify_packet(self, exp_pkt, 2) + verify_packet(self, exp_mirrored_pkt, 3) + + finally: + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + self.client.sai_thrift_remove_mirror_session(ingress_mirror_id) + + sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) + sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) + +@group('mirror') +class EgressLocalMirrorTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 1 -> ptf_intf 2, ptf_intf 3 (local mirror)" + + switch_init(self.client) + vlan_id = 10 + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + mac1 = '00:11:11:11:11:11' + mac2 = '00:22:22:22:22:22' + mac_action = SAI_PACKET_ACTION_FORWARD + + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=vlan_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) + sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) + + # setup local mirror session + mirror_type = SAI_MIRROR_SESSION_TYPE_LOCAL + monitor_port = port3 + print "Create mirror session: mirror_type = SAI_MIRROR_TYPE_LOCAL, monitor_port = ptf_intf 3 " + egress_mirror_id = sai_thrift_create_mirror_session(self.client, + mirror_type, + monitor_port, + None, None, None, + None, None, None, + None, None, None, + None, None, None) + print "egress_mirror_id = %d" %egress_mirror_id + + attr_value = sai_thrift_attribute_value_t(oid=egress_mirror_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + try: + assert egress_mirror_id > 0, 'egress_mirror_id is <= 0' + + pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64) + exp_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=10, + ip_id=102, + ip_ttl=64, + pktlen=104) + + print '#### Sending 00:22:22:22:22:22 | 00:11:11:11:11:11 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 1 ####' + send_packet(self, 1, str(pkt)) + verify_each_packet_on_each_port(self, [exp_pkt, exp_pkt], [2, 3]) + + finally: + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_mirror_session(egress_mirror_id) + + sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) + sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) + +@group('mirror') +class EgressERSpanMirrorTest(sai_base_test.ThriftInterfaceDataPlane): + def runTest(self): + print + print '----------------------------------------------------------------------------------------------' + print "Sending packet ptf_intf 1 -> ptf_intf 2, ptf_intf 3 (erspan mirror)" + + switch_init(self.client) + vlan_id = 10 + port1 = port_list[1] + port2 = port_list[2] + port3 = port_list[3] + mac1 = '00:11:11:11:11:11' + mac2 = '00:22:22:22:22:22' + mac_action = SAI_PACKET_ACTION_FORWARD + + vlan_oid = sai_thrift_create_vlan(self.client, vlan_id) + vlan_member1 = sai_thrift_create_vlan_member(self.client, vlan_oid, port1, SAI_VLAN_TAGGING_MODE_UNTAGGED) + vlan_member2 = sai_thrift_create_vlan_member(self.client, vlan_oid, port2, SAI_VLAN_TAGGING_MODE_TAGGED) + + attr_value = sai_thrift_attribute_value_t(u16=vlan_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port1, attr) + + sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) + sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) + + # setup enhanced remote mirror session + mirror_type = SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE + monitor_port = port3 + vlan = vlan_id + addr_family = SAI_IP_ADDR_FAMILY_IPV4 + tunnel_src_ip = "1.1.1.1" + tunnel_dst_ip = "1.1.1.2" + + tunnel_src_mac = router_mac + tunnel_dst_mac = "00:33:33:33:33:33" + protocol = 47 + + print "Create mirror session: mirror_type = SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE, monitor_port = ptf_intf 3 " + egress_mirror_id = sai_thrift_create_mirror_session(self.client, + mirror_type, + monitor_port, + vlan, None, None, + tunnel_src_mac, tunnel_dst_mac, + addr_family, tunnel_src_ip, tunnel_dst_ip, + None, protocol, None, None) + print "egress_mirror_id = %d" %egress_mirror_id + + attr_value = sai_thrift_attribute_value_t(oid=egress_mirror_id) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + try: + assert egress_mirror_id > 0, 'egress_mirror_id is <= 0' + + pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + ip_id=102, + ip_ttl=64) + exp_pkt = simple_tcp_packet(eth_dst=mac2, + eth_src=mac1, + ip_dst='10.0.0.1', + ip_src='192.168.0.1', + dl_vlan_enable=True, + vlan_vid=10, + ip_id=102, + ip_ttl=64, + pktlen=104) + exp_mirrored_pkt = ipv4_erspan_pkt(eth_dst=tunnel_dst_mac, + eth_src=tunnel_src_mac, + ip_src=tunnel_src_ip, + ip_dst=tunnel_dst_ip, + ip_id=0, + ip_ttl=64, + version=2, + mirror_id=(egress_mirror_id & 0x3FFFFFFF), + inner_frame=pkt); + print '#### Sending 00:22:22:22:22:22 | 00:11:11:11:11:11 | 10.0.0.1 | 192.168.0.1 | @ ptf_intf 1 ####' + send_packet(self, 1, str(pkt)) + verify_packet(self, exp_pkt, 2) + verify_packet(self, exp_mirrored_pkt, 3) + + finally: + attr_value = sai_thrift_attribute_value_t(oid=SAI_NULL_OBJECT_ID) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_mirror_session(egress_mirror_id) + + sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) + sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) + + attr_value = sai_thrift_attribute_value_t(u16=1) + attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) + self.client.sai_thrift_set_port_attribute(port2, attr) + + self.client.sai_thrift_remove_vlan_member(vlan_member1) + self.client.sai_thrift_remove_vlan_member(vlan_member2) + self.client.sai_thrift_remove_vlan(vlan_oid) diff --git a/test/saithrift/tests/switch.py b/test/saithrift/tests/switch.py index 4bd8033b8..9d872c5d6 100644 --- a/test/saithrift/tests/switch.py +++ b/test/saithrift/tests/switch.py @@ -40,6 +40,11 @@ this_dir = os.path.dirname(os.path.abspath(__file__)) +class VlanObj: + def __init__(self): + self.oid = 0 + self.vid = 0 + switch_inited=0 port_list = {} sai_port_list = [] @@ -48,14 +53,24 @@ router_mac='00:77:66:55:44:00' rewrite_mac1='00:77:66:55:44:01' rewrite_mac2='00:77:66:55:44:02' +default_vlan = VlanObj() is_bmv2 = ('BMV2_TEST' in os.environ) and (int(os.environ['BMV2_TEST']) == 1) def switch_init(client): global switch_inited + if switch_inited: return + ret = client.sai_thrift_get_default_vlan_id() + assert (ret.status == SAI_STATUS_SUCCESS), "Failed to get default vlan" + default_vlan.oid = ret.data.oid + + ret = client.sai_thrift_get_vlan_id(default_vlan.oid) + assert (ret.status == SAI_STATUS_SUCCESS), "Failed obtain default vlan id" + default_vlan.vid = ret.data.u16 + switch_attr_list = client.sai_thrift_get_switch_attribute() attr_list = switch_attr_list.attr_list for attribute in attr_list: @@ -104,6 +119,10 @@ def sai_thrift_get_cpu_port_id(client): cpu_port = client.sai_thrift_get_cpu_port_id() return cpu_port +def sai_thrift_get_default_vlan_id(client): + vlan_id = client.sai_thrift_get_default_vlan_id() + return vlan_id + def sai_thrift_get_default_router_id(client): default_router_id = client.sai_thrift_get_default_router_id() return default_router_id @@ -111,7 +130,7 @@ def sai_thrift_get_default_router_id(client): def sai_thrift_create_fdb(client, vlan_id, mac, port, mac_action): fdb_entry = sai_thrift_fdb_entry_t(mac_address=mac, vlan_id=vlan_id) #value 0 represents static entry, id=0, represents entry type - fdb_attribute1_value = sai_thrift_attribute_value_t(s32=SAI_FDB_ENTRY_STATIC) + fdb_attribute1_value = sai_thrift_attribute_value_t(s32=SAI_FDB_ENTRY_TYPE_STATIC) fdb_attribute1 = sai_thrift_attribute_t(id=SAI_FDB_ENTRY_ATTR_TYPE, value=fdb_attribute1_value) #value oid represents object id, id=1 represents port id @@ -133,7 +152,7 @@ def sai_thrift_flush_fdb_by_vlan(client, vlan_id): fdb_attribute1_value = sai_thrift_attribute_value_t(u16=vlan_id) fdb_attribute1 = sai_thrift_attribute_t(id=SAI_FDB_FLUSH_ATTR_VLAN_ID, value=fdb_attribute1_value) - fdb_attribute2_value = sai_thrift_attribute_value_t(s32=SAI_FDB_FLUSH_ENTRY_DYNAMIC) + fdb_attribute2_value = sai_thrift_attribute_value_t(s32=SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC) fdb_attribute2 = sai_thrift_attribute_t(id=SAI_FDB_FLUSH_ATTR_ENTRY_TYPE, value=fdb_attribute2_value) fdb_attr_list = [fdb_attribute1, fdb_attribute2] @@ -152,10 +171,10 @@ def sai_thrift_create_virtual_router(client, v4_enabled, v6_enabled): vr_id = client.sai_thrift_create_virtual_router(thrift_attr_list=vr_attr_list) return vr_id -def sai_thrift_create_router_interface(client, vr_id, is_port, port_id, vlan_id, v4_enabled, v6_enabled, mac): +def sai_thrift_create_router_interface(client, vr_oid, is_port, port_oid, vlan_oid, v4_enabled, v6_enabled, mac): #vrf attribute rif_attr_list = [] - rif_attribute1_value = sai_thrift_attribute_value_t(oid=vr_id) + rif_attribute1_value = sai_thrift_attribute_value_t(oid=vr_oid) rif_attribute1 = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID, value=rif_attribute1_value) rif_attr_list.append(rif_attribute1) @@ -165,7 +184,7 @@ def sai_thrift_create_router_interface(client, vr_id, is_port, port_id, vlan_id, rif_attribute2 = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_TYPE, value=rif_attribute2_value) rif_attr_list.append(rif_attribute2) - rif_attribute3_value = sai_thrift_attribute_value_t(oid=port_id) + rif_attribute3_value = sai_thrift_attribute_value_t(oid=port_oid) rif_attribute3 = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_PORT_ID, value=rif_attribute3_value) rif_attr_list.append(rif_attribute3) @@ -175,7 +194,7 @@ def sai_thrift_create_router_interface(client, vr_id, is_port, port_id, vlan_id, rif_attribute2 = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_TYPE, value=rif_attribute2_value) rif_attr_list.append(rif_attribute2) - rif_attribute3_value = sai_thrift_attribute_value_t(u16=vlan_id) + rif_attribute3_value = sai_thrift_attribute_value_t(oid=vlan_oid) rif_attribute3 = sai_thrift_attribute_t(id=SAI_ROUTER_INTERFACE_ATTR_VLAN_ID, value=rif_attribute3_value) rif_attr_list.append(rif_attribute3) @@ -210,18 +229,19 @@ def sai_thrift_create_route(client, vr_id, addr_family, ip_addr, ip_mask, nhop, mask = sai_thrift_ip_t(ip6=ip_mask) ip_prefix = sai_thrift_ip_prefix_t(addr_family=SAI_IP_ADDR_FAMILY_IPV6, addr=addr, mask=mask) route_attribute1_value = sai_thrift_attribute_value_t(oid=nhop) - route_attribute1 = sai_thrift_attribute_t(id=SAI_ROUTE_ATTR_NEXT_HOP_ID, + route_attribute1 = sai_thrift_attribute_t(id=SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, value=route_attribute1_value) - route = sai_thrift_unicast_route_entry_t(vr_id, ip_prefix) + route = sai_thrift_route_entry_t(vr_id, ip_prefix) route_attr_list = [route_attribute1] if packet_action != None: route_packet_action_value = sai_thrift_attribute_value_t(s32=packet_action) - route_packet_action_attr = sai_thrift_attribute_t(id=SAI_ROUTE_ATTR_PACKET_ACTION, value=route_packet_action_value) + route_packet_action_attr = sai_thrift_attribute_t(id=SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION, + value=route_packet_action_value) route_attr_list.append(route_packet_action_attr) - client.sai_thrift_create_route(thrift_unicast_route_entry=route, thrift_attr_list=route_attr_list) + client.sai_thrift_create_route(thrift_route_entry=route, thrift_attr_list=route_attr_list) return def sai_thrift_remove_route(client, vr_id, addr_family, ip_addr, ip_mask, nhop): @@ -233,8 +253,8 @@ def sai_thrift_remove_route(client, vr_id, addr_family, ip_addr, ip_mask, nhop): addr = sai_thrift_ip_t(ip6=ip_addr) mask = sai_thrift_ip_t(ip6=ip_mask) ip_prefix = sai_thrift_ip_prefix_t(addr_family=SAI_IP_ADDR_FAMILY_IPV6, addr=addr, mask=mask) - route = sai_thrift_unicast_route_entry_t(vr_id, ip_prefix) - client.sai_thrift_remove_route(thrift_unicast_route_entry=route) + route = sai_thrift_route_entry_t(vr_id, ip_prefix) + client.sai_thrift_remove_route(thrift_route_entry=route) def sai_thrift_create_nhop(client, addr_family, ip_addr, rif_id): if addr_family == SAI_IP_ADDR_FAMILY_IPV4: @@ -249,13 +269,17 @@ def sai_thrift_create_nhop(client, addr_family, ip_addr, rif_id): nhop_attribute2_value = sai_thrift_attribute_value_t(oid=rif_id) nhop_attribute2 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID, value=nhop_attribute2_value) - nhop_attribute3_value = sai_thrift_attribute_value_t(s32=SAI_NEXT_HOP_IP) + nhop_attribute3_value = sai_thrift_attribute_value_t(s32=SAI_NEXT_HOP_TYPE_IP) nhop_attribute3 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_ATTR_TYPE, value=nhop_attribute3_value) nhop_attr_list = [nhop_attribute1, nhop_attribute2, nhop_attribute3] nhop = client.sai_thrift_create_next_hop(thrift_attr_list=nhop_attr_list) return nhop +def sai_thrift_remove_nhop(client, nhop_list): + for nhop in nhop_list: + client.sai_thrift_remove_next_hop(nhop) + def sai_thrift_create_neighbor(client, addr_family, rif_id, ip_addr, dmac): if addr_family == SAI_IP_ADDR_FAMILY_IPV4: addr = sai_thrift_ip_t(ip4=ip_addr) @@ -264,11 +288,11 @@ def sai_thrift_create_neighbor(client, addr_family, rif_id, ip_addr, dmac): addr = sai_thrift_ip_t(ip6=ip_addr) ipaddr = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV6, addr=addr) neighbor_attribute1_value = sai_thrift_attribute_value_t(mac=dmac) - neighbor_attribute1 = sai_thrift_attribute_t(id=SAI_NEIGHBOR_ATTR_DST_MAC_ADDRESS, + neighbor_attribute1 = sai_thrift_attribute_t(id=SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS, value=neighbor_attribute1_value) neighbor_attr_list = [neighbor_attribute1] neighbor_entry = sai_thrift_neighbor_entry_t(rif_id=rif_id, ip_address=ipaddr) - client.sai_thrift_create_neighbor_entry(neighbor_entry, neighbor_attr_list) + return client.sai_thrift_create_neighbor_entry(neighbor_entry, neighbor_attr_list) def sai_thrift_remove_neighbor(client, addr_family, rif_id, ip_addr, dmac): if addr_family == SAI_IP_ADDR_FAMILY_IPV4: @@ -280,17 +304,40 @@ def sai_thrift_remove_neighbor(client, addr_family, rif_id, ip_addr, dmac): neighbor_entry = sai_thrift_neighbor_entry_t(rif_id=rif_id, ip_address=ipaddr) client.sai_thrift_remove_neighbor_entry(neighbor_entry) -def sai_thrift_create_next_hop_group(client, nhop_list): - nhop_group_attribute1_value = sai_thrift_attribute_value_t(s32=SAI_NEXT_HOP_GROUP_ECMP) - nhop_group_attribute1 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_ATTR_TYPE, - value=nhop_group_attribute1_value) - nhop_objlist = sai_thrift_object_list_t(count=len(nhop_list), object_id_list=nhop_list) - nhop_group_attribute2_value = sai_thrift_attribute_value_t(objlist=nhop_objlist) - nhop_group_attribute2 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_LIST, - value=nhop_group_attribute2_value) - nhop_group_attr_list = [nhop_group_attribute1, nhop_group_attribute2] - nhop_group = client.sai_thrift_create_next_hop_group(thrift_attr_list=nhop_group_attr_list) - return nhop_group +def sai_thrift_create_next_hop_group(client): + nhop_group_atr1_value = sai_thrift_attribute_value_t(s32=SAI_NEXT_HOP_GROUP_TYPE_ECMP) + nhop_group_atr1 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_ATTR_TYPE, + value=nhop_group_atr1_value) + nhop_group_attr_list = [nhop_group_atr1] + return client.sai_thrift_create_next_hop_group(nhop_group_attr_list) + +def sai_thrift_remove_next_hop_group(client, nhop_group_list): + for nhop_group in nhop_group_list: + client.sai_thrift_remove_next_hop_group(nhop_group) + +def sai_thrift_create_next_hop_group_member(client, nhop_group, nhop, weight=None): + nhop_gmember_atr1_value = sai_thrift_attribute_value_t(oid=nhop_group) + nhop_gmember_atr1 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID, + value=nhop_gmember_atr1_value) + nhop_gmember_atr2_value = sai_thrift_attribute_value_t(oid=nhop) + nhop_gmember_atr2 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID, + value=nhop_gmember_atr2_value) + if weight != None: + nhop_gmember_atr3_value = sai_thrift_attribute_value_t(u32=weight) + nhop_gmember_atr3 = sai_thrift_attribute_t(id=SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT, + value=nhop_gmember_atr3_value) + nhop_gmember_attr_list = [nhop_gmember_atr1, nhop_gmember_atr2, nhop_gmember_atr3] + else: + nhop_gmember_attr_list = [nhop_gmember_atr1, nhop_gmember_atr2] + return client.sai_thrift_create_next_hop_group_member(nhop_gmember_attr_list) + +def sai_thrift_remove_next_hop_group_member(client, nhop_gmember_list): + for nhop_gmember in nhop_gmember_list: + client.sai_thrift_remove_next_hop_group_member(nhop_gmember) + +def sai_thrift_remove_next_hop_from_group(client, nhop_list): + for hnop in nhop_list: + client.sai_thrift_remove_next_hop_from_group(hnop) def sai_thrift_create_lag(client, port_list): lag_port_list = sai_thrift_object_list_t(count=len(port_list), object_id_list=port_list) @@ -321,7 +368,6 @@ def sai_thrift_create_stp_entry(client, vlan_list): stp_id = client.sai_thrift_create_stp_entry(stp_attr_list) return stp_id - def sai_thrift_set_hostif_trap_group(client, trap_group_id, policer_id): policer_attr_value = sai_thrift_attribute_value_t(oid=policer_id) policer_attr = sai_thrift_attribute_t(id=SAI_HOSTIF_TRAP_GROUP_ATTR_POLICER, value=policer_attr_value) @@ -391,7 +437,7 @@ def sai_thrift_create_hostif(client, rif_or_port_id, intf_name): attribute1 = sai_thrift_attribute_t(id=SAI_HOSTIF_ATTR_TYPE, value=attribute1_value) attribute2_value = sai_thrift_attribute_value_t(oid=rif_or_port_id) - attribute2 = sai_thrift_attribute_t(id=SAI_HOSTIF_ATTR_RIF_OR_PORT_ID, + attribute2 = sai_thrift_attribute_t(id=SAI_HOSTIF_ATTR_OBJ_ID, value=attribute2_value) attribute3_value = sai_thrift_attribute_value_t(chardata=intf_name) attribute3 = sai_thrift_attribute_t(id=SAI_HOSTIF_ATTR_NAME, @@ -400,79 +446,142 @@ def sai_thrift_create_hostif(client, rif_or_port_id, intf_name): hif_id = client.sai_thrift_create_hostif(attr_list) return hif_id -def sai_thrift_create_acl_table(client, addr_family, +def sai_thrift_create_acl_table(client, + table_stage, + table_bind_point_list, + addr_family, + mac_src, mac_dst, ip_src, ip_dst, ip_proto, in_ports, out_ports, - in_port, out_port): - #print "aaa" + in_port, out_port, + src_l4_port, dst_l4_port): + acl_attr_list = [] + + if table_stage != None: + attribute_value = sai_thrift_attribute_value_t(s32=table_stage) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_ACL_STAGE, + value=attribute_value) + acl_attr_list.append(attribute) + + if table_bind_point_list != None: + acl_table_bind_point_list = sai_thrift_s32_list_t(count=len(table_bind_point_list), s32list=table_bind_point_list) + attribute_value = sai_thrift_attribute_value_t(s32list=acl_table_bind_point_list) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST, + value=attribute_value) + acl_attr_list.append(attribute) + + if mac_src != None: + attribute_value = sai_thrift_attribute_value_t(booldata=1) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC, + value=attribute_value) + acl_attr_list.append(attribute) + + if mac_dst != None: + attribute_value = sai_thrift_attribute_value_t(booldata=1) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_DST_MAC, + value=attribute_value) + acl_attr_list.append(attribute) + if ip_src != None: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_SRC_IP, value=attribute_value) acl_attr_list.append(attribute) + if ip_dst != None: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_DST_IP, value=attribute_value) acl_attr_list.append(attribute) + if ip_proto != None: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL, value=attribute_value) acl_attr_list.append(attribute) + if in_ports: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS, value=attribute_value) acl_attr_list.append(attribute) + if out_ports: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS, value=attribute_value) acl_attr_list.append(attribute) + if in_port != None: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_IN_PORT, value=attribute_value) acl_attr_list.append(attribute) + if out_port != None: attribute_value = sai_thrift_attribute_value_t(booldata=1) attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_OUT_PORT, value=attribute_value) acl_attr_list.append(attribute) - attribute_value = sai_thrift_attribute_value_t(u32=0) #TODO: Expose stage as function parameter - attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_STAGE, value=attribute_value) - acl_attr_list.append(attribute) - - #print "bbb" + if src_l4_port != None: + attribute_value = sai_thrift_attribute_value_t(booldata=1) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT, + value=attribute_value) + acl_attr_list.append(attribute) + + if dst_l4_port != None: + attribute_value = sai_thrift_attribute_value_t(booldata=1) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT, + value=attribute_value) + acl_attr_list.append(attribute) + acl_table_id = client.sai_thrift_create_acl_table(acl_attr_list) - #print acl_table_id return acl_table_id -def sai_thrift_create_acl_entry(client, acl_table_id, +def sai_thrift_create_acl_entry(client, + acl_table_id, + entry_priority, action, addr_family, + mac_src, mac_src_mask, + mac_dst, mac_dst_mask, ip_src, ip_src_mask, ip_dst, ip_dst_mask, ip_proto, in_port_list, out_port_list, in_port, out_port, + src_l4_port, dst_l4_port, ingress_mirror, egress_mirror): acl_attr_list = [] - #OID + #ACL table OID attribute_value = sai_thrift_attribute_value_t(oid=acl_table_id) attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_TABLE_ID, value=attribute_value) acl_attr_list.append(attribute) #Priority - attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(u32=10))) - attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_PRIORITY, - value=attribute_value) - acl_attr_list.append(attribute) + if entry_priority != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(u32=entry_priority))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_PRIORITY, + value=attribute_value) + acl_attr_list.append(attribute) + + #MAC source + if mac_src != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(mac=mac_src), mask = sai_thrift_acl_mask_t(mac=mac_src_mask))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_SRC_MAC, + value=attribute_value) + acl_attr_list.append(attribute) + + #MAC destination + if mac_dst != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(mac=mac_dst), mask = sai_thrift_acl_mask_t(mac=mac_dst_mask))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC, + value=attribute_value) + acl_attr_list.append(attribute) #Ip source if ip_src != None: @@ -497,48 +606,121 @@ def sai_thrift_create_acl_entry(client, acl_table_id, value=attribute_value) acl_attr_list.append(attribute) + #Input port if in_port != None: attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(oid=in_port))) attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT, value=attribute_value) acl_attr_list.append(attribute) + #Output port if out_port != None: attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(oid=out_port))) attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT, value=attribute_value) acl_attr_list.append(attribute) - #Packet action - if action == 1: - #Drop - attribute_value = sai_thrift_attribute_value_t(aclaction=sai_thrift_acl_action_data_t(parameter = sai_thrift_acl_data_t(u32=0))) - attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_PACKET_ACTION, + #L4 Source port + if src_l4_port != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(u16=src_l4_port), + mask = sai_thrift_acl_mask_t(u16=0))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT, value=attribute_value) acl_attr_list.append(attribute) - elif action == 2: - #Ingress mirroring - if ingress_mirror != None: - attribute_value = sai_thrift_attribute_value_t(aclaction=sai_thrift_acl_action_data_t(parameter = sai_thrift_acl_data_t(oid=ingress_mirror))) - attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS, value=attribute_value) - acl_attr_list.append(attribute) - elif egress_mirror != None: - attribute_value = sai_thrift_attribute_value_t(aclaction=sai_thrift_acl_action_data_t(parameter = sai_thrift_acl_data_t(oid=egress_mirror))) - attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS, value=attribute_value) - acl_attr_list.append(attribute) + + #L4 Destination port + if dst_l4_port != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(u16=dst_l4_port), + mask = sai_thrift_acl_mask_t(u16=0))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT, + value=attribute_value) + acl_attr_list.append(attribute) + + if action != None: + attribute_value = sai_thrift_attribute_value_t(aclaction=sai_thrift_acl_action_data_t(parameter = sai_thrift_acl_data_t(u32=action))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION, + value=attribute_value) + acl_attr_list.append(attribute) + + #Ingress mirroring + if ingress_mirror != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(oid=ingress_mirror))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS, value=attribute_value) + acl_attr_list.append(attribute) + + #Egress mirroring + if egress_mirror != None: + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(oid=egress_mirror))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS, value=attribute_value) + acl_attr_list.append(attribute) acl_entry_id = client.sai_thrift_create_acl_entry(acl_attr_list) return acl_entry_id +def sai_thrift_create_acl_table_group(client, + group_stage, + group_bind_point_list, + group_type): + acl_attr_list = [] + + if group_stage != None: + attribute_value = sai_thrift_attribute_value_t(s32=group_stage) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE, + value=attribute_value) + acl_attr_list.append(attribute) + + if group_bind_point_list != None: + acl_group_bind_point_list = sai_thrift_s32_list_t(count=len(group_bind_point_list), s32list=group_bind_point_list) + attribute_value = sai_thrift_attribute_value_t(aclfield=sai_thrift_acl_field_data_t(data = sai_thrift_acl_data_t(bind_point_list=acl_group_bind_point_list))) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST, + value=attribute_value) + acl_attr_list.append(attribute) + + if group_type != None: + attribute_value = sai_thrift_attribute_value_t(s32=group_type) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_ATTR_TYPE, + value=attribute_value) + acl_attr_list.append(attribute) + + acl_table_group_id = client.sai_thrift_create_acl_table_group(acl_attr_list) + return acl_table_group_id + +def sai_thrift_create_acl_table_group_member(client, + acl_table_group_id, + acl_table_id, + group_member_priority): + acl_attr_list = [] + + if acl_table_group_id != None: + attribute_value = sai_thrift_attribute_value_t(oid=acl_table_group_id) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID, + value=attribute_value) + acl_attr_list.append(attribute) + + if acl_table_id != None: + attribute_value = sai_thrift_attribute_value_t(oid=acl_table_id) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID, + value=attribute_value) + acl_attr_list.append(attribute) + + if group_member_priority != None: + attribute_value = sai_thrift_attribute_value_t(u32=group_member_priority) + attribute = sai_thrift_attribute_t(id=SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY, + value=attribute_value) + acl_attr_list.append(attribute) + + acl_table_group_member_id = client.sai_thrift_create_acl_table_group_member(acl_attr_list) + return acl_table_group_member_id + def sai_thrift_create_mirror_session(client, mirror_type, port, vlan, vlan_priority, vlan_tpid, src_mac, dst_mac, addr_family, src_ip, dst_ip, - encap_type, protocol, ttl, tos): + encap_type, protocol, ttl, tos, gre_type): mirror_attr_list = [] #Mirror type - attribute1_value = sai_thrift_attribute_value_t(u8=mirror_type) + attribute1_value = sai_thrift_attribute_value_t(s32=mirror_type) attribute1 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_TYPE, value=attribute1_value) mirror_attr_list.append(attribute1) @@ -549,63 +731,92 @@ def sai_thrift_create_mirror_session(client, mirror_type, port, value=attribute2_value) mirror_attr_list.append(attribute2) - if mirror_type == SAI_MIRROR_TYPE_LOCAL: - attribute4_value = sai_thrift_attribute_value_t(u16=vlan) - attribute4 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_ID, - value=attribute4_value) - mirror_attr_list.append(attribute4) - elif mirror_type == SAI_MIRROR_TYPE_REMOTE: - #vlan tpid - attribute3_value = sai_thrift_attribute_value_t(u16=vlan_tpid) - attribute3 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_TPID, + if mirror_type == SAI_MIRROR_SESSION_TYPE_REMOTE: + #vlan + attribute3_value = sai_thrift_attribute_value_t(u16=vlan) + attribute3 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_ID, value=attribute3_value) mirror_attr_list.append(attribute3) - - #vlan - attribute4_value = sai_thrift_attribute_value_t(u16=vlan) - attribute4 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_ID, - value=attribute4_value) + + #vlan tpid + attribute3_value = sai_thrift_attribute_value_t(u32=vlan_tpid) + attribute3 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_TPID, + value=attribute3_value) mirror_attr_list.append(attribute4) - + #vlan priority - attribute5_value = sai_thrift_attribute_value_t(u16=vlan_priority) - attribute4 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_PRI, + attribute5_value = sai_thrift_attribute_value_t(u8=vlan_priority) + attribute5 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_PRI, value=attribute5_value) mirror_attr_list.append(attribute5) - elif mirror_type == SAI_MIRROR_TYPE_ENHANCED_REMOTE: + elif mirror_type == SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE: #encap type - attribute3_value = sai_thrift_attribute_value_t(u8=encap_type) + attribute3_value = sai_thrift_attribute_value_t(s32=encap_type) attribute3 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_ENCAP_TYPE, value=attribute3_value) mirror_attr_list.append(attribute3) + #ip header version + attribute4_value = sai_thrift_attribute_value_t(u8=addr_family) + attribute4 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION, + value=attribute4_value) + mirror_attr_list.append(attribute4) + #source ip addr = sai_thrift_ip_t(ip4=src_ip) src_ip_addr = sai_thrift_ip_address_t(addr_family=addr_family, addr=addr) - attribute4_value = sai_thrift_attribute_value_t(ipaddr=src_ip_addr) - attribute4 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS, - value=attribute4_value) - mirror_attr_list.append(attribute4) + attribute5_value = sai_thrift_attribute_value_t(ipaddr=src_ip_addr) + attribute5 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS, + value=attribute5_value) + mirror_attr_list.append(attribute5) #dst ip addr = sai_thrift_ip_t(ip4=dst_ip) dst_ip_addr = sai_thrift_ip_address_t(addr_family=addr_family, addr=addr) - attribute5_value = sai_thrift_attribute_value_t(ipaddr=dst_ip_addr) - attribute5 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS, - value=attribute5_value) - mirror_attr_list.append(attribute5) - - #source mac - attribute6_value = sai_thrift_attribute_value_t(mac=src_mac) - attribute6 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS, + attribute6_value = sai_thrift_attribute_value_t(ipaddr=dst_ip_addr) + attribute6 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS, value=attribute6_value) mirror_attr_list.append(attribute6) - #dst mac - attribute7_value = sai_thrift_attribute_value_t(mac=dst_mac) - attribute7 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS, + #source mac + attribute7_value = sai_thrift_attribute_value_t(mac=src_mac) + attribute7 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS, value=attribute7_value) mirror_attr_list.append(attribute7) + + attribute8_value = sai_thrift_attribute_value_t(u32=gre_type) + attribute8 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE,value=attribute8_value) + mirror_attr_list.append(attribute8) + + attribute9_value = sai_thrift_attribute_value_t(u8=protocol) + attribute9 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION,value=attribute9_value) + mirror_attr_list.append(attribute9) + + attribute10_value = sai_thrift_attribute_value_t(u16=ttl) + attribute10 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_TTL,value=attribute10_value) + mirror_attr_list.append(attribute10) + + attribute11_value = sai_thrift_attribute_value_t(u32=vlan_tpid) + attribute11 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_TPID, + value=attribute11_value) + mirror_attr_list.append(attribute11) + + #vlan + attribute12_value = sai_thrift_attribute_value_t(u16=vlan) + attribute12 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_VLAN_ID, + value=attribute12_value) + mirror_attr_list.append(attribute12) + #tos + attribute13_value = sai_thrift_attribute_value_t(u16=tos) + attribute13 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_TOS, + value=attribute13_value) + mirror_attr_list.append(attribute13) + + #dst mac + attribute8_value = sai_thrift_attribute_value_t(mac=dst_mac) + attribute8 = sai_thrift_attribute_t(id=SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS, + value=attribute8_value) + mirror_attr_list.append(attribute8) mirror_id = client.sai_thrift_create_mirror_session(mirror_attr_list) return mirror_id @@ -724,29 +935,37 @@ def sai_thrift_read_port_counters(client,port): queue1+=1 return (counters_results, queue_counters_results) -def sai_thrift_create_vlan_member(client, vlan_id, port_id, tagging_mode): +def sai_thrift_create_vlan(client, vlan_id): + vlan_attr_list = [] + attribute_value = sai_thrift_attribute_value_t(u16=vlan_id) + attribute = sai_thrift_attribute_t(id=SAI_VLAN_ATTR_VLAN_ID, value=attribute_value) + vlan_attr_list.append(attribute) + vlan_oid = client.sai_thrift_create_vlan(vlan_attr_list) + return vlan_oid + +def sai_thrift_create_vlan_member(client, vlan_oid, port_oid, tagging_mode): vlan_member_attr_list = [] - attribute_value = sai_thrift_attribute_value_t(s32=vlan_id) + attribute_value = sai_thrift_attribute_value_t(oid=vlan_oid) attribute = sai_thrift_attribute_t(id=SAI_VLAN_MEMBER_ATTR_VLAN_ID, value=attribute_value) vlan_member_attr_list.append(attribute) - attribute_value = sai_thrift_attribute_value_t(oid=port_id) + attribute_value = sai_thrift_attribute_value_t(oid=port_oid) attribute = sai_thrift_attribute_t(id=SAI_VLAN_MEMBER_ATTR_PORT_ID, value=attribute_value) vlan_member_attr_list.append(attribute) attribute_value = sai_thrift_attribute_value_t(s32=tagging_mode) - attribute = sai_thrift_attribute_t(id=SAI_VLAN_MEMBER_ATTR_TAGGING_MODE, + attribute = sai_thrift_attribute_t(id=SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE, value=attribute_value) vlan_member_attr_list.append(attribute) vlan_member_id = client.sai_thrift_create_vlan_member(vlan_member_attr_list) return vlan_member_id -def sai_thrift_vlan_remove_all_ports(client, vid): +def sai_thrift_vlan_remove_all_ports(client, vlan_oid): vlan_members_list = [] - vlan_attr_list = client.sai_thrift_get_vlan_attribute(vid) + vlan_attr_list = client.sai_thrift_get_vlan_attribute(vlan_oid) attr_list = vlan_attr_list.attr_list for attribute in attr_list: if attribute.id == SAI_VLAN_ATTR_MEMBER_LIST: