0001
0002
0003
0004
0005
0006 #include "iavf.h"
0007
0008 #define GTPU_PORT 2152
0009 #define NAT_T_ESP_PORT 4500
0010 #define PFCP_PORT 8805
0011
0012 static const struct in6_addr ipv6_addr_full_mask = {
0013 .in6_u = {
0014 .u6_addr8 = {
0015 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0016 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0017 }
0018 }
0019 };
0020
0021
0022
0023
0024
0025 static u16 iavf_pkt_udp_no_pay_len(struct iavf_fdir_fltr *fltr)
0026 {
0027 return sizeof(struct ethhdr) +
0028 (fltr->ip_ver == 4 ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) +
0029 sizeof(struct udphdr);
0030 }
0031
0032
0033
0034
0035
0036
0037
0038
0039 static int
0040 iavf_fill_fdir_gtpu_hdr(struct iavf_fdir_fltr *fltr,
0041 struct virtchnl_proto_hdrs *proto_hdrs)
0042 {
0043 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1];
0044 struct virtchnl_proto_hdr *ghdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0045 struct virtchnl_proto_hdr *ehdr = NULL;
0046 u16 adj_offs, hdr_offs;
0047 int i;
0048
0049 VIRTCHNL_SET_PROTO_HDR_TYPE(ghdr, GTPU_IP);
0050
0051 adj_offs = iavf_pkt_udp_no_pay_len(fltr);
0052
0053 for (i = 0; i < fltr->flex_cnt; i++) {
0054 #define IAVF_GTPU_HDR_TEID_OFFS0 4
0055 #define IAVF_GTPU_HDR_TEID_OFFS1 6
0056 #define IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS 10
0057 #define IAVF_GTPU_HDR_NEXT_EXTHDR_TYPE_MASK 0x00FF
0058
0059 #define IAVF_GTPU_PSC_EXTHDR_TYPE 0x85
0060 #define IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS 13
0061 #define IAVF_GTPU_HDR_PSC_PDU_QFI_MASK 0x3F
0062 #define IAVF_GTPU_EH_QFI_IDX 1
0063
0064 if (fltr->flex_words[i].offset < adj_offs)
0065 return -EINVAL;
0066
0067 hdr_offs = fltr->flex_words[i].offset - adj_offs;
0068
0069 switch (hdr_offs) {
0070 case IAVF_GTPU_HDR_TEID_OFFS0:
0071 case IAVF_GTPU_HDR_TEID_OFFS1: {
0072 __be16 *pay_word = (__be16 *)ghdr->buffer;
0073
0074 pay_word[hdr_offs >> 1] = htons(fltr->flex_words[i].word);
0075 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(ghdr, GTPU_IP, TEID);
0076 }
0077 break;
0078 case IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS:
0079 if ((fltr->flex_words[i].word &
0080 IAVF_GTPU_HDR_NEXT_EXTHDR_TYPE_MASK) !=
0081 IAVF_GTPU_PSC_EXTHDR_TYPE)
0082 return -EOPNOTSUPP;
0083 if (!ehdr)
0084 ehdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0085 VIRTCHNL_SET_PROTO_HDR_TYPE(ehdr, GTPU_EH);
0086 break;
0087 case IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS:
0088 if (!ehdr)
0089 return -EINVAL;
0090 ehdr->buffer[IAVF_GTPU_EH_QFI_IDX] =
0091 fltr->flex_words[i].word &
0092 IAVF_GTPU_HDR_PSC_PDU_QFI_MASK;
0093 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(ehdr, GTPU_EH, QFI);
0094 break;
0095 default:
0096 return -EINVAL;
0097 }
0098 }
0099
0100 uhdr->field_selector = 0;
0101
0102 return 0;
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112 static int
0113 iavf_fill_fdir_pfcp_hdr(struct iavf_fdir_fltr *fltr,
0114 struct virtchnl_proto_hdrs *proto_hdrs)
0115 {
0116 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1];
0117 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0118 u16 adj_offs, hdr_offs;
0119 int i;
0120
0121 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, PFCP);
0122
0123 adj_offs = iavf_pkt_udp_no_pay_len(fltr);
0124
0125 for (i = 0; i < fltr->flex_cnt; i++) {
0126 #define IAVF_PFCP_HDR_SFIELD_AND_MSG_TYPE_OFFS 0
0127 if (fltr->flex_words[i].offset < adj_offs)
0128 return -EINVAL;
0129
0130 hdr_offs = fltr->flex_words[i].offset - adj_offs;
0131
0132 switch (hdr_offs) {
0133 case IAVF_PFCP_HDR_SFIELD_AND_MSG_TYPE_OFFS:
0134 hdr->buffer[0] = (fltr->flex_words[i].word >> 8) & 0xff;
0135 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, PFCP, S_FIELD);
0136 break;
0137 default:
0138 return -EINVAL;
0139 }
0140 }
0141
0142 uhdr->field_selector = 0;
0143
0144 return 0;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154 static int
0155 iavf_fill_fdir_nat_t_esp_hdr(struct iavf_fdir_fltr *fltr,
0156 struct virtchnl_proto_hdrs *proto_hdrs)
0157 {
0158 struct virtchnl_proto_hdr *uhdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1];
0159 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0160 u16 adj_offs, hdr_offs;
0161 u32 spi = 0;
0162 int i;
0163
0164 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ESP);
0165
0166 adj_offs = iavf_pkt_udp_no_pay_len(fltr);
0167
0168 for (i = 0; i < fltr->flex_cnt; i++) {
0169 #define IAVF_NAT_T_ESP_SPI_OFFS0 0
0170 #define IAVF_NAT_T_ESP_SPI_OFFS1 2
0171 if (fltr->flex_words[i].offset < adj_offs)
0172 return -EINVAL;
0173
0174 hdr_offs = fltr->flex_words[i].offset - adj_offs;
0175
0176 switch (hdr_offs) {
0177 case IAVF_NAT_T_ESP_SPI_OFFS0:
0178 spi |= fltr->flex_words[i].word << 16;
0179 break;
0180 case IAVF_NAT_T_ESP_SPI_OFFS1:
0181 spi |= fltr->flex_words[i].word;
0182 break;
0183 default:
0184 return -EINVAL;
0185 }
0186 }
0187
0188 if (!spi)
0189 return -EOPNOTSUPP;
0190
0191 *(__be32 *)hdr->buffer = htonl(spi);
0192 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ESP, SPI);
0193
0194 uhdr->field_selector = 0;
0195
0196 return 0;
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206 static int
0207 iavf_fill_fdir_udp_flex_pay_hdr(struct iavf_fdir_fltr *fltr,
0208 struct virtchnl_proto_hdrs *proto_hdrs)
0209 {
0210 int err;
0211
0212 switch (ntohs(fltr->ip_data.dst_port)) {
0213 case GTPU_PORT:
0214 err = iavf_fill_fdir_gtpu_hdr(fltr, proto_hdrs);
0215 break;
0216 case NAT_T_ESP_PORT:
0217 err = iavf_fill_fdir_nat_t_esp_hdr(fltr, proto_hdrs);
0218 break;
0219 case PFCP_PORT:
0220 err = iavf_fill_fdir_pfcp_hdr(fltr, proto_hdrs);
0221 break;
0222 default:
0223 err = -EOPNOTSUPP;
0224 break;
0225 }
0226
0227 return err;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237 static int
0238 iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr,
0239 struct virtchnl_proto_hdrs *proto_hdrs)
0240 {
0241 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0242 struct iphdr *iph = (struct iphdr *)hdr->buffer;
0243
0244 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
0245
0246 if (fltr->ip_mask.tos == U8_MAX) {
0247 iph->tos = fltr->ip_data.tos;
0248 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DSCP);
0249 }
0250
0251 if (fltr->ip_mask.proto == U8_MAX) {
0252 iph->protocol = fltr->ip_data.proto;
0253 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, PROT);
0254 }
0255
0256 if (fltr->ip_mask.v4_addrs.src_ip == htonl(U32_MAX)) {
0257 iph->saddr = fltr->ip_data.v4_addrs.src_ip;
0258 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, SRC);
0259 }
0260
0261 if (fltr->ip_mask.v4_addrs.dst_ip == htonl(U32_MAX)) {
0262 iph->daddr = fltr->ip_data.v4_addrs.dst_ip;
0263 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
0264 }
0265
0266 fltr->ip_ver = 4;
0267
0268 return 0;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278 static int
0279 iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr,
0280 struct virtchnl_proto_hdrs *proto_hdrs)
0281 {
0282 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0283 struct ipv6hdr *iph = (struct ipv6hdr *)hdr->buffer;
0284
0285 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
0286
0287 if (fltr->ip_mask.tclass == U8_MAX) {
0288 iph->priority = (fltr->ip_data.tclass >> 4) & 0xF;
0289 iph->flow_lbl[0] = (fltr->ip_data.tclass << 4) & 0xF0;
0290 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, TC);
0291 }
0292
0293 if (fltr->ip_mask.proto == U8_MAX) {
0294 iph->nexthdr = fltr->ip_data.proto;
0295 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, PROT);
0296 }
0297
0298 if (!memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask,
0299 sizeof(struct in6_addr))) {
0300 memcpy(&iph->saddr, &fltr->ip_data.v6_addrs.src_ip,
0301 sizeof(struct in6_addr));
0302 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, SRC);
0303 }
0304
0305 if (!memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask,
0306 sizeof(struct in6_addr))) {
0307 memcpy(&iph->daddr, &fltr->ip_data.v6_addrs.dst_ip,
0308 sizeof(struct in6_addr));
0309 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
0310 }
0311
0312 fltr->ip_ver = 6;
0313
0314 return 0;
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324 static int
0325 iavf_fill_fdir_tcp_hdr(struct iavf_fdir_fltr *fltr,
0326 struct virtchnl_proto_hdrs *proto_hdrs)
0327 {
0328 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0329 struct tcphdr *tcph = (struct tcphdr *)hdr->buffer;
0330
0331 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
0332
0333 if (fltr->ip_mask.src_port == htons(U16_MAX)) {
0334 tcph->source = fltr->ip_data.src_port;
0335 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, SRC_PORT);
0336 }
0337
0338 if (fltr->ip_mask.dst_port == htons(U16_MAX)) {
0339 tcph->dest = fltr->ip_data.dst_port;
0340 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, DST_PORT);
0341 }
0342
0343 return 0;
0344 }
0345
0346
0347
0348
0349
0350
0351
0352
0353 static int
0354 iavf_fill_fdir_udp_hdr(struct iavf_fdir_fltr *fltr,
0355 struct virtchnl_proto_hdrs *proto_hdrs)
0356 {
0357 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0358 struct udphdr *udph = (struct udphdr *)hdr->buffer;
0359
0360 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP);
0361
0362 if (fltr->ip_mask.src_port == htons(U16_MAX)) {
0363 udph->source = fltr->ip_data.src_port;
0364 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, SRC_PORT);
0365 }
0366
0367 if (fltr->ip_mask.dst_port == htons(U16_MAX)) {
0368 udph->dest = fltr->ip_data.dst_port;
0369 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, DST_PORT);
0370 }
0371
0372 if (!fltr->flex_cnt)
0373 return 0;
0374
0375 return iavf_fill_fdir_udp_flex_pay_hdr(fltr, proto_hdrs);
0376 }
0377
0378
0379
0380
0381
0382
0383
0384
0385 static int
0386 iavf_fill_fdir_sctp_hdr(struct iavf_fdir_fltr *fltr,
0387 struct virtchnl_proto_hdrs *proto_hdrs)
0388 {
0389 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0390 struct sctphdr *sctph = (struct sctphdr *)hdr->buffer;
0391
0392 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, SCTP);
0393
0394 if (fltr->ip_mask.src_port == htons(U16_MAX)) {
0395 sctph->source = fltr->ip_data.src_port;
0396 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, SRC_PORT);
0397 }
0398
0399 if (fltr->ip_mask.dst_port == htons(U16_MAX)) {
0400 sctph->dest = fltr->ip_data.dst_port;
0401 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT);
0402 }
0403
0404 return 0;
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414 static int
0415 iavf_fill_fdir_ah_hdr(struct iavf_fdir_fltr *fltr,
0416 struct virtchnl_proto_hdrs *proto_hdrs)
0417 {
0418 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0419 struct ip_auth_hdr *ah = (struct ip_auth_hdr *)hdr->buffer;
0420
0421 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, AH);
0422
0423 if (fltr->ip_mask.spi == htonl(U32_MAX)) {
0424 ah->spi = fltr->ip_data.spi;
0425 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, AH, SPI);
0426 }
0427
0428 return 0;
0429 }
0430
0431
0432
0433
0434
0435
0436
0437
0438 static int
0439 iavf_fill_fdir_esp_hdr(struct iavf_fdir_fltr *fltr,
0440 struct virtchnl_proto_hdrs *proto_hdrs)
0441 {
0442 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0443 struct ip_esp_hdr *esph = (struct ip_esp_hdr *)hdr->buffer;
0444
0445 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ESP);
0446
0447 if (fltr->ip_mask.spi == htonl(U32_MAX)) {
0448 esph->spi = fltr->ip_data.spi;
0449 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ESP, SPI);
0450 }
0451
0452 return 0;
0453 }
0454
0455
0456
0457
0458
0459
0460
0461
0462 static int
0463 iavf_fill_fdir_l4_hdr(struct iavf_fdir_fltr *fltr,
0464 struct virtchnl_proto_hdrs *proto_hdrs)
0465 {
0466 struct virtchnl_proto_hdr *hdr;
0467 __be32 *l4_4_data;
0468
0469 if (!fltr->ip_mask.proto)
0470 return 0;
0471
0472 hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0473 l4_4_data = (__be32 *)hdr->buffer;
0474
0475
0476 if (fltr->ip_data.proto == 115 && fltr->ip_mask.l4_header == htonl(U32_MAX)) {
0477 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, L2TPV3);
0478 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, L2TPV3, SESS_ID);
0479
0480 *l4_4_data = fltr->ip_data.l4_header;
0481 } else {
0482 return -EOPNOTSUPP;
0483 }
0484
0485 return 0;
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495 static int
0496 iavf_fill_fdir_eth_hdr(struct iavf_fdir_fltr *fltr,
0497 struct virtchnl_proto_hdrs *proto_hdrs)
0498 {
0499 struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
0500 struct ethhdr *ehdr = (struct ethhdr *)hdr->buffer;
0501
0502 VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ETH);
0503
0504 if (fltr->eth_mask.etype == htons(U16_MAX)) {
0505 if (fltr->eth_data.etype == htons(ETH_P_IP) ||
0506 fltr->eth_data.etype == htons(ETH_P_IPV6))
0507 return -EOPNOTSUPP;
0508
0509 ehdr->h_proto = fltr->eth_data.etype;
0510 VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ETH, ETHERTYPE);
0511 }
0512
0513 return 0;
0514 }
0515
0516
0517
0518
0519
0520
0521
0522
0523 int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
0524 {
0525 struct virtchnl_fdir_add *vc_msg = &fltr->vc_add_msg;
0526 struct virtchnl_proto_hdrs *proto_hdrs;
0527 int err;
0528
0529 proto_hdrs = &vc_msg->rule_cfg.proto_hdrs;
0530
0531 err = iavf_fill_fdir_eth_hdr(fltr, proto_hdrs);
0532 if (err)
0533 return err;
0534
0535 switch (fltr->flow_type) {
0536 case IAVF_FDIR_FLOW_IPV4_TCP:
0537 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0538 iavf_fill_fdir_tcp_hdr(fltr, proto_hdrs);
0539 break;
0540 case IAVF_FDIR_FLOW_IPV4_UDP:
0541 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0542 iavf_fill_fdir_udp_hdr(fltr, proto_hdrs);
0543 break;
0544 case IAVF_FDIR_FLOW_IPV4_SCTP:
0545 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0546 iavf_fill_fdir_sctp_hdr(fltr, proto_hdrs);
0547 break;
0548 case IAVF_FDIR_FLOW_IPV4_AH:
0549 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0550 iavf_fill_fdir_ah_hdr(fltr, proto_hdrs);
0551 break;
0552 case IAVF_FDIR_FLOW_IPV4_ESP:
0553 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0554 iavf_fill_fdir_esp_hdr(fltr, proto_hdrs);
0555 break;
0556 case IAVF_FDIR_FLOW_IPV4_OTHER:
0557 err = iavf_fill_fdir_ip4_hdr(fltr, proto_hdrs) |
0558 iavf_fill_fdir_l4_hdr(fltr, proto_hdrs);
0559 break;
0560 case IAVF_FDIR_FLOW_IPV6_TCP:
0561 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0562 iavf_fill_fdir_tcp_hdr(fltr, proto_hdrs);
0563 break;
0564 case IAVF_FDIR_FLOW_IPV6_UDP:
0565 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0566 iavf_fill_fdir_udp_hdr(fltr, proto_hdrs);
0567 break;
0568 case IAVF_FDIR_FLOW_IPV6_SCTP:
0569 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0570 iavf_fill_fdir_sctp_hdr(fltr, proto_hdrs);
0571 break;
0572 case IAVF_FDIR_FLOW_IPV6_AH:
0573 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0574 iavf_fill_fdir_ah_hdr(fltr, proto_hdrs);
0575 break;
0576 case IAVF_FDIR_FLOW_IPV6_ESP:
0577 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0578 iavf_fill_fdir_esp_hdr(fltr, proto_hdrs);
0579 break;
0580 case IAVF_FDIR_FLOW_IPV6_OTHER:
0581 err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
0582 iavf_fill_fdir_l4_hdr(fltr, proto_hdrs);
0583 break;
0584 case IAVF_FDIR_FLOW_NON_IP_L2:
0585 break;
0586 default:
0587 err = -EINVAL;
0588 break;
0589 }
0590
0591 if (err)
0592 return err;
0593
0594 vc_msg->vsi_id = adapter->vsi.id;
0595 vc_msg->rule_cfg.action_set.count = 1;
0596 vc_msg->rule_cfg.action_set.actions[0].type = fltr->action;
0597 vc_msg->rule_cfg.action_set.actions[0].act_conf.queue.index = fltr->q_index;
0598
0599 return 0;
0600 }
0601
0602
0603
0604
0605
0606 static const char *iavf_fdir_flow_proto_name(enum iavf_fdir_flow_type flow_type)
0607 {
0608 switch (flow_type) {
0609 case IAVF_FDIR_FLOW_IPV4_TCP:
0610 case IAVF_FDIR_FLOW_IPV6_TCP:
0611 return "TCP";
0612 case IAVF_FDIR_FLOW_IPV4_UDP:
0613 case IAVF_FDIR_FLOW_IPV6_UDP:
0614 return "UDP";
0615 case IAVF_FDIR_FLOW_IPV4_SCTP:
0616 case IAVF_FDIR_FLOW_IPV6_SCTP:
0617 return "SCTP";
0618 case IAVF_FDIR_FLOW_IPV4_AH:
0619 case IAVF_FDIR_FLOW_IPV6_AH:
0620 return "AH";
0621 case IAVF_FDIR_FLOW_IPV4_ESP:
0622 case IAVF_FDIR_FLOW_IPV6_ESP:
0623 return "ESP";
0624 case IAVF_FDIR_FLOW_IPV4_OTHER:
0625 case IAVF_FDIR_FLOW_IPV6_OTHER:
0626 return "Other";
0627 case IAVF_FDIR_FLOW_NON_IP_L2:
0628 return "Ethernet";
0629 default:
0630 return NULL;
0631 }
0632 }
0633
0634
0635
0636
0637
0638
0639
0640
0641 void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
0642 {
0643 const char *proto = iavf_fdir_flow_proto_name(fltr->flow_type);
0644
0645 if (!proto)
0646 return;
0647
0648 switch (fltr->flow_type) {
0649 case IAVF_FDIR_FLOW_IPV4_TCP:
0650 case IAVF_FDIR_FLOW_IPV4_UDP:
0651 case IAVF_FDIR_FLOW_IPV4_SCTP:
0652 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 %s: dst_port %hu src_port %hu\n",
0653 fltr->loc,
0654 &fltr->ip_data.v4_addrs.dst_ip,
0655 &fltr->ip_data.v4_addrs.src_ip,
0656 proto,
0657 ntohs(fltr->ip_data.dst_port),
0658 ntohs(fltr->ip_data.src_port));
0659 break;
0660 case IAVF_FDIR_FLOW_IPV4_AH:
0661 case IAVF_FDIR_FLOW_IPV4_ESP:
0662 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 %s: SPI %u\n",
0663 fltr->loc,
0664 &fltr->ip_data.v4_addrs.dst_ip,
0665 &fltr->ip_data.v4_addrs.src_ip,
0666 proto,
0667 ntohl(fltr->ip_data.spi));
0668 break;
0669 case IAVF_FDIR_FLOW_IPV4_OTHER:
0670 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI4 src_ip %pI4 proto: %u L4_bytes: 0x%x\n",
0671 fltr->loc,
0672 &fltr->ip_data.v4_addrs.dst_ip,
0673 &fltr->ip_data.v4_addrs.src_ip,
0674 fltr->ip_data.proto,
0675 ntohl(fltr->ip_data.l4_header));
0676 break;
0677 case IAVF_FDIR_FLOW_IPV6_TCP:
0678 case IAVF_FDIR_FLOW_IPV6_UDP:
0679 case IAVF_FDIR_FLOW_IPV6_SCTP:
0680 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 %s: dst_port %hu src_port %hu\n",
0681 fltr->loc,
0682 &fltr->ip_data.v6_addrs.dst_ip,
0683 &fltr->ip_data.v6_addrs.src_ip,
0684 proto,
0685 ntohs(fltr->ip_data.dst_port),
0686 ntohs(fltr->ip_data.src_port));
0687 break;
0688 case IAVF_FDIR_FLOW_IPV6_AH:
0689 case IAVF_FDIR_FLOW_IPV6_ESP:
0690 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 %s: SPI %u\n",
0691 fltr->loc,
0692 &fltr->ip_data.v6_addrs.dst_ip,
0693 &fltr->ip_data.v6_addrs.src_ip,
0694 proto,
0695 ntohl(fltr->ip_data.spi));
0696 break;
0697 case IAVF_FDIR_FLOW_IPV6_OTHER:
0698 dev_info(&adapter->pdev->dev, "Rule ID: %u dst_ip: %pI6 src_ip %pI6 proto: %u L4_bytes: 0x%x\n",
0699 fltr->loc,
0700 &fltr->ip_data.v6_addrs.dst_ip,
0701 &fltr->ip_data.v6_addrs.src_ip,
0702 fltr->ip_data.proto,
0703 ntohl(fltr->ip_data.l4_header));
0704 break;
0705 case IAVF_FDIR_FLOW_NON_IP_L2:
0706 dev_info(&adapter->pdev->dev, "Rule ID: %u eth_type: 0x%x\n",
0707 fltr->loc,
0708 ntohs(fltr->eth_data.etype));
0709 break;
0710 default:
0711 break;
0712 }
0713 }
0714
0715
0716
0717
0718
0719
0720
0721
0722 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
0723 {
0724 struct iavf_fdir_fltr *tmp;
0725
0726 list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
0727 if (tmp->flow_type != fltr->flow_type)
0728 continue;
0729
0730 if (!memcmp(&tmp->eth_data, &fltr->eth_data,
0731 sizeof(fltr->eth_data)) &&
0732 !memcmp(&tmp->ip_data, &fltr->ip_data,
0733 sizeof(fltr->ip_data)) &&
0734 !memcmp(&tmp->ext_data, &fltr->ext_data,
0735 sizeof(fltr->ext_data)))
0736 return true;
0737 }
0738
0739 return false;
0740 }
0741
0742
0743
0744
0745
0746
0747
0748
0749 struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter, u32 loc)
0750 {
0751 struct iavf_fdir_fltr *rule;
0752
0753 list_for_each_entry(rule, &adapter->fdir_list_head, list)
0754 if (rule->loc == loc)
0755 return rule;
0756
0757 return NULL;
0758 }
0759
0760
0761
0762
0763
0764
0765 void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
0766 {
0767 struct iavf_fdir_fltr *rule, *parent = NULL;
0768
0769 list_for_each_entry(rule, &adapter->fdir_list_head, list) {
0770 if (rule->loc >= fltr->loc)
0771 break;
0772 parent = rule;
0773 }
0774
0775 if (parent)
0776 list_add(&fltr->list, &parent->list);
0777 else
0778 list_add(&fltr->list, &adapter->fdir_list_head);
0779 }