1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020, Intel Corporation. */ 3 4 /* flow director ethtool support for iavf */ 5 6 #include "iavf.h" 7 8 #define GTPU_PORT 2152 9 #define NAT_T_ESP_PORT 4500 10 #define PFCP_PORT 8805 11 12 static const struct in6_addr ipv6_addr_full_mask = { 13 .in6_u = { 14 .u6_addr8 = { 15 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 16 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 17 } 18 } 19 }; 20 21 /** 22 * iavf_pkt_udp_no_pay_len - the length of UDP packet without payload 23 * @fltr: Flow Director filter data structure 24 */ 25 static u16 iavf_pkt_udp_no_pay_len(struct iavf_fdir_fltr *fltr) 26 { 27 return sizeof(struct ethhdr) + 28 (fltr->ip_ver == 4 ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) + 29 sizeof(struct udphdr); 30 } 31 32 /** 33 * iavf_fill_fdir_gtpu_hdr - fill the GTP-U protocol header 34 * @fltr: Flow Director filter data structure 35 * @proto_hdrs: Flow Director protocol headers data structure 36 * 37 * Returns 0 if the GTP-U protocol header is set successfully 38 */ 39 static int 40 iavf_fill_fdir_gtpu_hdr(struct iavf_fdir_fltr *fltr, 41 struct virtchnl_proto_hdrs *proto_hdrs) 42 { 43 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1]; 44 struct virtchnl_proto_hdr *ghdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 45 struct virtchnl_proto_hdr *ehdr = NULL; /* Extension Header if it exists */ 46 u16 adj_offs, hdr_offs; 47 int i; 48 49 VIRTCHNL_SET_PROTO_HDR_TYPE(ghdr, GTPU_IP); 50 51 adj_offs = iavf_pkt_udp_no_pay_len(fltr); 52 53 for (i = 0; i < fltr->flex_cnt; i++) { 54 #define IAVF_GTPU_HDR_TEID_OFFS0 4 55 #define IAVF_GTPU_HDR_TEID_OFFS1 6 56 #define IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS 10 57 #define IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS 13 58 #define IAVF_GTPU_PSC_EXTHDR_TYPE 0x85 /* PDU Session Container Extension Header */ 59 if (fltr->flex_words[i].offset < adj_offs) 60 return -EINVAL; 61 62 hdr_offs = fltr->flex_words[i].offset - adj_offs; 63 64 switch (hdr_offs) { 65 case IAVF_GTPU_HDR_TEID_OFFS0: 66 case IAVF_GTPU_HDR_TEID_OFFS1: { 67 __be16 *pay_word = (__be16 *)ghdr->buffer; 68 69 pay_word[hdr_offs >> 1] = htons(fltr->flex_words[i].word); 70 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(ghdr, GTPU_IP, TEID); 71 } 72 break; 73 case IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS: 74 if ((fltr->flex_words[i].word & 0xff) != IAVF_GTPU_PSC_EXTHDR_TYPE) 75 return -EOPNOTSUPP; 76 if (!ehdr) 77 ehdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 78 VIRTCHNL_SET_PROTO_HDR_TYPE(ehdr, GTPU_EH); 79 break; 80 case IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS: 81 if (!ehdr) 82 return -EINVAL; 83 ehdr->buffer[1] = fltr->flex_words[i].word & 0x3F; 84 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(ehdr, GTPU_EH, QFI); 85 break; 86 default: 87 return -EINVAL; 88 } 89 } 90 91 uhdr->field_selector = 0; /* The PF ignores the UDP header fields */ 92 93 return 0; 94 } 95 96 /** 97 * iavf_fill_fdir_pfcp_hdr - fill the PFCP protocol header 98 * @fltr: Flow Director filter data structure 99 * @proto_hdrs: Flow Director protocol headers data structure 100 * 101 * Returns 0 if the PFCP protocol header is set successfully 102 */ 103 static int 104 iavf_fill_fdir_pfcp_hdr(struct iavf_fdir_fltr *fltr, 105 struct virtchnl_proto_hdrs *proto_hdrs) 106 { 107 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1]; 108 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 109 u16 adj_offs, hdr_offs; 110 int i; 111 112 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, PFCP); 113 114 adj_offs = iavf_pkt_udp_no_pay_len(fltr); 115 116 for (i = 0; i < fltr->flex_cnt; i++) { 117 #define IAVF_PFCP_HDR_SFIELD_AND_MSG_TYPE_OFFS 0 118 if (fltr->flex_words[i].offset < adj_offs) 119 return -EINVAL; 120 121 hdr_offs = fltr->flex_words[i].offset - adj_offs; 122 123 switch (hdr_offs) { 124 case IAVF_PFCP_HDR_SFIELD_AND_MSG_TYPE_OFFS: 125 hdr->buffer[0] = (fltr->flex_words[i].word >> 8) & 0xff; 126 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, PFCP, S_FIELD); 127 break; 128 default: 129 return -EINVAL; 130 } 131 } 132 133 uhdr->field_selector = 0; /* The PF ignores the UDP header fields */ 134 135 return 0; 136 } 137 138 /** 139 * iavf_fill_fdir_nat_t_esp_hdr - fill the NAT-T-ESP protocol header 140 * @fltr: Flow Director filter data structure 141 * @proto_hdrs: Flow Director protocol headers data structure 142 * 143 * Returns 0 if the NAT-T-ESP protocol header is set successfully 144 */ 145 static int 146 iavf_fill_fdir_nat_t_esp_hdr(struct iavf_fdir_fltr *fltr, 147 struct virtchnl_proto_hdrs *proto_hdrs) 148 { 149 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1]; 150 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 151 u16 adj_offs, hdr_offs; 152 u32 spi = 0; 153 int i; 154 155 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ESP); 156 157 adj_offs = iavf_pkt_udp_no_pay_len(fltr); 158 159 for (i = 0; i < fltr->flex_cnt; i++) { 160 #define IAVF_NAT_T_ESP_SPI_OFFS0 0 161 #define IAVF_NAT_T_ESP_SPI_OFFS1 2 162 if (fltr->flex_words[i].offset < adj_offs) 163 return -EINVAL; 164 165 hdr_offs = fltr->flex_words[i].offset - adj_offs; 166 167 switch (hdr_offs) { 168 case IAVF_NAT_T_ESP_SPI_OFFS0: 169 spi |= fltr->flex_words[i].word << 16; 170 break; 171 case IAVF_NAT_T_ESP_SPI_OFFS1: 172 spi |= fltr->flex_words[i].word; 173 break; 174 default: 175 return -EINVAL; 176 } 177 } 178 179 if (!spi) 180 return -EOPNOTSUPP; /* Not support IKE Header Format with SPI 0 */ 181 182 *(__be32 *)hdr->buffer = htonl(spi); 183 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ESP, SPI); 184 185 uhdr->field_selector = 0; /* The PF ignores the UDP header fields */ 186 187 return 0; 188 } 189 190 /** 191 * iavf_fill_fdir_udp_flex_pay_hdr - fill the UDP payload header 192 * @fltr: Flow Director filter data structure 193 * @proto_hdrs: Flow Director protocol headers data structure 194 * 195 * Returns 0 if the UDP payload defined protocol header is set successfully 196 */ 197 static int 198 iavf_fill_fdir_udp_flex_pay_hdr(struct iavf_fdir_fltr *fltr, 199 struct virtchnl_proto_hdrs *proto_hdrs) 200 { 201 int err; 202 203 switch (ntohs(fltr->ip_data.dst_port)) { 204 case GTPU_PORT: 205 err = iavf_fill_fdir_gtpu_hdr(fltr, proto_hdrs); 206 break; 207 case NAT_T_ESP_PORT: 208 err = iavf_fill_fdir_nat_t_esp_hdr(fltr, proto_hdrs); 209 break; 210 case PFCP_PORT: 211 err = iavf_fill_fdir_pfcp_hdr(fltr, proto_hdrs); 212 break; 213 default: 214 err = -EOPNOTSUPP; 215 break; 216 } 217 218 return err; 219 } 220 221 /** 222 * iavf_fill_fdir_ip4_hdr - fill the IPv4 protocol header 223 * @fltr: Flow Director filter data structure 224 * @proto_hdrs: Flow Director protocol headers data structure 225 * 226 * Returns 0 if the IPv4 protocol header is set successfully 227 */ 228 static int 229 iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr, 230 struct virtchnl_proto_hdrs *proto_hdrs) 231 { 232 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 233 struct iphdr *iph = (struct iphdr *)hdr->buffer; 234 235 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4); 236 237 if (fltr->ip_mask.tos == U8_MAX) { 238 iph->tos = fltr->ip_data.tos; 239 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DSCP); 240 } 241 242 if (fltr->ip_mask.proto == U8_MAX) { 243 iph->protocol = fltr->ip_data.proto; 244 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, PROT); 245 } 246 247 if (fltr->ip_mask.v4_addrs.src_ip == htonl(U32_MAX)) { 248 iph->saddr = fltr->ip_data.v4_addrs.src_ip; 249 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, SRC); 250 } 251 252 if (fltr->ip_mask.v4_addrs.dst_ip == htonl(U32_MAX)) { 253 iph->daddr = fltr->ip_data.v4_addrs.dst_ip; 254 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST); 255 } 256 257 fltr->ip_ver = 4; 258 259 return 0; 260 } 261 262 /** 263 * iavf_fill_fdir_ip6_hdr - fill the IPv6 protocol header 264 * @fltr: Flow Director filter data structure 265 * @proto_hdrs: Flow Director protocol headers data structure 266 * 267 * Returns 0 if the IPv6 protocol header is set successfully 268 */ 269 static int 270 iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr, 271 struct virtchnl_proto_hdrs *proto_hdrs) 272 { 273 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 274 struct ipv6hdr *iph = (struct ipv6hdr *)hdr->buffer; 275 276 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6); 277 278 if (fltr->ip_mask.tclass == U8_MAX) { 279 iph->priority = (fltr->ip_data.tclass >> 4) & 0xF; 280 iph->flow_lbl[0] = (fltr->ip_data.tclass << 4) & 0xF0; 281 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, TC); 282 } 283 284 if (fltr->ip_mask.proto == U8_MAX) { 285 iph->nexthdr = fltr->ip_data.proto; 286 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, PROT); 287 } 288 289 if (!memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask, 290 sizeof(struct in6_addr))) { 291 memcpy(&iph->saddr, &fltr->ip_data.v6_addrs.src_ip, 292 sizeof(struct in6_addr)); 293 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, SRC); 294 } 295 296 if (!memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask, 297 sizeof(struct in6_addr))) { 298 memcpy(&iph->daddr, &fltr->ip_data.v6_addrs.dst_ip, 299 sizeof(struct in6_addr)); 300 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST); 301 } 302 303 fltr->ip_ver = 6; 304 305 return 0; 306 } 307 308 /** 309 * iavf_fill_fdir_tcp_hdr - fill the TCP protocol header 310 * @fltr: Flow Director filter data structure 311 * @proto_hdrs: Flow Director protocol headers data structure 312 * 313 * Returns 0 if the TCP protocol header is set successfully 314 */ 315 static int 316 iavf_fill_fdir_tcp_hdr(struct iavf_fdir_fltr *fltr, 317 struct virtchnl_proto_hdrs *proto_hdrs) 318 { 319 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 320 struct tcphdr *tcph = (struct tcphdr *)hdr->buffer; 321 322 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP); 323 324 if (fltr->ip_mask.src_port == htons(U16_MAX)) { 325 tcph->source = fltr->ip_data.src_port; 326 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, SRC_PORT); 327 } 328 329 if (fltr->ip_mask.dst_port == htons(U16_MAX)) { 330 tcph->dest = fltr->ip_data.dst_port; 331 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, DST_PORT); 332 } 333 334 return 0; 335 } 336 337 /** 338 * iavf_fill_fdir_udp_hdr - fill the UDP protocol header 339 * @fltr: Flow Director filter data structure 340 * @proto_hdrs: Flow Director protocol headers data structure 341 * 342 * Returns 0 if the UDP protocol header is set successfully 343 */ 344 static int 345 iavf_fill_fdir_udp_hdr(struct iavf_fdir_fltr *fltr, 346 struct virtchnl_proto_hdrs *proto_hdrs) 347 { 348 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 349 struct udphdr *udph = (struct udphdr *)hdr->buffer; 350 351 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP); 352 353 if (fltr->ip_mask.src_port == htons(U16_MAX)) { 354 udph->source = fltr->ip_data.src_port; 355 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, SRC_PORT); 356 } 357 358 if (fltr->ip_mask.dst_port == htons(U16_MAX)) { 359 udph->dest = fltr->ip_data.dst_port; 360 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, DST_PORT); 361 } 362 363 if (!fltr->flex_cnt) 364 return 0; 365 366 return iavf_fill_fdir_udp_flex_pay_hdr(fltr, proto_hdrs); 367 } 368 369 /** 370 * iavf_fill_fdir_sctp_hdr - fill the SCTP protocol header 371 * @fltr: Flow Director filter data structure 372 * @proto_hdrs: Flow Director protocol headers data structure 373 * 374 * Returns 0 if the SCTP protocol header is set successfully 375 */ 376 static int 377 iavf_fill_fdir_sctp_hdr(struct iavf_fdir_fltr *fltr, 378 struct virtchnl_proto_hdrs *proto_hdrs) 379 { 380 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 381 struct sctphdr *sctph = (struct sctphdr *)hdr->buffer; 382 383 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, SCTP); 384 385 if (fltr->ip_mask.src_port == htons(U16_MAX)) { 386 sctph->source = fltr->ip_data.src_port; 387 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, SRC_PORT); 388 } 389 390 if (fltr->ip_mask.dst_port == htons(U16_MAX)) { 391 sctph->dest = fltr->ip_data.dst_port; 392 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT); 393 } 394 395 return 0; 396 } 397 398 /** 399 * iavf_fill_fdir_ah_hdr - fill the AH protocol header 400 * @fltr: Flow Director filter data structure 401 * @proto_hdrs: Flow Director protocol headers data structure 402 * 403 * Returns 0 if the AH protocol header is set successfully 404 */ 405 static int 406 iavf_fill_fdir_ah_hdr(struct iavf_fdir_fltr *fltr, 407 struct virtchnl_proto_hdrs *proto_hdrs) 408 { 409 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 410 struct ip_auth_hdr *ah = (struct ip_auth_hdr *)hdr->buffer; 411 412 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, AH); 413 414 if (fltr->ip_mask.spi == htonl(U32_MAX)) { 415 ah->spi = fltr->ip_data.spi; 416 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, AH, SPI); 417 } 418 419 return 0; 420 } 421 422 /** 423 * iavf_fill_fdir_esp_hdr - fill the ESP protocol header 424 * @fltr: Flow Director filter data structure 425 * @proto_hdrs: Flow Director protocol headers data structure 426 * 427 * Returns 0 if the ESP protocol header is set successfully 428 */ 429 static int 430 iavf_fill_fdir_esp_hdr(struct iavf_fdir_fltr *fltr, 431 struct virtchnl_proto_hdrs *proto_hdrs) 432 { 433 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 434 struct ip_esp_hdr *esph = (struct ip_esp_hdr *)hdr->buffer; 435 436 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ESP); 437 438 if (fltr->ip_mask.spi == htonl(U32_MAX)) { 439 esph->spi = fltr->ip_data.spi; 440 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ESP, SPI); 441 } 442 443 return 0; 444 } 445 446 /** 447 * iavf_fill_fdir_l4_hdr - fill the L4 protocol header 448 * @fltr: Flow Director filter data structure 449 * @proto_hdrs: Flow Director protocol headers data structure 450 * 451 * Returns 0 if the L4 protocol header is set successfully 452 */ 453 static int 454 iavf_fill_fdir_l4_hdr(struct iavf_fdir_fltr *fltr, 455 struct virtchnl_proto_hdrs *proto_hdrs) 456 { 457 struct virtchnl_proto_hdr *hdr; 458 __be32 *l4_4_data; 459 460 if (!fltr->ip_mask.proto) /* IPv4/IPv6 header only */ 461 return 0; 462 463 hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 464 l4_4_data = (__be32 *)hdr->buffer; 465 466 /* L2TPv3 over IP with 'Session ID' */ 467 if (fltr->ip_data.proto == 115 && fltr->ip_mask.l4_header == htonl(U32_MAX)) { 468 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, L2TPV3); 469 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, L2TPV3, SESS_ID); 470 471 *l4_4_data = fltr->ip_data.l4_header; 472 } else { 473 return -EOPNOTSUPP; 474 } 475 476 return 0; 477 } 478 479 /** 480 * iavf_fill_fdir_eth_hdr - fill the Ethernet protocol header 481 * @fltr: Flow Director filter data structure 482 * @proto_hdrs: Flow Director protocol headers data structure 483 * 484 * Returns 0 if the Ethernet protocol header is set successfully 485 */ 486 static int 487 iavf_fill_fdir_eth_hdr(struct iavf_fdir_fltr *fltr, 488 struct virtchnl_proto_hdrs *proto_hdrs) 489 { 490 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; 491 struct ethhdr *ehdr = (struct ethhdr *)hdr->buffer; 492 493 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ETH); 494 495 if (fltr->eth_mask.etype == htons(U16_MAX)) { 496 if (fltr->eth_data.etype == htons(ETH_P_IP) || 497 fltr->eth_data.etype == htons(ETH_P_IPV6)) 498 return -EOPNOTSUPP; 499 500 ehdr->h_proto = fltr->eth_data.etype; 501 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ETH, ETHERTYPE); 502 } 503 504 return 0; 505 } 506 507 /** 508 * iavf_fill_fdir_add_msg - fill the Flow Director filter into virtchnl message 509 * @adapter: pointer to the VF adapter structure 510 * @fltr: Flow Director filter data structure 511 * 512 * Returns 0 if the add Flow Director virtchnl message is filled successfully 513 */ 514 int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) 515 { 516 struct virtchnl_fdir_add *vc_msg = &fltr->vc_add_msg; 517 struct virtchnl_proto_hdrs *proto_hdrs; 518 int err; 519 520 proto_hdrs = &vc_msg->rule_cfg.proto_hdrs; 521 522 err = iavf_fill_fdir_eth_hdr(fltr, proto_hdrs); /* L2 always exists */ 523 if (err) 524 return err; 525 526 switch (fltr->flow_type) { 527 case IAVF_FDIR_FLOW_IPV4_TCP: 528 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 529 iavf_fill_fdir_tcp_hdr(fltr, proto_hdrs); 530 break; 531 case IAVF_FDIR_FLOW_IPV4_UDP: 532 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 533 iavf_fill_fdir_udp_hdr(fltr, proto_hdrs); 534 break; 535 case IAVF_FDIR_FLOW_IPV4_SCTP: 536 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 537 iavf_fill_fdir_sctp_hdr(fltr, proto_hdrs); 538 break; 539 case IAVF_FDIR_FLOW_IPV4_AH: 540 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 541 iavf_fill_fdir_ah_hdr(fltr, proto_hdrs); 542 break; 543 case IAVF_FDIR_FLOW_IPV4_ESP: 544 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 545 iavf_fill_fdir_esp_hdr(fltr, proto_hdrs); 546 break; 547 case IAVF_FDIR_FLOW_IPV4_OTHER: 548 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) | 549 iavf_fill_fdir_l4_hdr(fltr, proto_hdrs); 550 break; 551 case IAVF_FDIR_FLOW_IPV6_TCP: 552 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 553 iavf_fill_fdir_tcp_hdr(fltr, proto_hdrs); 554 break; 555 case IAVF_FDIR_FLOW_IPV6_UDP: 556 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 557 iavf_fill_fdir_udp_hdr(fltr, proto_hdrs); 558 break; 559 case IAVF_FDIR_FLOW_IPV6_SCTP: 560 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 561 iavf_fill_fdir_sctp_hdr(fltr, proto_hdrs); 562 break; 563 case IAVF_FDIR_FLOW_IPV6_AH: 564 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 565 iavf_fill_fdir_ah_hdr(fltr, proto_hdrs); 566 break; 567 case IAVF_FDIR_FLOW_IPV6_ESP: 568 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 569 iavf_fill_fdir_esp_hdr(fltr, proto_hdrs); 570 break; 571 case IAVF_FDIR_FLOW_IPV6_OTHER: 572 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) | 573 iavf_fill_fdir_l4_hdr(fltr, proto_hdrs); 574 break; 575 case IAVF_FDIR_FLOW_NON_IP_L2: 576 break; 577 default: 578 err = -EINVAL; 579 break; 580 } 581 582 if (err) 583 return err; 584 585 vc_msg->vsi_id = adapter->vsi.id; 586 vc_msg->rule_cfg.action_set.count = 1; 587 vc_msg->rule_cfg.action_set.actions[0].type = fltr->action; 588 vc_msg->rule_cfg.action_set.actions[0].act_conf.queue.index = fltr->q_index; 589 590 return 0; 591 } 592 593 /** 594 * iavf_fdir_flow_proto_name - get the flow protocol name 595 * @flow_type: Flow Director filter flow type 596 **/ 597 static const char *iavf_fdir_flow_proto_name(enum iavf_fdir_flow_type flow_type) 598 { 599 switch (flow_type) { 600 case IAVF_FDIR_FLOW_IPV4_TCP: 601 case IAVF_FDIR_FLOW_IPV6_TCP: 602 return "TCP"; 603 case IAVF_FDIR_FLOW_IPV4_UDP: 604 case IAVF_FDIR_FLOW_IPV6_UDP: 605 return "UDP"; 606 case IAVF_FDIR_FLOW_IPV4_SCTP: 607 case IAVF_FDIR_FLOW_IPV6_SCTP: 608 return "SCTP"; 609 case IAVF_FDIR_FLOW_IPV4_AH: 610 case IAVF_FDIR_FLOW_IPV6_AH: 611 return "AH"; 612 case IAVF_FDIR_FLOW_IPV4_ESP: 613 case IAVF_FDIR_FLOW_IPV6_ESP: 614 return "ESP"; 615 case IAVF_FDIR_FLOW_IPV4_OTHER: 616 case IAVF_FDIR_FLOW_IPV6_OTHER: 617 return "Other"; 618 case IAVF_FDIR_FLOW_NON_IP_L2: 619 return "Ethernet"; 620 default: 621 return NULL; 622 } 623 } 624 625 /** 626 * iavf_print_fdir_fltr 627 * @adapter: adapter structure 628 * @fltr: Flow Director filter to print 629 * 630 * Print the Flow Director filter 631 **/ 632 void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) 633 { 634 const char *proto = iavf_fdir_flow_proto_name(fltr->flow_type); 635 636 if (!proto) 637 return; 638 639 switch (fltr->flow_type) { 640 case IAVF_FDIR_FLOW_IPV4_TCP: 641 case IAVF_FDIR_FLOW_IPV4_UDP: 642 case IAVF_FDIR_FLOW_IPV4_SCTP: 643 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 %s: dst_port %hu src_port %hu\n", 644 fltr->loc, 645 &fltr->ip_data.v4_addrs.dst_ip, 646 &fltr->ip_data.v4_addrs.src_ip, 647 proto, 648 ntohs(fltr->ip_data.dst_port), 649 ntohs(fltr->ip_data.src_port)); 650 break; 651 case IAVF_FDIR_FLOW_IPV4_AH: 652 case IAVF_FDIR_FLOW_IPV4_ESP: 653 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 %s: SPI %u\n", 654 fltr->loc, 655 &fltr->ip_data.v4_addrs.dst_ip, 656 &fltr->ip_data.v4_addrs.src_ip, 657 proto, 658 ntohl(fltr->ip_data.spi)); 659 break; 660 case IAVF_FDIR_FLOW_IPV4_OTHER: 661 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 proto: %u L4_bytes: 0x%x\n", 662 fltr->loc, 663 &fltr->ip_data.v4_addrs.dst_ip, 664 &fltr->ip_data.v4_addrs.src_ip, 665 fltr->ip_data.proto, 666 ntohl(fltr->ip_data.l4_header)); 667 break; 668 case IAVF_FDIR_FLOW_IPV6_TCP: 669 case IAVF_FDIR_FLOW_IPV6_UDP: 670 case IAVF_FDIR_FLOW_IPV6_SCTP: 671 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 %s: dst_port %hu src_port %hu\n", 672 fltr->loc, 673 &fltr->ip_data.v6_addrs.dst_ip, 674 &fltr->ip_data.v6_addrs.src_ip, 675 proto, 676 ntohs(fltr->ip_data.dst_port), 677 ntohs(fltr->ip_data.src_port)); 678 break; 679 case IAVF_FDIR_FLOW_IPV6_AH: 680 case IAVF_FDIR_FLOW_IPV6_ESP: 681 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 %s: SPI %u\n", 682 fltr->loc, 683 &fltr->ip_data.v6_addrs.dst_ip, 684 &fltr->ip_data.v6_addrs.src_ip, 685 proto, 686 ntohl(fltr->ip_data.spi)); 687 break; 688 case IAVF_FDIR_FLOW_IPV6_OTHER: 689 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 proto: %u L4_bytes: 0x%x\n", 690 fltr->loc, 691 &fltr->ip_data.v6_addrs.dst_ip, 692 &fltr->ip_data.v6_addrs.src_ip, 693 fltr->ip_data.proto, 694 ntohl(fltr->ip_data.l4_header)); 695 break; 696 case IAVF_FDIR_FLOW_NON_IP_L2: 697 dev_info(&adapter->pdev->dev, "Rule ID: %u eth_type: 0x%x\n", 698 fltr->loc, 699 ntohs(fltr->eth_data.etype)); 700 break; 701 default: 702 break; 703 } 704 } 705 706 /** 707 * iavf_fdir_is_dup_fltr - test if filter is already in list 708 * @adapter: pointer to the VF adapter structure 709 * @fltr: Flow Director filter data structure 710 * 711 * Returns true if the filter is found in the list 712 */ 713 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) 714 { 715 struct iavf_fdir_fltr *tmp; 716 bool ret = false; 717 718 list_for_each_entry(tmp, &adapter->fdir_list_head, list) { 719 if (tmp->flow_type != fltr->flow_type) 720 continue; 721 722 if (!memcmp(&tmp->eth_data, &fltr->eth_data, 723 sizeof(fltr->eth_data)) && 724 !memcmp(&tmp->ip_data, &fltr->ip_data, 725 sizeof(fltr->ip_data)) && 726 !memcmp(&tmp->ext_data, &fltr->ext_data, 727 sizeof(fltr->ext_data))) { 728 ret = true; 729 break; 730 } 731 } 732 733 return ret; 734 } 735 736 /** 737 * iavf_find_fdir_fltr_by_loc - find filter with location 738 * @adapter: pointer to the VF adapter structure 739 * @loc: location to find. 740 * 741 * Returns pointer to Flow Director filter if found or null 742 */ 743 struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter, u32 loc) 744 { 745 struct iavf_fdir_fltr *rule; 746 747 list_for_each_entry(rule, &adapter->fdir_list_head, list) 748 if (rule->loc == loc) 749 return rule; 750 751 return NULL; 752 } 753 754 /** 755 * iavf_fdir_list_add_fltr - add a new node to the flow director filter list 756 * @adapter: pointer to the VF adapter structure 757 * @fltr: filter node to add to structure 758 */ 759 void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) 760 { 761 struct iavf_fdir_fltr *rule, *parent = NULL; 762 763 list_for_each_entry(rule, &adapter->fdir_list_head, list) { 764 if (rule->loc >= fltr->loc) 765 break; 766 parent = rule; 767 } 768 769 if (parent) 770 list_add(&fltr->list, &parent->list); 771 else 772 list_add(&fltr->list, &adapter->fdir_list_head); 773 } 774