1675e31d8SVenkat Duvvuru /* SPDX-License-Identifier: BSD-3-Clause 2e6e8f03eSRandy Schacher * Copyright(c) 2014-2023 Broadcom 3675e31d8SVenkat Duvvuru * All rights reserved. 4675e31d8SVenkat Duvvuru */ 5675e31d8SVenkat Duvvuru 6bdf4a3c6SKishore Padmanabha #include "bnxt.h" 7bdf4a3c6SKishore Padmanabha #include "bnxt_ulp.h" 8*0c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h" 9675e31d8SVenkat Duvvuru #include "ulp_tun.h" 10bdf4a3c6SKishore Padmanabha #include "ulp_utils.h" 11675e31d8SVenkat Duvvuru 12bdf4a3c6SKishore Padmanabha /* returns negative on error, 1 if new entry is allocated or zero if old */ 13bdf4a3c6SKishore Padmanabha int32_t 14bdf4a3c6SKishore Padmanabha ulp_app_tun_search_entry(struct bnxt_ulp_context *ulp_ctx, 15bdf4a3c6SKishore Padmanabha struct rte_flow_tunnel *app_tunnel, 16bdf4a3c6SKishore Padmanabha struct bnxt_flow_app_tun_ent **tun_entry) 17675e31d8SVenkat Duvvuru { 18bdf4a3c6SKishore Padmanabha struct bnxt_flow_app_tun_ent *tun_ent_list; 19bdf4a3c6SKishore Padmanabha int32_t i, rc = 0, free_entry = -1; 20675e31d8SVenkat Duvvuru 21bdf4a3c6SKishore Padmanabha tun_ent_list = bnxt_ulp_cntxt_ptr2_app_tun_list_get(ulp_ctx); 22bdf4a3c6SKishore Padmanabha if (!tun_ent_list) { 23dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "unable to get the app tunnel list\n"); 24bdf4a3c6SKishore Padmanabha return -EINVAL; 25675e31d8SVenkat Duvvuru } 26675e31d8SVenkat Duvvuru 27bdf4a3c6SKishore Padmanabha for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) { 28bdf4a3c6SKishore Padmanabha if (!tun_ent_list[i].ref_cnt) { 29bdf4a3c6SKishore Padmanabha if (free_entry < 0) 30bdf4a3c6SKishore Padmanabha free_entry = i; 31bdf4a3c6SKishore Padmanabha } else { 32bdf4a3c6SKishore Padmanabha if (!memcmp(&tun_ent_list[i].app_tunnel, 33bdf4a3c6SKishore Padmanabha app_tunnel, 34bdf4a3c6SKishore Padmanabha sizeof(struct rte_flow_tunnel))) { 35bdf4a3c6SKishore Padmanabha *tun_entry = &tun_ent_list[i]; 36bdf4a3c6SKishore Padmanabha tun_ent_list[free_entry].ref_cnt++; 37bdf4a3c6SKishore Padmanabha return rc; 38bdf4a3c6SKishore Padmanabha } 39bdf4a3c6SKishore Padmanabha } 40bdf4a3c6SKishore Padmanabha } 41bdf4a3c6SKishore Padmanabha if (free_entry >= 0) { 42bdf4a3c6SKishore Padmanabha *tun_entry = &tun_ent_list[free_entry]; 43bdf4a3c6SKishore Padmanabha memcpy(&tun_ent_list[free_entry].app_tunnel, app_tunnel, 44bdf4a3c6SKishore Padmanabha sizeof(struct rte_flow_tunnel)); 45bdf4a3c6SKishore Padmanabha tun_ent_list[free_entry].ref_cnt = 1; 46bdf4a3c6SKishore Padmanabha rc = 1; 47bdf4a3c6SKishore Padmanabha } else { 48dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "ulp app tunnel list is full\n"); 49bdf4a3c6SKishore Padmanabha return -ENOMEM; 50bdf4a3c6SKishore Padmanabha } 51bdf4a3c6SKishore Padmanabha 52bdf4a3c6SKishore Padmanabha return rc; 53bdf4a3c6SKishore Padmanabha } 54bdf4a3c6SKishore Padmanabha 55bdf4a3c6SKishore Padmanabha void 56bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_delete(struct bnxt_flow_app_tun_ent *tun_entry) 57675e31d8SVenkat Duvvuru { 58bdf4a3c6SKishore Padmanabha if (tun_entry) { 59bdf4a3c6SKishore Padmanabha if (tun_entry->ref_cnt) { 60bdf4a3c6SKishore Padmanabha tun_entry->ref_cnt--; 61bdf4a3c6SKishore Padmanabha if (!tun_entry->ref_cnt) 62bdf4a3c6SKishore Padmanabha memset(tun_entry, 0, 63bdf4a3c6SKishore Padmanabha sizeof(struct bnxt_flow_app_tun_ent)); 64bdf4a3c6SKishore Padmanabha } 65ddaf0afaSKishore Padmanabha } 66675e31d8SVenkat Duvvuru } 67675e31d8SVenkat Duvvuru 68bdf4a3c6SKishore Padmanabha int32_t 69bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_set_decap_action(struct bnxt_flow_app_tun_ent *tun_entry) 70675e31d8SVenkat Duvvuru { 71bdf4a3c6SKishore Padmanabha if (!tun_entry) 72bdf4a3c6SKishore Padmanabha return -EINVAL; 73675e31d8SVenkat Duvvuru 74bdf4a3c6SKishore Padmanabha tun_entry->action.type = (typeof(tun_entry->action.type)) 75bdf4a3c6SKishore Padmanabha BNXT_RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; 76bdf4a3c6SKishore Padmanabha tun_entry->action.conf = tun_entry; 77bdf4a3c6SKishore Padmanabha return 0; 78ddaf0afaSKishore Padmanabha } 79675e31d8SVenkat Duvvuru 80bdf4a3c6SKishore Padmanabha int32_t 81bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_set_decap_item(struct bnxt_flow_app_tun_ent *tun_entry) 82675e31d8SVenkat Duvvuru { 83bdf4a3c6SKishore Padmanabha if (!tun_entry) 84bdf4a3c6SKishore Padmanabha return -EINVAL; 85675e31d8SVenkat Duvvuru 86bdf4a3c6SKishore Padmanabha tun_entry->item.type = (typeof(tun_entry->item.type)) 87bdf4a3c6SKishore Padmanabha BNXT_RTE_FLOW_ITEM_TYPE_VXLAN_DECAP; 88bdf4a3c6SKishore Padmanabha tun_entry->item.spec = tun_entry; 89bdf4a3c6SKishore Padmanabha tun_entry->item.last = NULL; 90bdf4a3c6SKishore Padmanabha tun_entry->item.mask = NULL; 91bdf4a3c6SKishore Padmanabha return 0; 92675e31d8SVenkat Duvvuru } 93675e31d8SVenkat Duvvuru 94bdf4a3c6SKishore Padmanabha struct bnxt_flow_app_tun_ent * 95bdf4a3c6SKishore Padmanabha ulp_app_tun_match_entry(struct bnxt_ulp_context *ulp_ctx, 96bdf4a3c6SKishore Padmanabha const void *ctx) 97675e31d8SVenkat Duvvuru { 98bdf4a3c6SKishore Padmanabha struct bnxt_flow_app_tun_ent *tun_ent_list; 99bdf4a3c6SKishore Padmanabha int32_t i; 100675e31d8SVenkat Duvvuru 101bdf4a3c6SKishore Padmanabha tun_ent_list = bnxt_ulp_cntxt_ptr2_app_tun_list_get(ulp_ctx); 102bdf4a3c6SKishore Padmanabha if (!tun_ent_list) { 103dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "unable to get the app tunnel list\n"); 104bdf4a3c6SKishore Padmanabha return NULL; 105bdf4a3c6SKishore Padmanabha } 106675e31d8SVenkat Duvvuru 107bdf4a3c6SKishore Padmanabha for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) { 108bdf4a3c6SKishore Padmanabha if (&tun_ent_list[i] == ctx) 109bdf4a3c6SKishore Padmanabha return &tun_ent_list[i]; 110bdf4a3c6SKishore Padmanabha } 111bdf4a3c6SKishore Padmanabha return NULL; 112675e31d8SVenkat Duvvuru } 113675e31d8SVenkat Duvvuru 114675e31d8SVenkat Duvvuru static int32_t 115675e31d8SVenkat Duvvuru ulp_get_tun_entry(struct ulp_rte_parser_params *params, 116675e31d8SVenkat Duvvuru struct bnxt_tun_cache_entry **tun_entry, 117675e31d8SVenkat Duvvuru uint16_t *tun_idx) 118675e31d8SVenkat Duvvuru { 119bdf4a3c6SKishore Padmanabha int32_t i, first_free_entry = BNXT_ULP_TUN_ENTRY_INVALID; 120675e31d8SVenkat Duvvuru struct bnxt_tun_cache_entry *tun_tbl; 121bdf4a3c6SKishore Padmanabha uint32_t dip_idx, dmac_idx, use_ipv4 = 0; 122675e31d8SVenkat Duvvuru 123675e31d8SVenkat Duvvuru tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(params->ulp_ctx); 124bdf4a3c6SKishore Padmanabha if (!tun_tbl) { 125dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Error: could not get Tunnel table\n"); 126675e31d8SVenkat Duvvuru return BNXT_TF_RC_ERROR; 127bdf4a3c6SKishore Padmanabha } 128bdf4a3c6SKishore Padmanabha 129bdf4a3c6SKishore Padmanabha /* get the outer destination ip field index */ 130bdf4a3c6SKishore Padmanabha dip_idx = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_TUN_OFF_DIP_ID); 131bdf4a3c6SKishore Padmanabha dmac_idx = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_TUN_OFF_DMAC_ID); 132bdf4a3c6SKishore Padmanabha if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_O_IPV4)) 133bdf4a3c6SKishore Padmanabha use_ipv4 = 1; 134675e31d8SVenkat Duvvuru 135675e31d8SVenkat Duvvuru for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) { 136bdf4a3c6SKishore Padmanabha if (!tun_tbl[i].t_dst_ip_valid) { 137bdf4a3c6SKishore Padmanabha if (first_free_entry == BNXT_ULP_TUN_ENTRY_INVALID) 138675e31d8SVenkat Duvvuru first_free_entry = i; 139bdf4a3c6SKishore Padmanabha continue; 140675e31d8SVenkat Duvvuru } 141bdf4a3c6SKishore Padmanabha /* match on the destination ip of the tunnel */ 142bdf4a3c6SKishore Padmanabha if ((use_ipv4 && !memcmp(&tun_tbl[i].t_dst_ip, 143bdf4a3c6SKishore Padmanabha params->hdr_field[dip_idx].spec, 144bdf4a3c6SKishore Padmanabha sizeof(rte_be32_t))) || 145bdf4a3c6SKishore Padmanabha (!use_ipv4 && 146bdf4a3c6SKishore Padmanabha !memcmp(tun_tbl[i].t_dst_ip6, 147bdf4a3c6SKishore Padmanabha params->hdr_field[dip_idx].spec, 148bdf4a3c6SKishore Padmanabha sizeof(((struct bnxt_tun_cache_entry *) 149bdf4a3c6SKishore Padmanabha NULL)->t_dst_ip6)))) { 150675e31d8SVenkat Duvvuru *tun_entry = &tun_tbl[i]; 151675e31d8SVenkat Duvvuru *tun_idx = i; 152bdf4a3c6SKishore Padmanabha return 0; 153675e31d8SVenkat Duvvuru } 154bdf4a3c6SKishore Padmanabha } 155bdf4a3c6SKishore Padmanabha if (first_free_entry == BNXT_ULP_TUN_ENTRY_INVALID) { 156dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 157dd0191d5SShuanglin Wang "Error: No entry available in tunnel table\n"); 158bdf4a3c6SKishore Padmanabha return BNXT_TF_RC_ERROR; 159bdf4a3c6SKishore Padmanabha } 160bdf4a3c6SKishore Padmanabha 161bdf4a3c6SKishore Padmanabha *tun_idx = first_free_entry; 162bdf4a3c6SKishore Padmanabha *tun_entry = &tun_tbl[first_free_entry]; 163bdf4a3c6SKishore Padmanabha tun_tbl[first_free_entry].t_dst_ip_valid = true; 164bdf4a3c6SKishore Padmanabha 165bdf4a3c6SKishore Padmanabha /* Update the destination ip and mac */ 166bdf4a3c6SKishore Padmanabha if (use_ipv4) 167bdf4a3c6SKishore Padmanabha memcpy(&tun_tbl[first_free_entry].t_dst_ip, 168bdf4a3c6SKishore Padmanabha params->hdr_field[dip_idx].spec, sizeof(rte_be32_t)); 169bdf4a3c6SKishore Padmanabha else 170bdf4a3c6SKishore Padmanabha memcpy(tun_tbl[first_free_entry].t_dst_ip6, 171bdf4a3c6SKishore Padmanabha params->hdr_field[dip_idx].spec, 172bdf4a3c6SKishore Padmanabha sizeof(((struct bnxt_tun_cache_entry *) 173bdf4a3c6SKishore Padmanabha NULL)->t_dst_ip6)); 174bdf4a3c6SKishore Padmanabha memcpy(tun_tbl[first_free_entry].t_dmac, 175bdf4a3c6SKishore Padmanabha params->hdr_field[dmac_idx].spec, RTE_ETHER_ADDR_LEN); 176675e31d8SVenkat Duvvuru 177675e31d8SVenkat Duvvuru return 0; 178675e31d8SVenkat Duvvuru } 179675e31d8SVenkat Duvvuru 180bdf4a3c6SKishore Padmanabha /* Tunnel API to delete the tunnel entry */ 181bdf4a3c6SKishore Padmanabha void 182bdf4a3c6SKishore Padmanabha ulp_tunnel_offload_entry_clear(struct bnxt_tun_cache_entry *tun_tbl, 183bdf4a3c6SKishore Padmanabha uint8_t tun_idx) 184675e31d8SVenkat Duvvuru { 185bdf4a3c6SKishore Padmanabha memset(&tun_tbl[tun_idx], 0, sizeof(struct bnxt_tun_cache_entry)); 186bdf4a3c6SKishore Padmanabha } 187bdf4a3c6SKishore Padmanabha 188bdf4a3c6SKishore Padmanabha /* Tunnel API to perform tunnel offload process when there is F1/F2 flows */ 189bdf4a3c6SKishore Padmanabha int32_t 190bdf4a3c6SKishore Padmanabha ulp_tunnel_offload_process(struct ulp_rte_parser_params *params) 191bdf4a3c6SKishore Padmanabha { 192675e31d8SVenkat Duvvuru struct bnxt_tun_cache_entry *tun_entry; 193675e31d8SVenkat Duvvuru uint16_t tun_idx; 194bdf4a3c6SKishore Padmanabha int32_t rc = BNXT_TF_RC_SUCCESS; 195675e31d8SVenkat Duvvuru 196bdf4a3c6SKishore Padmanabha /* Perform the tunnel offload only for F1 and F2 flows */ 197bdf4a3c6SKishore Padmanabha if (!ULP_BITMAP_ISSET(params->hdr_bitmap.bits, 198bdf4a3c6SKishore Padmanabha BNXT_ULP_HDR_BIT_F1) && 199bdf4a3c6SKishore Padmanabha !ULP_BITMAP_ISSET(params->hdr_bitmap.bits, 200bdf4a3c6SKishore Padmanabha BNXT_ULP_HDR_BIT_F2)) 201bdf4a3c6SKishore Padmanabha return rc; 202675e31d8SVenkat Duvvuru 203bdf4a3c6SKishore Padmanabha /* search for the tunnel entry if not found create one */ 204675e31d8SVenkat Duvvuru rc = ulp_get_tun_entry(params, &tun_entry, &tun_idx); 205675e31d8SVenkat Duvvuru if (rc == BNXT_TF_RC_ERROR) 206675e31d8SVenkat Duvvuru return rc; 207675e31d8SVenkat Duvvuru 208bdf4a3c6SKishore Padmanabha /* Tunnel offload for the outer Tunnel flow */ 209bdf4a3c6SKishore Padmanabha if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, 210bdf4a3c6SKishore Padmanabha BNXT_ULP_HDR_BIT_F1)) { 211bdf4a3c6SKishore Padmanabha /* Reset the JUMP action bit in the action bitmap as we don't 212bdf4a3c6SKishore Padmanabha * offload this action. 213ddaf0afaSKishore Padmanabha */ 214bdf4a3c6SKishore Padmanabha ULP_BITMAP_RESET(params->act_bitmap.bits, 215bdf4a3c6SKishore Padmanabha BNXT_ULP_ACT_BIT_JUMP); 216bdf4a3c6SKishore Padmanabha params->parent_flow = true; 217bdf4a3c6SKishore Padmanabha params->tun_idx = tun_idx; 218bdf4a3c6SKishore Padmanabha tun_entry->outer_tun_flow_id = params->fid; 219bdf4a3c6SKishore Padmanabha } else if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, 220bdf4a3c6SKishore Padmanabha BNXT_ULP_HDR_BIT_F2)) { 221bdf4a3c6SKishore Padmanabha /* add the vxlan decap action for F2 flows */ 222bdf4a3c6SKishore Padmanabha ULP_BITMAP_SET(params->act_bitmap.bits, 223bdf4a3c6SKishore Padmanabha BNXT_ULP_ACT_BIT_VXLAN_DECAP); 224bdf4a3c6SKishore Padmanabha params->child_flow = true; 225bdf4a3c6SKishore Padmanabha params->tun_idx = tun_idx; 226bdf4a3c6SKishore Padmanabha params->parent_flow = false; 227ddaf0afaSKishore Padmanabha } 228bdf4a3c6SKishore Padmanabha ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_TUNNEL_ID, tun_idx); 229bdf4a3c6SKishore Padmanabha return rc; 2308665487eSVenkat Duvvuru } 231