diff --git a/doc/IPsec/SAI_IPsec_API_Proposal.md b/doc/IPsec/SAI_IPsec_API_Proposal.md new file mode 100644 index 000000000..c2cd3fa36 --- /dev/null +++ b/doc/IPsec/SAI_IPsec_API_Proposal.md @@ -0,0 +1,261 @@ +SAI IPsec API Proposal +===================== + +Title | SAI IPsec API Proposal +------------|---------------------- +Authors | Arista Networks, Inc. +Status | Draft +Type | Standards track +Created | 03/18/2021 +SAI-Version | ? +------------------------------- + +# Scope # + +This document defines the technical specifications for the API used to support RFC-4303 IPsec ESP tunnel mode and RFC-3948 UDP-encapsulated IPsec ESP tunnel mode in Open Compute Project Switch Abstraction Interface (SAI). This API only supports the IPsec datapath security using GCM-AES ciphersuite. The key exchange protocol is outside the scope of this document and SAI IPsec API. + +# Overview # + +IPsec secures packets between a pair of end-points identified by a pair of IP addresses. The switch becomes such an end-point in case it originates and terminates tunnels with another end-point. So, IPsec in a switch is always associated with tunnel origination and termination.The SAI IPsec API supports 3 such tunneled frame formats described in Fig-1, with the underlay IP header source or destination address identifying this switch. + +![Fig-1](figures/ipsecFig1.png) + +Packet security includes confidentiality, integrity and authenticity protection. The SAI IPsec API provides a software interface for related data-path packet transformation, which includes: +1. Egress transformation + 1. Tunnel origination: This includes: + 1. Switching a packet to a IP tunnel + 1. Adding a tunnel header (IP header and optionally a UDP-ESP header). + 1. Egress packet security: This includes: + 1. Adding ESP header and trailer and and the ICV (Integrity Check Value) + 1. Optionally encrypt the packet. +1. Ingress transformation + 1. Ingress packet security: This includes: + 1. Decrypting the tunnel payload and check the integrity and authenticity + 1. Removing the ESP header and trailer and and the ICV. (In one implementation, the UDP-ESP header is also removed here.) + 1. Tunnel termination: This includes: + 1. Removing the tunnel header + 1. Switching the tunnel payload based on the inner packet + +The tunnel origination and termination functions are performed in the Packet Processor inside the Switch ASIC. The packet security functions are performed by Security Engines that process packets going between the Packet Processor and the external ports of the Network Switch. + +![Fig-2](figures/ipsecFig2.png) + +Since the Packet Processor typically performs tunnel termination based only on packet headers, it cannot make use of the Next Header field in the ESP trailer. To get around this problem, the Packet Processor may make use of a per-SA parsing configuration. Each SA is configured to have decrypted payload start with one of the following 2 types of header: +1. IP header used for IPINIP, where IPv4 and IPv6 are distinguished by first nibble of the header +2. UDP header (used for VXLAN_UDP_ESP) + +For IPsec to be terminated in such a Packet Processor, these 2 types of encrypted payload cannot share the same SA. + +In the SAI model, a Network Switch may be composed of a Switch ASIC and multiple PHY Chips, each of which is a separate sai_switch object. A PHY Chip connects network ports to Switch ASIC ports. Some network ports may not require a PHY Chip and may be directly connected to Switch ASIC ports. Each PHY Chip may support a subset of the remaining Switch ASIC ports. These Switch ASIC ports are connected to network ports through PHY Chip(s). + +![Fig-3](figures/ipsecFig3.png) + +As shown in the diagrams above, the packet security function for a port may be of one of the following types: +1. Not supported +1. Supported by Security Engine embedded in Switch ASIC +1. Supported by Security Engine embedded in PHY Chip + +For each network port, a Security Engine can normally perform either IPsec or MACsec functions, not both. + +An integer object named sa_index carried in the packet metadata header associates a tunnel in the Packet Processor with a SA in the Security Engine. The sa_index value is carried in packet metadata between the Packet Processor and the Security Engine. + +In case of Security Engine(s) embedded in the Switch ASIC (as in Fig-2), the format of this metadata is implementation-specific. In case of Security Engine(s) embedded in a PHY Chip, this is carried in the SA-Tag right after the underlay Ethernet header, as shown in Fig-4. + +![Fig-4](figures/ipsecFig4.png) + +The SA-Tag format is similar to 802.1Q tag and is distinguished by a reserved TPID value that is not used for network traffic. The egress SA-Tag carries the sa_index to the Security Engine. The ingress SA-Tag indicates (by its presence) that the data is from a successfully verified IPsec packet. Both formats are shown in Fig-5. + +![Fig-5](figures/ipsecFig5.png) + +Each Security Engine maintains SA (Security Association) states to secure packets. For egress, the SA is selected by the sa_index coming from the Packet Processor with the packet. Some important SA states are the encryption key, the SPI (Security Parameter Index) and the 64-bit IV (Initialization Vector). For ingress, the SA is selected by the SPI value in the encrypted packet header. The Security Engine only decrypts IPsec packets where the outer IP header and and the SPI match the valid SA. All other packets are passed unmodified to the Packet Processor. For IPsec packets that are not decrypted by the Security Engine, the Packet Processor can be programmed to: +1. Send such packets to software for decryption +1. Drop and count such packets using ACL rules + +The network ports used for IPsec are constrained by the following: +1. Each Security Engine services a subset of network ports. +1. Current hardware does not allow sharing the same egress SA between multiple Security Engines for encryption + +Given one egress SA per tunnel, this leads to the following load-balancing constraints in the encrypting switch. + +Feature | Constraints +----------------------|---------------------- +Underlay ECMP and LAG | Limited to ports of 1 Security Engine for each tunnel. +Overlay ECMP | No constraint for overlay ECMP over multiple tunnels. Each tunnel is limited by the constraints above. +------------------------------------------ + +# Object Relationships # + +IPsec makes use of: +1. saitunnel.h for tunnel definition. This would be used only in teh Switch ASIC. +1. saiipsec.h for securing the packet. This would be used in the sai_switch object that implements the Security Engine, which could either be a Switch ASIC or a Phy Chip. + + +## saitunnel.h changes for IPsec support ## + +sai_tunnel_type_t is extended to include 3 encrypted frame formats, as shown in Fig-1. + + +New attributes are defined for: +1. SAI_TUNNEL_ATTR_SA_INDEX for IPsec egress SA binding +1. SAI_TUNNEL_TERM_TABLE_ENTRY_IPSEC_VERIFIED for checking IPsec verification status in the Packet Processor before terminating IPsec tunnels +1. SAI_TUNNEL_ATTR_SA_PORT_LIST for the list of ports that are programmed with SA for this tunnel + + +## saiipsec.h ## + +This supports the following objects types: +1. sai_ipsec has sai_switch level capabilities and configurations +1. sai_ipsec_port is used for port level IPsec attributes (e.g. packet parsing control, native Vlan Id, etc.) +1. sai_ipsec_sa is used for IPsec Security Associations + + +Each (line-side) sai_port that supports IPsec encryption/decryption, has an associated sai_ipsec_port object. +A sai_port object is created for each: +1. IPsec-capable port of the Switch ASIC, in case of Security Engine(s) embedded in the Switch ASIC +1. IPsec-capable Line-side port of the Phy Chip, in case of Security Engine(s) embedded in the Phy Chip. + + +Each IPsec tunnel has 2 active ipsec_sa, one for ingress and one for egress. For rekeying, a new ipsec_sa replaces the old one. For egress rekeying, the sa_index of the tunnel is changed to switch from the old SA to the new one. For ingress rekeying, after a new SA is created, both the old and new SA are active, selected by SPI in the received packets. After a period, the old SA is removed. + +![Fig-6](figures/ipsecFig6.png) + +# Function call sequences # +The following sequences assume: +1. sai_tunnel, sai_ipsec and sai_ipsec_port objects have already been created. +1. The Security Engine is in the PHY Chip. + +In case of Security Engine(s) embedded in the Switch ASIC, the PHY Chip referneces below should be replaced by Switch ASIC references. + +## Create an egress SA and attach its index to a tunnel ## +~~~cpp +// Create egress ipsec_sa for a PHY chip +sai_object_id_t ingr_ipsec_sa_id11 = 0ULL; +ipsec_attr_list[0].id = SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION; +ipsec_attr_list[0].value.s32 = SAI_IPSEC_DIRECTION_EGRESS; + +ipsec_attr_list[1].id = SAI_IPSEC_SA_ATTR_IPSEC_ID; +ipsec_attr_list[1].value.oid = ipsec_id1; + +ipsec_attr_list[2].id = SAI_IPSEC_SA_ATTR_IPSEC_SPI; +ipsec_attr_list[2].value.u32 = egr_ipsec_spi1; + +ipsec_attr_list[3].id = SAI_IPSEC_SA_ATTR_IPSEC_ENCRYPTION_KEY; +ipsec_attr_list[3].value.macsecsak = egr_ipsec_encryption_key1; + +ipsec_attr_list[4].id = SAI_IPSEC_SA_ATTR_IPSEC_SALT; +ipsec_attr_list[4].value.u32 = egr_ipsec_salt1; + +ipsec_attr_list[5].id = SAI_IPSEC_SA_ATTR_IPSEC_AUTH_KEY; +ipsec_attr_list[5].value.macsecauthkey = egr_ipsec_auth_key1; + +ipsec_attr_list[6].id = SAI_IPSEC_SA_ATTR_IPSEC_PORT_LIST; +ipsec_attr_list[6].value.objlist = egr_ipsec_port_list1; + +saistatus = sai_ipsec_api->create_ipsec_sa(&egr_ipsec_sa_id11, 7, + ipsec_attr_list); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +// Get sa_index from PHY Chip +ipsec_attr_list[0].id = SAI_IPSEC_SA_ATTR_SA_INDEX; +saistatus = sai_ipsec_api->get_ipsec_sa_attribute(&egr_ipsec_sa_id11, +1, &ipsec_attr_list); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} +sa_index = ipsec_attr_list[0].value; + +// Assign sa_index to corresponding tunnel in Switch ASIC +tunnel_attr.id = SAI_TUNNEL_ATTR_SA_INDEX; +tunnel_attr.value = sa_index; + +saistatus = sai_tunnel_api->set_tunnel_sa_attribute(&tunnel_id11, +&tunnel_attr); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} +~~~ + +## Create an ingress SA ## +~~~cpp +// Create ingress ipsec_sa in PHY Chip +sai_object_id_t ingr_ipsec_sa_id11 = 0ULL; +ipsec_attr_list[0].id = SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION; +ipsec_attr_list[0].value.s32 = SAI_IPSEC_DIRECTION_INGRESS; // different from egress + +ipsec_attr_list[1].id = SAI_IPSEC_SA_ATTR_IPSEC_ID; +ipsec_attr_list[1].value.oid = ingr_ipsec_id1; + +ipsec_attr_list[2].id = SAI_IPSEC_SA_ATTR_IPSEC_SPI; +ipsec_attr_list[2].value.u32 = ingr_ipsec_spi1; + +ipsec_attr_list[3].id = SAI_IPSEC_SA_ATTR_IPSEC_ENCRYPTION_KEY; +ipsec_attr_list[3].value.macsecsak = ingr_ipsec_encryption_key1; + +ipsec_attr_list[4].id = SAI_IPSEC_SA_ATTR_IPSEC_SALT; +ipsec_attr_list[4].value.u32 = ingr_ipsec_salt1; + +ipsec_attr_list[5].id = SAI_IPSEC_SA_ATTR_IPSEC_AUTH_KEY; +ipsec_attr_list[5].value.macsecauthkey = ingr_ipsec_auth_key1; + +ipsec_attr_list[6].id = SAI_IPSEC_SA_ATTR_TERM_DST_IP; // only for ingress SA +ipsec_attr_list[6].value.ipaddr = ipsec_term_dst_ip1; + +ipsec_attr_list[7].id = SAI_IPSEC_SA_ATTR_IPSEC_PORT_LIST; +ipsec_attr_list[7].value.objlist = ingr_ipsec_port_list1; + +saistatus = sai_ipsec_api->create_ipsec_sa(&ingr_ipsec_sa_id11, 8, + ipsec_attr_list); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} +~~~ + +## Remove an SA after collecting its last statistics ## + +The steps are identical for ingress and egress. The following example is for egress. +~~~cpp +// Collect last statistics for SA from PHY Chip +saistatus = sai_ipsec_api->get_ipsec_sa_stats_ext(&egr_ipsec_sa_id11, +SA_STATS_COUNT, &ipsec_counter_list, SAI_IPSEC_ATTR_STATS_MODE); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +UPDATE_EGRESS_SA_STATISTICS(ipsec_counter_list); + +// Remove old SA from PHY Chip +saistatus = sai_ipsec_api->remove_ipsec_sa(&egr_ipsec_sa_id11); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} +~~~ + +## Replace egress SA for a tunnel ## + +Create a new egress SA and attach its index to a tunnel as described earlier. The tunnel starts using the new SA and stops using the old SA. + + +Then find the old SA for that tunnel (from NOS database) and remove it after collecting its last statistics, as described earlier. + +## Replace an ingress SA ## + +While rekeying, multiple ingress SAs may be active at the same time. So replacing an SA is includes 2 separate events coordinated with the encryptor by the key exchange protocol: +1. First create a new ingress SA, as described earlier. +1. Later remove the old SA after collecting its last statistics, as described earlier. + +# Notes # + +## Unsupported Features ## + + +The SAI IPsec API does not support any interrupt or event notification to NOS. Possible uses of notification could include: +1. Egress packet number crossing threshold. The last used egress packet number can be polled or indirectly inferred from periodically collected egress packet statistics. +1. A new packet SA observed at ingress. This can be polled to determine when to remove the old SA. + +## Hidden Complexities ## +Resources used to implement an IPsec SA resources are shared with MACsec. These include macsec_flow, macsec_sc and macsec_sa resources, and TCAM resources that are used to identify tunnel header and SPI. + + +Multiple ports in different Security Engines have to use the same sa_index for the same tunnel. Unless all Security Engines are programmed identically for IPsec, this can complicate Security Engine resource management. diff --git a/doc/IPsec/figures/ipsecFig1.png b/doc/IPsec/figures/ipsecFig1.png new file mode 100644 index 000000000..7b518c84e Binary files /dev/null and b/doc/IPsec/figures/ipsecFig1.png differ diff --git a/doc/IPsec/figures/ipsecFig2.png b/doc/IPsec/figures/ipsecFig2.png new file mode 100644 index 000000000..1f264ce98 Binary files /dev/null and b/doc/IPsec/figures/ipsecFig2.png differ diff --git a/doc/IPsec/figures/ipsecFig3.png b/doc/IPsec/figures/ipsecFig3.png new file mode 100644 index 000000000..021c8cd60 Binary files /dev/null and b/doc/IPsec/figures/ipsecFig3.png differ diff --git a/doc/IPsec/figures/ipsecFig4.png b/doc/IPsec/figures/ipsecFig4.png new file mode 100644 index 000000000..243f1d10b Binary files /dev/null and b/doc/IPsec/figures/ipsecFig4.png differ diff --git a/doc/IPsec/figures/ipsecFig5.png b/doc/IPsec/figures/ipsecFig5.png new file mode 100644 index 000000000..a51063927 Binary files /dev/null and b/doc/IPsec/figures/ipsecFig5.png differ diff --git a/doc/IPsec/figures/ipsecFig6.png b/doc/IPsec/figures/ipsecFig6.png new file mode 100644 index 000000000..026c01186 Binary files /dev/null and b/doc/IPsec/figures/ipsecFig6.png differ diff --git a/inc/sai.h b/inc/sai.h index 1a127540b..082a8594e 100644 --- a/inc/sai.h +++ b/inc/sai.h @@ -34,6 +34,7 @@ #include "saihostif.h" #include "saiipmcgroup.h" #include "saiipmc.h" +#include "saiipsec.h" #include "sail2mcgroup.h" #include "sail2mc.h" #include "sailag.h" @@ -135,7 +136,8 @@ typedef enum _sai_api_t SAI_API_MACSEC = 43, /**< sai_macsec_api_t */ SAI_API_SYSTEM_PORT = 44, /**< sai_system_port_api_t */ SAI_API_MY_MAC = 45, /**< sai_my_mac_api_t */ - SAI_API_MAX = 46, /**< total number of APIs */ + SAI_API_IPSEC = 46, /**< sai_ipsec_api_t */ + SAI_API_MAX, /**< total number of APIs */ } sai_api_t; /** diff --git a/inc/saiipsec.h b/inc/saiipsec.h new file mode 100644 index 000000000..985899f8d --- /dev/null +++ b/inc/saiipsec.h @@ -0,0 +1,1020 @@ +/** + * 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, MERCHANTABILITY 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., Marvell International Ltd. + * + * @file saiipsec.h + * + * @brief This module defines SAI IPsec interface + */ + +#if !defined (__SAIIPSEC_H_) +#define __SAIIPSEC_H_ + +#include + +/** + * @defgroup SAIIPSEC SAI - IPsec specific API definitions + * + * @{ + */ + +/** + * @brief IPsec direction types + * For PHY ASIC Egress is system to line direction and ingress is the opposite. + */ +typedef enum _sai_ipsec_direction_t +{ + SAI_IPSEC_DIRECTION_EGRESS, + SAI_IPSEC_DIRECTION_INGRESS, +} sai_ipsec_direction_t; + +/** + * @brief IPsec cipher suite types + */ +typedef enum _sai_ipsec_cipher_t +{ + SAI_IPSEC_CIPHER_AES128_GCM16, + SAI_IPSEC_CIPHER_AES256_GCM16, + SAI_IPSEC_CIPHER_AES128_GMAC, + SAI_IPSEC_CIPHER_AES256_GMAC, +} sai_ipsec_cipher_t; + +/** + * @brief IPsec SA sequence number status type + */ +typedef enum _sai_ipsec_sa_octet_count_status_t +{ + /** SA byte count below lower of 2 watermarks */ + SAI_IPSEC_SA_OCTET_COUNT_STATUS_BELOW_LOW_WATERMARK, + + /** SA byte count below higher of 2 watermarks */ + SAI_IPSEC_SA_OCTET_COUNT_STATUS_BELOW_HIGH_WATERMARK, + + /** SA byte count above higher of 2 watermarks */ + SAI_IPSEC_SA_OCTET_COUNT_STATUS_ABOVE_HIGH_WATERMARK, + +} sai_ipsec_sa_octet_count_status_t; + +/** + * @brief IPsec SA status for notification + */ +typedef struct _sai_ipsec_sa_status_notification_t +{ + /** + * @brief IPsec SA object id + * + * @objects SAI_OBJECT_TYPE_IPSEC_SA + */ + sai_object_id_t ipsec_sa_id; + + /** + * @brief IPsec SA byte count status + */ + sai_ipsec_sa_octet_count_status_t ipsec_sa_octet_count_status; + + /** + * @brief IPsec egress SA sequence number at max limit + */ + bool ipsec_egress_sn_at_max_limit; + +} sai_ipsec_sa_status_notification_t; + +/** + * @brief Attribute Id for sai_ipsec + */ +typedef enum _sai_ipsec_attr_t +{ + /** + * @brief Start of IPsec attributes + */ + SAI_IPSEC_ATTR_START, + + /** + * @brief Security Engine supports matching source IP address for tunnel termination. + * + * If false, source IP address cannot be checked before decryption. + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_TERM_REMOTE_IP_MATCH_SUPPORTED = SAI_IPSEC_ATTR_START, + + /** + * @brief SAI_SWITCH_SWITCHING_MODE_CUT_THROUGH supported + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_SWITCHING_MODE_CUT_THROUGH_SUPPORTED, + + /** + * @brief SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD supported + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_SWITCHING_MODE_STORE_AND_FORWARD_SUPPORTED, + + /** + * @brief SAI_STATS_MODE_READ supported + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_STATS_MODE_READ_SUPPORTED, + + /** + * @brief SAI_STATS_MODE_READ_CLEAR supported + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_STATS_MODE_READ_CLEAR_SUPPORTED, + + /** + * @brief Indicates if 32-bit Sequence Number (SN) is supported. + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_SN_32BIT_SUPPORTED, + + /** + * @brief Indicates if 64-bit Extended Sequence Number (ESN) is supported. + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_ESN_64BIT_SUPPORTED, + + /** + * @brief List of supported cipher suites + * + * @type sai_s32_list_t sai_ipsec_cipher_t + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_SUPPORTED_CIPHER_LIST, + + /** + * @brief IPsec MTU capability on system side (not including IPsec overhead). + * + * @type sai_uint16_t + * @flags READ_ONLY + * @isvlan false + */ + SAI_IPSEC_ATTR_SYSTEM_SIDE_MTU, + + /** + * @brief Warm boot is supported for all saiipsec objects. + * + * @type bool + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_WARM_BOOT_SUPPORTED, + + /** + * @brief If false, disables creation of saiipsec objects during warm-boot. + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_IPSEC_ATTR_WARM_BOOT_ENABLE, + + /** + * @brief If true, SA Index is assigned by NOS. + * If false, SA Index is assigned by IPsec SAI driver. + * + * @type bool + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_ATTR_EXTERNAL_SA_INDEX_ENABLE, + + /** + * @brief TPID value used to identify C-tag. + * + * @type sai_uint16_t + * @flags CREATE_AND_SET + * @isvlan false + * @default 0x8100 + */ + SAI_IPSEC_ATTR_CTAG_TPID, + + /** + * @brief TPID value used to identify S-tag. + * + * @type sai_uint16_t + * @flags CREATE_AND_SET + * @isvlan false + * @default 0x88A8 + */ + SAI_IPSEC_ATTR_STAG_TPID, + + /** + * @brief Maximum number of VLAN tags to parse. + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_IPSEC_ATTR_MAX_VLAN_TAGS_PARSED, + + /** + * @brief High watermark for byte count. + * + * The sai_ipsec_sa_status changes when a new packet is processed and the per + * SA octet count crosses this watermark. This watermark is used even if only + * 1 watermark is needed. + * + * @type sai_uint64_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_IPSEC_ATTR_OCTET_COUNT_HIGH_WATERMARK, + + /** + * @brief Low watermark for byte count + * + * The sai_ipsec_sa_status changes when a new packet is processed and the per + * SA octet count crosses this watermark. This watermark is used only if 2 + * watermarks are needed. + * + * @type sai_uint64_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_IPSEC_ATTR_OCTET_COUNT_LOW_WATERMARK, + + /** + * @brief Global setting of read-clear or read-only for statistics read. + * The mode parameter for get_ipsec__stats_ext should match this. + * + * @type sai_stats_mode_t + * @flags CREATE_AND_SET + * @default SAI_STATS_MODE_READ_AND_CLEAR + */ + SAI_IPSEC_ATTR_STATS_MODE, + + /** + * @brief Available IPsec Security Associations. + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_IPSEC_ATTR_AVAILABLE_IPSEC_SA, + + /** + * @brief IPsec SA list + * + * @type sai_object_list_t + * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_IPSEC_SA + */ + SAI_IPSEC_ATTR_SA_LIST, + + /** + * @brief End of IPsec attributes + */ + SAI_IPSEC_ATTR_END, + + /** + * @brief Custom range base value + */ + SAI_IPSEC_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** + * @brief End of custom range base + */ + SAI_IPSEC_ATTR_CUSTOM_RANGE_END +} sai_ipsec_attr_t; + +/** + * @brief Attribute Id for sai_ipsec_port + */ +typedef enum _sai_ipsec_port_attr_t +{ + /** + * @brief Start of IPsec Port attributes + */ + SAI_IPSEC_PORT_ATTR_START, + + /** + * @brief Associated port id + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_PORT + */ + SAI_IPSEC_PORT_ATTR_PORT_ID = SAI_IPSEC_PORT_ATTR_START, + + /** + * @brief Enable vlan tag parsing for C-tag TPID + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_IPSEC_PORT_ATTR_CTAG_ENABLE, + + /** + * @brief Enable vlan tag parsing for S-tag TPID + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_IPSEC_PORT_ATTR_STAG_ENABLE, + + /** + * @brief Port native Vlan Id used for Security Engine SA termination. + * + * @type sai_uint16_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan true + */ + SAI_IPSEC_PORT_ATTR_NATIVE_VLAN_ID, + + /** + * @brief Enable VRF identification from ingress parsed packet Vlan. + * + * False means only port native Vlan can be used for tunnel termination VRF. + * True means packet Vlan tag is also used. + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_IPSEC_PORT_ATTR_VRF_FROM_PACKET_VLAN_ENABLE, + + /** + * @brief Switching mode for port. If configured as cut-through, the IPG + * for Tx MAC in the switch ASIC has to be increased to accommodate the + * IPsec packet size expansion. + * + * @type sai_switch_switching_mode_t + * @flags CREATE_AND_SET + * @default SAI_SWITCH_SWITCHING_MODE_CUT_THROUGH + */ + SAI_IPSEC_PORT_ATTR_SWITCH_SWITCHING_MODE, + + /** + * @brief End of IPsec Port attributes + */ + SAI_IPSEC_PORT_ATTR_END, + + /** + * @brief Custom range base value + */ + SAI_IPSEC_PORT_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** + * @brief End of custom range base + */ + SAI_IPSEC_PORT_ATTR_CUSTOM_RANGE_END +} sai_ipsec_port_attr_t; + +/** + * @brief IPsec flow counter IDs in sai_get_ipsec_sa_stats() call. + */ +typedef enum _sai_ipsec_port_stat_t +{ + /** + * @brief Packets dropped after receive MAC and before IPsec SA processing. + * This could be due to malformed header, buffer overrun, etc + */ + SAI_IPSEC_PORT_STAT_TX_ERROR_PKTS, + + /** + * @brief Packets mapped to an SA for IPsec processing. + */ + SAI_IPSEC_PORT_STAT_TX_IPSEC_PKTS, + + /** + * @brief Non-IPsec packets that pass through this port. + */ + SAI_IPSEC_PORT_STAT_TX_NON_IPSEC_PKTS, + + /** + * @brief Packets dropped after receive MAC and before IPsec SA processing. + * This could be due to malformed header, buffer overrun, etc + */ + SAI_IPSEC_PORT_STAT_RX_ERROR_PKTS, + + /** + * @brief Packets mapped to an SA for IPsec processing. + */ + SAI_IPSEC_PORT_STAT_RX_IPSEC_PKTS, + + /** + * @brief Non-IPsec packets that pass through this port. + */ + SAI_IPSEC_PORT_STAT_RX_NON_IPSEC_PKTS, +} sai_ipsec_port_stat_t; + +/** + * @brief Attribute Id for sai_ipsec_sa + */ +typedef enum _sai_ipsec_sa_attr_t +{ + /** + * @brief Start of IPsec Security Association attributes + */ + SAI_IPSEC_SA_ATTR_START, + + /** + * @brief IPsec direction + * + * @type sai_ipsec_direction_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION = SAI_IPSEC_SA_ATTR_START, + + /** + * @brief IPsec object id + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @objects SAI_OBJECT_TYPE_IPSEC + */ + SAI_IPSEC_SA_ATTR_IPSEC_ID, + + /** + * @brief SA byte count status. + * + * @type sai_ipsec_sa_octet_count_status_t + * @flags READ_ONLY + */ + SAI_IPSEC_SA_ATTR_OCTET_COUNT_STATUS, + + /** + * @brief Externally assigned SA Index value for this Security Association. + * Used only when SAI_IPSEC_ATTR_EXTERNAL_SA_INDEX_ENABLE == true. + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_IPSEC_SA_ATTR_EXTERNAL_SA_INDEX, + + /** + * @brief SA Index value for this Security Association. + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_IPSEC_SA_ATTR_SA_INDEX, + + /** + * @brief List of IPsec ports for this SA. + * + * @type sai_object_list_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_IPSEC_PORT + * @default empty + */ + SAI_IPSEC_SA_ATTR_IPSEC_PORT_LIST, + + /** + * @brief SPI value for this Security Association, carried in ESP header. + * + * @type sai_uint32_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_SA_ATTR_IPSEC_SPI, + + /** + * @brief Enable 64-bit ESN (vs 32-bit SN) for this Security Association + * + * @type bool + * @flags CREATE_ONLY + * @default true + */ + SAI_IPSEC_SA_ATTR_IPSEC_ESN_ENABLE, + + /** + * @brief Cipher suite for this SA. + * + * @type sai_ipsec_cipher_t + * @flags CREATE_ONLY + * @default SAI_IPSEC_CIPHER_AES256_GCM16 + */ + SAI_IPSEC_SA_ATTR_IPSEC_CIPHER, + + /** + * @brief IPsec Traffic Encryption Key used for encryption/decryption. + * Network Byte order. AES128 uses only Bytes 16..31. + * + * @type sai_encrypt_key_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_SA_ATTR_ENCRYPT_KEY, + + /** + * @brief IPsec Salt portion of IV + * Network Byte order. + * + * @type sai_uint32_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_SA_ATTR_SALT, + + /** + * @brief IPsec Authentication Key + * Network Byte order. + * + * @type sai_auth_key_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_IPSEC_SA_ATTR_AUTH_KEY, + + /** + * @brief Replay protection enable for this Security Association. + * + * @type bool + * @flags CREATE_AND_SET + * @default false + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_IPSEC_REPLAY_PROTECTION_ENABLE, + + /** + * @brief Replay protection window for this Security Association. + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_IPSEC_REPLAY_PROTECTION_WINDOW, + + /** + * @brief SA local IP address for tunnel termination. + * + * @type sai_ip_address_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_TERM_DST_IP, + + /** + * @brief Match Vlan Id for tunnel termination. + * + * @type bool + * @flags CREATE_ONLY + * @default false + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_TERM_VLAN_ID_ENABLE, + + /** + * @brief Vlan Id for tunnel termination. + * + * @type sai_uint16_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isvlan true + * @condition SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS and SAI_IPSEC_SA_ATTR_TERM_VLAN_ID_ENABLE == true + */ + SAI_IPSEC_SA_ATTR_TERM_VLAN_ID, + + /** + * @brief Match remote IP address for tunnel termination. + * + * @type bool + * @flags CREATE_ONLY + * @default false + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_TERM_SRC_IP_ENABLE, + + /** + * @brief Remote IP address for tunnel termination. + * + * @type sai_ip_address_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @condition SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS and SAI_IPSEC_SA_ATTR_TERM_SRC_IP_ENABLE == true + */ + SAI_IPSEC_SA_ATTR_TERM_SRC_IP, + + /** + * @brief IPsec egress sequence number (SN). One less than the next SN. + * + * @type sai_uint64_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_EGRESS + */ + SAI_IPSEC_SA_ATTR_EGRESS_ESN, + + /** + * @brief Minimum value of ingress IPsec sequence number (SN). + * Can be Updated by value from IPsec peer for gross level delay prevention. + * + * @type sai_uint64_t + * @flags CREATE_AND_SET + * @default 1 + * @validonly SAI_IPSEC_SA_ATTR_IPSEC_DIRECTION == SAI_IPSEC_DIRECTION_INGRESS + */ + SAI_IPSEC_SA_ATTR_MINIMUM_INGRESS_ESN, + + /** + * @brief End of IPsec Security Association attributes + */ + SAI_IPSEC_SA_ATTR_END, + + /** + * @brief Custom range base value + */ + SAI_IPSEC_SA_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** + * @brief End of custom range base + */ + SAI_IPSEC_SA_ATTR_CUSTOM_RANGE_END +} sai_ipsec_sa_attr_t; + +/** + * @brief IPsec flow counter IDs in sai_get_ipsec_sa_stats() call. + */ +typedef enum _sai_ipsec_sa_stat_t +{ + /** + * @brief Total octets in all Ethernet frames processed by this SA. + */ + SAI_IPSEC_SA_STAT_PROTECTED_OCTETS, + + /** + * @brief Count of Ethernet frames processed by this SA. This should + * normally be the sum of all the good and error packets for this SA. + */ + SAI_IPSEC_SA_STAT_PROTECTED_PKTS, + + /** + * @brief Count of validated error-free received (ingress) packets + * for this SA. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_GOOD_PKTS, + + /** + * @brief Count of packets with bad header for this SA. This could be due + * the packet header being different from the format expected for this SA. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_BAD_HEADER_PKTS_IN, + + /** + * @brief Count of replayed packets. This also includes late packets if + * the hardware does not provide a separate counter for late packets. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_REPLAYED_PKTS_IN, + + /** + * @brief Count of packets outside the replay window. Always 0 if the + * hardware does not provide a separate counter for late packets. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_LATE_PKTS_IN, + + /** + * @brief Count of packets with bad trailer. This could be due to + * insufficient or invalid padding, etc. For cut-through switching, this + * drop would normally be implemented as CRC corruption. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_BAD_TRAILER_PKTS_IN, + + /** + * @brief Count of packets with authentication and integrity failure + * For cut-through switching, this drop would normally be implemented as + * CRC corruption. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_AUTH_FAIL_PKTS_IN, + + /** + * @brief Count of dummy packets dropped by IPsec logic. These are packets + * with 59 as the next header field value in IPsec trailer. For + * cut-through switching, this drop would normally be implemented as CRC + * corruption. + * Valid only for ingress, always returns 0 for egress. + */ + SAI_IPSEC_SA_STAT_DUMMY_DROPPED_PKTS_IN, + + /** + * @brief Count of other packets dropped by IPsec logic. This could be due + * to not programmed or incorrectly programmed SA, MTU violation, etc. + */ + SAI_IPSEC_SA_STAT_OTHER_DROPPED_PKTS, +} sai_ipsec_sa_stat_t; + +/** + * @brief Create a IPsec object + * + * @param[out] ipsec_id The IPsec object id associated with this switch/PHY + * @param[in] switch_id The switch/PHY Object 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_ipsec_fn)( + _Out_ sai_object_id_t *ipsec_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Delete the IPsec object + * + * @param[in] ipsec_id The IPsec object id associated with this switch/PHY + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_ipsec_fn)( + _In_ sai_object_id_t ipsec_id); + +/** + * @brief Set IPsec attribute + * + * @param[in] ipsec_id The IPsec object id associated with this switch/PHY + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_ipsec_attribute_fn)( + _In_ sai_object_id_t ipsec_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get IPsec attribute + * + * @param[in] ipsec_id The IPsec object id associated with this switch/PHY + * @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_ipsec_attribute_fn)( + _In_ sai_object_id_t ipsec_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +/** + * @brief Create a IPsec port + * + * @param[out] ipsec_port_id The IPsec port id + * @param[in] switch_id The switch/PHY Object 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_ipsec_port_fn)( + _Out_ sai_object_id_t *ipsec_port_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Delete a IPsec port + * + * @param[in] ipsec_port_id The IPsec port id + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_ipsec_port_fn)( + _In_ sai_object_id_t ipsec_port_id); + +/** + * @brief Set IPsec port attribute + * + * @param[in] ipsec_port_id The IPsec port id + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_ipsec_port_attribute_fn)( + _In_ sai_object_id_t ipsec_port_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get IPsec port attribute + * + * @param[in] ipsec_port_id IPsec port 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_ipsec_port_attribute_fn)( + _In_ sai_object_id_t ipsec_port_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +/** + * @brief Get IPsec port counters + * + * @param[in] ipsec_port_id IPsec port id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * @param[out] counters Array of resulting counter values. + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ipsec_port_stats_fn)( + _In_ sai_object_id_t ipsec_port_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _Out_ uint64_t *counters); + +/** + * @brief Get IPsec port counters extended + * + * @param[in] ipsec_port_id IPsec port id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * @param[in] mode Should match SAI_IPSEC_ATTR_STATS_MODE + * @param[out] counters Array of resulting counter values. + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ipsec_port_stats_ext_fn)( + _In_ sai_object_id_t ipsec_port_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _In_ sai_stats_mode_t mode, + _Out_ uint64_t *counters); + +/** + * @brief Clear IPsec port counters + * + * @param[in] ipsec_port_id IPsec port id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_clear_ipsec_port_stats_fn)( + _In_ sai_object_id_t ipsec_port_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids); + +/** + * @brief Create a IPsec Security Association + * + * @param[out] ipsec_sa_id The IPsec Security Association id + * @param[in] switch_id The switch/PHY Object 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_ipsec_sa_fn)( + _Out_ sai_object_id_t *ipsec_sa_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Delete a IPsec Security Association + * + * @param[in] ipsec_sa_id The IPsec Security Association id + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_ipsec_sa_fn)( + _In_ sai_object_id_t ipsec_sa_id); + +/** + * @brief Set IPsec Security Association attribute + * + * @param[in] ipsec_sa_id The IPsec Security Association id + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_ipsec_sa_attribute_fn)( + _In_ sai_object_id_t ipsec_sa_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get IPsec Security Association attribute + * + * @param[in] ipsec_sa_id IPsec Security Association 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_ipsec_sa_attribute_fn)( + _In_ sai_object_id_t ipsec_sa_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +/** + * @brief Get IPsec Security Association counters + * + * @param[in] ipsec_sa_id IPsec Security Association id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * @param[out] counters Array of resulting counter values. + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ipsec_sa_stats_fn)( + _In_ sai_object_id_t ipsec_sa_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _Out_ uint64_t *counters); + +/** + * @brief Get IPsec Security Association counters extended + * + * @param[in] ipsec_sa_id IPsec Security Association id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * @param[in] mode Should match SAI_IPSEC_ATTR_STATS_MODE + * @param[out] counters Array of resulting counter values. + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ipsec_sa_stats_ext_fn)( + _In_ sai_object_id_t ipsec_sa_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _In_ sai_stats_mode_t mode, + _Out_ uint64_t *counters); + +/** + * @brief Clear IPsec Security Association counters + * + * @param[in] ipsec_sa_id IPsec Security Association id + * @param[in] number_of_counters Number of counters in the array + * @param[in] counter_ids Specifies the array of counter ids + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_clear_ipsec_sa_stats_fn)( + _In_ sai_object_id_t ipsec_sa_id, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids); + +/** + * @brief IPsec SA status change notification + * + * Passed as a parameter into sai_initialize_switch() + * + * @count data[count] + * + * @param[in] count Number of notifications + * @param[in] data Array of notifications + */ +typedef void (*sai_ipsec_sa_status_change_notification_fn)( + _In_ uint32_t count, + _In_ const sai_ipsec_sa_status_notification_t *data); + +/** + * @brief IPsec methods table retrieved with sai_api_query() + */ +typedef struct _sai_ipsec_api_t +{ + sai_create_ipsec_fn create_ipsec; + sai_remove_ipsec_fn remove_ipsec; + sai_set_ipsec_attribute_fn set_ipsec_attribute; + sai_get_ipsec_attribute_fn get_ipsec_attribute; + sai_create_ipsec_port_fn create_ipsec_port; + sai_remove_ipsec_port_fn remove_ipsec_port; + sai_set_ipsec_port_attribute_fn set_ipsec_port_attribute; + sai_get_ipsec_port_attribute_fn get_ipsec_port_attribute; + sai_get_ipsec_port_stats_fn get_ipsec_port_stats; + sai_get_ipsec_port_stats_ext_fn get_ipsec_port_stats_ext; + sai_clear_ipsec_port_stats_fn clear_ipsec_port_stats; + sai_create_ipsec_sa_fn create_ipsec_sa; + sai_remove_ipsec_sa_fn remove_ipsec_sa; + sai_set_ipsec_sa_attribute_fn set_ipsec_sa_attribute; + sai_get_ipsec_sa_attribute_fn get_ipsec_sa_attribute; + sai_get_ipsec_sa_stats_fn get_ipsec_sa_stats; + sai_get_ipsec_sa_stats_ext_fn get_ipsec_sa_stats_ext; + sai_clear_ipsec_sa_stats_fn clear_ipsec_sa_stats; +} sai_ipsec_api_t; + +/** + * @} + */ +#endif /** __SAIIPSEC_H_ */ diff --git a/inc/saiport.h b/inc/saiport.h index cd0ee7331..e54acc231 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -2032,6 +2032,15 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP, + /** + * @brief Associated IPsec port + * + * @type sai_object_id_t + * @flags READ_ONLY + * @objects SAI_OBJECT_TYPE_IPSEC_PORT + */ + SAI_PORT_ATTR_IPSEC_PORT, + /** * @brief End of attributes */ diff --git a/inc/saiswitch.h b/inc/saiswitch.h index 7d8498519..2d27a6984 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -342,6 +342,12 @@ typedef enum _sai_tunnel_type_t SAI_TUNNEL_TYPE_NVGRE, + SAI_TUNNEL_TYPE_IPINIP_ESP, + + SAI_TUNNEL_TYPE_IPINIP_UDP_ESP, + + SAI_TUNNEL_TYPE_VXLAN_UDP_ESP, + } sai_tunnel_type_t; /** @@ -2652,6 +2658,43 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP, + /** + * @brief IPsec object for this switch. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_IPSEC + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_SWITCH_ATTR_IPSEC_OBJECT_ID, + + /** + * @brief TPID in IPsec SA-Tag. This is used only between a Switch ASIC + * and IPsec-enabled PHY chips and not packets on external network. + * + * @type sai_uint16_t + * @flags CREATE_AND_SET + * @isvlan false + * @default 0xFFFE + */ + SAI_SWITCH_ATTR_IPSEC_SA_TAG_TPID, + + /** + * @brief IPsec SA status change notification callback function. + * + * In case driver does not support this attribute, The Host adapter should poll + * IPsec SA status by SAI_IPSEC_SA_ATTR_OCTET_COUNT_STATUS and + * SAI_IPSEC_SA_ATTR_EGRESS_ESN. + * + * Use sai_ipsec_sa_status_change_notification_fn as notification function. + * + * @type sai_pointer_t sai_ipsec_sa_status_change_notification_fn + * @flags CREATE_AND_SET + * @default NULL + */ + SAI_SWITCH_ATTR_IPSEC_SA_STATUS_CHANGE_NOTIFY, + /** * @brief End of attributes */ diff --git a/inc/saitunnel.h b/inc/saitunnel.h index c0c91aa54..9339ca77e 100644 --- a/inc/saitunnel.h +++ b/inc/saitunnel.h @@ -444,7 +444,7 @@ typedef enum _sai_tunnel_attr_t * @type sai_object_id_t * @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 or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_VXLAN or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_SRV6 or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_NVGRE + * @condition SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_GRE or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_VXLAN or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_SRV6 or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_NVGRE or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_ESP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_UDP_ESP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_VXLAN_UDP_ESP */ SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE, @@ -456,7 +456,7 @@ typedef enum _sai_tunnel_attr_t * @type sai_object_id_t * @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 + * @condition SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_GRE or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_ESP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_UDP_ESP */ SAI_TUNNEL_ATTR_OVERLAY_INTERFACE, @@ -658,6 +658,34 @@ typedef enum _sai_tunnel_attr_t */ SAI_TUNNEL_ATTR_VXLAN_UDP_SPORT_MASK, + /** + * @brief IPsec encryption SA index + * + * Index to bind an egress IPsec SA to a tunnel. + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_ESP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_IPINIP_UDP_ESP or SAI_TUNNEL_ATTR_TYPE == SAI_TUNNEL_TYPE_VXLAN_UDP_ESP + */ + SAI_TUNNEL_ATTR_SA_INDEX, + + /** + * @brief List of ports that are programmed with SAs for this IPsec tunnel. + * Useful only when IPsec is implemented in a PHY Chip (different sai_switch + * object). + * + * For IPsec hardware in the Switch ASIC, the per-tunnel port list can be + * derived from the union of SAI_IPSEC_SA_ATTR_IPSEC_PORT_LIST for all + * sai_ipsec_sa objects for that tunnel. + * + * @type sai_object_list_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_PORT + * @default empty + */ + SAI_TUNNEL_ATTR_IPSEC_SA_PORT_LIST, + /** * @brief End of attributes */ @@ -902,6 +930,17 @@ typedef enum _sai_tunnel_term_table_entry_attr_t */ SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_IP_ADDR_FAMILY, + /** + * @brief IPsec packet verified by hardware Security Engine. Valid only for + * tunnel type SAI_TUNNEL_TYPE_IPINIP_ESP, SAI_TUNNEL_TYPE_IPINIP_UDP_ESP + * or SAI_TUNNEL_TYPE_VXLAN_UDP_ESP + * + * @type bool + * @flags CREATE_AND_SET + * @default true + */ + SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_IPSEC_VERIFIED, + /** * @brief End of attributes */ diff --git a/inc/saitypes.h b/inc/saitypes.h index beba5e3b4..46e3a6a60 100644 --- a/inc/saitypes.h +++ b/inc/saitypes.h @@ -56,6 +56,8 @@ typedef UINT8 sai_ip6_t[16]; typedef UINT32 sai_switch_hash_seed_t; typedef UINT32 sai_label_id_t; typedef UINT32 sai_stat_id_t; +typedef UINT8 sai_encrypt_key_t[32]; +typedef UINT8 sai_auth_key_t[16]; typedef UINT8 sai_macsec_sak_t[32]; typedef UINT8 sai_macsec_auth_key_t[16]; typedef UINT8 sai_macsec_salt_t[12]; @@ -99,6 +101,8 @@ typedef uint8_t sai_ip6_t[16]; typedef uint32_t sai_switch_hash_seed_t; typedef uint32_t sai_label_id_t; typedef uint32_t sai_stat_id_t; +typedef uint8_t sai_encrypt_key_t[32]; +typedef uint8_t sai_auth_key_t[16]; typedef uint8_t sai_macsec_sak_t[32]; typedef uint8_t sai_macsec_auth_key_t[16]; typedef uint8_t sai_macsec_salt_t[12]; @@ -281,6 +285,9 @@ typedef enum _sai_object_type_t SAI_OBJECT_TYPE_MY_SID_ENTRY = 96, SAI_OBJECT_TYPE_MY_MAC = 97, SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP = 98, + SAI_OBJECT_TYPE_IPSEC = 99, + SAI_OBJECT_TYPE_IPSEC_PORT = 100, + SAI_OBJECT_TYPE_IPSEC_SA = 101, SAI_OBJECT_TYPE_MAX, /* Must remain in last position */ } sai_object_type_t; @@ -1258,6 +1265,12 @@ typedef union _sai_attribute_value_t /** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_TIMESPEC */ sai_timespec_t timespec; + /** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY */ + sai_encrypt_key_t encrypt_key; + + /** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_AUTH_KEY */ + sai_auth_key_t authkey; + /** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_MACSEC_SAK */ sai_macsec_sak_t macsecsak; diff --git a/meta/acronyms.txt b/meta/acronyms.txt index 3abd71ae0..d64c5b0f5 100644 --- a/meta/acronyms.txt +++ b/meta/acronyms.txt @@ -39,6 +39,7 @@ ECT - ECN Capable Transport EEE - Electrical and Electronics Engineering EEPROM - Electrically erasable programmable read-only memory ERSPAN - Encapsulated Remote SPAN +ESN - Extended Sequence Number FCS - Frame Check Sequence FD - File Descriptor FDB - Forwarding Data Base @@ -118,6 +119,7 @@ SNAT - Source Network Address Translation SNMP - Simple Network Management Protocol SNR - Signal to Noise Ratio SPAN - Switched Port Analyzer +SPI - Security Parameter Index SQE - Signal Quality Errors SRH - Segment Routing Header SRV6 - Segment Routing with IPv6 @@ -128,6 +130,7 @@ STP - Spanning Tree Protocol TC - Traffic Control TCAM - Ternary Content Addressable Memory TCP - Transmission Control Protocol +TEK - Traffic Encryption Key TLS - Transport Layer Security TOS - Type Of Service TPID - Tag Protocol Identifier diff --git a/meta/aspell.en.pws b/meta/aspell.en.pws index 18772c60e..672b40338 100644 --- a/meta/aspell.en.pws +++ b/meta/aspell.en.pws @@ -56,6 +56,7 @@ InPktsLate InSegment Inservice ipredriver +IPsec isprint isresourcetype isvlan diff --git a/meta/parse.pl b/meta/parse.pl index 0c3d331dd..042b49d21 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -2427,6 +2427,8 @@ sub ProcessStructValueType return "SAI_ATTR_VALUE_TYPE_UINT32" if $type eq "uint32_t"; return "SAI_ATTR_VALUE_TYPE_INT32" if $type =~ /^sai_\w+_type_t$/; # enum return "SAI_ATTR_VALUE_TYPE_NAT_ENTRY_DATA" if $type eq "sai_nat_entry_data_t"; + return "SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY" if $type eq "sai_encrypt_key_t"; + return "SAI_ATTR_VALUE_TYPE_AUTH_KEY" if $type eq "sai_auth_key_t"; return "SAI_ATTR_VALUE_TYPE_MACSEC_SAK" if $type eq "sai_macsec_sak_t"; return "SAI_ATTR_VALUE_TYPE_MACSEC_AUTH_KEY" if $type eq "sai_macsec_auth_key_t"; return "SAI_ATTR_VALUE_TYPE_MACSEC_SALT" if $type eq "sai_macsec_salt_t"; diff --git a/meta/saimetadatatypes.h b/meta/saimetadatatypes.h index 2b97335f6..ec4c97375 100644 --- a/meta/saimetadatatypes.h +++ b/meta/saimetadatatypes.h @@ -435,6 +435,17 @@ typedef enum _sai_attr_value_type_t * @brief Attribute value is fabric port error status. */ SAI_ATTR_VALUE_TYPE_PORT_ERR_STATUS_LIST, + + /** + * @brief Attribute value is encryption key. + */ + SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY, + + /** + * @brief Attribute value is authentication Key. + */ + SAI_ATTR_VALUE_TYPE_AUTH_KEY, + } sai_attr_value_type_t; /** diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c index 49d3cbb7c..8c1681605 100644 --- a/meta/saisanitycheck.c +++ b/meta/saisanitycheck.c @@ -693,6 +693,9 @@ void check_attr_object_type_provided( case SAI_ATTR_VALUE_TYPE_IPV4: case SAI_ATTR_VALUE_TYPE_IPV6: + case SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY: + case SAI_ATTR_VALUE_TYPE_AUTH_KEY: + case SAI_ATTR_VALUE_TYPE_MACSEC_SAK: case SAI_ATTR_VALUE_TYPE_MACSEC_AUTH_KEY: case SAI_ATTR_VALUE_TYPE_MACSEC_SALT: @@ -2642,6 +2645,8 @@ void check_attr_is_primitive( case SAI_ATTR_VALUE_TYPE_TIMESPEC: case SAI_ATTR_VALUE_TYPE_IPV4: case SAI_ATTR_VALUE_TYPE_IPV6: + case SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY: + case SAI_ATTR_VALUE_TYPE_AUTH_KEY: case SAI_ATTR_VALUE_TYPE_MACSEC_SAK: case SAI_ATTR_VALUE_TYPE_MACSEC_AUTH_KEY: case SAI_ATTR_VALUE_TYPE_MACSEC_SALT: @@ -3512,6 +3517,8 @@ void check_non_object_id_object_types() case SAI_ATTR_VALUE_TYPE_IP_PREFIX: case SAI_ATTR_VALUE_TYPE_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_NAT_ENTRY_DATA: + case SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY: + case SAI_ATTR_VALUE_TYPE_AUTH_KEY: case SAI_ATTR_VALUE_TYPE_MACSEC_SAK: case SAI_ATTR_VALUE_TYPE_MACSEC_AUTH_KEY: case SAI_ATTR_VALUE_TYPE_MACSEC_SALT: diff --git a/meta/saiserialize.c b/meta/saiserialize.c index 20a3c82c7..22ab479e2 100644 --- a/meta/saiserialize.c +++ b/meta/saiserialize.c @@ -497,9 +497,9 @@ int sai_deserialize_mac( return SAI_SERIALIZE_ERROR; } -int sai_serialize_macsec_sak( +int sai_serialize_encrypt_key( _Out_ char *buffer, - _In_ const sai_macsec_sak_t sak) + _In_ const sai_encrypt_key_t sak) { return sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\ %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\ @@ -511,9 +511,9 @@ int sai_serialize_macsec_sak( sak[24], sak[25], sak[26], sak[27], sak[28], sak[29],sak[30], sak[31]); } -int sai_deserialize_macsec_sak( +int sai_deserialize_encrypt_key( _In_ const char *buffer, - _Out_ sai_macsec_sak_t sak) + _Out_ sai_encrypt_key_t sak) { int arr[32]; int read; @@ -539,13 +539,13 @@ int sai_deserialize_macsec_sak( return read; } - SAI_META_LOG_WARN("failed to deserialize '%.*s' as macsec_sak", MAX_CHARS_PRINT, buffer); + SAI_META_LOG_WARN("failed to deserialize '%.*s' as encrypt_key", MAX_CHARS_PRINT, buffer); return SAI_SERIALIZE_ERROR; } -int sai_serialize_macsec_auth_key( +int sai_serialize_auth_key( _Out_ char *buffer, - _In_ const sai_macsec_auth_key_t auth) + _In_ const sai_auth_key_t auth) { return sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\ %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", @@ -553,9 +553,9 @@ int sai_serialize_macsec_auth_key( auth[8], auth[9], auth[10], auth[11], auth[12], auth[13],auth[14], auth[15]); } -int sai_deserialize_macsec_auth_key( +int sai_deserialize_auth_key( _In_ const char *buffer, - _Out_ sai_macsec_auth_key_t auth) + _Out_ sai_auth_key_t auth) { int arr[16]; int read; @@ -576,10 +576,38 @@ int sai_deserialize_macsec_auth_key( return read; } - SAI_META_LOG_WARN("failed to deserialize '%.*s' as macsec_auth_key", MAX_CHARS_PRINT, buffer); + SAI_META_LOG_WARN("failed to deserialize '%.*s' as auth_key", MAX_CHARS_PRINT, buffer); return SAI_SERIALIZE_ERROR; } +int sai_serialize_macsec_sak( + _Out_ char *buffer, + _In_ const sai_macsec_sak_t sak) +{ + return sai_serialize_encrypt_key(buffer, sak); +} + +int sai_deserialize_macsec_sak( + _In_ const char *buffer, + _Out_ sai_macsec_sak_t sak) +{ + return sai_deserialize_encrypt_key(buffer, sak); +} + +int sai_serialize_macsec_auth_key( + _Out_ char *buffer, + _In_ const sai_macsec_auth_key_t auth) +{ + return sai_serialize_auth_key(buffer, auth); +} + +int sai_deserialize_macsec_auth_key( + _In_ const char *buffer, + _Out_ sai_macsec_auth_key_t auth) +{ + return sai_deserialize_auth_key(buffer, auth); +} + int sai_serialize_macsec_salt( _Out_ char *buffer, _In_ const sai_macsec_salt_t salt) diff --git a/meta/saiserialize.h b/meta/saiserialize.h index 9716ec368..bd90ef1af 100644 --- a/meta/saiserialize.h +++ b/meta/saiserialize.h @@ -415,6 +415,58 @@ int sai_deserialize_mac( _In_ const char *buffer, _Out_ sai_mac_t mac); +/** + * @brief Serialize encrypt_key. + * + * @param[out] buffer Output buffer for serialized value. + * @param[in] key The encrypt_key to be serialized. + * + * @return Number of characters written to buffer excluding '\0', + * or #SAI_SERIALIZE_ERROR on error. + */ +int sai_serialize_encrypt_key( + _Out_ char *buffer, + _In_ const sai_encrypt_key_t key); + +/** + * @brief Deserialize encrypt_key. + * + * @param[in] buffer Input buffer to be examined. + * @param[out] key The encrypt_key deserialized value. + * + * @return Number of characters consumed from the buffer, + * or #SAI_SERIALIZE_ERROR on error. + */ +int sai_deserialize_encrypt_key( + _In_ const char *buffer, + _Out_ sai_encrypt_key_t key); + +/** + * @brief Serialize auth_key. + * + * @param[out] buffer Output buffer for serialized value. + * @param[in] auth The auth_key to be serialized. + * + * @return Number of characters written to buffer excluding '\0', + * or #SAI_SERIALIZE_ERROR on error. + */ +int sai_serialize_auth_key( + _Out_ char *buffer, + _In_ const sai_auth_key_t auth); + +/** + * @brief Deserialize auth_key. + * + * @param[in] buffer Input buffer to be examined. + * @param[out] auth The auth_key deserialized value. + * + * @return Number of characters consumed from the buffer, + * or #SAI_SERIALIZE_ERROR on error. + */ +int sai_deserialize_auth_key( + _In_ const char *buffer, + _Out_ sai_auth_key_t auth); + /** * @brief Serialize macsec_sak. * diff --git a/meta/saiserializetest.c b/meta/saiserializetest.c index 740fd2dbb..e1140eebc 100644 --- a/meta/saiserializetest.c +++ b/meta/saiserializetest.c @@ -305,51 +305,99 @@ void test_deserialize_mac() ASSERT_TRUE(res < 0, "expected negative"); } -void test_serialize_macsec_sak() +void test_serialize_encrypt_key() { int res; char buf[PRIMITIVE_BUFFER_SIZE]; - sai_macsec_sak_t macsec_sak; + sai_encrypt_key_t encrypt_key; - memcpy(macsec_sak, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 32); + memcpy(encrypt_key, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 32); - res = sai_serialize_macsec_sak(buf, macsec_sak); + res = sai_serialize_encrypt_key(buf, encrypt_key); ASSERT_STR_EQ(buf, "01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", res); } -void test_deserialize_macsec_sak() +void test_deserialize_encrypt_key() { int res; - sai_macsec_sak_t macsec_sak; + sai_encrypt_key_t encrypt_key; - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", encrypt_key); ASSERT_TRUE(res == 95, "expected 95 length"); - ASSERT_TRUE(memcmp(macsec_sak, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 32) == 0, "expected equal"); + ASSERT_TRUE(memcmp(encrypt_key, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 32) == 0, "expected equal"); - res = sai_deserialize_macsec_sak("1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b", macsec_sak); + res = sai_deserialize_encrypt_key("1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("001:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", macsec_sak); + res = sai_deserialize_encrypt_key("001:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:zF", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:zF", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:Ej", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:Ej", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:]F", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:]F", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89::CD:EF", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89::CD:EF", encrypt_key); ASSERT_TRUE(res < 0, "expected negative"); - res = sai_deserialize_macsec_sak("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45::67:89:AB:CD:EF", macsec_sak); + res = sai_deserialize_encrypt_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45::67:89:AB:CD:EF", encrypt_key); + ASSERT_TRUE(res < 0, "expected negative"); +} + +void test_serialize_auth_key() +{ + int res; + char buf[PRIMITIVE_BUFFER_SIZE]; + + sai_auth_key_t auth_key; + + memcpy(auth_key, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 16); + + res = sai_serialize_auth_key(buf, auth_key); + + ASSERT_STR_EQ(buf, "01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", res); +} + +void test_deserialize_auth_key() +{ + int res; + sai_auth_key_t auth_key; + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", auth_key); + ASSERT_TRUE(res == 47, "expected 47 length"); + ASSERT_TRUE(memcmp(auth_key, "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef", 16) == 0, "expected equal"); + + res = sai_deserialize_auth_key("1:2:3:4:5:f:a:b:1:2:3:4:5:f:a:b", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("001:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:zF", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:Ej", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:]F", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89::CD:EF", auth_key); + ASSERT_TRUE(res < 0, "expected negative"); + + res = sai_deserialize_auth_key("01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB::CD:EF", auth_key); ASSERT_TRUE(res < 0, "expected negative"); } diff --git a/meta/style.pm b/meta/style.pm index c7d0a1fcd..8d4b82efd 100644 --- a/meta/style.pm +++ b/meta/style.pm @@ -1094,7 +1094,7 @@ sub CheckHeadersStyle next if defined $exceptions{$word}; next if $word =~ /^sai\w+/i; - next if $word =~ /0x\S+L/; + next if $word =~ /0x\S+/; next if "$pre$word" =~ /802.\d+\w+/; next if defined $wordsChecked{$word};