LCOV - code coverage report
Current view: top level - drivers/common/sfc_efx/base - rhead_tunnel.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 90 0.0 %
Date: 2024-01-22 15:55:54 Functions: 0 5 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *
       3                 :            :  * Copyright(c) 2021 Xilinx, Inc.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "efx.h"
       7                 :            : #include "efx_impl.h"
       8                 :            : 
       9                 :            : #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_TUNNEL
      10                 :            : 
      11                 :            : /* Match by Ether-type */
      12                 :            : #define EFX_VNIC_ENCAP_RULE_MATCH_ETHER_TYPE \
      13                 :            :         (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_ETHER_TYPE_LBN)
      14                 :            : /* Match by outer VLAN ID */
      15                 :            : #define EFX_VNIC_ENCAP_RULE_MATCH_OUTER_VID \
      16                 :            :         (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_OUTER_VLAN_LBN)
      17                 :            : /* Match by local IP host address */
      18                 :            : #define EFX_VNIC_ENCAP_RULE_MATCH_LOC_HOST \
      19                 :            :         (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_DST_IP_LBN)
      20                 :            : /* Match by IP transport protocol */
      21                 :            : #define EFX_VNIC_ENCAP_RULE_MATCH_IP_PROTO \
      22                 :            :         (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_IP_PROTO_LBN)
      23                 :            : /* Match by local TCP/UDP port */
      24                 :            : #define EFX_VNIC_ENCAP_RULE_MATCH_LOC_PORT \
      25                 :            :         (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_DST_PORT_LBN)
      26                 :            : 
      27                 :            : /*
      28                 :            :  * Helper structure to pass parameters to MCDI function to add a VNIC
      29                 :            :  * encapsulation rule.
      30                 :            :  */
      31                 :            : typedef struct efx_vnic_encap_rule_spec_s {
      32                 :            :         uint32_t                evers_mport_selector; /* Host-endian */
      33                 :            :         uint32_t                evers_match_flags; /* Host-endian */
      34                 :            :         uint16_t                evers_ether_type; /* Host-endian */
      35                 :            :         uint16_t                evers_outer_vid; /* Host-endian */
      36                 :            :         efx_oword_t             evers_loc_host; /* Big-endian */
      37                 :            :         uint8_t                 evers_ip_proto;
      38                 :            :         uint16_t                evers_loc_port; /* Host-endian */
      39                 :            :         efx_tunnel_protocol_t   evers_encap_type;
      40                 :            : } efx_vnic_encap_rule_spec_t;
      41                 :            : 
      42                 :            : static                          uint32_t
      43                 :            : efx_tunnel_protocol2mae_encap_type(
      44                 :            :         __in            efx_tunnel_protocol_t proto,
      45                 :            :         __out           uint32_t *typep)
      46                 :            : {
      47                 :            :         efx_rc_t rc;
      48                 :            : 
      49                 :            :         switch (proto) {
      50                 :            :         case EFX_TUNNEL_PROTOCOL_NONE:
      51                 :            :                 *typep = MAE_MCDI_ENCAP_TYPE_NONE;
      52                 :            :                 break;
      53                 :            :         case EFX_TUNNEL_PROTOCOL_VXLAN:
      54                 :            :                 *typep = MAE_MCDI_ENCAP_TYPE_VXLAN;
      55                 :            :                 break;
      56                 :            :         case EFX_TUNNEL_PROTOCOL_GENEVE:
      57                 :            :                 *typep = MAE_MCDI_ENCAP_TYPE_GENEVE;
      58                 :            :                 break;
      59                 :            :         case EFX_TUNNEL_PROTOCOL_NVGRE:
      60                 :            :                 *typep = MAE_MCDI_ENCAP_TYPE_NVGRE;
      61                 :            :                 break;
      62                 :          0 :         default:
      63                 :            :                 rc = EINVAL;
      64                 :          0 :                 goto fail1;
      65                 :            :         }
      66                 :            : 
      67                 :            :         return (0);
      68                 :            : 
      69                 :            : fail1:
      70                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
      71                 :            : 
      72                 :          0 :         return (rc);
      73                 :            : }
      74                 :            : 
      75                 :            : static  __checkReturn           efx_rc_t
      76                 :          0 : efx_mcdi_vnic_encap_rule_add(
      77                 :            :         __in                    efx_nic_t *enp,
      78                 :            :         __in                    const efx_vnic_encap_rule_spec_t *spec,
      79                 :            :         __out                   efx_vnic_encap_rule_handle_t *handle)
      80                 :            : 
      81                 :            : {
      82                 :            :         efx_mcdi_req_t req;
      83                 :          0 :         EFX_MCDI_DECLARE_BUF(payload,
      84                 :            :                 MC_CMD_VNIC_ENCAP_RULE_ADD_IN_LEN,
      85                 :            :                 MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN);
      86                 :            :         uint32_t encap_type;
      87                 :            :         efx_rc_t rc;
      88                 :            : 
      89                 :          0 :         req.emr_cmd = MC_CMD_VNIC_ENCAP_RULE_ADD;
      90                 :          0 :         req.emr_in_buf = payload;
      91                 :          0 :         req.emr_in_length = MC_CMD_VNIC_ENCAP_RULE_ADD_IN_LEN;
      92                 :          0 :         req.emr_out_buf = payload;
      93                 :          0 :         req.emr_out_length = MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN;
      94                 :            : 
      95                 :          0 :         MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_MPORT_SELECTOR,
      96                 :            :             spec->evers_mport_selector);
      97                 :          0 :         MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_MATCH_FLAGS,
      98                 :            :             spec->evers_match_flags);
      99                 :            : 
     100                 :          0 :         MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_ETHER_TYPE,
     101                 :            :             __CPU_TO_BE_16(spec->evers_ether_type));
     102                 :          0 :         MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_OUTER_VLAN_WORD,
     103                 :            :             __CPU_TO_BE_16(spec->evers_outer_vid));
     104                 :            : 
     105                 :            :         /*
     106                 :            :          * Address is already in network order as well as the MCDI field,
     107                 :            :          * so plain copy is used.
     108                 :            :          */
     109                 :            :         EFX_STATIC_ASSERT(sizeof (spec->evers_loc_host) ==
     110                 :            :             MC_CMD_VNIC_ENCAP_RULE_ADD_IN_DST_IP_LEN);
     111                 :            :         memcpy(MCDI_IN2(req, uint8_t, VNIC_ENCAP_RULE_ADD_IN_DST_IP),
     112                 :          0 :             &spec->evers_loc_host.eo_byte[0],
     113                 :            :             MC_CMD_VNIC_ENCAP_RULE_ADD_IN_DST_IP_LEN);
     114                 :            : 
     115                 :          0 :         MCDI_IN_SET_BYTE(req, VNIC_ENCAP_RULE_ADD_IN_IP_PROTO,
     116                 :            :             spec->evers_ip_proto);
     117                 :          0 :         MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_DST_PORT,
     118                 :            :             __CPU_TO_BE_16(spec->evers_loc_port));
     119                 :            : 
     120         [ #  # ]:          0 :         rc = efx_tunnel_protocol2mae_encap_type(spec->evers_encap_type,
     121                 :            :             &encap_type);
     122         [ #  # ]:          0 :         if (rc != 0)
     123                 :          0 :                 goto fail1;
     124                 :            : 
     125                 :          0 :         MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_ENCAP_TYPE, encap_type);
     126                 :            : 
     127                 :          0 :         efx_mcdi_execute(enp, &req);
     128                 :            : 
     129         [ #  # ]:          0 :         if (req.emr_rc != 0) {
     130                 :            :                 rc = req.emr_rc;
     131                 :          0 :                 goto fail2;
     132                 :            :         }
     133                 :            : 
     134         [ #  # ]:          0 :         if (req.emr_out_length_used != MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN) {
     135                 :            :                 rc = EMSGSIZE;
     136                 :          0 :                 goto fail3;
     137                 :            :         }
     138                 :            : 
     139         [ #  # ]:          0 :         if (handle != NULL)
     140                 :          0 :                 *handle = MCDI_OUT_DWORD(req, VNIC_ENCAP_RULE_ADD_OUT_HANDLE);
     141                 :            : 
     142                 :            :         return (0);
     143                 :            : 
     144                 :            : fail3:
     145                 :            :         EFSYS_PROBE(fail3);
     146                 :            : 
     147                 :            : fail2:
     148                 :            :         EFSYS_PROBE(fail2);
     149                 :            : 
     150                 :            : fail1:
     151                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     152                 :            : 
     153                 :            :         return (rc);
     154                 :            : }
     155                 :            : 
     156                 :            : static  __checkReturn           efx_rc_t
     157                 :          0 : efx_mcdi_vnic_encap_rule_remove(
     158                 :            :         __in                    efx_nic_t *enp,
     159                 :            :         __in                    efx_vnic_encap_rule_handle_t handle)
     160                 :            : 
     161                 :            : {
     162                 :            :         efx_mcdi_req_t req;
     163                 :          0 :         EFX_MCDI_DECLARE_BUF(payload,
     164                 :            :             MC_CMD_VNIC_ENCAP_RULE_REMOVE_IN_LEN,
     165                 :            :             MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN);
     166                 :            :         efx_rc_t rc;
     167                 :            : 
     168                 :          0 :         req.emr_cmd = MC_CMD_VNIC_ENCAP_RULE_REMOVE;
     169                 :          0 :         req.emr_in_buf = payload;
     170                 :          0 :         req.emr_in_length = MC_CMD_VNIC_ENCAP_RULE_REMOVE_IN_LEN;
     171                 :          0 :         req.emr_out_buf = payload;
     172                 :          0 :         req.emr_out_length = MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN;
     173                 :            : 
     174                 :          0 :         MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_REMOVE_IN_HANDLE, handle);
     175                 :            : 
     176                 :          0 :         efx_mcdi_execute(enp, &req);
     177                 :            : 
     178         [ #  # ]:          0 :         if (req.emr_rc != 0) {
     179                 :            :                 rc = req.emr_rc;
     180                 :          0 :                 goto fail1;
     181                 :            :         }
     182                 :            : 
     183         [ #  # ]:          0 :         if (req.emr_out_length_used != MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN) {
     184                 :            :                 rc = EMSGSIZE;
     185                 :          0 :                 goto fail2;
     186                 :            :         }
     187                 :            : 
     188                 :            :         return (0);
     189                 :            : 
     190                 :            : fail2:
     191                 :            :         EFSYS_PROBE(fail2);
     192                 :            : 
     193                 :            : fail1:
     194                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     195                 :            : 
     196                 :            :         return (rc);
     197                 :            : }
     198                 :            : 
     199                 :            : static                  void
     200                 :            : rhead_vnic_encap_rule_spec_init(
     201                 :            :         __in            const efx_tunnel_udp_entry_t *etuep,
     202                 :            :         __out           efx_vnic_encap_rule_spec_t *spec)
     203                 :            : {
     204                 :            :         memset(spec, 0, sizeof (*spec));
     205                 :            : 
     206                 :          0 :         spec->evers_mport_selector = MAE_MPORT_SELECTOR_ASSIGNED;
     207                 :          0 :         spec->evers_match_flags = EFX_VNIC_ENCAP_RULE_MATCH_IP_PROTO |
     208                 :            :             EFX_VNIC_ENCAP_RULE_MATCH_LOC_PORT;
     209                 :          0 :         spec->evers_ip_proto = EFX_IPPROTO_UDP;
     210                 :          0 :         spec->evers_loc_port = etuep->etue_port;
     211                 :          0 :         spec->evers_encap_type = etuep->etue_protocol;
     212                 :            : }
     213                 :            : 
     214                 :            : static  __checkReturn   efx_rc_t
     215                 :          0 : rhead_udp_port_tunnel_add(
     216                 :            :         __in            efx_nic_t *enp,
     217                 :            :         __inout         efx_tunnel_udp_entry_t *etuep)
     218                 :            : {
     219                 :            :         efx_vnic_encap_rule_spec_t spec;
     220                 :            : 
     221                 :            :         rhead_vnic_encap_rule_spec_init(etuep, &spec);
     222                 :          0 :         return (efx_mcdi_vnic_encap_rule_add(enp, &spec, &etuep->etue_handle));
     223                 :            : }
     224                 :            : 
     225                 :            : static  __checkReturn   efx_rc_t
     226                 :            : rhead_udp_port_tunnel_remove(
     227                 :            :         __in            efx_nic_t *enp,
     228                 :            :         __in            efx_tunnel_udp_entry_t *etuep)
     229                 :            : {
     230                 :          0 :         return (efx_mcdi_vnic_encap_rule_remove(enp, etuep->etue_handle));
     231                 :            : }
     232                 :            : 
     233                 :            :         __checkReturn   efx_rc_t
     234                 :          0 : rhead_tunnel_reconfigure(
     235                 :            :         __in            efx_nic_t *enp)
     236                 :            : {
     237                 :          0 :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     238                 :            :         efx_rc_t rc;
     239                 :            :         efsys_lock_state_t state;
     240                 :            :         efx_tunnel_cfg_t etc;
     241                 :            :         efx_tunnel_cfg_t added;
     242                 :            :         unsigned int i;
     243                 :            :         unsigned int j;
     244                 :            : 
     245                 :            :         memset(&added, 0, sizeof(added));
     246                 :            : 
     247                 :            :         /*
     248                 :            :          * Make a local copy of UDP tunnel table to release the lock
     249                 :            :          * when executing MCDIs.
     250                 :            :          */
     251                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     252                 :            :         memcpy(&etc, etcp, sizeof (etc));
     253                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     254                 :            : 
     255         [ #  # ]:          0 :         for (i = 0; i < etc.etc_udp_entries_num; i++) {
     256                 :          0 :                 efx_tunnel_udp_entry_t *etc_entry = &etc.etc_udp_entries[i];
     257                 :            : 
     258         [ #  # ]:          0 :                 if (etc_entry->etue_busy == B_FALSE)
     259                 :          0 :                         continue;
     260                 :            : 
     261   [ #  #  #  # ]:          0 :                 switch (etc_entry->etue_state) {
     262                 :            :                 case EFX_TUNNEL_UDP_ENTRY_APPLIED:
     263                 :            :                         break;
     264                 :          0 :                 case EFX_TUNNEL_UDP_ENTRY_ADDED:
     265                 :          0 :                         rc = rhead_udp_port_tunnel_add(enp, etc_entry);
     266         [ #  # ]:          0 :                         if (rc != 0)
     267                 :          0 :                                 goto fail1;
     268                 :          0 :                         added.etc_udp_entries[added.etc_udp_entries_num] =
     269                 :            :                             *etc_entry;
     270                 :          0 :                         added.etc_udp_entries_num++;
     271                 :          0 :                         break;
     272                 :            :                 case EFX_TUNNEL_UDP_ENTRY_REMOVED:
     273                 :            :                         rc = rhead_udp_port_tunnel_remove(enp, etc_entry);
     274         [ #  # ]:          0 :                         if (rc != 0)
     275                 :          0 :                                 goto fail2;
     276                 :            :                         break;
     277                 :            :                 default:
     278                 :          0 :                         EFSYS_ASSERT(0);
     279                 :            :                         break;
     280                 :            :                 }
     281                 :            :         }
     282                 :            : 
     283                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     284                 :            : 
     285                 :            :         /*
     286                 :            :          * Adding or removing non-busy entries does not change the
     287                 :            :          * order of busy entries. Therefore one linear search iteration
     288                 :            :          * suffices.
     289                 :            :          */
     290         [ #  # ]:          0 :         for (i = 0, j = 0; i < etcp->etc_udp_entries_num; i++) {
     291                 :            :                 efx_tunnel_udp_entry_t *cur_entry = &etcp->etc_udp_entries[i];
     292                 :            :                 efx_tunnel_udp_entry_t *added_entry = &added.etc_udp_entries[j];
     293                 :            : 
     294         [ #  # ]:          0 :                 if (cur_entry->etue_state == EFX_TUNNEL_UDP_ENTRY_ADDED &&
     295         [ #  # ]:          0 :                     cur_entry->etue_port == added_entry->etue_port) {
     296                 :          0 :                         cur_entry->etue_handle = added_entry->etue_handle;
     297                 :          0 :                         j++;
     298                 :            :                 }
     299                 :            :         }
     300                 :            : 
     301                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     302                 :            : 
     303                 :          0 :         return (0);
     304                 :            : 
     305                 :            : fail2:
     306                 :            :         EFSYS_PROBE(fail2);
     307                 :            : 
     308                 :          0 : fail1:
     309                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     310                 :            : 
     311         [ #  # ]:          0 :         while (i-- > 0) {
     312         [ #  # ]:          0 :                 if (etc.etc_udp_entries[i].etue_busy == B_FALSE)
     313                 :          0 :                         continue;
     314                 :            : 
     315   [ #  #  #  # ]:          0 :                 switch (etc.etc_udp_entries[i].etue_state) {
     316                 :            :                 case EFX_TUNNEL_UDP_ENTRY_APPLIED:
     317                 :            :                         break;
     318                 :          0 :                 case EFX_TUNNEL_UDP_ENTRY_ADDED:
     319                 :            :                         (void) rhead_udp_port_tunnel_remove(enp,
     320                 :            :                                         &etc.etc_udp_entries[i]);
     321                 :            :                         break;
     322                 :          0 :                 case EFX_TUNNEL_UDP_ENTRY_REMOVED:
     323                 :          0 :                         (void) rhead_udp_port_tunnel_add(enp,
     324                 :            :                                         &etc.etc_udp_entries[i]);
     325                 :          0 :                         break;
     326                 :            :                 default:
     327                 :          0 :                         EFSYS_ASSERT(0);
     328                 :            :                         break;
     329                 :            :                 }
     330                 :            :         }
     331                 :            : 
     332                 :            :         return (rc);
     333                 :            : }
     334                 :            : 
     335                 :            :                         void
     336                 :          0 : rhead_tunnel_fini(
     337                 :            :         __in            efx_nic_t *enp)
     338                 :            : {
     339                 :          0 :         (void) efx_tunnel_config_clear(enp);
     340                 :          0 :         (void) efx_tunnel_reconfigure(enp);
     341                 :          0 : }
     342                 :            : 
     343                 :            : #endif  /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_TUNNEL */

Generated by: LCOV version 1.14