1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2019 3 */ 4 5 #include "ice_common.h" 6 #include "ice_fdir.h" 7 8 /* These are dummy packet headers used to program flow director filters. */ 9 static const u8 ice_fdir_tcpv4_pkt[] = { 10 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 12 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 13 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 14 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 16 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 17 }; 18 19 static const u8 ice_fdir_udpv4_pkt[] = { 20 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 22 0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11, 23 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 0x00, 0x00, 26 }; 27 28 static const u8 ice_fdir_sctpv4_pkt[] = { 29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 30 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 31 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84, 32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 }; 36 37 static const u8 ice_fdir_ipv4_pkt[] = { 38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 40 0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10, 41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 0x00, 0x00 43 }; 44 45 static const u8 ice_fdir_tcpv6_pkt[] = { 46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00, 48 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00, 49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 55 0x00, 0x00, 56 }; 57 58 static const u8 ice_fdir_udpv6_pkt[] = { 59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00, 61 0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00, 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 67 }; 68 69 static const u8 ice_fdir_sctpv6_pkt[] = { 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00, 72 0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 0x00, 0x00, 79 }; 80 81 static const u8 ice_fdir_ipv6_pkt[] = { 82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00, 84 0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00, 85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 }; 90 91 /* Flow Director dummy packet table */ 92 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = { 93 { 94 ICE_FLTR_PTYPE_NONF_IPV4_TCP, 95 sizeof(ice_fdir_tcpv4_pkt), 96 ice_fdir_tcpv4_pkt, 97 }, 98 { 99 ICE_FLTR_PTYPE_NONF_IPV4_UDP, 100 sizeof(ice_fdir_udpv4_pkt), 101 ice_fdir_udpv4_pkt, 102 }, 103 { 104 ICE_FLTR_PTYPE_NONF_IPV4_SCTP, 105 sizeof(ice_fdir_sctpv4_pkt), 106 ice_fdir_sctpv4_pkt, 107 }, 108 { 109 ICE_FLTR_PTYPE_NONF_IPV4_OTHER, 110 sizeof(ice_fdir_ipv4_pkt), 111 ice_fdir_ipv4_pkt, 112 }, 113 { 114 ICE_FLTR_PTYPE_NONF_IPV6_TCP, 115 sizeof(ice_fdir_tcpv6_pkt), 116 ice_fdir_tcpv6_pkt, 117 }, 118 { 119 ICE_FLTR_PTYPE_NONF_IPV6_UDP, 120 sizeof(ice_fdir_udpv6_pkt), 121 ice_fdir_udpv6_pkt, 122 }, 123 { 124 ICE_FLTR_PTYPE_NONF_IPV6_SCTP, 125 sizeof(ice_fdir_sctpv6_pkt), 126 ice_fdir_sctpv6_pkt, 127 }, 128 { 129 ICE_FLTR_PTYPE_NONF_IPV6_OTHER, 130 sizeof(ice_fdir_ipv6_pkt), 131 ice_fdir_ipv6_pkt, 132 }, 133 }; 134 135 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt) 136 137 /* Flow Direcotr (FD) filter program descriptor Context */ 138 static const struct ice_ctx_ele ice_fd_fltr_desc_ctx_info[] = { 139 /* Field Width LSB */ 140 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, qindex, 11, 0), 141 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_q, 1, 11), 142 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_report, 2, 12), 143 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_space, 2, 14), 144 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_index, 13, 16), 145 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_ena, 2, 29), 146 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, evict_ena, 1, 31), 147 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq, 3, 32), 148 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq_prio, 3, 35), 149 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dpu_recipe, 2, 38), 150 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, drop, 1, 40), 151 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_prio, 3, 41), 152 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_mdid, 4, 44), 153 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_val, 16, 48), 154 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dtype, 4, 64), 155 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, pcmd, 1, 68), 156 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof_prio, 3, 69), 157 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof, 6, 72), 158 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_vsi, 10, 78), 159 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, swap, 1, 88), 160 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_prio, 3, 89), 161 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_mdid, 4, 92), 162 ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid, 32, 96), 163 { 0 } 164 }; 165 166 /** 167 * ice_set_dflt_val_fd_desc 168 * @fd_fltr_ctx: pointer to fd filter descriptor 169 */ 170 void 171 ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx) 172 { 173 fd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO; 174 fd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL; 175 fd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST; 176 fd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS; 177 fd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE; 178 fd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX; 179 fd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1; 180 fd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT; 181 fd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO; 182 fd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE; 183 fd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0; 184 fd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0; 185 fd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG; 186 fd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO; 187 fd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO; 188 fd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET; 189 fd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ZERO; 190 fd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD; 191 fd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO; 192 } 193 194 /** 195 * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct 196 * @hw: pointer to the hardware structure 197 * @input: filter 198 * @fdesc: filter descriptor 199 * @add: if add is true, this is an add operation, false implies delete 200 */ 201 void 202 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input, 203 struct ice_fltr_desc *fdesc, bool add) 204 { 205 struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 }; 206 207 /* set default context info */ 208 ice_set_dflt_val_fd_desc(&fdir_fltr_ctx); 209 210 /* change sideband filtering values */ 211 fdir_fltr_ctx.fdid = input->fltr_id; 212 if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) { 213 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES; 214 fdir_fltr_ctx.qindex = 0; 215 } else { 216 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO; 217 fdir_fltr_ctx.qindex = input->q_index; 218 } 219 fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS; 220 fdir_fltr_ctx.cnt_index = input->cnt_index; 221 fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi); 222 fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE; 223 fdir_fltr_ctx.toq_prio = 3; 224 fdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD : 225 ICE_FXD_FLTR_QW1_PCMD_REMOVE; 226 fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET; 227 fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO; 228 fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW; 229 fdir_fltr_ctx.fdid_prio = 3; 230 fdir_fltr_ctx.desc_prof = 1; 231 fdir_fltr_ctx.desc_prof_prio = 3; 232 ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc); 233 } 234 235 /** 236 * ice_set_fd_desc_val 237 * @fd_fltr_ctx: pointer to fd filter descriptor context 238 * @fdir_desc: populated with fd filter descriptor values 239 */ 240 void 241 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx, 242 struct ice_fltr_desc *fdir_desc) 243 { 244 u64 ctx_buf[2] = { 0 }; 245 246 ice_set_ctx((u8 *)fd_fltr_ctx, (u8 *)ctx_buf, 247 ice_fd_fltr_desc_ctx_info); 248 fdir_desc->qidx_compq_space_stat = CPU_TO_LE64(ctx_buf[0]); 249 fdir_desc->dtype_cmd_vsi_fdid = CPU_TO_LE64(ctx_buf[1]); 250 } 251 252 /** 253 * ice_alloc_fd_res_cntr - obtain counter resource for FD type 254 * @hw: pointer to the hardware structure 255 * @cntr_id: returns counter index 256 */ 257 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id) 258 { 259 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK, 260 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id); 261 } 262 263 /** 264 * ice_free_fd_res_cntr - Free counter resource for FD type 265 * @hw: pointer to the hardware structure 266 * @cntr_id: counter index to be freed 267 */ 268 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id) 269 { 270 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK, 271 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id); 272 } 273 274 /** 275 * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries 276 * @hw: pointer to the hardware structure 277 * @cntr_id: returns counter index 278 * @num_fltr: number of filter entries to be allocated 279 */ 280 enum ice_status 281 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr) 282 { 283 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES, 284 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr, 285 cntr_id); 286 } 287 288 /** 289 * ice_free_fd_guar_item - Free flow director guaranteed entries 290 * @hw: pointer to the hardware structure 291 * @cntr_id: counter index that needs to be freed 292 * @num_fltr: number of filters to be freed 293 */ 294 enum ice_status 295 ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr) 296 { 297 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES, 298 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr, 299 cntr_id); 300 } 301 302 /** 303 * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries 304 * @hw: pointer to the hardware structure 305 * @cntr_id: returns counter index 306 * @num_fltr: number of filter entries to be allocated 307 */ 308 enum ice_status 309 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr) 310 { 311 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES, 312 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr, 313 cntr_id); 314 } 315 316 /** 317 * ice_free_fd_shrd_item - Free flow director shared entries 318 * @hw: pointer to the hardware structure 319 * @cntr_id: counter index that needs to be freed 320 * @num_fltr: number of filters to be freed 321 */ 322 enum ice_status 323 ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr) 324 { 325 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES, 326 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr, 327 cntr_id); 328 } 329 330 /** 331 * ice_get_fdir_cnt_all - get the number of Flow Director filters 332 * @hw: hardware data structure 333 * 334 * Returns the number of filters available on device 335 */ 336 int ice_get_fdir_cnt_all(struct ice_hw *hw) 337 { 338 return hw->func_caps.fd_fltr_guar + 339 hw->func_caps.fd_fltr_best_effort; 340 } 341 342 /** 343 * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer. 344 * @pkt: packet buffer 345 * @offset: offset into buffer 346 * @addr: IPv6 address to convert and insert into pkt at offset 347 */ 348 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr) 349 { 350 int idx; 351 352 for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++) 353 ice_memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx], 354 sizeof(*addr), ICE_NONDMA_TO_NONDMA); 355 } 356 357 /** 358 * ice_pkt_insert_u16 - insert a be16 value into a memory buffer. 359 * @pkt: packet buffer 360 * @offset: offset into buffer 361 * @data: 16 bit value to convert and insert into pkt at offset 362 */ 363 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data) 364 { 365 ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA); 366 } 367 368 /** 369 * ice_pkt_insert_u32 - insert a be32 value into a memory buffer. 370 * @pkt: packet buffer 371 * @offset: offset into buffer 372 * @data: 32 bit value to convert and insert into pkt at offset 373 */ 374 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data) 375 { 376 ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA); 377 } 378 379 /** 380 * ice_fdir_get_prgm_pkt - generate a dummy packet 381 * @input: flow director filter data structure 382 * @pkt: pointer to return filter packet 383 * @frag: generate a fragment packet 384 */ 385 enum ice_status 386 ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag) 387 { 388 enum ice_fltr_ptype flow; 389 u16 idx; 390 391 if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) { 392 switch (input->ip.v4.proto) { 393 case ICE_IP_PROTO_TCP: 394 flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP; 395 break; 396 case ICE_IP_PROTO_UDP: 397 flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP; 398 break; 399 case ICE_IP_PROTO_SCTP: 400 flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP; 401 break; 402 case ICE_IP_PROTO_IP: 403 flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER; 404 break; 405 default: 406 return ICE_ERR_PARAM; 407 } 408 } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) { 409 switch (input->ip.v6.proto) { 410 case ICE_IP_PROTO_TCP: 411 flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP; 412 break; 413 case ICE_IP_PROTO_UDP: 414 flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP; 415 break; 416 case ICE_IP_PROTO_SCTP: 417 flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP; 418 break; 419 case ICE_IP_PROTO_IP: 420 flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER; 421 break; 422 default: 423 return ICE_ERR_PARAM; 424 } 425 } else { 426 flow = input->flow_type; 427 } 428 429 for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++) 430 if (ice_fdir_pkt[idx].flow == flow) 431 break; 432 if (idx == ICE_FDIR_NUM_PKT) 433 return ICE_ERR_PARAM; 434 ice_memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len, 435 ICE_NONDMA_TO_NONDMA); 436 437 switch (flow) { 438 case ICE_FLTR_PTYPE_NONF_IPV4_TCP: 439 ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET, 440 input->ip.v4.dst_ip); 441 ice_pkt_insert_u16(pkt, ICE_IPV4_TCP_DST_PORT_OFFSET, 442 input->ip.v4.dst_port); 443 ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET, 444 input->ip.v4.src_ip); 445 ice_pkt_insert_u16(pkt, ICE_IPV4_TCP_SRC_PORT_OFFSET, 446 input->ip.v4.src_port); 447 if (frag) 448 pkt[20] = ICE_FDIR_IPV4_PKT_FLAG_DF; 449 break; 450 case ICE_FLTR_PTYPE_NONF_IPV4_UDP: 451 ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET, 452 input->ip.v4.dst_ip); 453 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET, 454 input->ip.v4.dst_port); 455 ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET, 456 input->ip.v4.src_ip); 457 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_SRC_PORT_OFFSET, 458 input->ip.v4.src_port); 459 break; 460 case ICE_FLTR_PTYPE_NONF_IPV4_SCTP: 461 ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET, 462 input->ip.v4.dst_ip); 463 ice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_DST_PORT_OFFSET, 464 input->ip.v4.dst_port); 465 ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET, 466 input->ip.v4.src_ip); 467 ice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_SRC_PORT_OFFSET, 468 input->ip.v4.src_port); 469 break; 470 case ICE_FLTR_PTYPE_NONF_IPV4_OTHER: 471 ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET, 472 input->ip.v4.dst_ip); 473 ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET, 474 input->ip.v4.src_ip); 475 ice_pkt_insert_u16(pkt, ICE_IPV4_PROTO_OFFSET, 0); 476 break; 477 case ICE_FLTR_PTYPE_NONF_IPV6_TCP: 478 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET, 479 input->ip.v6.dst_ip); 480 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET, 481 input->ip.v6.src_ip); 482 ice_pkt_insert_u16(pkt, ICE_IPV6_TCP_DST_PORT_OFFSET, 483 input->ip.v6.dst_port); 484 ice_pkt_insert_u16(pkt, ICE_IPV6_TCP_SRC_PORT_OFFSET, 485 input->ip.v6.src_port); 486 break; 487 case ICE_FLTR_PTYPE_NONF_IPV6_UDP: 488 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET, 489 input->ip.v6.dst_ip); 490 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET, 491 input->ip.v6.src_ip); 492 ice_pkt_insert_u16(pkt, ICE_IPV6_UDP_DST_PORT_OFFSET, 493 input->ip.v6.dst_port); 494 ice_pkt_insert_u16(pkt, ICE_IPV6_UDP_SRC_PORT_OFFSET, 495 input->ip.v6.src_port); 496 break; 497 case ICE_FLTR_PTYPE_NONF_IPV6_SCTP: 498 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET, 499 input->ip.v6.dst_ip); 500 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET, 501 input->ip.v6.src_ip); 502 ice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_DST_PORT_OFFSET, 503 input->ip.v6.dst_port); 504 ice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_SRC_PORT_OFFSET, 505 input->ip.v6.src_port); 506 break; 507 case ICE_FLTR_PTYPE_NONF_IPV6_OTHER: 508 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET, 509 input->ip.v6.dst_ip); 510 ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET, 511 input->ip.v6.src_ip); 512 break; 513 default: 514 return ICE_ERR_PARAM; 515 } 516 517 if (input->flex_fltr) 518 ice_pkt_insert_u16(pkt, input->flex_offset, input->flex_word); 519 520 return ICE_SUCCESS; 521 } 522 523 /** 524 * ice_fdir_has_frag - does flow type have 2 ptypes 525 * @flow: flow ptype 526 * 527 * returns true is there is a fragment packet for this ptype 528 */ 529 bool ice_fdir_has_frag(enum ice_fltr_ptype flow) 530 { 531 if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) 532 return true; 533 else 534 return false; 535 } 536 537 /** 538 * ice_fdir_find_by_idx - find filter with idx 539 * @hw: pointer to hardware structure 540 * @fltr_idx: index to find. 541 * 542 * Returns pointer to filter if found or null 543 */ 544 struct ice_fdir_fltr * 545 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx) 546 { 547 struct ice_fdir_fltr *rule = NULL; 548 549 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr, 550 fltr_node) { 551 /* rule ID found in the list */ 552 if (fltr_idx == rule->fltr_id) 553 return rule; 554 if (fltr_idx < rule->fltr_id) 555 break; 556 } 557 return NULL; 558 } 559 560 /** 561 * ice_fdir_list_add_fltr - add a new node to the flow director filter list 562 * @hw: hardware structure 563 * @fltr: filter node to add to structure 564 */ 565 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr) 566 { 567 struct ice_fdir_fltr *rule, *parent = NULL; 568 569 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr, 570 fltr_node) { 571 /* rule ID found or pass its spot in the list */ 572 if (rule->fltr_id >= fltr->fltr_id) 573 break; 574 parent = rule; 575 } 576 577 if (parent) 578 LIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node); 579 else 580 LIST_ADD(&fltr->fltr_node, &hw->fdir_list_head); 581 } 582 583 /** 584 * ice_fdir_update_cntrs - increment / decrement filter counter 585 * @hw: pointer to hardware structure 586 * @flow: filter flow type 587 * @add: true implies filters added 588 */ 589 void 590 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add) 591 { 592 int incr; 593 594 incr = (add) ? 1 : -1; 595 hw->fdir_active_fltr += incr; 596 if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX) 597 ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow); 598 else 599 hw->fdir_fltr_cnt[flow] += incr; 600 } 601 602 /** 603 * ice_cmp_ipv6_addr - compare 2 IP v6 addresses 604 * @a: IP v6 address 605 * @b: IP v6 address 606 * 607 * Returns 0 on equal, returns non-0 if different 608 */ 609 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b) 610 { 611 return memcmp(a, b, 4 * sizeof(__be32)); 612 } 613 614 /** 615 * ice_fdir_comp_ipv6_rules - compare 2 filters 616 * @a: a Flow Director filter data structure 617 * @b: a Flow Director filter data structure 618 * @v6: bool true if v6 filter 619 * 620 * Returns true if the filters match 621 */ 622 static bool 623 ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b, bool v6) 624 { 625 enum ice_fltr_ptype flow_type = a->flow_type; 626 627 /* The calling function already checks that the two filters have the 628 * same flow_type. 629 */ 630 if (!v6) { 631 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP || 632 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP || 633 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) { 634 if (a->ip.v4.dst_ip == b->ip.v4.dst_ip && 635 a->ip.v4.src_ip == b->ip.v4.src_ip && 636 a->ip.v4.dst_port == b->ip.v4.dst_port && 637 a->ip.v4.src_port == b->ip.v4.src_port) 638 return true; 639 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) { 640 if (a->ip.v4.dst_ip == b->ip.v4.dst_ip && 641 a->ip.v4.src_ip == b->ip.v4.src_ip && 642 a->ip.v4.l4_header == b->ip.v4.l4_header && 643 a->ip.v4.proto == b->ip.v4.proto && 644 a->ip.v4.ip_ver == b->ip.v4.ip_ver && 645 a->ip.v4.tos == b->ip.v4.tos) 646 return true; 647 } 648 } else { 649 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP || 650 flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP || 651 flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) { 652 if (a->ip.v6.dst_port == b->ip.v6.dst_port && 653 a->ip.v6.src_port == b->ip.v6.src_port && 654 !ice_cmp_ipv6_addr(a->ip.v6.dst_ip, 655 b->ip.v6.dst_ip) && 656 !ice_cmp_ipv6_addr(a->ip.v6.src_ip, 657 b->ip.v6.src_ip)) 658 return true; 659 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) { 660 if (a->ip.v6.dst_port == b->ip.v6.dst_port && 661 a->ip.v6.src_port == b->ip.v6.src_port) 662 return true; 663 } 664 } 665 666 return false; 667 } 668 669 /** 670 * ice_fdir_is_dup_fltr - test if filter is already in list for PF 671 * @hw: hardware data structure 672 * @input: Flow Director filter data structure 673 * 674 * Returns true if the filter is found in the list 675 */ 676 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input) 677 { 678 enum ice_fltr_ptype flow_type; 679 struct ice_fdir_fltr *rule; 680 bool ret = false; 681 682 rule = NULL; 683 684 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr, 685 fltr_node) { 686 if (rule->flow_type == input->flow_type) { 687 flow_type = input->flow_type; 688 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP || 689 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP || 690 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP || 691 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) 692 ret = ice_fdir_comp_rules(rule, input, false); 693 else 694 ret = ice_fdir_comp_rules(rule, input, true); 695 if (ret) 696 break; 697 } 698 } 699 700 return ret; 701 } 702 703 /** 704 * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI 705 * @hw: hardware data structure 706 * @vsi_num: vsi_num (HW VSI num) 707 * 708 * Clears FD table entries by issuing admin command (direct, 0x0B06) 709 * Must to pass valid vsi_num as returned by "AddVSI". 710 */ 711 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num) 712 { 713 struct ice_aqc_clear_fd_table *cmd; 714 struct ice_aq_desc desc; 715 716 cmd = &desc.params.clear_fd_table; 717 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table); 718 cmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX; 719 720 cmd->vsi_index = CPU_TO_LE16(vsi_num); 721 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 722 } 723 724 /** 725 * ice_clear_pf_fd_table - admin command to clear FD table for PF 726 * @hw: hardware data structure 727 * 728 * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06) 729 */ 730 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw) 731 { 732 struct ice_aqc_clear_fd_table *cmd; 733 struct ice_aq_desc desc; 734 735 cmd = &desc.params.clear_fd_table; 736 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table); 737 cmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX; 738 /* vsi_index must be 0 to clear FD table for a PF */ 739 cmd->vsi_index = CPU_TO_LE16(0); 740 741 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 742 } 743