1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2021 Intel Corporation 3 */ 4 5 #include "ice_common.h" 6 #include "ice_parser_util.h" 7 8 #define ICE_SEC_DATA_OFFSET 4 9 #define ICE_SID_RXPARSER_IMEM_ENTRY_SIZE 48 10 #define ICE_SID_RXPARSER_METADATA_INIT_ENTRY_SIZE 24 11 #define ICE_SID_RXPARSER_CAM_ENTRY_SIZE 16 12 #define ICE_SID_RXPARSER_PG_SPILL_ENTRY_SIZE 17 13 #define ICE_SID_RXPARSER_NOMATCH_CAM_ENTRY_SIZE 12 14 #define ICE_SID_RXPARSER_NOMATCH_SPILL_ENTRY_SIZE 13 15 #define ICE_SID_RXPARSER_BOOST_TCAM_ENTRY_SIZE 88 16 #define ICE_SID_RXPARSER_MARKER_TYPE_ENTRY_SIZE 24 17 #define ICE_SID_RXPARSER_MARKER_GRP_ENTRY_SIZE 8 18 #define ICE_SID_RXPARSER_PROTO_GRP_ENTRY_SIZE 24 19 #define ICE_SID_RXPARSER_FLAG_REDIR_ENTRY_SIZE 1 20 21 #define ICE_SEC_LBL_DATA_OFFSET 2 22 #define ICE_SID_LBL_ENTRY_SIZE 66 23 24 void ice_lbl_dump(struct ice_hw *hw, struct ice_lbl_item *item) 25 { 26 ice_info(hw, "index = %d\n", item->idx); 27 ice_info(hw, "label = %s\n", item->label); 28 } 29 30 void ice_parse_item_dflt(struct ice_hw *hw, u16 idx, void *item, 31 void *data, int size) 32 { 33 ice_memcpy(item, data, size, ICE_DMA_TO_NONDMA); 34 } 35 36 /** 37 * ice_parser_sect_item_get - parse a item from a section 38 * @sect_type: section type 39 * @section: section object 40 * @index: index of the item to get 41 * @offset: dummy as prototype of ice_pkg_enum_entry's last parameter 42 */ 43 void *ice_parser_sect_item_get(u32 sect_type, void *section, 44 u32 index, u32 *offset) 45 { 46 struct ice_pkg_sect_hdr *hdr; 47 int data_off = ICE_SEC_DATA_OFFSET; 48 int size; 49 50 if (!section) 51 return NULL; 52 53 switch (sect_type) { 54 case ICE_SID_RXPARSER_IMEM: 55 size = ICE_SID_RXPARSER_IMEM_ENTRY_SIZE; 56 break; 57 case ICE_SID_RXPARSER_METADATA_INIT: 58 size = ICE_SID_RXPARSER_METADATA_INIT_ENTRY_SIZE; 59 break; 60 case ICE_SID_RXPARSER_CAM: 61 size = ICE_SID_RXPARSER_CAM_ENTRY_SIZE; 62 break; 63 case ICE_SID_RXPARSER_PG_SPILL: 64 size = ICE_SID_RXPARSER_PG_SPILL_ENTRY_SIZE; 65 break; 66 case ICE_SID_RXPARSER_NOMATCH_CAM: 67 size = ICE_SID_RXPARSER_NOMATCH_CAM_ENTRY_SIZE; 68 break; 69 case ICE_SID_RXPARSER_NOMATCH_SPILL: 70 size = ICE_SID_RXPARSER_NOMATCH_SPILL_ENTRY_SIZE; 71 break; 72 case ICE_SID_RXPARSER_BOOST_TCAM: 73 size = ICE_SID_RXPARSER_BOOST_TCAM_ENTRY_SIZE; 74 break; 75 case ICE_SID_LBL_RXPARSER_TMEM: 76 data_off = ICE_SEC_LBL_DATA_OFFSET; 77 size = ICE_SID_LBL_ENTRY_SIZE; 78 break; 79 case ICE_SID_RXPARSER_MARKER_PTYPE: 80 size = ICE_SID_RXPARSER_MARKER_TYPE_ENTRY_SIZE; 81 break; 82 case ICE_SID_RXPARSER_MARKER_GRP: 83 size = ICE_SID_RXPARSER_MARKER_GRP_ENTRY_SIZE; 84 break; 85 case ICE_SID_RXPARSER_PROTO_GRP: 86 size = ICE_SID_RXPARSER_PROTO_GRP_ENTRY_SIZE; 87 break; 88 case ICE_SID_RXPARSER_FLAG_REDIR: 89 size = ICE_SID_RXPARSER_FLAG_REDIR_ENTRY_SIZE; 90 break; 91 default: 92 return NULL; 93 } 94 95 hdr = (struct ice_pkg_sect_hdr *)section; 96 if (index >= LE16_TO_CPU(hdr->count)) 97 return NULL; 98 99 return (void *)((uintptr_t)section + data_off + index * size); 100 } 101 102 /** 103 * ice_parser_create_table - create a item table from a section 104 * @hw: pointer to the hardware structure 105 * @sect_type: section type 106 * @item_size: item size in byte 107 * @length: number of items in the table to create 108 * @item_get: the function will be parsed to ice_pkg_enum_entry 109 * @parser_item: the function to parse the item 110 * @no_offset: ignore header offset, calculate index from 0 111 */ 112 void *ice_parser_create_table(struct ice_hw *hw, u32 sect_type, 113 u32 item_size, u32 length, 114 void *(*item_get)(u32 sect_type, void *section, 115 u32 index, u32 *offset), 116 void (*parse_item)(struct ice_hw *hw, u16 idx, 117 void *item, void *data, 118 int size), 119 bool no_offset) 120 { 121 struct ice_seg *seg = hw->seg; 122 struct ice_pkg_enum state; 123 u16 idx = 0xffff; 124 void *table; 125 void *data; 126 127 if (!seg) 128 return NULL; 129 130 table = ice_malloc(hw, item_size * length); 131 if (!table) { 132 ice_debug(hw, ICE_DBG_PARSER, "failed to allocate memory for table type %d.\n", 133 sect_type); 134 return NULL; 135 } 136 137 ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); 138 do { 139 data = ice_pkg_enum_entry(seg, &state, sect_type, NULL, 140 item_get); 141 seg = NULL; 142 if (data) { 143 struct ice_pkg_sect_hdr *hdr = 144 (struct ice_pkg_sect_hdr *)state.sect; 145 146 if (no_offset) 147 idx++; 148 else 149 idx = hdr->offset + state.entry_idx; 150 parse_item(hw, idx, 151 (void *)((uintptr_t)table + idx * item_size), 152 data, item_size); 153 } 154 } while (data); 155 156 return table; 157 } 158 159 /** 160 * ice_parser_create - create a parser instance 161 * @hw: pointer to the hardware structure 162 * @psr: output parameter for a new parser instance be created 163 */ 164 enum ice_status ice_parser_create(struct ice_hw *hw, struct ice_parser **psr) 165 { 166 enum ice_status status; 167 struct ice_parser *p; 168 169 p = (struct ice_parser *)ice_malloc(hw, sizeof(struct ice_parser)); 170 if (!p) 171 return ICE_ERR_NO_MEMORY; 172 173 p->hw = hw; 174 p->rt.psr = p; 175 176 p->imem_table = ice_imem_table_get(hw); 177 if (!p->imem_table) { 178 status = ICE_ERR_PARAM; 179 goto err; 180 } 181 182 p->mi_table = ice_metainit_table_get(hw); 183 if (!p->mi_table) { 184 status = ICE_ERR_PARAM; 185 goto err; 186 } 187 188 p->pg_cam_table = ice_pg_cam_table_get(hw); 189 if (!p->pg_cam_table) { 190 status = ICE_ERR_PARAM; 191 goto err; 192 } 193 194 p->pg_sp_cam_table = ice_pg_sp_cam_table_get(hw); 195 if (!p->pg_sp_cam_table) { 196 status = ICE_ERR_PARAM; 197 goto err; 198 } 199 200 p->pg_nm_cam_table = ice_pg_nm_cam_table_get(hw); 201 if (!p->pg_nm_cam_table) { 202 status = ICE_ERR_PARAM; 203 goto err; 204 } 205 206 p->pg_nm_sp_cam_table = ice_pg_nm_sp_cam_table_get(hw); 207 if (!p->pg_nm_sp_cam_table) { 208 status = ICE_ERR_PARAM; 209 goto err; 210 } 211 212 p->bst_tcam_table = ice_bst_tcam_table_get(hw); 213 if (!p->bst_tcam_table) { 214 status = ICE_ERR_PARAM; 215 goto err; 216 } 217 218 p->bst_lbl_table = ice_bst_lbl_table_get(hw); 219 if (!p->bst_lbl_table) { 220 status = ICE_ERR_PARAM; 221 goto err; 222 } 223 224 p->ptype_mk_tcam_table = ice_ptype_mk_tcam_table_get(hw); 225 if (!p->ptype_mk_tcam_table) { 226 status = ICE_ERR_PARAM; 227 goto err; 228 } 229 230 p->mk_grp_table = ice_mk_grp_table_get(hw); 231 if (!p->mk_grp_table) { 232 status = ICE_ERR_PARAM; 233 goto err; 234 } 235 236 p->proto_grp_table = ice_proto_grp_table_get(hw); 237 if (!p->proto_grp_table) { 238 status = ICE_ERR_PARAM; 239 goto err; 240 } 241 242 p->flg_rd_table = ice_flg_rd_table_get(hw); 243 if (!p->flg_rd_table) { 244 status = ICE_ERR_PARAM; 245 goto err; 246 } 247 248 p->xlt_kb_sw = ice_xlt_kb_get_sw(hw); 249 if (!p->xlt_kb_sw) { 250 status = ICE_ERR_PARAM; 251 goto err; 252 } 253 254 p->xlt_kb_acl = ice_xlt_kb_get_acl(hw); 255 if (!p->xlt_kb_acl) { 256 status = ICE_ERR_PARAM; 257 goto err; 258 } 259 260 p->xlt_kb_fd = ice_xlt_kb_get_fd(hw); 261 if (!p->xlt_kb_fd) { 262 status = ICE_ERR_PARAM; 263 goto err; 264 } 265 266 p->xlt_kb_rss = ice_xlt_kb_get_rss(hw); 267 if (!p->xlt_kb_rss) { 268 status = ICE_ERR_PARAM; 269 goto err; 270 } 271 272 *psr = p; 273 return ICE_SUCCESS; 274 err: 275 ice_parser_destroy(p); 276 return status; 277 } 278 279 /** 280 * ice_parser_destroy - destroy a parser instance 281 * @psr: pointer to a parser instance 282 */ 283 void ice_parser_destroy(struct ice_parser *psr) 284 { 285 ice_free(psr->hw, psr->imem_table); 286 ice_free(psr->hw, psr->mi_table); 287 ice_free(psr->hw, psr->pg_cam_table); 288 ice_free(psr->hw, psr->pg_sp_cam_table); 289 ice_free(psr->hw, psr->pg_nm_cam_table); 290 ice_free(psr->hw, psr->pg_nm_sp_cam_table); 291 ice_free(psr->hw, psr->bst_tcam_table); 292 ice_free(psr->hw, psr->bst_lbl_table); 293 ice_free(psr->hw, psr->ptype_mk_tcam_table); 294 ice_free(psr->hw, psr->mk_grp_table); 295 ice_free(psr->hw, psr->proto_grp_table); 296 ice_free(psr->hw, psr->flg_rd_table); 297 ice_free(psr->hw, psr->xlt_kb_sw); 298 ice_free(psr->hw, psr->xlt_kb_acl); 299 ice_free(psr->hw, psr->xlt_kb_fd); 300 ice_free(psr->hw, psr->xlt_kb_rss); 301 302 ice_free(psr->hw, psr); 303 } 304 305 /** 306 * ice_parser_run - parse on a packet in binary and return the result 307 * @psr: pointer to a parser instance 308 * @pkt_buf: packet data 309 * @pkt_len: packet length 310 * @rslt: input/output parameter to save parser result. 311 */ 312 enum ice_status ice_parser_run(struct ice_parser *psr, const u8 *pkt_buf, 313 int pkt_len, struct ice_parser_result *rslt) 314 { 315 ice_parser_rt_reset(&psr->rt); 316 ice_parser_rt_pktbuf_set(&psr->rt, pkt_buf, pkt_len); 317 318 return ice_parser_rt_execute(&psr->rt, rslt); 319 } 320 321 /** 322 * ice_parser_result_dump - dump a parser result info 323 * @hw: pointer to the hardware structure 324 * @rslt: parser result info to dump 325 */ 326 void ice_parser_result_dump(struct ice_hw *hw, struct ice_parser_result *rslt) 327 { 328 int i; 329 330 ice_info(hw, "ptype = %d\n", rslt->ptype); 331 for (i = 0; i < rslt->po_num; i++) 332 ice_info(hw, "proto = %d, offset = %d\n", 333 rslt->po[i].proto_id, rslt->po[i].offset); 334 335 ice_info(hw, "flags_psr = 0x%016" PRIx64 "\n", rslt->flags_psr); 336 ice_info(hw, "flags_pkt = 0x%016" PRIx64 "\n", rslt->flags_pkt); 337 ice_info(hw, "flags_sw = 0x%04x\n", rslt->flags_sw); 338 ice_info(hw, "flags_fd = 0x%04x\n", rslt->flags_fd); 339 ice_info(hw, "flags_rss = 0x%04x\n", rslt->flags_rss); 340 } 341 342 static void _bst_vm_set(struct ice_parser *psr, const char *prefix, bool on) 343 { 344 struct ice_bst_tcam_item *item; 345 u16 i = 0; 346 347 while (true) { 348 item = ice_bst_tcam_search(psr->bst_tcam_table, 349 psr->bst_lbl_table, 350 prefix, &i); 351 if (!item) 352 break; 353 item->key[0] = (u8)(on ? 0xff : 0xfe); 354 item->key_inv[0] = (u8)(on ? 0xff : 0xfe); 355 i++; 356 } 357 } 358 359 /** 360 * ice_parser_dvm_set - configure double vlan mode for parser 361 * @psr: pointer to a parser instance 362 */ 363 void ice_parser_dvm_set(struct ice_parser *psr, bool on) 364 { 365 _bst_vm_set(psr, "BOOST_MAC_VLAN_DVM", on); 366 _bst_vm_set(psr, "BOOST_MAC_VLAN_SVM", !on); 367 } 368 369 static enum ice_status 370 _tunnel_port_set(struct ice_parser *psr, const char *prefix, u16 udp_port, 371 bool on) 372 { 373 u8 *buf = (u8 *)&udp_port; 374 struct ice_bst_tcam_item *item; 375 u16 i = 0; 376 377 while (true) { 378 item = ice_bst_tcam_search(psr->bst_tcam_table, 379 psr->bst_lbl_table, 380 prefix, &i); 381 if (!item) 382 break; 383 384 /* found empty slot to add */ 385 if (on && item->key[16] == 0xfe && item->key_inv[16] == 0xfe) { 386 item->key_inv[15] = buf[0]; 387 item->key_inv[16] = buf[1]; 388 item->key[15] = (u8)(0xff - buf[0]); 389 item->key[16] = (u8)(0xff - buf[1]); 390 391 return ICE_SUCCESS; 392 /* found a matched slot to delete */ 393 } else if (!on && (item->key_inv[15] == buf[0] || 394 item->key_inv[16] == buf[1])) { 395 item->key_inv[15] = 0xff; 396 item->key_inv[16] = 0xfe; 397 item->key[15] = 0xff; 398 item->key[16] = 0xfe; 399 400 return ICE_SUCCESS; 401 } 402 i++; 403 } 404 405 return ICE_ERR_PARAM; 406 } 407 408 /** 409 * ice_parser_vxlan_tunnel_set - configure vxlan tunnel for parser 410 * @psr: pointer to a parser instance 411 * @udp_port: vxlan tunnel port in UDP header 412 * @on: true to turn on; false to turn off 413 */ 414 enum ice_status ice_parser_vxlan_tunnel_set(struct ice_parser *psr, 415 u16 udp_port, bool on) 416 { 417 return _tunnel_port_set(psr, "TNL_VXLAN", udp_port, on); 418 } 419 420 /** 421 * ice_parser_geneve_tunnel_set - configure geneve tunnel for parser 422 * @psr: pointer to a parser instance 423 * @udp_port: geneve tunnel port in UDP header 424 * @on: true to turn on; false to turn off 425 */ 426 enum ice_status ice_parser_geneve_tunnel_set(struct ice_parser *psr, 427 u16 udp_port, bool on) 428 { 429 return _tunnel_port_set(psr, "TNL_GENEVE", udp_port, on); 430 } 431 432 /** 433 * ice_parser_ecpri_tunnel_set - configure ecpri tunnel for parser 434 * @psr: pointer to a parser instance 435 * @udp_port: ecpri tunnel port in UDP header 436 * @on: true to turn on; false to turn off 437 */ 438 enum ice_status ice_parser_ecpri_tunnel_set(struct ice_parser *psr, 439 u16 udp_port, bool on) 440 { 441 return _tunnel_port_set(psr, "TNL_UDP_ECPRI", udp_port, on); 442 } 443 444 static bool _nearest_proto_id(struct ice_parser_result *rslt, u16 offset, 445 u8 *proto_id, u16 *proto_off) 446 { 447 u16 dist = 0xffff; 448 u8 p = 0; 449 int i; 450 451 for (i = 0; i < rslt->po_num; i++) { 452 if (offset < rslt->po[i].offset) 453 continue; 454 if (offset - rslt->po[i].offset < dist) { 455 p = rslt->po[i].proto_id; 456 dist = offset - rslt->po[i].offset; 457 } 458 } 459 460 if (dist % 2) 461 return false; 462 463 *proto_id = p; 464 *proto_off = dist; 465 466 return true; 467 } 468 469 /** default flag mask to cover GTP_EH_PDU, GTP_EH_PDU_LINK and TUN2 470 * In future, the flag masks should learn from DDP 471 */ 472 #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW 0x4002 473 #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL 0x0000 474 #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD 0x6080 475 #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS 0x6010 476 477 /** 478 * ice_parser_profile_init - initialize a FXP profile base on parser result 479 * @rslt: a instance of a parser result 480 * @pkt_buf: packet data buffer 481 * @pkt_msk: packet mask buffer 482 * @pkt_len: packet length 483 * @blk: FXP pipeline stage 484 * @prefix_match: match protocol stack exactly or only prefix 485 * @prof: input/output parameter to save the profile 486 */ 487 enum ice_status ice_parser_profile_init(struct ice_parser_result *rslt, 488 const u8 *pkt_buf, const u8 *msk_buf, 489 int buf_len, enum ice_block blk, 490 bool prefix_match, 491 struct ice_parser_profile *prof) 492 { 493 u8 proto_id = 0xff; 494 u16 proto_off = 0; 495 u16 off; 496 497 ice_memset(prof, 0, sizeof(*prof), ICE_NONDMA_MEM); 498 ice_set_bit(rslt->ptype, prof->ptypes); 499 if (blk == ICE_BLK_SW) { 500 prof->flags = rslt->flags_sw; 501 prof->flags_msk = ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW; 502 } else if (blk == ICE_BLK_ACL) { 503 prof->flags = rslt->flags_acl; 504 prof->flags_msk = ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL; 505 } else if (blk == ICE_BLK_FD) { 506 prof->flags = rslt->flags_fd; 507 prof->flags_msk = ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD; 508 } else if (blk == ICE_BLK_RSS) { 509 prof->flags = rslt->flags_rss; 510 prof->flags_msk = ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS; 511 } else { 512 return ICE_ERR_PARAM; 513 } 514 515 for (off = 0; off < buf_len - 1; off++) { 516 if (msk_buf[off] == 0 && msk_buf[off + 1] == 0) 517 continue; 518 if (!_nearest_proto_id(rslt, off, &proto_id, &proto_off)) 519 continue; 520 if (prof->fv_num >= 32) 521 return ICE_ERR_PARAM; 522 523 prof->fv[prof->fv_num].proto_id = proto_id; 524 prof->fv[prof->fv_num].offset = proto_off; 525 prof->fv[prof->fv_num].spec = *(const u16 *)&pkt_buf[off]; 526 prof->fv[prof->fv_num].msk = *(const u16 *)&msk_buf[off]; 527 prof->fv_num++; 528 } 529 530 return ICE_SUCCESS; 531 } 532 533 /** 534 * ice_parser_profile_dump - dump an FXP profile info 535 * @hw: pointer to the hardware structure 536 * @prof: profile info to dump 537 */ 538 void ice_parser_profile_dump(struct ice_hw *hw, struct ice_parser_profile *prof) 539 { 540 u16 i; 541 542 ice_info(hw, "ptypes:\n"); 543 for (i = 0; i < ICE_FLOW_PTYPE_MAX; i++) 544 if (ice_is_bit_set(prof->ptypes, i)) 545 ice_info(hw, "\t%d\n", i); 546 547 for (i = 0; i < prof->fv_num; i++) 548 ice_info(hw, "proto = %d, offset = %d spec = 0x%04x, mask = 0x%04x\n", 549 prof->fv[i].proto_id, prof->fv[i].offset, 550 prof->fv[i].spec, prof->fv[i].msk); 551 552 ice_info(hw, "flags = 0x%04x\n", prof->flags); 553 ice_info(hw, "flags_msk = 0x%04x\n", prof->flags_msk); 554 } 555