1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Huawei Technologies Co., Ltd 3 */ 4 5 #include <stdio.h> 6 #include <errno.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include <rte_byteorder.h> 12 #include <rte_common.h> 13 #include <rte_ether.h> 14 #include <rte_ethdev.h> 15 #include <rte_malloc.h> 16 #include <rte_flow.h> 17 #include <rte_flow_driver.h> 18 #include "base/hinic_compat.h" 19 #include "base/hinic_pmd_hwdev.h" 20 #include "base/hinic_pmd_hwif.h" 21 #include "base/hinic_pmd_wq.h" 22 #include "base/hinic_pmd_cmdq.h" 23 #include "base/hinic_pmd_niccfg.h" 24 #include "hinic_pmd_ethdev.h" 25 26 #define HINIC_MAX_RX_QUEUE_NUM 64 27 28 #ifndef UINT8_MAX 29 #define UINT8_MAX (u8)(~((u8)0)) /* 0xFF */ 30 #define UINT16_MAX (u16)(~((u16)0)) /* 0xFFFF */ 31 #define UINT32_MAX (u32)(~((u32)0)) /* 0xFFFFFFFF */ 32 #define UINT64_MAX (u64)(~((u64)0)) /* 0xFFFFFFFFFFFFFFFF */ 33 #define ASCII_MAX (0x7F) 34 #endif 35 36 /* IPSURX MACRO */ 37 #define PA_ETH_TYPE_ROCE 0 38 #define PA_ETH_TYPE_IPV4 1 39 #define PA_ETH_TYPE_IPV6 2 40 #define PA_ETH_TYPE_OTHER 3 41 42 #define PA_IP_PROTOCOL_TYPE_TCP 1 43 #define PA_IP_PROTOCOL_TYPE_UDP 2 44 #define PA_IP_PROTOCOL_TYPE_ICMP 3 45 #define PA_IP_PROTOCOL_TYPE_IPV4_IGMP 4 46 #define PA_IP_PROTOCOL_TYPE_SCTP 5 47 #define PA_IP_PROTOCOL_TYPE_VRRP 112 48 49 #define IP_HEADER_PROTOCOL_TYPE_TCP 6 50 #define IP_HEADER_PROTOCOL_TYPE_UDP 17 51 #define IP_HEADER_PROTOCOL_TYPE_ICMP 1 52 #define IP_HEADER_PROTOCOL_TYPE_ICMPV6 58 53 54 #define FDIR_TCAM_NORMAL_PACKET 0 55 #define FDIR_TCAM_TUNNEL_PACKET 1 56 57 #define HINIC_MIN_N_TUPLE_PRIO 1 58 #define HINIC_MAX_N_TUPLE_PRIO 7 59 60 /* TCAM type mask in hardware */ 61 #define TCAM_PKT_BGP_SPORT 1 62 #define TCAM_PKT_VRRP 2 63 #define TCAM_PKT_BGP_DPORT 3 64 #define TCAM_PKT_LACP 4 65 66 #define TCAM_DIP_IPV4_TYPE 0 67 #define TCAM_DIP_IPV6_TYPE 1 68 69 #define BGP_DPORT_ID 179 70 #define IPPROTO_VRRP 112 71 72 /* Packet type defined in hardware to perform filter */ 73 #define PKT_IGMP_IPV4_TYPE 64 74 #define PKT_ICMP_IPV4_TYPE 65 75 #define PKT_ICMP_IPV6_TYPE 66 76 #define PKT_ICMP_IPV6RS_TYPE 67 77 #define PKT_ICMP_IPV6RA_TYPE 68 78 #define PKT_ICMP_IPV6NS_TYPE 69 79 #define PKT_ICMP_IPV6NA_TYPE 70 80 #define PKT_ICMP_IPV6RE_TYPE 71 81 #define PKT_DHCP_IPV4_TYPE 72 82 #define PKT_DHCP_IPV6_TYPE 73 83 #define PKT_LACP_TYPE 74 84 #define PKT_ARP_REQ_TYPE 79 85 #define PKT_ARP_REP_TYPE 80 86 #define PKT_ARP_TYPE 81 87 #define PKT_BGPD_DPORT_TYPE 83 88 #define PKT_BGPD_SPORT_TYPE 84 89 #define PKT_VRRP_TYPE 85 90 91 #define HINIC_DEV_PRIVATE_TO_FILTER_INFO(nic_dev) \ 92 (&((struct hinic_nic_dev *)nic_dev)->filter) 93 94 #define HINIC_DEV_PRIVATE_TO_TCAM_INFO(nic_dev) \ 95 (&((struct hinic_nic_dev *)nic_dev)->tcam) 96 97 98 enum hinic_atr_flow_type { 99 HINIC_ATR_FLOW_TYPE_IPV4_DIP = 0x1, 100 HINIC_ATR_FLOW_TYPE_IPV4_SIP = 0x2, 101 HINIC_ATR_FLOW_TYPE_DPORT = 0x3, 102 HINIC_ATR_FLOW_TYPE_SPORT = 0x4, 103 }; 104 105 /* Structure to store fdir's info. */ 106 struct hinic_fdir_info { 107 uint8_t fdir_flag; 108 uint8_t qid; 109 uint32_t fdir_key; 110 }; 111 112 /** 113 * Endless loop will never happen with below assumption 114 * 1. there is at least one no-void item(END) 115 * 2. cur is before END. 116 */ 117 static inline const struct rte_flow_item * 118 next_no_void_pattern(const struct rte_flow_item pattern[], 119 const struct rte_flow_item *cur) 120 { 121 const struct rte_flow_item *next = 122 cur ? cur + 1 : &pattern[0]; 123 while (1) { 124 if (next->type != RTE_FLOW_ITEM_TYPE_VOID) 125 return next; 126 next++; 127 } 128 } 129 130 static inline const struct rte_flow_action * 131 next_no_void_action(const struct rte_flow_action actions[], 132 const struct rte_flow_action *cur) 133 { 134 const struct rte_flow_action *next = 135 cur ? cur + 1 : &actions[0]; 136 while (1) { 137 if (next->type != RTE_FLOW_ACTION_TYPE_VOID) 138 return next; 139 next++; 140 } 141 } 142 143 static int hinic_check_ethertype_attr_ele(const struct rte_flow_attr *attr, 144 struct rte_flow_error *error) 145 { 146 /* Must be input direction */ 147 if (!attr->ingress) { 148 rte_flow_error_set(error, EINVAL, 149 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 150 attr, "Only support ingress."); 151 return -rte_errno; 152 } 153 154 if (attr->egress) { 155 rte_flow_error_set(error, EINVAL, 156 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 157 attr, "Not support egress."); 158 return -rte_errno; 159 } 160 161 if (attr->priority) { 162 rte_flow_error_set(error, EINVAL, 163 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 164 attr, "Not support priority."); 165 return -rte_errno; 166 } 167 168 if (attr->group) { 169 rte_flow_error_set(error, EINVAL, 170 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 171 attr, "Not support group."); 172 return -rte_errno; 173 } 174 175 return 0; 176 } 177 178 static int hinic_check_filter_arg(const struct rte_flow_attr *attr, 179 const struct rte_flow_item *pattern, 180 const struct rte_flow_action *actions, 181 struct rte_flow_error *error) 182 { 183 if (!pattern) { 184 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, 185 NULL, "NULL pattern."); 186 return -rte_errno; 187 } 188 189 if (!actions) { 190 rte_flow_error_set(error, EINVAL, 191 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 192 NULL, "NULL action."); 193 return -rte_errno; 194 } 195 196 if (!attr) { 197 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, 198 NULL, "NULL attribute."); 199 return -rte_errno; 200 } 201 202 return 0; 203 } 204 205 static int hinic_check_ethertype_first_item(const struct rte_flow_item *item, 206 struct rte_flow_error *error) 207 { 208 /* The first non-void item should be MAC */ 209 if (item->type != RTE_FLOW_ITEM_TYPE_ETH) { 210 rte_flow_error_set(error, EINVAL, 211 RTE_FLOW_ERROR_TYPE_ITEM, 212 item, "Not supported by ethertype filter"); 213 return -rte_errno; 214 } 215 216 /* Not supported last point for range */ 217 if (item->last) { 218 rte_flow_error_set(error, EINVAL, 219 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 220 item, "Not supported last point for range"); 221 return -rte_errno; 222 } 223 224 /* Get the MAC info. */ 225 if (!item->spec || !item->mask) { 226 rte_flow_error_set(error, EINVAL, 227 RTE_FLOW_ERROR_TYPE_ITEM, 228 item, "Not supported by ethertype filter"); 229 return -rte_errno; 230 } 231 return 0; 232 } 233 234 static int 235 hinic_parse_ethertype_aciton(const struct rte_flow_action *actions, 236 const struct rte_flow_action *act, 237 const struct rte_flow_action_queue *act_q, 238 struct rte_eth_ethertype_filter *filter, 239 struct rte_flow_error *error) 240 { 241 /* Parse action */ 242 act = next_no_void_action(actions, NULL); 243 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE && 244 act->type != RTE_FLOW_ACTION_TYPE_DROP) { 245 rte_flow_error_set(error, EINVAL, 246 RTE_FLOW_ERROR_TYPE_ACTION, 247 act, "Not supported action."); 248 return -rte_errno; 249 } 250 251 if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) { 252 act_q = (const struct rte_flow_action_queue *)act->conf; 253 filter->queue = act_q->index; 254 } else { 255 filter->flags |= RTE_ETHTYPE_FLAGS_DROP; 256 } 257 258 /* Check if the next non-void item is END */ 259 act = next_no_void_action(actions, act); 260 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 261 rte_flow_error_set(error, EINVAL, 262 RTE_FLOW_ERROR_TYPE_ACTION, 263 act, "Not supported action."); 264 return -rte_errno; 265 } 266 267 return 0; 268 } 269 270 /** 271 * Parse the rule to see if it is a ethertype rule. 272 * And get the ethertype filter info BTW. 273 * pattern: 274 * The first not void item can be ETH. 275 * The next not void item must be END. 276 * action: 277 * The first not void action should be QUEUE. 278 * The next not void action should be END. 279 * pattern example: 280 * ITEM Spec Mask 281 * ETH type 0x0807 0xFFFF 282 * END 283 * other members in mask and spec should set to 0x00. 284 * item->last should be NULL. 285 */ 286 static int cons_parse_ethertype_filter(const struct rte_flow_attr *attr, 287 const struct rte_flow_item *pattern, 288 const struct rte_flow_action *actions, 289 struct rte_eth_ethertype_filter *filter, 290 struct rte_flow_error *error) 291 { 292 const struct rte_flow_item *item; 293 const struct rte_flow_action *act = NULL; 294 const struct rte_flow_item_eth *eth_spec; 295 const struct rte_flow_item_eth *eth_mask; 296 const struct rte_flow_action_queue *act_q = NULL; 297 298 if (hinic_check_filter_arg(attr, pattern, actions, error)) 299 return -rte_errno; 300 301 item = next_no_void_pattern(pattern, NULL); 302 if (hinic_check_ethertype_first_item(item, error)) 303 return -rte_errno; 304 305 eth_spec = (const struct rte_flow_item_eth *)item->spec; 306 eth_mask = (const struct rte_flow_item_eth *)item->mask; 307 308 /* 309 * Mask bits of source MAC address must be full of 0. 310 * Mask bits of destination MAC address must be full 311 * of 1 or full of 0. 312 */ 313 if (!rte_is_zero_ether_addr(ð_mask->hdr.src_addr) || 314 (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr) && 315 !rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr))) { 316 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 317 item, "Invalid ether address mask"); 318 return -rte_errno; 319 } 320 321 if ((eth_mask->hdr.ether_type & UINT16_MAX) != UINT16_MAX) { 322 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 323 item, "Invalid ethertype mask"); 324 return -rte_errno; 325 } 326 327 /* 328 * If mask bits of destination MAC address 329 * are full of 1, set RTE_ETHTYPE_FLAGS_MAC. 330 */ 331 if (rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr)) { 332 filter->mac_addr = eth_spec->hdr.dst_addr; 333 filter->flags |= RTE_ETHTYPE_FLAGS_MAC; 334 } else { 335 filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC; 336 } 337 filter->ether_type = rte_be_to_cpu_16(eth_spec->hdr.ether_type); 338 339 /* Check if the next non-void item is END. */ 340 item = next_no_void_pattern(pattern, item); 341 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 342 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 343 item, "Not supported by ethertype filter."); 344 return -rte_errno; 345 } 346 347 if (hinic_parse_ethertype_aciton(actions, act, act_q, filter, error)) 348 return -rte_errno; 349 350 if (hinic_check_ethertype_attr_ele(attr, error)) 351 return -rte_errno; 352 353 return 0; 354 } 355 356 static int hinic_parse_ethertype_filter(struct rte_eth_dev *dev, 357 const struct rte_flow_attr *attr, 358 const struct rte_flow_item pattern[], 359 const struct rte_flow_action actions[], 360 struct rte_eth_ethertype_filter *filter, 361 struct rte_flow_error *error) 362 { 363 if (cons_parse_ethertype_filter(attr, pattern, actions, filter, error)) 364 return -rte_errno; 365 366 /* NIC doesn't support MAC address. */ 367 if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { 368 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 369 rte_flow_error_set(error, EINVAL, 370 RTE_FLOW_ERROR_TYPE_ITEM, 371 NULL, "Not supported by ethertype filter"); 372 return -rte_errno; 373 } 374 375 if (filter->queue >= dev->data->nb_rx_queues) { 376 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 377 rte_flow_error_set(error, EINVAL, 378 RTE_FLOW_ERROR_TYPE_ITEM, 379 NULL, "Queue index much too big"); 380 return -rte_errno; 381 } 382 383 if (filter->ether_type == RTE_ETHER_TYPE_IPV4 || 384 filter->ether_type == RTE_ETHER_TYPE_IPV6) { 385 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 386 rte_flow_error_set(error, EINVAL, 387 RTE_FLOW_ERROR_TYPE_ITEM, 388 NULL, "IPv4/IPv6 not supported by ethertype filter"); 389 return -rte_errno; 390 } 391 392 if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { 393 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 394 rte_flow_error_set(error, EINVAL, 395 RTE_FLOW_ERROR_TYPE_ITEM, 396 NULL, "Drop option is unsupported"); 397 return -rte_errno; 398 } 399 400 /* Hinic only support LACP/ARP for ether type */ 401 if (filter->ether_type != RTE_ETHER_TYPE_SLOW && 402 filter->ether_type != RTE_ETHER_TYPE_ARP) { 403 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 404 rte_flow_error_set(error, EINVAL, 405 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 406 "only lacp/arp type supported by ethertype filter"); 407 return -rte_errno; 408 } 409 410 return 0; 411 } 412 413 static int hinic_check_ntuple_attr_ele(const struct rte_flow_attr *attr, 414 struct rte_eth_ntuple_filter *filter, 415 struct rte_flow_error *error) 416 { 417 /* Must be input direction */ 418 if (!attr->ingress) { 419 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 420 rte_flow_error_set(error, EINVAL, 421 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 422 attr, "Only support ingress."); 423 return -rte_errno; 424 } 425 426 if (attr->egress) { 427 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 428 rte_flow_error_set(error, EINVAL, 429 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 430 attr, "Not support egress."); 431 return -rte_errno; 432 } 433 434 if (attr->priority > 0xFFFF) { 435 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 436 rte_flow_error_set(error, EINVAL, 437 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 438 attr, "Error priority."); 439 return -rte_errno; 440 } 441 442 if (attr->priority < HINIC_MIN_N_TUPLE_PRIO || 443 attr->priority > HINIC_MAX_N_TUPLE_PRIO) 444 filter->priority = 1; 445 else 446 filter->priority = (uint16_t)attr->priority; 447 448 return 0; 449 } 450 451 static int 452 hinic_check_ntuple_act_ele(__rte_unused const struct rte_flow_item *item, 453 const struct rte_flow_action actions[], 454 struct rte_eth_ntuple_filter *filter, 455 struct rte_flow_error *error) 456 { 457 const struct rte_flow_action *act; 458 /* 459 * n-tuple only supports forwarding, 460 * check if the first not void action is QUEUE. 461 */ 462 act = next_no_void_action(actions, NULL); 463 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) { 464 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 465 rte_flow_error_set(error, EINVAL, 466 RTE_FLOW_ERROR_TYPE_ACTION, 467 act, "Flow action type is not QUEUE."); 468 return -rte_errno; 469 } 470 filter->queue = 471 ((const struct rte_flow_action_queue *)act->conf)->index; 472 473 /* Check if the next not void item is END */ 474 act = next_no_void_action(actions, act); 475 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 476 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 477 rte_flow_error_set(error, EINVAL, 478 RTE_FLOW_ERROR_TYPE_ACTION, 479 act, "Next not void item is not END."); 480 return -rte_errno; 481 } 482 483 return 0; 484 } 485 486 static int hinic_ntuple_item_check_ether(const struct rte_flow_item **ipv4_item, 487 const struct rte_flow_item pattern[], 488 struct rte_flow_error *error) 489 { 490 const struct rte_flow_item *item; 491 492 /* The first not void item can be MAC or IPv4 */ 493 item = next_no_void_pattern(pattern, NULL); 494 495 if (item->type != RTE_FLOW_ITEM_TYPE_ETH && 496 item->type != RTE_FLOW_ITEM_TYPE_IPV4) { 497 rte_flow_error_set(error, EINVAL, 498 RTE_FLOW_ERROR_TYPE_ITEM, 499 item, "Not supported by ntuple filter"); 500 return -rte_errno; 501 } 502 503 /* Skip Ethernet */ 504 if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { 505 /* Not supported last point for range */ 506 if (item->last) { 507 rte_flow_error_set(error, 508 EINVAL, 509 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 510 item, "Not supported last point for range"); 511 return -rte_errno; 512 } 513 /* if the first item is MAC, the content should be NULL */ 514 if (item->spec || item->mask) { 515 rte_flow_error_set(error, EINVAL, 516 RTE_FLOW_ERROR_TYPE_ITEM, 517 item, "Not supported by ntuple filter"); 518 return -rte_errno; 519 } 520 /* check if the next not void item is IPv4 */ 521 item = next_no_void_pattern(pattern, item); 522 if (item->type != RTE_FLOW_ITEM_TYPE_IPV4) { 523 rte_flow_error_set(error, 524 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 525 item, "Not supported by ntuple filter"); 526 return -rte_errno; 527 } 528 } 529 530 *ipv4_item = item; 531 return 0; 532 } 533 534 static int 535 hinic_ntuple_item_check_ipv4(const struct rte_flow_item **in_out_item, 536 const struct rte_flow_item pattern[], 537 struct rte_eth_ntuple_filter *filter, 538 struct rte_flow_error *error) 539 { 540 const struct rte_flow_item_ipv4 *ipv4_spec; 541 const struct rte_flow_item_ipv4 *ipv4_mask; 542 const struct rte_flow_item *item = *in_out_item; 543 544 /* Get the IPv4 info */ 545 if (!item->spec || !item->mask) { 546 rte_flow_error_set(error, EINVAL, 547 RTE_FLOW_ERROR_TYPE_ITEM, 548 item, "Invalid ntuple mask"); 549 return -rte_errno; 550 } 551 /* Not supported last point for range */ 552 if (item->last) { 553 rte_flow_error_set(error, EINVAL, 554 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 555 item, "Not supported last point for range"); 556 return -rte_errno; 557 } 558 559 ipv4_mask = (const struct rte_flow_item_ipv4 *)item->mask; 560 /* 561 * Only support src & dst addresses, protocol, 562 * others should be masked. 563 */ 564 if (ipv4_mask->hdr.version_ihl || 565 ipv4_mask->hdr.type_of_service || 566 ipv4_mask->hdr.total_length || 567 ipv4_mask->hdr.packet_id || 568 ipv4_mask->hdr.fragment_offset || 569 ipv4_mask->hdr.time_to_live || 570 ipv4_mask->hdr.hdr_checksum || 571 !ipv4_mask->hdr.next_proto_id) { 572 rte_flow_error_set(error, 573 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 574 item, "Not supported by ntuple filter"); 575 return -rte_errno; 576 } 577 578 filter->dst_ip_mask = ipv4_mask->hdr.dst_addr; 579 filter->src_ip_mask = ipv4_mask->hdr.src_addr; 580 filter->proto_mask = ipv4_mask->hdr.next_proto_id; 581 582 ipv4_spec = (const struct rte_flow_item_ipv4 *)item->spec; 583 filter->dst_ip = ipv4_spec->hdr.dst_addr; 584 filter->src_ip = ipv4_spec->hdr.src_addr; 585 filter->proto = ipv4_spec->hdr.next_proto_id; 586 587 /* Get next no void item */ 588 *in_out_item = next_no_void_pattern(pattern, item); 589 return 0; 590 } 591 592 static int hinic_ntuple_item_check_l4(const struct rte_flow_item **in_out_item, 593 const struct rte_flow_item pattern[], 594 struct rte_eth_ntuple_filter *filter, 595 struct rte_flow_error *error) 596 { 597 const struct rte_flow_item_tcp *tcp_spec; 598 const struct rte_flow_item_tcp *tcp_mask; 599 const struct rte_flow_item_icmp *icmp_mask; 600 const struct rte_flow_item *item = *in_out_item; 601 u32 ntuple_filter_size = sizeof(struct rte_eth_ntuple_filter); 602 603 if (item->type == RTE_FLOW_ITEM_TYPE_END) 604 return 0; 605 606 /* Get TCP or UDP info */ 607 if (item->type != RTE_FLOW_ITEM_TYPE_END && 608 (!item->spec || !item->mask)) { 609 memset(filter, 0, ntuple_filter_size); 610 rte_flow_error_set(error, EINVAL, 611 RTE_FLOW_ERROR_TYPE_ITEM, 612 item, "Invalid ntuple mask"); 613 return -rte_errno; 614 } 615 616 /* Not supported last point for range */ 617 if (item->last) { 618 memset(filter, 0, ntuple_filter_size); 619 rte_flow_error_set(error, EINVAL, 620 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 621 item, "Not supported last point for range"); 622 return -rte_errno; 623 } 624 625 if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { 626 tcp_mask = (const struct rte_flow_item_tcp *)item->mask; 627 628 /* 629 * Only support src & dst ports, tcp flags, 630 * others should be masked. 631 */ 632 if (tcp_mask->hdr.sent_seq || 633 tcp_mask->hdr.recv_ack || 634 tcp_mask->hdr.data_off || 635 tcp_mask->hdr.rx_win || 636 tcp_mask->hdr.cksum || 637 tcp_mask->hdr.tcp_urp) { 638 memset(filter, 0, ntuple_filter_size); 639 rte_flow_error_set(error, EINVAL, 640 RTE_FLOW_ERROR_TYPE_ITEM, 641 item, "Not supported by ntuple filter"); 642 return -rte_errno; 643 } 644 645 filter->dst_port_mask = tcp_mask->hdr.dst_port; 646 filter->src_port_mask = tcp_mask->hdr.src_port; 647 if (tcp_mask->hdr.tcp_flags == 0xFF) { 648 filter->flags |= RTE_NTUPLE_FLAGS_TCP_FLAG; 649 } else if (!tcp_mask->hdr.tcp_flags) { 650 filter->flags &= ~RTE_NTUPLE_FLAGS_TCP_FLAG; 651 } else { 652 memset(filter, 0, ntuple_filter_size); 653 rte_flow_error_set(error, EINVAL, 654 RTE_FLOW_ERROR_TYPE_ITEM, 655 item, "Not supported by ntuple filter"); 656 return -rte_errno; 657 } 658 659 tcp_spec = (const struct rte_flow_item_tcp *)item->spec; 660 filter->dst_port = tcp_spec->hdr.dst_port; 661 filter->src_port = tcp_spec->hdr.src_port; 662 filter->tcp_flags = tcp_spec->hdr.tcp_flags; 663 } else if (item->type == RTE_FLOW_ITEM_TYPE_ICMP) { 664 icmp_mask = (const struct rte_flow_item_icmp *)item->mask; 665 666 /* ICMP all should be masked. */ 667 if (icmp_mask->hdr.icmp_cksum || 668 icmp_mask->hdr.icmp_ident || 669 icmp_mask->hdr.icmp_seq_nb || 670 icmp_mask->hdr.icmp_type || 671 icmp_mask->hdr.icmp_code) { 672 memset(filter, 0, ntuple_filter_size); 673 rte_flow_error_set(error, EINVAL, 674 RTE_FLOW_ERROR_TYPE_ITEM, 675 item, "Not supported by ntuple filter"); 676 return -rte_errno; 677 } 678 } 679 680 /* Get next no void item */ 681 *in_out_item = next_no_void_pattern(pattern, item); 682 return 0; 683 } 684 685 static int hinic_ntuple_item_check_end(const struct rte_flow_item *item, 686 struct rte_eth_ntuple_filter *filter, 687 struct rte_flow_error *error) 688 { 689 /* Check if the next not void item is END */ 690 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 691 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 692 rte_flow_error_set(error, EINVAL, 693 RTE_FLOW_ERROR_TYPE_ITEM, 694 item, "Not supported by ntuple filter"); 695 return -rte_errno; 696 } 697 698 return 0; 699 } 700 701 static int hinic_check_ntuple_item_ele(const struct rte_flow_item *item, 702 const struct rte_flow_item pattern[], 703 struct rte_eth_ntuple_filter *filter, 704 struct rte_flow_error *error) 705 { 706 if (hinic_ntuple_item_check_ether(&item, pattern, error) || 707 hinic_ntuple_item_check_ipv4(&item, pattern, filter, error) || 708 hinic_ntuple_item_check_l4(&item, pattern, filter, error) || 709 hinic_ntuple_item_check_end(item, filter, error)) 710 return -rte_errno; 711 712 return 0; 713 } 714 715 /** 716 * Parse the rule to see if it is a n-tuple rule. 717 * And get the n-tuple filter info BTW. 718 * pattern: 719 * The first not void item can be ETH or IPV4. 720 * The second not void item must be IPV4 if the first one is ETH. 721 * The third not void item must be UDP or TCP. 722 * The next not void item must be END. 723 * action: 724 * The first not void action should be QUEUE. 725 * The next not void action should be END. 726 * pattern example: 727 * ITEM Spec Mask 728 * ETH NULL NULL 729 * IPV4 src_addr 192.168.1.20 0xFFFFFFFF 730 * dst_addr 192.167.3.50 0xFFFFFFFF 731 * next_proto_id 17 0xFF 732 * UDP/TCP/ src_port 80 0xFFFF 733 * SCTP dst_port 80 0xFFFF 734 * END 735 * other members in mask and spec should set to 0x00. 736 * item->last should be NULL. 737 * Please be aware there's an assumption for all the parsers. 738 * rte_flow_item is using big endian, rte_flow_attr and 739 * rte_flow_action are using CPU order. 740 * Because the pattern is used to describe the packets, 741 * normally the packets should use network order. 742 */ 743 static int cons_parse_ntuple_filter(const struct rte_flow_attr *attr, 744 const struct rte_flow_item pattern[], 745 const struct rte_flow_action actions[], 746 struct rte_eth_ntuple_filter *filter, 747 struct rte_flow_error *error) 748 { 749 const struct rte_flow_item *item = NULL; 750 751 if (hinic_check_filter_arg(attr, pattern, actions, error)) 752 return -rte_errno; 753 754 if (hinic_check_ntuple_item_ele(item, pattern, filter, error)) 755 return -rte_errno; 756 757 if (hinic_check_ntuple_act_ele(item, actions, filter, error)) 758 return -rte_errno; 759 760 if (hinic_check_ntuple_attr_ele(attr, filter, error)) 761 return -rte_errno; 762 763 return 0; 764 } 765 766 static int hinic_parse_ntuple_filter(struct rte_eth_dev *dev, 767 const struct rte_flow_attr *attr, 768 const struct rte_flow_item pattern[], 769 const struct rte_flow_action actions[], 770 struct rte_eth_ntuple_filter *filter, 771 struct rte_flow_error *error) 772 { 773 int ret; 774 775 ret = cons_parse_ntuple_filter(attr, pattern, actions, filter, error); 776 if (ret) 777 return ret; 778 779 /* Hinic doesn't support tcp flags */ 780 if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG) { 781 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 782 rte_flow_error_set(error, EINVAL, 783 RTE_FLOW_ERROR_TYPE_ITEM, 784 NULL, "Not supported by ntuple filter"); 785 return -rte_errno; 786 } 787 788 /* Hinic doesn't support many priorities */ 789 if (filter->priority < HINIC_MIN_N_TUPLE_PRIO || 790 filter->priority > HINIC_MAX_N_TUPLE_PRIO) { 791 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 792 rte_flow_error_set(error, EINVAL, 793 RTE_FLOW_ERROR_TYPE_ITEM, 794 NULL, "Priority not supported by ntuple filter"); 795 return -rte_errno; 796 } 797 798 if (filter->queue >= dev->data->nb_rx_queues) 799 return -rte_errno; 800 801 /* Fixed value for hinic */ 802 filter->flags = RTE_5TUPLE_FLAGS; 803 return 0; 804 } 805 806 static int hinic_normal_item_check_ether(const struct rte_flow_item **ip_item, 807 const struct rte_flow_item pattern[], 808 struct rte_flow_error *error) 809 { 810 const struct rte_flow_item *item; 811 812 /* The first not void item can be MAC or IPv4 or TCP or UDP */ 813 item = next_no_void_pattern(pattern, NULL); 814 815 if (item->type != RTE_FLOW_ITEM_TYPE_ETH && 816 item->type != RTE_FLOW_ITEM_TYPE_IPV4 && 817 item->type != RTE_FLOW_ITEM_TYPE_TCP && 818 item->type != RTE_FLOW_ITEM_TYPE_UDP) { 819 rte_flow_error_set(error, EINVAL, 820 RTE_FLOW_ERROR_TYPE_ITEM, item, 821 "Not supported by fdir filter,support mac,ipv4,tcp,udp"); 822 return -rte_errno; 823 } 824 825 /* Not supported last point for range */ 826 if (item->last) { 827 rte_flow_error_set(error, EINVAL, 828 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item, 829 "Not supported last point for range"); 830 return -rte_errno; 831 } 832 833 /* Skip Ethernet */ 834 if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { 835 /* All should be masked. */ 836 if (item->spec || item->mask) { 837 rte_flow_error_set(error, EINVAL, 838 RTE_FLOW_ERROR_TYPE_ITEM, 839 item, "Not supported by fdir filter,support mac"); 840 return -rte_errno; 841 } 842 /* Check if the next not void item is IPv4 */ 843 item = next_no_void_pattern(pattern, item); 844 if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 && 845 item->type != RTE_FLOW_ITEM_TYPE_IPV6) { 846 rte_flow_error_set(error, EINVAL, 847 RTE_FLOW_ERROR_TYPE_ITEM, item, 848 "Not supported by fdir filter,support mac,ipv4"); 849 return -rte_errno; 850 } 851 } 852 853 *ip_item = item; 854 return 0; 855 } 856 857 static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item, 858 const struct rte_flow_item pattern[], 859 struct hinic_fdir_rule *rule, 860 struct rte_flow_error *error) 861 { 862 const struct rte_flow_item_ipv4 *ipv4_spec; 863 const struct rte_flow_item_ipv4 *ipv4_mask; 864 const struct rte_flow_item_ipv6 *ipv6_spec; 865 const struct rte_flow_item_ipv6 *ipv6_mask; 866 const struct rte_flow_item *item = *in_out_item; 867 int i; 868 869 /* Get the IPv4 info */ 870 if (item->type == RTE_FLOW_ITEM_TYPE_IPV4) { 871 /* Not supported last point for range */ 872 if (item->last) { 873 rte_flow_error_set(error, EINVAL, 874 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 875 item, "Not supported last point for range"); 876 return -rte_errno; 877 } 878 879 if (!item->mask) { 880 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 881 rte_flow_error_set(error, EINVAL, 882 RTE_FLOW_ERROR_TYPE_ITEM, 883 item, "Invalid fdir filter mask"); 884 return -rte_errno; 885 } 886 887 ipv4_mask = (const struct rte_flow_item_ipv4 *)item->mask; 888 /* 889 * Only support src & dst addresses, 890 * others should be masked. 891 */ 892 if (ipv4_mask->hdr.version_ihl || 893 ipv4_mask->hdr.type_of_service || 894 ipv4_mask->hdr.total_length || 895 ipv4_mask->hdr.packet_id || 896 ipv4_mask->hdr.fragment_offset || 897 ipv4_mask->hdr.time_to_live || 898 ipv4_mask->hdr.next_proto_id || 899 ipv4_mask->hdr.hdr_checksum) { 900 rte_flow_error_set(error, 901 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, 902 "Not supported by fdir filter, support src,dst ip"); 903 return -rte_errno; 904 } 905 906 rule->mask.dst_ipv4_mask = ipv4_mask->hdr.dst_addr; 907 rule->mask.src_ipv4_mask = ipv4_mask->hdr.src_addr; 908 rule->mode = HINIC_FDIR_MODE_NORMAL; 909 910 if (item->spec) { 911 ipv4_spec = 912 (const struct rte_flow_item_ipv4 *)item->spec; 913 rule->hinic_fdir.dst_ip = ipv4_spec->hdr.dst_addr; 914 rule->hinic_fdir.src_ip = ipv4_spec->hdr.src_addr; 915 } 916 917 /* 918 * Check if the next not void item is 919 * TCP or UDP or END. 920 */ 921 item = next_no_void_pattern(pattern, item); 922 if (item->type != RTE_FLOW_ITEM_TYPE_TCP && 923 item->type != RTE_FLOW_ITEM_TYPE_UDP && 924 item->type != RTE_FLOW_ITEM_TYPE_ICMP && 925 item->type != RTE_FLOW_ITEM_TYPE_ANY && 926 item->type != RTE_FLOW_ITEM_TYPE_END) { 927 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 928 rte_flow_error_set(error, EINVAL, 929 RTE_FLOW_ERROR_TYPE_ITEM, item, 930 "Not supported by fdir filter, support tcp, udp, end"); 931 return -rte_errno; 932 } 933 } else if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) { 934 /* Not supported last point for range */ 935 if (item->last) { 936 rte_flow_error_set(error, EINVAL, 937 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 938 item, "Not supported last point for range"); 939 return -rte_errno; 940 } 941 942 if (!item->mask) { 943 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 944 rte_flow_error_set(error, EINVAL, 945 RTE_FLOW_ERROR_TYPE_ITEM, 946 item, "Invalid fdir filter mask"); 947 return -rte_errno; 948 } 949 950 ipv6_mask = (const struct rte_flow_item_ipv6 *)item->mask; 951 952 /* Only support dst addresses, others should be masked */ 953 if (ipv6_mask->hdr.vtc_flow || 954 ipv6_mask->hdr.payload_len || 955 ipv6_mask->hdr.proto || 956 ipv6_mask->hdr.hop_limits) { 957 rte_flow_error_set(error, EINVAL, 958 RTE_FLOW_ERROR_TYPE_ITEM, item, 959 "Not supported by fdir filter, support dst ipv6"); 960 return -rte_errno; 961 } 962 963 /* check ipv6 src addr mask, ipv6 src addr is 16 bytes */ 964 for (i = 0; i < 16; i++) { 965 if (ipv6_mask->hdr.src_addr.a[i] == UINT8_MAX) { 966 rte_flow_error_set(error, EINVAL, 967 RTE_FLOW_ERROR_TYPE_ITEM, item, 968 "Not supported by fdir filter, do not support src ipv6"); 969 return -rte_errno; 970 } 971 } 972 973 if (!item->spec) { 974 rte_flow_error_set(error, EINVAL, 975 RTE_FLOW_ERROR_TYPE_ITEM, item, 976 "Not supported by fdir filter, ipv6 spec is NULL"); 977 return -rte_errno; 978 } 979 980 for (i = 0; i < 16; i++) { 981 if (ipv6_mask->hdr.dst_addr.a[i] == UINT8_MAX) 982 rule->mask.dst_ipv6_mask |= 1 << i; 983 } 984 985 ipv6_spec = (const struct rte_flow_item_ipv6 *)item->spec; 986 rte_memcpy(rule->hinic_fdir.dst_ipv6, 987 &ipv6_spec->hdr.dst_addr, 16); 988 989 /* 990 * Check if the next not void item is TCP or UDP or ICMP. 991 */ 992 item = next_no_void_pattern(pattern, item); 993 if (item->type != RTE_FLOW_ITEM_TYPE_TCP && 994 item->type != RTE_FLOW_ITEM_TYPE_UDP && 995 item->type != RTE_FLOW_ITEM_TYPE_ICMP && 996 item->type != RTE_FLOW_ITEM_TYPE_ICMP6){ 997 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 998 rte_flow_error_set(error, EINVAL, 999 RTE_FLOW_ERROR_TYPE_ITEM, item, 1000 "Not supported by fdir filter, support tcp, udp, icmp"); 1001 return -rte_errno; 1002 } 1003 } 1004 1005 *in_out_item = item; 1006 return 0; 1007 } 1008 1009 static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, 1010 __rte_unused const struct rte_flow_item pattern[], 1011 __rte_unused struct hinic_fdir_rule *rule, 1012 struct rte_flow_error *error) 1013 { 1014 const struct rte_flow_item *item = *in_out_item; 1015 1016 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 1017 rte_flow_error_set(error, EINVAL, 1018 RTE_FLOW_ERROR_TYPE_ITEM, 1019 item, "Not supported by normal fdir filter, not support l4"); 1020 return -rte_errno; 1021 } 1022 1023 return 0; 1024 } 1025 1026 1027 static int hinic_normal_item_check_end(const struct rte_flow_item *item, 1028 struct hinic_fdir_rule *rule, 1029 struct rte_flow_error *error) 1030 { 1031 /* Check if the next not void item is END */ 1032 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 1033 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1034 rte_flow_error_set(error, EINVAL, 1035 RTE_FLOW_ERROR_TYPE_ITEM, 1036 item, "Not supported by fdir filter, support end"); 1037 return -rte_errno; 1038 } 1039 1040 return 0; 1041 } 1042 1043 static int hinic_check_normal_item_ele(const struct rte_flow_item *item, 1044 const struct rte_flow_item pattern[], 1045 struct hinic_fdir_rule *rule, 1046 struct rte_flow_error *error) 1047 { 1048 if (hinic_normal_item_check_ether(&item, pattern, error) || 1049 hinic_normal_item_check_ip(&item, pattern, rule, error) || 1050 hinic_normal_item_check_l4(&item, pattern, rule, error) || 1051 hinic_normal_item_check_end(item, rule, error)) 1052 return -rte_errno; 1053 1054 return 0; 1055 } 1056 1057 static int 1058 hinic_tcam_normal_item_check_l4(const struct rte_flow_item **in_out_item, 1059 const struct rte_flow_item pattern[], 1060 struct hinic_fdir_rule *rule, 1061 struct rte_flow_error *error) 1062 { 1063 const struct rte_flow_item *item = *in_out_item; 1064 const struct rte_flow_item_tcp *tcp_spec; 1065 const struct rte_flow_item_tcp *tcp_mask; 1066 const struct rte_flow_item_udp *udp_spec; 1067 const struct rte_flow_item_udp *udp_mask; 1068 1069 if (item->type == RTE_FLOW_ITEM_TYPE_ICMP) { 1070 rule->mode = HINIC_FDIR_MODE_TCAM; 1071 rule->mask.proto_mask = UINT16_MAX; 1072 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_ICMP; 1073 } else if (item->type == RTE_FLOW_ITEM_TYPE_ICMP6) { 1074 rule->mode = HINIC_FDIR_MODE_TCAM; 1075 rule->mask.proto_mask = UINT16_MAX; 1076 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_ICMPV6; 1077 } else if (item->type == RTE_FLOW_ITEM_TYPE_ANY) { 1078 rule->mode = HINIC_FDIR_MODE_TCAM; 1079 } else if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { 1080 if (!item->mask) { 1081 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1082 rte_flow_error_set(error, EINVAL, 1083 RTE_FLOW_ERROR_TYPE_ITEM, 1084 item, "Not supported by fdir filter, support src, dst ports"); 1085 return -rte_errno; 1086 } 1087 1088 tcp_mask = (const struct rte_flow_item_tcp *)item->mask; 1089 1090 /* 1091 * Only support src & dst ports, tcp flags, 1092 * others should be masked. 1093 */ 1094 if (tcp_mask->hdr.sent_seq || 1095 tcp_mask->hdr.recv_ack || 1096 tcp_mask->hdr.data_off || 1097 tcp_mask->hdr.rx_win || 1098 tcp_mask->hdr.cksum || 1099 tcp_mask->hdr.tcp_urp) { 1100 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1101 rte_flow_error_set(error, EINVAL, 1102 RTE_FLOW_ERROR_TYPE_ITEM, 1103 item, "Not supported by fdir normal tcam filter"); 1104 return -rte_errno; 1105 } 1106 1107 rule->mode = HINIC_FDIR_MODE_TCAM; 1108 rule->mask.proto_mask = UINT16_MAX; 1109 rule->mask.dst_port_mask = tcp_mask->hdr.dst_port; 1110 rule->mask.src_port_mask = tcp_mask->hdr.src_port; 1111 1112 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_TCP; 1113 if (item->spec) { 1114 tcp_spec = (const struct rte_flow_item_tcp *)item->spec; 1115 rule->hinic_fdir.dst_port = tcp_spec->hdr.dst_port; 1116 rule->hinic_fdir.src_port = tcp_spec->hdr.src_port; 1117 } 1118 } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { 1119 /* 1120 * Only care about src & dst ports, 1121 * others should be masked. 1122 */ 1123 if (!item->mask) { 1124 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1125 rte_flow_error_set(error, EINVAL, 1126 RTE_FLOW_ERROR_TYPE_ITEM, 1127 item, "Not supported by fdir filter, support src, dst ports"); 1128 return -rte_errno; 1129 } 1130 1131 udp_mask = (const struct rte_flow_item_udp *)item->mask; 1132 if (udp_mask->hdr.dgram_len || 1133 udp_mask->hdr.dgram_cksum) { 1134 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1135 rte_flow_error_set(error, EINVAL, 1136 RTE_FLOW_ERROR_TYPE_ITEM, 1137 item, "Not supported by fdir filter, support udp"); 1138 return -rte_errno; 1139 } 1140 1141 rule->mode = HINIC_FDIR_MODE_TCAM; 1142 rule->mask.proto_mask = UINT16_MAX; 1143 rule->mask.src_port_mask = udp_mask->hdr.src_port; 1144 rule->mask.dst_port_mask = udp_mask->hdr.dst_port; 1145 1146 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_UDP; 1147 if (item->spec) { 1148 udp_spec = (const struct rte_flow_item_udp *)item->spec; 1149 rule->hinic_fdir.src_port = udp_spec->hdr.src_port; 1150 rule->hinic_fdir.dst_port = udp_spec->hdr.dst_port; 1151 } 1152 } else { 1153 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1154 rte_flow_error_set(error, EINVAL, 1155 RTE_FLOW_ERROR_TYPE_ITEM, 1156 item, "Not supported by fdir filter tcam normal, l4 only support icmp, tcp"); 1157 return -rte_errno; 1158 } 1159 1160 item = next_no_void_pattern(pattern, item); 1161 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 1162 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1163 rte_flow_error_set(error, EINVAL, 1164 RTE_FLOW_ERROR_TYPE_ITEM, 1165 item, "Not supported by fdir filter tcam normal, support end"); 1166 return -rte_errno; 1167 } 1168 1169 /* get next no void item */ 1170 *in_out_item = item; 1171 1172 return 0; 1173 } 1174 1175 static int hinic_check_tcam_normal_item_ele(const struct rte_flow_item *item, 1176 const struct rte_flow_item pattern[], 1177 struct hinic_fdir_rule *rule, 1178 struct rte_flow_error *error) 1179 { 1180 if (hinic_normal_item_check_ether(&item, pattern, error) || 1181 hinic_normal_item_check_ip(&item, pattern, rule, error) || 1182 hinic_tcam_normal_item_check_l4(&item, pattern, rule, error) || 1183 hinic_normal_item_check_end(item, rule, error)) 1184 return -rte_errno; 1185 1186 return 0; 1187 } 1188 1189 static int hinic_tunnel_item_check_l4(const struct rte_flow_item **in_out_item, 1190 const struct rte_flow_item pattern[], 1191 struct hinic_fdir_rule *rule, 1192 struct rte_flow_error *error) 1193 { 1194 const struct rte_flow_item *item = *in_out_item; 1195 1196 if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { 1197 item = next_no_void_pattern(pattern, item); 1198 if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) { 1199 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1200 rte_flow_error_set(error, EINVAL, 1201 RTE_FLOW_ERROR_TYPE_ITEM, 1202 item, "Not supported by fdir filter, support vxlan"); 1203 return -rte_errno; 1204 } 1205 1206 *in_out_item = item; 1207 } else { 1208 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1209 rte_flow_error_set(error, EINVAL, 1210 RTE_FLOW_ERROR_TYPE_ITEM, 1211 item, "Not supported by fdir filter tcam tunnel, outer l4 only support udp"); 1212 return -rte_errno; 1213 } 1214 1215 return 0; 1216 } 1217 1218 static int 1219 hinic_tunnel_item_check_vxlan(const struct rte_flow_item **in_out_item, 1220 const struct rte_flow_item pattern[], 1221 struct hinic_fdir_rule *rule, 1222 struct rte_flow_error *error) 1223 { 1224 const struct rte_flow_item *item = *in_out_item; 1225 1226 1227 if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN) { 1228 item = next_no_void_pattern(pattern, item); 1229 if (item->type != RTE_FLOW_ITEM_TYPE_TCP && 1230 item->type != RTE_FLOW_ITEM_TYPE_UDP && 1231 item->type != RTE_FLOW_ITEM_TYPE_ANY) { 1232 (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1233 rte_flow_error_set(error, EINVAL, 1234 RTE_FLOW_ERROR_TYPE_ITEM, 1235 item, "Not supported by fdir filter, support tcp/udp"); 1236 return -rte_errno; 1237 } 1238 1239 *in_out_item = item; 1240 } 1241 1242 return 0; 1243 } 1244 1245 static int 1246 hinic_tunnel_inner_item_check_l4(const struct rte_flow_item **in_out_item, 1247 const struct rte_flow_item pattern[], 1248 struct hinic_fdir_rule *rule, 1249 struct rte_flow_error *error) 1250 { 1251 const struct rte_flow_item_tcp *tcp_spec; 1252 const struct rte_flow_item_tcp *tcp_mask; 1253 const struct rte_flow_item_udp *udp_spec; 1254 const struct rte_flow_item_udp *udp_mask; 1255 const struct rte_flow_item *item = *in_out_item; 1256 1257 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 1258 /* Not supported last point for range */ 1259 if (item->last) { 1260 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1261 rte_flow_error_set(error, EINVAL, 1262 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1263 item, "Not supported last point for range"); 1264 return -rte_errno; 1265 } 1266 1267 /* get the TCP/UDP info */ 1268 if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { 1269 /* 1270 * Only care about src & dst ports, 1271 * others should be masked. 1272 */ 1273 if (!item->mask) { 1274 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1275 rte_flow_error_set(error, EINVAL, 1276 RTE_FLOW_ERROR_TYPE_ITEM, 1277 item, "Not supported by fdir filter, support src, dst ports"); 1278 return -rte_errno; 1279 } 1280 1281 tcp_mask = (const struct rte_flow_item_tcp *)item->mask; 1282 if (tcp_mask->hdr.sent_seq || 1283 tcp_mask->hdr.recv_ack || 1284 tcp_mask->hdr.data_off || 1285 tcp_mask->hdr.tcp_flags || 1286 tcp_mask->hdr.rx_win || 1287 tcp_mask->hdr.cksum || 1288 tcp_mask->hdr.tcp_urp) { 1289 (void)memset(rule, 0, 1290 sizeof(struct hinic_fdir_rule)); 1291 rte_flow_error_set(error, EINVAL, 1292 RTE_FLOW_ERROR_TYPE_ITEM, 1293 item, "Not supported by fdir filter, support tcp"); 1294 return -rte_errno; 1295 } 1296 1297 rule->mode = HINIC_FDIR_MODE_TCAM; 1298 rule->mask.tunnel_flag = UINT16_MAX; 1299 rule->mask.tunnel_inner_src_port_mask = 1300 tcp_mask->hdr.src_port; 1301 rule->mask.tunnel_inner_dst_port_mask = 1302 tcp_mask->hdr.dst_port; 1303 rule->mask.proto_mask = UINT16_MAX; 1304 1305 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_TCP; 1306 if (item->spec) { 1307 tcp_spec = 1308 (const struct rte_flow_item_tcp *)item->spec; 1309 rule->hinic_fdir.tunnel_inner_src_port = 1310 tcp_spec->hdr.src_port; 1311 rule->hinic_fdir.tunnel_inner_dst_port = 1312 tcp_spec->hdr.dst_port; 1313 } 1314 } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { 1315 /* 1316 * Only care about src & dst ports, 1317 * others should be masked. 1318 */ 1319 if (!item->mask) { 1320 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1321 rte_flow_error_set(error, EINVAL, 1322 RTE_FLOW_ERROR_TYPE_ITEM, 1323 item, "Not supported by fdir filter, support src, dst ports"); 1324 return -rte_errno; 1325 } 1326 1327 udp_mask = (const struct rte_flow_item_udp *)item->mask; 1328 if (udp_mask->hdr.dgram_len || 1329 udp_mask->hdr.dgram_cksum) { 1330 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1331 rte_flow_error_set(error, EINVAL, 1332 RTE_FLOW_ERROR_TYPE_ITEM, 1333 item, "Not supported by fdir filter, support udp"); 1334 return -rte_errno; 1335 } 1336 1337 rule->mode = HINIC_FDIR_MODE_TCAM; 1338 rule->mask.tunnel_flag = UINT16_MAX; 1339 rule->mask.tunnel_inner_src_port_mask = 1340 udp_mask->hdr.src_port; 1341 rule->mask.tunnel_inner_dst_port_mask = 1342 udp_mask->hdr.dst_port; 1343 rule->mask.proto_mask = UINT16_MAX; 1344 1345 rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_UDP; 1346 if (item->spec) { 1347 udp_spec = 1348 (const struct rte_flow_item_udp *)item->spec; 1349 rule->hinic_fdir.tunnel_inner_src_port = 1350 udp_spec->hdr.src_port; 1351 rule->hinic_fdir.tunnel_inner_dst_port = 1352 udp_spec->hdr.dst_port; 1353 } 1354 } else if (item->type == RTE_FLOW_ITEM_TYPE_ANY) { 1355 rule->mode = HINIC_FDIR_MODE_TCAM; 1356 rule->mask.tunnel_flag = UINT16_MAX; 1357 } else { 1358 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1359 rte_flow_error_set(error, EINVAL, 1360 RTE_FLOW_ERROR_TYPE_ITEM, 1361 item, "Not supported by fdir filter, support tcp/udp"); 1362 return -rte_errno; 1363 } 1364 1365 /* get next no void item */ 1366 *in_out_item = next_no_void_pattern(pattern, item); 1367 } 1368 1369 return 0; 1370 } 1371 1372 static int hinic_check_tcam_tunnel_item_ele(const struct rte_flow_item *item, 1373 const struct rte_flow_item pattern[], 1374 struct hinic_fdir_rule *rule, 1375 struct rte_flow_error *error) 1376 { 1377 if (hinic_normal_item_check_ether(&item, pattern, error) || 1378 hinic_normal_item_check_ip(&item, pattern, rule, error) || 1379 hinic_tunnel_item_check_l4(&item, pattern, rule, error) || 1380 hinic_tunnel_item_check_vxlan(&item, pattern, rule, error) || 1381 hinic_tunnel_inner_item_check_l4(&item, pattern, rule, error) || 1382 hinic_normal_item_check_end(item, rule, error)) 1383 return -rte_errno; 1384 1385 return 0; 1386 } 1387 1388 static int hinic_check_normal_attr_ele(const struct rte_flow_attr *attr, 1389 struct hinic_fdir_rule *rule, 1390 struct rte_flow_error *error) 1391 { 1392 /* Must be input direction */ 1393 if (!attr->ingress) { 1394 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1395 rte_flow_error_set(error, EINVAL, 1396 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1397 attr, "Only support ingress."); 1398 return -rte_errno; 1399 } 1400 1401 /* Not supported */ 1402 if (attr->egress) { 1403 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1404 rte_flow_error_set(error, EINVAL, 1405 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 1406 attr, "Not support egress."); 1407 return -rte_errno; 1408 } 1409 1410 /* Not supported */ 1411 if (attr->priority) { 1412 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1413 rte_flow_error_set(error, EINVAL, 1414 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1415 attr, "Not support priority."); 1416 return -rte_errno; 1417 } 1418 1419 return 0; 1420 } 1421 1422 static int hinic_check_normal_act_ele(const struct rte_flow_item *item, 1423 const struct rte_flow_action actions[], 1424 struct hinic_fdir_rule *rule, 1425 struct rte_flow_error *error) 1426 { 1427 const struct rte_flow_action *act; 1428 1429 /* Check if the first not void action is QUEUE */ 1430 act = next_no_void_action(actions, NULL); 1431 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) { 1432 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1433 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, 1434 item, "Not supported action."); 1435 return -rte_errno; 1436 } 1437 1438 rule->queue = ((const struct rte_flow_action_queue *)act->conf)->index; 1439 1440 /* Check if the next not void item is END */ 1441 act = next_no_void_action(actions, act); 1442 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 1443 memset(rule, 0, sizeof(struct hinic_fdir_rule)); 1444 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, 1445 act, "Not supported action."); 1446 return -rte_errno; 1447 } 1448 1449 return 0; 1450 } 1451 1452 /** 1453 * Parse the rule to see if it is a IP or MAC VLAN flow director rule. 1454 * And get the flow director filter info BTW. 1455 * UDP/TCP/SCTP PATTERN: 1456 * The first not void item can be ETH or IPV4 or IPV6 1457 * The second not void item must be IPV4 or IPV6 if the first one is ETH. 1458 * The next not void item could be UDP or TCP(optional) 1459 * The next not void item must be END. 1460 * ACTION: 1461 * The first not void action should be QUEUE. 1462 * The second not void optional action should be MARK, 1463 * mark_id is a uint32_t number. 1464 * The next not void action should be END. 1465 * UDP/TCP pattern example: 1466 * ITEM Spec Mask 1467 * ETH NULL NULL 1468 * IPV4 src_addr 1.2.3.6 0xFFFFFFFF 1469 * dst_addr 1.2.3.5 0xFFFFFFFF 1470 * UDP/TCP src_port 80 0xFFFF 1471 * dst_port 80 0xFFFF 1472 * END 1473 * Other members in mask and spec should set to 0x00. 1474 * Item->last should be NULL. 1475 */ 1476 static int 1477 hinic_parse_fdir_filter_normal(const struct rte_flow_attr *attr, 1478 const struct rte_flow_item pattern[], 1479 const struct rte_flow_action actions[], 1480 struct hinic_fdir_rule *rule, 1481 struct rte_flow_error *error) 1482 { 1483 const struct rte_flow_item *item = NULL; 1484 1485 if (hinic_check_filter_arg(attr, pattern, actions, error)) 1486 return -rte_errno; 1487 1488 if (hinic_check_normal_item_ele(item, pattern, rule, error)) 1489 return -rte_errno; 1490 1491 if (hinic_check_normal_attr_ele(attr, rule, error)) 1492 return -rte_errno; 1493 1494 if (hinic_check_normal_act_ele(item, actions, rule, error)) 1495 return -rte_errno; 1496 1497 return 0; 1498 } 1499 1500 /** 1501 * Parse the rule to see if it is a IP or MAC VLAN flow director rule. 1502 * And get the flow director filter info BTW. 1503 * UDP/TCP/SCTP PATTERN: 1504 * The first not void item can be ETH or IPV4 or IPV6 1505 * The second not void item must be IPV4 or IPV6 if the first one is ETH. 1506 * The next not void item can be ANY/TCP/UDP 1507 * ACTION: 1508 * The first not void action should be QUEUE. 1509 * The second not void optional action should be MARK, 1510 * mark_id is a uint32_t number. 1511 * The next not void action should be END. 1512 * UDP/TCP pattern example: 1513 * ITEM Spec Mask 1514 * ETH NULL NULL 1515 * IPV4 src_addr 1.2.3.6 0xFFFFFFFF 1516 * dst_addr 1.2.3.5 0xFFFFFFFF 1517 * UDP/TCP src_port 80 0xFFFF 1518 * dst_port 80 0xFFFF 1519 * END 1520 * Other members in mask and spec should set to 0x00. 1521 * Item->last should be NULL. 1522 */ 1523 static int 1524 hinic_parse_fdir_filter_tcam_normal(const struct rte_flow_attr *attr, 1525 const struct rte_flow_item pattern[], 1526 const struct rte_flow_action actions[], 1527 struct hinic_fdir_rule *rule, 1528 struct rte_flow_error *error) 1529 { 1530 const struct rte_flow_item *item = NULL; 1531 1532 if (hinic_check_filter_arg(attr, pattern, actions, error)) 1533 return -rte_errno; 1534 1535 if (hinic_check_tcam_normal_item_ele(item, pattern, rule, error)) 1536 return -rte_errno; 1537 1538 if (hinic_check_normal_attr_ele(attr, rule, error)) 1539 return -rte_errno; 1540 1541 if (hinic_check_normal_act_ele(item, actions, rule, error)) 1542 return -rte_errno; 1543 1544 return 0; 1545 } 1546 1547 /** 1548 * Parse the rule to see if it is a IP or MAC VLAN flow director rule. 1549 * And get the flow director filter info BTW. 1550 * UDP/TCP/SCTP PATTERN: 1551 * The first not void item can be ETH or IPV4 or IPV6 1552 * The second not void item must be IPV4 or IPV6 if the first one is ETH. 1553 * The next not void item must be UDP 1554 * The next not void item must be VXLAN(optional) 1555 * The first not void item can be ETH or IPV4 or IPV6 1556 * The next not void item could be ANY or UDP or TCP(optional) 1557 * The next not void item must be END. 1558 * ACTION: 1559 * The first not void action should be QUEUE. 1560 * The second not void optional action should be MARK, 1561 * mark_id is a uint32_t number. 1562 * The next not void action should be END. 1563 * UDP/TCP pattern example: 1564 * ITEM Spec Mask 1565 * ETH NULL NULL 1566 * IPV4 src_addr 1.2.3.6 0xFFFFFFFF 1567 * dst_addr 1.2.3.5 0xFFFFFFFF 1568 * UDP NULL NULL 1569 * VXLAN NULL NULL 1570 * UDP/TCP src_port 80 0xFFFF 1571 * dst_port 80 0xFFFF 1572 * END 1573 * Other members in mask and spec should set to 0x00. 1574 * Item->last should be NULL. 1575 */ 1576 static int 1577 hinic_parse_fdir_filter_tacm_tunnel(const struct rte_flow_attr *attr, 1578 const struct rte_flow_item pattern[], 1579 const struct rte_flow_action actions[], 1580 struct hinic_fdir_rule *rule, 1581 struct rte_flow_error *error) 1582 { 1583 const struct rte_flow_item *item = NULL; 1584 1585 if (hinic_check_filter_arg(attr, pattern, actions, error)) 1586 return -rte_errno; 1587 1588 if (hinic_check_tcam_tunnel_item_ele(item, pattern, rule, error)) 1589 return -rte_errno; 1590 1591 if (hinic_check_normal_attr_ele(attr, rule, error)) 1592 return -rte_errno; 1593 1594 if (hinic_check_normal_act_ele(item, actions, rule, error)) 1595 return -rte_errno; 1596 1597 return 0; 1598 } 1599 1600 static int hinic_parse_fdir_filter(struct rte_eth_dev *dev, 1601 const struct rte_flow_attr *attr, 1602 const struct rte_flow_item pattern[], 1603 const struct rte_flow_action actions[], 1604 struct hinic_fdir_rule *rule, 1605 struct rte_flow_error *error) 1606 { 1607 int ret; 1608 1609 ret = hinic_parse_fdir_filter_normal(attr, pattern, actions, 1610 rule, error); 1611 if (!ret) 1612 goto step_next; 1613 1614 ret = hinic_parse_fdir_filter_tcam_normal(attr, pattern, actions, 1615 rule, error); 1616 if (!ret) 1617 goto step_next; 1618 1619 ret = hinic_parse_fdir_filter_tacm_tunnel(attr, pattern, actions, 1620 rule, error); 1621 if (ret) 1622 return ret; 1623 1624 step_next: 1625 if (rule->queue >= dev->data->nb_rx_queues) 1626 return -ENOTSUP; 1627 1628 return ret; 1629 } 1630 1631 /** 1632 * Check if the flow rule is supported by nic. 1633 * It only checks the format. Don't guarantee the rule can be programmed into 1634 * the HW. Because there can be no enough room for the rule. 1635 */ 1636 static int hinic_flow_validate(struct rte_eth_dev *dev, 1637 const struct rte_flow_attr *attr, 1638 const struct rte_flow_item pattern[], 1639 const struct rte_flow_action actions[], 1640 struct rte_flow_error *error) 1641 { 1642 struct rte_eth_ethertype_filter ethertype_filter; 1643 struct rte_eth_ntuple_filter ntuple_filter; 1644 struct hinic_fdir_rule fdir_rule; 1645 int ret; 1646 1647 memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter)); 1648 ret = hinic_parse_ntuple_filter(dev, attr, pattern, 1649 actions, &ntuple_filter, error); 1650 if (!ret) 1651 return 0; 1652 1653 memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter)); 1654 ret = hinic_parse_ethertype_filter(dev, attr, pattern, 1655 actions, ðertype_filter, error); 1656 1657 if (!ret) 1658 return 0; 1659 1660 memset(&fdir_rule, 0, sizeof(struct hinic_fdir_rule)); 1661 ret = hinic_parse_fdir_filter(dev, attr, pattern, 1662 actions, &fdir_rule, error); 1663 1664 return ret; 1665 } 1666 1667 static inline int ntuple_ip_filter(struct rte_eth_ntuple_filter *filter, 1668 struct hinic_5tuple_filter_info *hinic_filter_info) 1669 { 1670 switch (filter->dst_ip_mask) { 1671 case UINT32_MAX: 1672 hinic_filter_info->dst_ip_mask = 0; 1673 hinic_filter_info->dst_ip = filter->dst_ip; 1674 break; 1675 case 0: 1676 hinic_filter_info->dst_ip_mask = 1; 1677 hinic_filter_info->dst_ip = 0; 1678 break; 1679 default: 1680 PMD_DRV_LOG(ERR, "Invalid dst_ip mask."); 1681 return -EINVAL; 1682 } 1683 1684 switch (filter->src_ip_mask) { 1685 case UINT32_MAX: 1686 hinic_filter_info->src_ip_mask = 0; 1687 hinic_filter_info->src_ip = filter->src_ip; 1688 break; 1689 case 0: 1690 hinic_filter_info->src_ip_mask = 1; 1691 hinic_filter_info->src_ip = 0; 1692 break; 1693 default: 1694 PMD_DRV_LOG(ERR, "Invalid src_ip mask."); 1695 return -EINVAL; 1696 } 1697 return 0; 1698 } 1699 1700 static inline int ntuple_port_filter(struct rte_eth_ntuple_filter *filter, 1701 struct hinic_5tuple_filter_info *hinic_filter_info) 1702 { 1703 switch (filter->dst_port_mask) { 1704 case UINT16_MAX: 1705 hinic_filter_info->dst_port_mask = 0; 1706 hinic_filter_info->dst_port = filter->dst_port; 1707 break; 1708 case 0: 1709 hinic_filter_info->dst_port_mask = 1; 1710 hinic_filter_info->dst_port = 0; 1711 break; 1712 default: 1713 PMD_DRV_LOG(ERR, "Invalid dst_port mask."); 1714 return -EINVAL; 1715 } 1716 1717 switch (filter->src_port_mask) { 1718 case UINT16_MAX: 1719 hinic_filter_info->src_port_mask = 0; 1720 hinic_filter_info->src_port = filter->src_port; 1721 break; 1722 case 0: 1723 hinic_filter_info->src_port_mask = 1; 1724 hinic_filter_info->src_port = 0; 1725 break; 1726 default: 1727 PMD_DRV_LOG(ERR, "Invalid src_port mask."); 1728 return -EINVAL; 1729 } 1730 1731 return 0; 1732 } 1733 1734 static inline int ntuple_proto_filter(struct rte_eth_ntuple_filter *filter, 1735 struct hinic_5tuple_filter_info *hinic_filter_info) 1736 { 1737 switch (filter->proto_mask) { 1738 case UINT8_MAX: 1739 hinic_filter_info->proto_mask = 0; 1740 hinic_filter_info->proto = filter->proto; 1741 break; 1742 case 0: 1743 hinic_filter_info->proto_mask = 1; 1744 hinic_filter_info->proto = 0; 1745 break; 1746 default: 1747 PMD_DRV_LOG(ERR, "Invalid protocol mask."); 1748 return -EINVAL; 1749 } 1750 1751 return 0; 1752 } 1753 1754 static inline int ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, 1755 struct hinic_5tuple_filter_info *filter_info) 1756 { 1757 if (filter->queue >= HINIC_MAX_RX_QUEUE_NUM || 1758 filter->priority > HINIC_MAX_N_TUPLE_PRIO || 1759 filter->priority < HINIC_MIN_N_TUPLE_PRIO) 1760 return -EINVAL; 1761 1762 if (ntuple_ip_filter(filter, filter_info) || 1763 ntuple_port_filter(filter, filter_info) || 1764 ntuple_proto_filter(filter, filter_info)) 1765 return -EINVAL; 1766 1767 filter_info->priority = (uint8_t)filter->priority; 1768 return 0; 1769 } 1770 1771 static inline struct hinic_5tuple_filter * 1772 hinic_5tuple_filter_lookup(struct hinic_5tuple_filter_list *filter_list, 1773 struct hinic_5tuple_filter_info *key) 1774 { 1775 struct hinic_5tuple_filter *it; 1776 1777 TAILQ_FOREACH(it, filter_list, entries) { 1778 if (memcmp(key, &it->filter_info, 1779 sizeof(struct hinic_5tuple_filter_info)) == 0) { 1780 return it; 1781 } 1782 } 1783 1784 return NULL; 1785 } 1786 1787 static int hinic_set_lacp_tcam(struct hinic_nic_dev *nic_dev) 1788 { 1789 struct tag_pa_rule lacp_rule; 1790 struct tag_pa_action lacp_action; 1791 1792 memset(&lacp_rule, 0, sizeof(lacp_rule)); 1793 memset(&lacp_action, 0, sizeof(lacp_action)); 1794 /* LACP TCAM rule */ 1795 lacp_rule.eth_type = PA_ETH_TYPE_OTHER; 1796 lacp_rule.l2_header.eth_type.val16 = 0x8809; 1797 lacp_rule.l2_header.eth_type.mask16 = 0xffff; 1798 1799 /* LACP TCAM action */ 1800 lacp_action.err_type = 0x3f; /* err from ipsu, not convert */ 1801 lacp_action.fwd_action = 0x7; /* 0x3:drop; 0x7: not convert */ 1802 lacp_action.pkt_type = PKT_LACP_TYPE; 1803 lacp_action.pri = 0x0; 1804 lacp_action.push_len = 0xf; /* push_len:0xf, not convert */ 1805 1806 return hinic_set_fdir_tcam(nic_dev->hwdev, TCAM_PKT_LACP, 1807 &lacp_rule, &lacp_action); 1808 } 1809 1810 static int hinic_set_bgp_dport_tcam(struct hinic_nic_dev *nic_dev) 1811 { 1812 struct tag_pa_rule bgp_rule; 1813 struct tag_pa_action bgp_action; 1814 1815 memset(&bgp_rule, 0, sizeof(bgp_rule)); 1816 memset(&bgp_action, 0, sizeof(bgp_action)); 1817 /* BGP TCAM rule */ 1818 bgp_rule.eth_type = PA_ETH_TYPE_IPV4; /* Eth type is IPV4 */ 1819 bgp_rule.ip_header.protocol.val8 = IP_HEADER_PROTOCOL_TYPE_TCP; 1820 bgp_rule.ip_header.protocol.mask8 = UINT8_MAX; 1821 bgp_rule.ip_protocol_type = PA_IP_PROTOCOL_TYPE_TCP; 1822 bgp_rule.eth_ip_tcp.dport.val16 = BGP_DPORT_ID; /* Dport is 179 */ 1823 bgp_rule.eth_ip_tcp.dport.mask16 = UINT16_MAX; 1824 1825 /* BGP TCAM action */ 1826 bgp_action.err_type = 0x3f; /* err from ipsu, not convert */ 1827 bgp_action.fwd_action = 0x7; /* 0x3:drop; 0x7: not convert */ 1828 bgp_action.pkt_type = PKT_BGPD_DPORT_TYPE; /* bgp_dport: 83 */ 1829 bgp_action.pri = 0xf; /* pri of BGP is 0xf, result from ipsu parse 1830 * results, not need to convert 1831 */ 1832 bgp_action.push_len = 0xf; /* push_len:0xf, not convert */ 1833 1834 return hinic_set_fdir_tcam(nic_dev->hwdev, 1835 TCAM_PKT_BGP_DPORT, &bgp_rule, &bgp_action); 1836 } 1837 1838 static int hinic_set_bgp_sport_tcam(struct hinic_nic_dev *nic_dev) 1839 { 1840 struct tag_pa_rule bgp_rule; 1841 struct tag_pa_action bgp_action; 1842 1843 memset(&bgp_rule, 0, sizeof(bgp_rule)); 1844 memset(&bgp_action, 0, sizeof(bgp_action)); 1845 /* BGP TCAM rule */ 1846 bgp_rule.eth_type = PA_ETH_TYPE_IPV4; 1847 bgp_rule.ip_header.protocol.val8 = IP_HEADER_PROTOCOL_TYPE_TCP; 1848 bgp_rule.ip_header.protocol.mask8 = UINT8_MAX; 1849 bgp_rule.ip_protocol_type = PA_IP_PROTOCOL_TYPE_TCP; 1850 bgp_rule.eth_ip_tcp.sport.val16 = BGP_DPORT_ID; 1851 bgp_rule.eth_ip_tcp.sport.mask16 = UINT16_MAX; 1852 1853 /* BGP TCAM action */ 1854 bgp_action.err_type = 0x3f; /* err from ipsu, not convert */ 1855 bgp_action.fwd_action = 0x7; /* 0x3:drop; 0x7: not convert */ 1856 bgp_action.pkt_type = PKT_BGPD_SPORT_TYPE; /* bgp:sport: 84 */ 1857 bgp_action.pri = 0xf; /* pri of BGP is 0xf, result from ipsu parse 1858 * results, not need to convert 1859 */ 1860 bgp_action.push_len = 0xf; /* push_len:0xf, not convert */ 1861 1862 return hinic_set_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT, 1863 &bgp_rule, &bgp_action); 1864 } 1865 1866 static int hinic_set_vrrp_tcam(struct hinic_nic_dev *nic_dev) 1867 { 1868 struct tag_pa_rule vrrp_rule; 1869 struct tag_pa_action vrrp_action; 1870 1871 memset(&vrrp_rule, 0, sizeof(vrrp_rule)); 1872 memset(&vrrp_action, 0, sizeof(vrrp_action)); 1873 /* VRRP TCAM rule */ 1874 vrrp_rule.eth_type = PA_ETH_TYPE_IPV4; 1875 vrrp_rule.ip_protocol_type = PA_IP_PROTOCOL_TYPE_TCP; 1876 vrrp_rule.ip_header.protocol.mask8 = 0xff; 1877 vrrp_rule.ip_header.protocol.val8 = PA_IP_PROTOCOL_TYPE_VRRP; 1878 1879 /* VRRP TCAM action */ 1880 vrrp_action.err_type = 0x3f; 1881 vrrp_action.fwd_action = 0x7; 1882 vrrp_action.pkt_type = PKT_VRRP_TYPE; /* VRRP: 85 */ 1883 vrrp_action.pri = 0xf; 1884 vrrp_action.push_len = 0xf; 1885 1886 return hinic_set_fdir_tcam(nic_dev->hwdev, TCAM_PKT_VRRP, 1887 &vrrp_rule, &vrrp_action); 1888 } 1889 1890 /** 1891 * Clear all fdir configuration. 1892 * 1893 * @param nic_dev 1894 * The hardware interface of a Ethernet device. 1895 * 1896 * @return 1897 * 0 on success, 1898 * negative error value otherwise. 1899 */ 1900 void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev) 1901 { 1902 (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); 1903 1904 (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); 1905 1906 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_DPORT); 1907 1908 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT); 1909 1910 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_VRRP); 1911 1912 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_LACP); 1913 1914 (void)hinic_flush_tcam_rule(nic_dev->hwdev); 1915 } 1916 1917 static int hinic_filter_info_init(struct hinic_5tuple_filter *filter, 1918 struct hinic_filter_info *filter_info) 1919 { 1920 switch (filter->filter_info.proto) { 1921 case IPPROTO_TCP: 1922 /* Filter type is bgp type if dst_port or src_port is 179 */ 1923 if (filter->filter_info.dst_port == RTE_BE16(BGP_DPORT_ID) && 1924 !(filter->filter_info.dst_port_mask)) { 1925 filter_info->pkt_type = PKT_BGPD_DPORT_TYPE; 1926 } else if (filter->filter_info.src_port == 1927 RTE_BE16(BGP_DPORT_ID) && 1928 !(filter->filter_info.src_port_mask)) { 1929 filter_info->pkt_type = PKT_BGPD_SPORT_TYPE; 1930 } else { 1931 PMD_DRV_LOG(INFO, "TCP PROTOCOL:5tuple filters" 1932 " just support BGP now, proto:0x%x, " 1933 "dst_port:0x%x, dst_port_mask:0x%x." 1934 "src_port:0x%x, src_port_mask:0x%x.", 1935 filter->filter_info.proto, 1936 filter->filter_info.dst_port, 1937 filter->filter_info.dst_port_mask, 1938 filter->filter_info.src_port, 1939 filter->filter_info.src_port_mask); 1940 return -EINVAL; 1941 } 1942 break; 1943 1944 case IPPROTO_VRRP: 1945 filter_info->pkt_type = PKT_VRRP_TYPE; 1946 break; 1947 1948 case IPPROTO_ICMP: 1949 filter_info->pkt_type = PKT_ICMP_IPV4_TYPE; 1950 break; 1951 1952 case IPPROTO_ICMPV6: 1953 filter_info->pkt_type = PKT_ICMP_IPV6_TYPE; 1954 break; 1955 1956 default: 1957 PMD_DRV_LOG(ERR, "5tuple filters just support BGP/VRRP/ICMP now, " 1958 "proto: 0x%x, dst_port: 0x%x, dst_port_mask: 0x%x." 1959 "src_port: 0x%x, src_port_mask: 0x%x.", 1960 filter->filter_info.proto, filter->filter_info.dst_port, 1961 filter->filter_info.dst_port_mask, 1962 filter->filter_info.src_port, 1963 filter->filter_info.src_port_mask); 1964 return -EINVAL; 1965 } 1966 1967 return 0; 1968 } 1969 1970 static int hinic_lookup_new_filter(struct hinic_5tuple_filter *filter, 1971 struct hinic_filter_info *filter_info, int *index) 1972 { 1973 int type_id; 1974 1975 type_id = HINIC_PKT_TYPE_FIND_ID(filter_info->pkt_type); 1976 1977 if (type_id > HINIC_MAX_Q_FILTERS - 1) { 1978 PMD_DRV_LOG(ERR, "Pkt filters only support 64 filter type."); 1979 return -EINVAL; 1980 } 1981 1982 if (!(filter_info->type_mask & (1 << type_id))) { 1983 filter_info->type_mask |= 1 << type_id; 1984 filter->index = type_id; 1985 filter_info->pkt_filters[type_id].enable = true; 1986 filter_info->pkt_filters[type_id].pkt_proto = 1987 filter->filter_info.proto; 1988 TAILQ_INSERT_TAIL(&filter_info->fivetuple_list, 1989 filter, entries); 1990 } else { 1991 PMD_DRV_LOG(ERR, "Filter type: %d exists.", type_id); 1992 return -EIO; 1993 } 1994 1995 *index = type_id; 1996 return 0; 1997 } 1998 1999 /* 2000 * Add a 5tuple filter 2001 * 2002 * @param dev: 2003 * Pointer to struct rte_eth_dev. 2004 * @param filter: 2005 * Pointer to the filter that will be added. 2006 * @return 2007 * - On success, zero. 2008 * - On failure, a negative value. 2009 */ 2010 static int hinic_add_5tuple_filter(struct rte_eth_dev *dev, 2011 struct hinic_5tuple_filter *filter) 2012 { 2013 struct hinic_filter_info *filter_info = 2014 HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 2015 int i, ret_fw; 2016 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2017 2018 if (hinic_filter_info_init(filter, filter_info) || 2019 hinic_lookup_new_filter(filter, filter_info, &i)) 2020 return -EFAULT; 2021 2022 ret_fw = hinic_set_fdir_filter(nic_dev->hwdev, filter_info->pkt_type, 2023 filter_info->qid, 2024 filter_info->pkt_filters[i].enable, 2025 true); 2026 if (ret_fw) { 2027 PMD_DRV_LOG(ERR, "Set fdir filter failed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2028 filter_info->pkt_type, filter->queue, 2029 filter_info->pkt_filters[i].enable); 2030 return -EFAULT; 2031 } 2032 2033 PMD_DRV_LOG(INFO, "Add 5tuple succeed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2034 filter_info->pkt_type, filter_info->qid, 2035 filter_info->pkt_filters[filter->index].enable); 2036 2037 switch (filter->filter_info.proto) { 2038 case IPPROTO_TCP: 2039 if (filter->filter_info.dst_port == RTE_BE16(BGP_DPORT_ID)) { 2040 ret_fw = hinic_set_bgp_dport_tcam(nic_dev); 2041 if (ret_fw) { 2042 PMD_DRV_LOG(ERR, "Set dport bgp failed, " 2043 "type: 0x%x, qid: 0x%x, enable: 0x%x", 2044 filter_info->pkt_type, filter->queue, 2045 filter_info->pkt_filters[i].enable); 2046 return -EFAULT; 2047 } 2048 2049 PMD_DRV_LOG(INFO, "Set dport bgp succeed, qid: 0x%x, enable: 0x%x", 2050 filter->queue, 2051 filter_info->pkt_filters[i].enable); 2052 } else if (filter->filter_info.src_port == 2053 RTE_BE16(BGP_DPORT_ID)) { 2054 ret_fw = hinic_set_bgp_sport_tcam(nic_dev); 2055 if (ret_fw) { 2056 PMD_DRV_LOG(ERR, "Set sport bgp failed, " 2057 "type: 0x%x, qid: 0x%x, enable: 0x%x", 2058 filter_info->pkt_type, filter->queue, 2059 filter_info->pkt_filters[i].enable); 2060 return -EFAULT; 2061 } 2062 2063 PMD_DRV_LOG(INFO, "Set sport bgp succeed, qid: 0x%x, enable: 0x%x", 2064 filter->queue, 2065 filter_info->pkt_filters[i].enable); 2066 } 2067 2068 break; 2069 2070 case IPPROTO_VRRP: 2071 ret_fw = hinic_set_vrrp_tcam(nic_dev); 2072 if (ret_fw) { 2073 PMD_DRV_LOG(ERR, "Set VRRP failed, " 2074 "type: 0x%x, qid: 0x%x, enable: 0x%x", 2075 filter_info->pkt_type, filter->queue, 2076 filter_info->pkt_filters[i].enable); 2077 return -EFAULT; 2078 } 2079 PMD_DRV_LOG(INFO, "Set VRRP succeed, qid: 0x%x, enable: 0x%x", 2080 filter->queue, 2081 filter_info->pkt_filters[i].enable); 2082 break; 2083 2084 default: 2085 break; 2086 } 2087 2088 return 0; 2089 } 2090 2091 /* 2092 * Remove a 5tuple filter 2093 * 2094 * @param dev 2095 * Pointer to struct rte_eth_dev. 2096 * @param filter 2097 * The pointer of the filter will be removed. 2098 */ 2099 static void hinic_remove_5tuple_filter(struct rte_eth_dev *dev, 2100 struct hinic_5tuple_filter *filter) 2101 { 2102 struct hinic_filter_info *filter_info = 2103 HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 2104 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2105 2106 switch (filter->filter_info.proto) { 2107 case IPPROTO_VRRP: 2108 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_VRRP); 2109 break; 2110 2111 case IPPROTO_TCP: 2112 if (filter->filter_info.dst_port == RTE_BE16(BGP_DPORT_ID)) 2113 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, 2114 TCAM_PKT_BGP_DPORT); 2115 else if (filter->filter_info.src_port == RTE_BE16(BGP_DPORT_ID)) 2116 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, 2117 TCAM_PKT_BGP_SPORT); 2118 break; 2119 2120 default: 2121 break; 2122 } 2123 2124 hinic_filter_info_init(filter, filter_info); 2125 2126 filter_info->pkt_filters[filter->index].enable = false; 2127 filter_info->pkt_filters[filter->index].pkt_proto = 0; 2128 2129 PMD_DRV_LOG(INFO, "Del 5tuple succeed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2130 filter_info->pkt_type, 2131 filter_info->pkt_filters[filter->index].qid, 2132 filter_info->pkt_filters[filter->index].enable); 2133 (void)hinic_set_fdir_filter(nic_dev->hwdev, filter_info->pkt_type, 2134 filter_info->pkt_filters[filter->index].qid, 2135 filter_info->pkt_filters[filter->index].enable, 2136 true); 2137 2138 filter_info->pkt_type = 0; 2139 filter_info->qid = 0; 2140 filter_info->pkt_filters[filter->index].qid = 0; 2141 filter_info->type_mask &= ~(1 << (filter->index)); 2142 TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries); 2143 2144 rte_free(filter); 2145 } 2146 2147 /* 2148 * Add or delete a ntuple filter 2149 * 2150 * @param dev 2151 * Pointer to struct rte_eth_dev. 2152 * @param ntuple_filter 2153 * Pointer to struct rte_eth_ntuple_filter 2154 * @param add 2155 * If true, add filter; if false, remove filter 2156 * @return 2157 * - On success, zero. 2158 * - On failure, a negative value. 2159 */ 2160 static int hinic_add_del_ntuple_filter(struct rte_eth_dev *dev, 2161 struct rte_eth_ntuple_filter *ntuple_filter, 2162 bool add) 2163 { 2164 struct hinic_filter_info *filter_info = 2165 HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 2166 struct hinic_5tuple_filter_info filter_5tuple; 2167 struct hinic_5tuple_filter *filter; 2168 int ret; 2169 2170 if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { 2171 PMD_DRV_LOG(ERR, "Only 5tuple is supported."); 2172 return -EINVAL; 2173 } 2174 2175 memset(&filter_5tuple, 0, sizeof(struct hinic_5tuple_filter_info)); 2176 ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); 2177 if (ret < 0) 2178 return ret; 2179 2180 filter = hinic_5tuple_filter_lookup(&filter_info->fivetuple_list, 2181 &filter_5tuple); 2182 if (filter != NULL && add) { 2183 PMD_DRV_LOG(ERR, "Filter exists."); 2184 return -EEXIST; 2185 } 2186 if (filter == NULL && !add) { 2187 PMD_DRV_LOG(ERR, "Filter doesn't exist."); 2188 return -ENOENT; 2189 } 2190 2191 if (add) { 2192 filter = rte_zmalloc("hinic_5tuple_filter", 2193 sizeof(struct hinic_5tuple_filter), 0); 2194 if (filter == NULL) 2195 return -ENOMEM; 2196 rte_memcpy(&filter->filter_info, &filter_5tuple, 2197 sizeof(struct hinic_5tuple_filter_info)); 2198 filter->queue = ntuple_filter->queue; 2199 2200 filter_info->qid = ntuple_filter->queue; 2201 2202 ret = hinic_add_5tuple_filter(dev, filter); 2203 if (ret) 2204 rte_free(filter); 2205 2206 return ret; 2207 } 2208 2209 hinic_remove_5tuple_filter(dev, filter); 2210 2211 return 0; 2212 } 2213 2214 static inline int 2215 hinic_check_ethertype_filter(struct rte_eth_ethertype_filter *filter) 2216 { 2217 if (filter->queue >= HINIC_MAX_RX_QUEUE_NUM) 2218 return -EINVAL; 2219 2220 if (filter->ether_type == RTE_ETHER_TYPE_IPV4 || 2221 filter->ether_type == RTE_ETHER_TYPE_IPV6) { 2222 PMD_DRV_LOG(ERR, "Unsupported ether_type(0x%04x) in" 2223 " ethertype filter", filter->ether_type); 2224 return -EINVAL; 2225 } 2226 2227 if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { 2228 PMD_DRV_LOG(ERR, "Mac compare is not supported"); 2229 return -EINVAL; 2230 } 2231 if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { 2232 PMD_DRV_LOG(ERR, "Drop option is not supported"); 2233 return -EINVAL; 2234 } 2235 2236 return 0; 2237 } 2238 2239 static inline int 2240 hinic_ethertype_filter_lookup(struct hinic_filter_info *filter_info, 2241 struct hinic_pkt_filter *ethertype_filter) 2242 { 2243 switch (ethertype_filter->pkt_proto) { 2244 case RTE_ETHER_TYPE_SLOW: 2245 filter_info->pkt_type = PKT_LACP_TYPE; 2246 break; 2247 2248 case RTE_ETHER_TYPE_ARP: 2249 filter_info->pkt_type = PKT_ARP_TYPE; 2250 break; 2251 2252 default: 2253 PMD_DRV_LOG(ERR, "Just support LACP/ARP for ethertype filters"); 2254 return -EIO; 2255 } 2256 2257 return HINIC_PKT_TYPE_FIND_ID(filter_info->pkt_type); 2258 } 2259 2260 static inline int 2261 hinic_ethertype_filter_insert(struct hinic_filter_info *filter_info, 2262 struct hinic_pkt_filter *ethertype_filter) 2263 { 2264 int id; 2265 2266 /* Find LACP or VRRP type id */ 2267 id = hinic_ethertype_filter_lookup(filter_info, ethertype_filter); 2268 if (id < 0) 2269 return -EINVAL; 2270 2271 if (!(filter_info->type_mask & (1 << id))) { 2272 filter_info->type_mask |= 1 << id; 2273 filter_info->pkt_filters[id].pkt_proto = 2274 ethertype_filter->pkt_proto; 2275 filter_info->pkt_filters[id].enable = ethertype_filter->enable; 2276 filter_info->qid = ethertype_filter->qid; 2277 return id; 2278 } 2279 2280 PMD_DRV_LOG(ERR, "Filter type: %d exists", id); 2281 return -EINVAL; 2282 } 2283 2284 static inline void 2285 hinic_ethertype_filter_remove(struct hinic_filter_info *filter_info, 2286 uint8_t idx) 2287 { 2288 if (idx >= HINIC_MAX_Q_FILTERS) 2289 return; 2290 2291 filter_info->pkt_type = 0; 2292 filter_info->type_mask &= ~(1 << idx); 2293 filter_info->pkt_filters[idx].pkt_proto = (uint16_t)0; 2294 filter_info->pkt_filters[idx].enable = FALSE; 2295 filter_info->pkt_filters[idx].qid = 0; 2296 } 2297 2298 static inline int 2299 hinic_add_del_ethertype_filter(struct rte_eth_dev *dev, 2300 struct rte_eth_ethertype_filter *filter, 2301 bool add) 2302 { 2303 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2304 struct hinic_filter_info *filter_info = 2305 HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 2306 struct hinic_pkt_filter ethertype_filter; 2307 int i; 2308 int ret_fw; 2309 2310 if (hinic_check_ethertype_filter(filter)) 2311 return -EINVAL; 2312 2313 if (add) { 2314 ethertype_filter.pkt_proto = filter->ether_type; 2315 ethertype_filter.enable = TRUE; 2316 ethertype_filter.qid = (u8)filter->queue; 2317 i = hinic_ethertype_filter_insert(filter_info, 2318 ðertype_filter); 2319 if (i < 0) 2320 return -ENOSPC; 2321 2322 ret_fw = hinic_set_fdir_filter(nic_dev->hwdev, 2323 filter_info->pkt_type, filter_info->qid, 2324 filter_info->pkt_filters[i].enable, true); 2325 if (ret_fw) { 2326 PMD_DRV_LOG(ERR, "add ethertype failed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2327 filter_info->pkt_type, filter->queue, 2328 filter_info->pkt_filters[i].enable); 2329 2330 hinic_ethertype_filter_remove(filter_info, i); 2331 return -ENOENT; 2332 } 2333 PMD_DRV_LOG(INFO, "Add ethertype succeed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2334 filter_info->pkt_type, filter->queue, 2335 filter_info->pkt_filters[i].enable); 2336 2337 switch (ethertype_filter.pkt_proto) { 2338 case RTE_ETHER_TYPE_SLOW: 2339 ret_fw = hinic_set_lacp_tcam(nic_dev); 2340 if (ret_fw) { 2341 PMD_DRV_LOG(ERR, "Add lacp tcam failed"); 2342 hinic_ethertype_filter_remove(filter_info, i); 2343 return -ENOENT; 2344 } 2345 2346 PMD_DRV_LOG(INFO, "Add lacp tcam succeed"); 2347 break; 2348 default: 2349 break; 2350 } 2351 } else { 2352 ethertype_filter.pkt_proto = filter->ether_type; 2353 i = hinic_ethertype_filter_lookup(filter_info, 2354 ðertype_filter); 2355 if (i < 0) 2356 return -EINVAL; 2357 2358 if ((filter_info->type_mask & (1 << i))) { 2359 filter_info->pkt_filters[i].enable = FALSE; 2360 (void)hinic_set_fdir_filter(nic_dev->hwdev, 2361 filter_info->pkt_type, 2362 filter_info->pkt_filters[i].qid, 2363 filter_info->pkt_filters[i].enable, 2364 true); 2365 2366 PMD_DRV_LOG(INFO, "Del ethertype succeed, type: 0x%x, qid: 0x%x, enable: 0x%x", 2367 filter_info->pkt_type, 2368 filter_info->pkt_filters[i].qid, 2369 filter_info->pkt_filters[i].enable); 2370 2371 switch (ethertype_filter.pkt_proto) { 2372 case RTE_ETHER_TYPE_SLOW: 2373 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, 2374 TCAM_PKT_LACP); 2375 PMD_DRV_LOG(INFO, "Del lacp tcam succeed"); 2376 break; 2377 default: 2378 break; 2379 } 2380 2381 hinic_ethertype_filter_remove(filter_info, i); 2382 2383 } else { 2384 PMD_DRV_LOG(ERR, "Ethertype doesn't exist, type: 0x%x, qid: 0x%x, enable: 0x%x", 2385 filter_info->pkt_type, filter->queue, 2386 filter_info->pkt_filters[i].enable); 2387 return -ENOENT; 2388 } 2389 } 2390 2391 return 0; 2392 } 2393 2394 static int hinic_fdir_info_init(struct hinic_fdir_rule *rule, 2395 struct hinic_fdir_info *fdir_info) 2396 { 2397 switch (rule->mask.src_ipv4_mask) { 2398 case UINT32_MAX: 2399 fdir_info->fdir_flag = HINIC_ATR_FLOW_TYPE_IPV4_SIP; 2400 fdir_info->qid = rule->queue; 2401 fdir_info->fdir_key = rule->hinic_fdir.src_ip; 2402 return 0; 2403 2404 case 0: 2405 break; 2406 2407 default: 2408 PMD_DRV_LOG(ERR, "Invalid src_ip mask."); 2409 return -EINVAL; 2410 } 2411 2412 switch (rule->mask.dst_ipv4_mask) { 2413 case UINT32_MAX: 2414 fdir_info->fdir_flag = HINIC_ATR_FLOW_TYPE_IPV4_DIP; 2415 fdir_info->qid = rule->queue; 2416 fdir_info->fdir_key = rule->hinic_fdir.dst_ip; 2417 return 0; 2418 2419 case 0: 2420 break; 2421 2422 default: 2423 PMD_DRV_LOG(ERR, "Invalid dst_ip mask."); 2424 return -EINVAL; 2425 } 2426 2427 if (fdir_info->fdir_flag == 0) { 2428 PMD_DRV_LOG(ERR, "All support mask is NULL."); 2429 return -EINVAL; 2430 } 2431 2432 return 0; 2433 } 2434 2435 static inline int hinic_add_del_fdir_filter(struct rte_eth_dev *dev, 2436 struct hinic_fdir_rule *rule, bool add) 2437 { 2438 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2439 struct hinic_fdir_info fdir_info; 2440 int ret; 2441 2442 memset(&fdir_info, 0, sizeof(struct hinic_fdir_info)); 2443 2444 ret = hinic_fdir_info_init(rule, &fdir_info); 2445 if (ret) { 2446 PMD_DRV_LOG(ERR, "Init hinic fdir info failed!"); 2447 return ret; 2448 } 2449 2450 if (add) { 2451 ret = hinic_set_normal_filter(nic_dev->hwdev, fdir_info.qid, 2452 true, fdir_info.fdir_key, 2453 true, fdir_info.fdir_flag); 2454 if (ret) { 2455 PMD_DRV_LOG(ERR, "Add fdir filter failed, flag: 0x%x, qid: 0x%x, key: 0x%x", 2456 fdir_info.fdir_flag, fdir_info.qid, 2457 fdir_info.fdir_key); 2458 return -ENOENT; 2459 } 2460 PMD_DRV_LOG(INFO, "Add fdir filter succeed, flag: 0x%x, qid: 0x%x, key: 0x%x", 2461 fdir_info.fdir_flag, fdir_info.qid, 2462 fdir_info.fdir_key); 2463 } else { 2464 ret = hinic_set_normal_filter(nic_dev->hwdev, fdir_info.qid, 2465 false, fdir_info.fdir_key, true, 2466 fdir_info.fdir_flag); 2467 if (ret) { 2468 PMD_DRV_LOG(ERR, "Del fdir filter failed, flag: 0x%x, qid: 0x%x, key: 0x%x", 2469 fdir_info.fdir_flag, fdir_info.qid, 2470 fdir_info.fdir_key); 2471 return -ENOENT; 2472 } 2473 PMD_DRV_LOG(INFO, "Del fdir filter succeed, flag: 0x%x, qid: 0x%x, key: 0x%x", 2474 fdir_info.fdir_flag, fdir_info.qid, 2475 fdir_info.fdir_key); 2476 } 2477 2478 return 0; 2479 } 2480 2481 static void tcam_translate_key_y(u8 *key_y, u8 *src_input, u8 *mask, u8 len) 2482 { 2483 u8 idx; 2484 2485 for (idx = 0; idx < len; idx++) 2486 key_y[idx] = src_input[idx] & mask[idx]; 2487 } 2488 2489 static void tcam_translate_key_x(u8 *key_x, u8 *key_y, u8 *mask, u8 len) 2490 { 2491 u8 idx; 2492 2493 for (idx = 0; idx < len; idx++) 2494 key_x[idx] = key_y[idx] ^ mask[idx]; 2495 } 2496 2497 static void tcam_key_calculate(struct tag_tcam_key *tcam_key, 2498 struct tag_tcam_cfg_rule *fdir_tcam_rule) 2499 { 2500 tcam_translate_key_y(fdir_tcam_rule->key.y, 2501 (u8 *)(&tcam_key->key_info), 2502 (u8 *)(&tcam_key->key_mask), 2503 TCAM_FLOW_KEY_SIZE); 2504 tcam_translate_key_x(fdir_tcam_rule->key.x, 2505 fdir_tcam_rule->key.y, 2506 (u8 *)(&tcam_key->key_mask), 2507 TCAM_FLOW_KEY_SIZE); 2508 } 2509 2510 static int hinic_fdir_tcam_ipv4_init(struct rte_eth_dev *dev, 2511 struct hinic_fdir_rule *rule, 2512 struct tag_tcam_key *tcam_key) 2513 { 2514 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2515 2516 switch (rule->mask.dst_ipv4_mask) { 2517 case UINT32_MAX: 2518 tcam_key->key_info.ext_dip_h = 2519 (rule->hinic_fdir.dst_ip >> 16) & 0xffffU; 2520 tcam_key->key_info.ext_dip_l = 2521 rule->hinic_fdir.dst_ip & 0xffffU; 2522 tcam_key->key_mask.ext_dip_h = 2523 (rule->mask.dst_ipv4_mask >> 16) & 0xffffU; 2524 tcam_key->key_mask.ext_dip_l = 2525 rule->mask.dst_ipv4_mask & 0xffffU; 2526 break; 2527 2528 case 0: 2529 break; 2530 2531 default: 2532 PMD_DRV_LOG(ERR, "invalid src_ip mask."); 2533 return -EINVAL; 2534 } 2535 2536 if (rule->mask.dst_port_mask > 0) { 2537 tcam_key->key_info.dst_port = rule->hinic_fdir.dst_port; 2538 tcam_key->key_mask.dst_port = rule->mask.dst_port_mask; 2539 } 2540 2541 if (rule->mask.src_port_mask > 0) { 2542 tcam_key->key_info.src_port = rule->hinic_fdir.src_port; 2543 tcam_key->key_mask.src_port = rule->mask.src_port_mask; 2544 } 2545 2546 switch (rule->mask.tunnel_flag) { 2547 case UINT16_MAX: 2548 tcam_key->key_info.tunnel_flag = FDIR_TCAM_TUNNEL_PACKET; 2549 tcam_key->key_mask.tunnel_flag = UINT8_MAX; 2550 break; 2551 2552 case 0: 2553 tcam_key->key_info.tunnel_flag = FDIR_TCAM_NORMAL_PACKET; 2554 tcam_key->key_mask.tunnel_flag = 0; 2555 break; 2556 2557 default: 2558 PMD_DRV_LOG(ERR, "invalid tunnel flag mask."); 2559 return -EINVAL; 2560 } 2561 2562 if (rule->mask.tunnel_inner_dst_port_mask > 0) { 2563 tcam_key->key_info.dst_port = 2564 rule->hinic_fdir.tunnel_inner_dst_port; 2565 tcam_key->key_mask.dst_port = 2566 rule->mask.tunnel_inner_dst_port_mask; 2567 } 2568 2569 if (rule->mask.tunnel_inner_src_port_mask > 0) { 2570 tcam_key->key_info.src_port = 2571 rule->hinic_fdir.tunnel_inner_src_port; 2572 tcam_key->key_mask.src_port = 2573 rule->mask.tunnel_inner_src_port_mask; 2574 } 2575 2576 switch (rule->mask.proto_mask) { 2577 case UINT16_MAX: 2578 tcam_key->key_info.protocol = rule->hinic_fdir.proto; 2579 tcam_key->key_mask.protocol = UINT8_MAX; 2580 break; 2581 2582 case 0: 2583 break; 2584 2585 default: 2586 PMD_DRV_LOG(ERR, "invalid tunnel flag mask."); 2587 return -EINVAL; 2588 } 2589 2590 tcam_key->key_mask.function_id = UINT16_MAX; 2591 tcam_key->key_info.function_id = 2592 hinic_global_func_id(nic_dev->hwdev) & 0x7fff; 2593 2594 return 0; 2595 } 2596 2597 static int hinic_fdir_tcam_ipv6_init(struct rte_eth_dev *dev, 2598 struct hinic_fdir_rule *rule, 2599 struct tag_tcam_key *tcam_key) 2600 { 2601 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2602 2603 switch (rule->mask.dst_ipv6_mask) { 2604 case UINT16_MAX: 2605 tcam_key->key_info_ipv6.ipv6_key0 = 2606 ((rule->hinic_fdir.dst_ipv6[0] << 8) & 0xff00) | 2607 rule->hinic_fdir.dst_ipv6[1]; 2608 tcam_key->key_info_ipv6.ipv6_key1 = 2609 ((rule->hinic_fdir.dst_ipv6[2] << 8) & 0xff00) | 2610 rule->hinic_fdir.dst_ipv6[3]; 2611 tcam_key->key_info_ipv6.ipv6_key2 = 2612 ((rule->hinic_fdir.dst_ipv6[4] << 8) & 0xff00) | 2613 rule->hinic_fdir.dst_ipv6[5]; 2614 tcam_key->key_info_ipv6.ipv6_key3 = 2615 ((rule->hinic_fdir.dst_ipv6[6] << 8) & 0xff00) | 2616 rule->hinic_fdir.dst_ipv6[7]; 2617 tcam_key->key_info_ipv6.ipv6_key4 = 2618 ((rule->hinic_fdir.dst_ipv6[8] << 8) & 0xff00) | 2619 rule->hinic_fdir.dst_ipv6[9]; 2620 tcam_key->key_info_ipv6.ipv6_key5 = 2621 ((rule->hinic_fdir.dst_ipv6[10] << 8) & 0xff00) | 2622 rule->hinic_fdir.dst_ipv6[11]; 2623 tcam_key->key_info_ipv6.ipv6_key6 = 2624 ((rule->hinic_fdir.dst_ipv6[12] << 8) & 0xff00) | 2625 rule->hinic_fdir.dst_ipv6[13]; 2626 tcam_key->key_info_ipv6.ipv6_key7 = 2627 ((rule->hinic_fdir.dst_ipv6[14] << 8) & 0xff00) | 2628 rule->hinic_fdir.dst_ipv6[15]; 2629 tcam_key->key_mask_ipv6.ipv6_key0 = UINT16_MAX; 2630 tcam_key->key_mask_ipv6.ipv6_key1 = UINT16_MAX; 2631 tcam_key->key_mask_ipv6.ipv6_key2 = UINT16_MAX; 2632 tcam_key->key_mask_ipv6.ipv6_key3 = UINT16_MAX; 2633 tcam_key->key_mask_ipv6.ipv6_key4 = UINT16_MAX; 2634 tcam_key->key_mask_ipv6.ipv6_key5 = UINT16_MAX; 2635 tcam_key->key_mask_ipv6.ipv6_key6 = UINT16_MAX; 2636 tcam_key->key_mask_ipv6.ipv6_key7 = UINT16_MAX; 2637 break; 2638 2639 case 0: 2640 break; 2641 2642 default: 2643 PMD_DRV_LOG(ERR, "invalid dst_ipv6 mask"); 2644 return -EINVAL; 2645 } 2646 2647 if (rule->mask.dst_port_mask > 0) { 2648 tcam_key->key_info_ipv6.dst_port = rule->hinic_fdir.dst_port; 2649 tcam_key->key_mask_ipv6.dst_port = rule->mask.dst_port_mask; 2650 } 2651 2652 switch (rule->mask.proto_mask) { 2653 case UINT16_MAX: 2654 tcam_key->key_info_ipv6.protocol = 2655 (rule->hinic_fdir.proto) & 0x7F; 2656 tcam_key->key_mask_ipv6.protocol = 0x7F; 2657 break; 2658 2659 case 0: 2660 break; 2661 2662 default: 2663 PMD_DRV_LOG(ERR, "invalid tunnel flag mask"); 2664 return -EINVAL; 2665 } 2666 2667 tcam_key->key_info_ipv6.ipv6_flag = 1; 2668 tcam_key->key_mask_ipv6.ipv6_flag = 1; 2669 2670 tcam_key->key_mask_ipv6.function_id = UINT8_MAX; 2671 tcam_key->key_info_ipv6.function_id = 2672 (u8)hinic_global_func_id(nic_dev->hwdev); 2673 2674 return 0; 2675 } 2676 2677 static int hinic_fdir_tcam_info_init(struct rte_eth_dev *dev, 2678 struct hinic_fdir_rule *rule, 2679 struct tag_tcam_key *tcam_key, 2680 struct tag_tcam_cfg_rule *fdir_tcam_rule) 2681 { 2682 int ret = -1; 2683 2684 if (rule->mask.dst_ipv4_mask == UINT32_MAX) 2685 ret = hinic_fdir_tcam_ipv4_init(dev, rule, tcam_key); 2686 else if (rule->mask.dst_ipv6_mask == UINT16_MAX) 2687 ret = hinic_fdir_tcam_ipv6_init(dev, rule, tcam_key); 2688 2689 if (ret < 0) 2690 return ret; 2691 2692 fdir_tcam_rule->data.qid = rule->queue; 2693 2694 tcam_key_calculate(tcam_key, fdir_tcam_rule); 2695 2696 return 0; 2697 } 2698 2699 static inline struct hinic_tcam_filter * 2700 hinic_tcam_filter_lookup(struct hinic_tcam_filter_list *filter_list, 2701 struct tag_tcam_key *key) 2702 { 2703 struct hinic_tcam_filter *it; 2704 2705 TAILQ_FOREACH(it, filter_list, entries) { 2706 if (memcmp(key, &it->tcam_key, 2707 sizeof(struct tag_tcam_key)) == 0) { 2708 return it; 2709 } 2710 } 2711 2712 return NULL; 2713 } 2714 2715 static int hinic_lookup_new_tcam_filter(struct rte_eth_dev *dev, 2716 struct hinic_tcam_info *tcam_info, 2717 struct hinic_tcam_filter *tcam_filter, 2718 u16 *tcam_index) 2719 { 2720 int index; 2721 int max_index; 2722 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2723 2724 if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) 2725 max_index = HINIC_VF_MAX_TCAM_FILTERS; 2726 else 2727 max_index = HINIC_PF_MAX_TCAM_FILTERS; 2728 2729 for (index = 0; index < max_index; index++) { 2730 if (tcam_info->tcam_index_array[index] == 0) 2731 break; 2732 } 2733 2734 if (index == max_index) { 2735 PMD_DRV_LOG(ERR, "function 0x%x tcam filters only support %d filter rules", 2736 hinic_global_func_id(nic_dev->hwdev), max_index); 2737 return -EINVAL; 2738 } 2739 2740 tcam_filter->index = index; 2741 *tcam_index = index; 2742 2743 return 0; 2744 } 2745 2746 static int hinic_add_tcam_filter(struct rte_eth_dev *dev, 2747 struct hinic_tcam_filter *tcam_filter, 2748 struct tag_tcam_cfg_rule *fdir_tcam_rule) 2749 { 2750 struct hinic_tcam_info *tcam_info = 2751 HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); 2752 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2753 u16 index = 0; 2754 u16 tcam_block_index = 0; 2755 int rc; 2756 2757 if (hinic_lookup_new_tcam_filter(dev, tcam_info, tcam_filter, &index)) 2758 return -EINVAL; 2759 2760 if (tcam_info->tcam_rule_nums == 0) { 2761 if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { 2762 rc = hinic_alloc_tcam_block(nic_dev->hwdev, 2763 HINIC_TCAM_BLOCK_TYPE_VF, &tcam_block_index); 2764 if (rc != 0) { 2765 PMD_DRV_LOG(ERR, "VF fdir filter tcam alloc block failed!"); 2766 return -EFAULT; 2767 } 2768 } else { 2769 rc = hinic_alloc_tcam_block(nic_dev->hwdev, 2770 HINIC_TCAM_BLOCK_TYPE_PF, &tcam_block_index); 2771 if (rc != 0) { 2772 PMD_DRV_LOG(ERR, "PF fdir filter tcam alloc block failed!"); 2773 return -EFAULT; 2774 } 2775 } 2776 2777 tcam_info->tcam_block_index = tcam_block_index; 2778 } else { 2779 tcam_block_index = tcam_info->tcam_block_index; 2780 } 2781 2782 if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { 2783 fdir_tcam_rule->index = 2784 HINIC_PKT_VF_TCAM_INDEX_START(tcam_block_index) + index; 2785 } else { 2786 fdir_tcam_rule->index = 2787 tcam_block_index * HINIC_PF_MAX_TCAM_FILTERS + index; 2788 } 2789 2790 rc = hinic_add_tcam_rule(nic_dev->hwdev, fdir_tcam_rule); 2791 if (rc != 0) { 2792 PMD_DRV_LOG(ERR, "Fdir_tcam_rule add failed!"); 2793 return -EFAULT; 2794 } 2795 2796 PMD_DRV_LOG(INFO, "Add fdir_tcam_rule function_id: 0x%x," 2797 "tcam_block_id: %d, index: %d, queue: %d, tcam_rule_nums: %d succeed", 2798 hinic_global_func_id(nic_dev->hwdev), tcam_block_index, 2799 fdir_tcam_rule->index, fdir_tcam_rule->data.qid, 2800 tcam_info->tcam_rule_nums + 1); 2801 2802 if (tcam_info->tcam_rule_nums == 0) { 2803 rc = hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, true); 2804 if (rc < 0) { 2805 (void)hinic_del_tcam_rule(nic_dev->hwdev, 2806 fdir_tcam_rule->index); 2807 return rc; 2808 } 2809 2810 rc = hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true); 2811 if (rc && rc != HINIC_MGMT_CMD_UNSUPPORTED) { 2812 /* 2813 * hinic supports two methods: linear table and tcam 2814 * table, if tcam filter enables failed but linear table 2815 * is ok, which also needs to enable filter, so for this 2816 * scene, driver should not close fdir switch. 2817 */ 2818 (void)hinic_del_tcam_rule(nic_dev->hwdev, 2819 fdir_tcam_rule->index); 2820 return rc; 2821 } 2822 } 2823 2824 TAILQ_INSERT_TAIL(&tcam_info->tcam_list, tcam_filter, entries); 2825 2826 tcam_info->tcam_index_array[index] = 1; 2827 tcam_info->tcam_rule_nums++; 2828 2829 return 0; 2830 } 2831 2832 static int hinic_del_tcam_filter(struct rte_eth_dev *dev, 2833 struct hinic_tcam_filter *tcam_filter) 2834 { 2835 struct hinic_tcam_info *tcam_info = 2836 HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); 2837 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2838 u32 index = 0; 2839 u16 tcam_block_index = tcam_info->tcam_block_index; 2840 int rc; 2841 u8 block_type = 0; 2842 2843 if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { 2844 index = HINIC_PKT_VF_TCAM_INDEX_START(tcam_block_index) + 2845 tcam_filter->index; 2846 block_type = HINIC_TCAM_BLOCK_TYPE_VF; 2847 } else { 2848 index = tcam_block_index * HINIC_PF_MAX_TCAM_FILTERS + 2849 tcam_filter->index; 2850 block_type = HINIC_TCAM_BLOCK_TYPE_PF; 2851 } 2852 2853 rc = hinic_del_tcam_rule(nic_dev->hwdev, index); 2854 if (rc != 0) { 2855 PMD_DRV_LOG(ERR, "fdir_tcam_rule del failed!"); 2856 return -EFAULT; 2857 } 2858 2859 PMD_DRV_LOG(INFO, "Del fdir_tcam_rule function_id: 0x%x, " 2860 "tcam_block_id: %d, index: %d, tcam_rule_nums: %d succeed", 2861 hinic_global_func_id(nic_dev->hwdev), tcam_block_index, index, 2862 tcam_info->tcam_rule_nums - 1); 2863 2864 TAILQ_REMOVE(&tcam_info->tcam_list, tcam_filter, entries); 2865 2866 tcam_info->tcam_index_array[tcam_filter->index] = 0; 2867 2868 rte_free(tcam_filter); 2869 2870 tcam_info->tcam_rule_nums--; 2871 2872 if (tcam_info->tcam_rule_nums == 0) { 2873 (void)hinic_free_tcam_block(nic_dev->hwdev, block_type, 2874 &tcam_block_index); 2875 } 2876 2877 return 0; 2878 } 2879 2880 static int hinic_add_del_tcam_fdir_filter(struct rte_eth_dev *dev, 2881 struct hinic_fdir_rule *rule, bool add) 2882 { 2883 struct hinic_tcam_info *tcam_info = 2884 HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); 2885 struct hinic_tcam_filter *tcam_filter; 2886 struct tag_tcam_cfg_rule fdir_tcam_rule; 2887 struct tag_tcam_key tcam_key; 2888 int ret; 2889 2890 memset(&fdir_tcam_rule, 0, sizeof(struct tag_tcam_cfg_rule)); 2891 memset((void *)&tcam_key, 0, sizeof(struct tag_tcam_key)); 2892 2893 ret = hinic_fdir_tcam_info_init(dev, rule, &tcam_key, &fdir_tcam_rule); 2894 if (ret) { 2895 PMD_DRV_LOG(ERR, "Init hinic fdir info failed!"); 2896 return ret; 2897 } 2898 2899 tcam_filter = hinic_tcam_filter_lookup(&tcam_info->tcam_list, 2900 &tcam_key); 2901 if (tcam_filter != NULL && add) { 2902 PMD_DRV_LOG(ERR, "Filter exists."); 2903 return -EEXIST; 2904 } 2905 if (tcam_filter == NULL && !add) { 2906 PMD_DRV_LOG(ERR, "Filter doesn't exist."); 2907 return -ENOENT; 2908 } 2909 2910 if (add) { 2911 tcam_filter = rte_zmalloc("hinic_5tuple_filter", 2912 sizeof(struct hinic_tcam_filter), 0); 2913 if (tcam_filter == NULL) 2914 return -ENOMEM; 2915 (void)rte_memcpy(&tcam_filter->tcam_key, 2916 &tcam_key, sizeof(struct tag_tcam_key)); 2917 tcam_filter->queue = fdir_tcam_rule.data.qid; 2918 2919 ret = hinic_add_tcam_filter(dev, tcam_filter, &fdir_tcam_rule); 2920 if (ret < 0) { 2921 rte_free(tcam_filter); 2922 return ret; 2923 } 2924 2925 rule->tcam_index = fdir_tcam_rule.index; 2926 2927 } else { 2928 PMD_DRV_LOG(INFO, "begin to hinic_del_tcam_filter"); 2929 ret = hinic_del_tcam_filter(dev, tcam_filter); 2930 if (ret < 0) 2931 return ret; 2932 } 2933 2934 return 0; 2935 } 2936 2937 /** 2938 * Create or destroy a flow rule. 2939 * Theorically one rule can match more than one filters. 2940 * We will let it use the filter which it hitt first. 2941 * So, the sequence matters. 2942 */ 2943 static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, 2944 const struct rte_flow_attr *attr, 2945 const struct rte_flow_item pattern[], 2946 const struct rte_flow_action actions[], 2947 struct rte_flow_error *error) 2948 { 2949 int ret; 2950 struct rte_eth_ntuple_filter ntuple_filter; 2951 struct rte_eth_ethertype_filter ethertype_filter; 2952 struct hinic_fdir_rule fdir_rule; 2953 struct rte_flow *flow = NULL; 2954 struct hinic_ethertype_filter_ele *ethertype_filter_ptr; 2955 struct hinic_ntuple_filter_ele *ntuple_filter_ptr; 2956 struct hinic_fdir_rule_ele *fdir_rule_ptr; 2957 struct hinic_flow_mem *hinic_flow_mem_ptr; 2958 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2959 2960 flow = rte_zmalloc("hinic_rte_flow", sizeof(struct rte_flow), 0); 2961 if (!flow) { 2962 PMD_DRV_LOG(ERR, "Failed to allocate flow memory"); 2963 return NULL; 2964 } 2965 2966 hinic_flow_mem_ptr = rte_zmalloc("hinic_flow_mem", 2967 sizeof(struct hinic_flow_mem), 0); 2968 if (!hinic_flow_mem_ptr) { 2969 PMD_DRV_LOG(ERR, "Failed to allocate hinic_flow_mem_ptr"); 2970 rte_free(flow); 2971 return NULL; 2972 } 2973 2974 hinic_flow_mem_ptr->flow = flow; 2975 TAILQ_INSERT_TAIL(&nic_dev->hinic_flow_list, hinic_flow_mem_ptr, 2976 entries); 2977 2978 /* Add ntuple filter */ 2979 memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter)); 2980 ret = hinic_parse_ntuple_filter(dev, attr, pattern, 2981 actions, &ntuple_filter, error); 2982 if (!ret) { 2983 ret = hinic_add_del_ntuple_filter(dev, &ntuple_filter, TRUE); 2984 if (!ret) { 2985 ntuple_filter_ptr = rte_zmalloc("hinic_ntuple_filter", 2986 sizeof(struct hinic_ntuple_filter_ele), 0); 2987 if (ntuple_filter_ptr == NULL) { 2988 PMD_DRV_LOG(ERR, "Failed to allocate ntuple_filter_ptr"); 2989 (void)hinic_add_del_ntuple_filter(dev, 2990 &ntuple_filter, FALSE); 2991 goto out; 2992 } 2993 rte_memcpy(&ntuple_filter_ptr->filter_info, 2994 &ntuple_filter, 2995 sizeof(struct rte_eth_ntuple_filter)); 2996 TAILQ_INSERT_TAIL(&nic_dev->filter_ntuple_list, 2997 ntuple_filter_ptr, entries); 2998 flow->rule = ntuple_filter_ptr; 2999 flow->filter_type = RTE_ETH_FILTER_NTUPLE; 3000 3001 PMD_DRV_LOG(INFO, "Create flow ntuple succeed, func_id: 0x%x", 3002 hinic_global_func_id(nic_dev->hwdev)); 3003 return flow; 3004 } 3005 goto out; 3006 } 3007 3008 /* Add ethertype filter */ 3009 memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter)); 3010 ret = hinic_parse_ethertype_filter(dev, attr, pattern, actions, 3011 ðertype_filter, error); 3012 if (!ret) { 3013 ret = hinic_add_del_ethertype_filter(dev, ðertype_filter, 3014 TRUE); 3015 if (!ret) { 3016 ethertype_filter_ptr = 3017 rte_zmalloc("hinic_ethertype_filter", 3018 sizeof(struct hinic_ethertype_filter_ele), 0); 3019 if (ethertype_filter_ptr == NULL) { 3020 PMD_DRV_LOG(ERR, "Failed to allocate ethertype_filter_ptr"); 3021 (void)hinic_add_del_ethertype_filter(dev, 3022 ðertype_filter, FALSE); 3023 goto out; 3024 } 3025 rte_memcpy(ðertype_filter_ptr->filter_info, 3026 ðertype_filter, 3027 sizeof(struct rte_eth_ethertype_filter)); 3028 TAILQ_INSERT_TAIL(&nic_dev->filter_ethertype_list, 3029 ethertype_filter_ptr, entries); 3030 flow->rule = ethertype_filter_ptr; 3031 flow->filter_type = RTE_ETH_FILTER_ETHERTYPE; 3032 3033 PMD_DRV_LOG(INFO, "Create flow ethertype succeed, func_id: 0x%x", 3034 hinic_global_func_id(nic_dev->hwdev)); 3035 return flow; 3036 } 3037 goto out; 3038 } 3039 3040 /* Add fdir filter */ 3041 memset(&fdir_rule, 0, sizeof(struct hinic_fdir_rule)); 3042 ret = hinic_parse_fdir_filter(dev, attr, pattern, 3043 actions, &fdir_rule, error); 3044 if (!ret) { 3045 if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) { 3046 ret = hinic_add_del_fdir_filter(dev, &fdir_rule, TRUE); 3047 } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) { 3048 ret = hinic_add_del_tcam_fdir_filter(dev, &fdir_rule, 3049 TRUE); 3050 } else { 3051 PMD_DRV_LOG(INFO, "flow fdir rule create failed, rule mode wrong"); 3052 goto out; 3053 } 3054 if (!ret) { 3055 fdir_rule_ptr = rte_zmalloc("hinic_fdir_rule", 3056 sizeof(struct hinic_fdir_rule_ele), 0); 3057 if (fdir_rule_ptr == NULL) { 3058 PMD_DRV_LOG(ERR, "Failed to allocate fdir_rule_ptr"); 3059 if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) 3060 hinic_add_del_fdir_filter(dev, 3061 &fdir_rule, FALSE); 3062 else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) 3063 hinic_add_del_tcam_fdir_filter(dev, 3064 &fdir_rule, FALSE); 3065 3066 goto out; 3067 } 3068 rte_memcpy(&fdir_rule_ptr->filter_info, &fdir_rule, 3069 sizeof(struct hinic_fdir_rule)); 3070 TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list, 3071 fdir_rule_ptr, entries); 3072 flow->rule = fdir_rule_ptr; 3073 flow->filter_type = RTE_ETH_FILTER_FDIR; 3074 3075 PMD_DRV_LOG(INFO, "Create flow fdir rule succeed, func_id : 0x%x", 3076 hinic_global_func_id(nic_dev->hwdev)); 3077 return flow; 3078 } 3079 goto out; 3080 } 3081 3082 out: 3083 TAILQ_REMOVE(&nic_dev->hinic_flow_list, hinic_flow_mem_ptr, entries); 3084 rte_flow_error_set(error, -ret, 3085 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 3086 "Failed to create flow."); 3087 rte_free(hinic_flow_mem_ptr); 3088 rte_free(flow); 3089 return NULL; 3090 } 3091 3092 /* Destroy a flow rule on hinic. */ 3093 static int hinic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, 3094 struct rte_flow_error *error) 3095 { 3096 int ret; 3097 struct rte_flow *pmd_flow = flow; 3098 enum rte_filter_type filter_type = pmd_flow->filter_type; 3099 struct rte_eth_ntuple_filter ntuple_filter; 3100 struct rte_eth_ethertype_filter ethertype_filter; 3101 struct hinic_fdir_rule fdir_rule; 3102 struct hinic_ntuple_filter_ele *ntuple_filter_ptr; 3103 struct hinic_ethertype_filter_ele *ethertype_filter_ptr; 3104 struct hinic_fdir_rule_ele *fdir_rule_ptr; 3105 struct hinic_flow_mem *hinic_flow_mem_ptr; 3106 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3107 3108 switch (filter_type) { 3109 case RTE_ETH_FILTER_NTUPLE: 3110 ntuple_filter_ptr = (struct hinic_ntuple_filter_ele *) 3111 pmd_flow->rule; 3112 rte_memcpy(&ntuple_filter, &ntuple_filter_ptr->filter_info, 3113 sizeof(struct rte_eth_ntuple_filter)); 3114 ret = hinic_add_del_ntuple_filter(dev, &ntuple_filter, FALSE); 3115 if (!ret) { 3116 TAILQ_REMOVE(&nic_dev->filter_ntuple_list, 3117 ntuple_filter_ptr, entries); 3118 rte_free(ntuple_filter_ptr); 3119 } 3120 break; 3121 case RTE_ETH_FILTER_ETHERTYPE: 3122 ethertype_filter_ptr = (struct hinic_ethertype_filter_ele *) 3123 pmd_flow->rule; 3124 rte_memcpy(ðertype_filter, 3125 ðertype_filter_ptr->filter_info, 3126 sizeof(struct rte_eth_ethertype_filter)); 3127 ret = hinic_add_del_ethertype_filter(dev, 3128 ðertype_filter, FALSE); 3129 if (!ret) { 3130 TAILQ_REMOVE(&nic_dev->filter_ethertype_list, 3131 ethertype_filter_ptr, entries); 3132 rte_free(ethertype_filter_ptr); 3133 } 3134 break; 3135 case RTE_ETH_FILTER_FDIR: 3136 fdir_rule_ptr = (struct hinic_fdir_rule_ele *)pmd_flow->rule; 3137 rte_memcpy(&fdir_rule, 3138 &fdir_rule_ptr->filter_info, 3139 sizeof(struct hinic_fdir_rule)); 3140 if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) { 3141 ret = hinic_add_del_fdir_filter(dev, &fdir_rule, FALSE); 3142 } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) { 3143 ret = hinic_add_del_tcam_fdir_filter(dev, &fdir_rule, 3144 FALSE); 3145 } else { 3146 PMD_DRV_LOG(ERR, "FDIR Filter type is wrong!"); 3147 ret = -EINVAL; 3148 } 3149 if (!ret) { 3150 TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, 3151 fdir_rule_ptr, entries); 3152 rte_free(fdir_rule_ptr); 3153 } 3154 break; 3155 default: 3156 PMD_DRV_LOG(WARNING, "Filter type (%d) is not supported", 3157 filter_type); 3158 ret = -EINVAL; 3159 break; 3160 } 3161 3162 if (ret) { 3163 rte_flow_error_set(error, EINVAL, 3164 RTE_FLOW_ERROR_TYPE_HANDLE, 3165 NULL, "Failed to destroy flow"); 3166 return ret; 3167 } 3168 3169 TAILQ_FOREACH(hinic_flow_mem_ptr, &nic_dev->hinic_flow_list, entries) { 3170 if (hinic_flow_mem_ptr->flow == pmd_flow) { 3171 TAILQ_REMOVE(&nic_dev->hinic_flow_list, 3172 hinic_flow_mem_ptr, entries); 3173 rte_free(hinic_flow_mem_ptr); 3174 break; 3175 } 3176 } 3177 rte_free(flow); 3178 3179 PMD_DRV_LOG(INFO, "Destroy flow succeed, func_id: 0x%x", 3180 hinic_global_func_id(nic_dev->hwdev)); 3181 3182 return ret; 3183 } 3184 3185 /* Remove all the n-tuple filters */ 3186 static void hinic_clear_all_ntuple_filter(struct rte_eth_dev *dev) 3187 { 3188 struct hinic_filter_info *filter_info = 3189 HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 3190 struct hinic_5tuple_filter *p_5tuple; 3191 3192 while ((p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list))) 3193 hinic_remove_5tuple_filter(dev, p_5tuple); 3194 } 3195 3196 /* Remove all the ether type filters */ 3197 static void hinic_clear_all_ethertype_filter(struct rte_eth_dev *dev) 3198 { 3199 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3200 struct hinic_filter_info *filter_info = 3201 HINIC_DEV_PRIVATE_TO_FILTER_INFO(nic_dev); 3202 int ret = 0; 3203 3204 if (filter_info->type_mask & 3205 (1 << HINIC_PKT_TYPE_FIND_ID(PKT_LACP_TYPE))) { 3206 hinic_ethertype_filter_remove(filter_info, 3207 HINIC_PKT_TYPE_FIND_ID(PKT_LACP_TYPE)); 3208 ret = hinic_set_fdir_filter(nic_dev->hwdev, PKT_LACP_TYPE, 3209 filter_info->qid, false, true); 3210 3211 (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_LACP); 3212 } 3213 3214 if (filter_info->type_mask & 3215 (1 << HINIC_PKT_TYPE_FIND_ID(PKT_ARP_TYPE))) { 3216 hinic_ethertype_filter_remove(filter_info, 3217 HINIC_PKT_TYPE_FIND_ID(PKT_ARP_TYPE)); 3218 ret = hinic_set_fdir_filter(nic_dev->hwdev, PKT_ARP_TYPE, 3219 filter_info->qid, false, true); 3220 } 3221 3222 if (ret) 3223 PMD_DRV_LOG(ERR, "Clear ethertype failed, filter type: 0x%x", 3224 filter_info->pkt_type); 3225 } 3226 3227 /* Remove all the ether type filters */ 3228 static void hinic_clear_all_fdir_filter(struct rte_eth_dev *dev) 3229 { 3230 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3231 struct hinic_tcam_info *tcam_info = 3232 HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); 3233 struct hinic_tcam_filter *tcam_filter_ptr; 3234 3235 while ((tcam_filter_ptr = TAILQ_FIRST(&tcam_info->tcam_list))) 3236 (void)hinic_del_tcam_filter(dev, tcam_filter_ptr); 3237 3238 (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); 3239 3240 (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); 3241 3242 (void)hinic_flush_tcam_rule(nic_dev->hwdev); 3243 } 3244 3245 static void hinic_filterlist_flush(struct rte_eth_dev *dev) 3246 { 3247 struct hinic_ntuple_filter_ele *ntuple_filter_ptr; 3248 struct hinic_ethertype_filter_ele *ethertype_filter_ptr; 3249 struct hinic_fdir_rule_ele *fdir_rule_ptr; 3250 struct hinic_flow_mem *hinic_flow_mem_ptr; 3251 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3252 3253 while ((ntuple_filter_ptr = 3254 TAILQ_FIRST(&nic_dev->filter_ntuple_list))) { 3255 TAILQ_REMOVE(&nic_dev->filter_ntuple_list, ntuple_filter_ptr, 3256 entries); 3257 rte_free(ntuple_filter_ptr); 3258 } 3259 3260 while ((ethertype_filter_ptr = 3261 TAILQ_FIRST(&nic_dev->filter_ethertype_list))) { 3262 TAILQ_REMOVE(&nic_dev->filter_ethertype_list, 3263 ethertype_filter_ptr, 3264 entries); 3265 rte_free(ethertype_filter_ptr); 3266 } 3267 3268 while ((fdir_rule_ptr = 3269 TAILQ_FIRST(&nic_dev->filter_fdir_rule_list))) { 3270 TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, fdir_rule_ptr, 3271 entries); 3272 rte_free(fdir_rule_ptr); 3273 } 3274 3275 while ((hinic_flow_mem_ptr = 3276 TAILQ_FIRST(&nic_dev->hinic_flow_list))) { 3277 TAILQ_REMOVE(&nic_dev->hinic_flow_list, hinic_flow_mem_ptr, 3278 entries); 3279 rte_free(hinic_flow_mem_ptr->flow); 3280 rte_free(hinic_flow_mem_ptr); 3281 } 3282 } 3283 3284 /* Destroy all flow rules associated with a port on hinic. */ 3285 static int hinic_flow_flush(struct rte_eth_dev *dev, 3286 __rte_unused struct rte_flow_error *error) 3287 { 3288 struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3289 3290 hinic_clear_all_ntuple_filter(dev); 3291 hinic_clear_all_ethertype_filter(dev); 3292 hinic_clear_all_fdir_filter(dev); 3293 hinic_filterlist_flush(dev); 3294 3295 PMD_DRV_LOG(INFO, "Flush flow succeed, func_id: 0x%x", 3296 hinic_global_func_id(nic_dev->hwdev)); 3297 return 0; 3298 } 3299 3300 void hinic_destroy_fdir_filter(struct rte_eth_dev *dev) 3301 { 3302 hinic_clear_all_ntuple_filter(dev); 3303 hinic_clear_all_ethertype_filter(dev); 3304 hinic_clear_all_fdir_filter(dev); 3305 hinic_filterlist_flush(dev); 3306 } 3307 3308 const struct rte_flow_ops hinic_flow_ops = { 3309 .validate = hinic_flow_validate, 3310 .create = hinic_flow_create, 3311 .destroy = hinic_flow_destroy, 3312 .flush = hinic_flow_flush, 3313 }; 3314