Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iavf: add support for offloading tc U32 cls filters

Add support for offloading cls U32 filters. Only "skbedit queue_mapping"
and "drop" actions are supported. Also, only "ip" and "802_3" tc
protocols are allowed. The PF must advertise the VIRTCHNL_VF_OFFLOAD_TC_U32
capability flag.

Since the filters will be enabled via the FD stage at the PF, a new type
of FDIR filters is added and the existing list and state machine are used.

The new filters can be used to configure flow directors based on raw
(binary) pattern in the rx packet.

Examples:

0. # tc qdisc add dev enp175s0v0 ingress

1. Redirect UDP from src IP 192.168.2.1 to queue 12:

# tc filter add dev <dev> protocol ip ingress u32 \
match u32 0x45000000 0xff000000 at 0 \
match u32 0x00110000 0x00ff0000 at 8 \
match u32 0xC0A80201 0xffffffff at 12 \
match u32 0x00000000 0x00000000 at 24 \
action skbedit queue_mapping 12 skip_sw

2. Drop all ICMP:

# tc filter add dev <dev> protocol ip ingress u32 \
match u32 0x45000000 0xff000000 at 0 \
match u32 0x00010000 0x00ff0000 at 8 \
match u32 0x00000000 0x00000000 at 24 \
action drop skip_sw

3. Redirect ICMP traffic from MAC 3c:fd:fe:a5:47:e0 to queue 7
(note proto: 802_3):

# tc filter add dev <dev> protocol 802_3 ingress u32 \
match u32 0x00003CFD 0x0000ffff at 4 \
match u32 0xFEA547E0 0xffffffff at 8 \
match u32 0x08004500 0xffffff00 at 12 \
match u32 0x00000001 0x000000ff at 20 \
match u32 0x0000 0x0000 at 40 \
action skbedit queue_mapping 7 skip_sw

Notes on matches:
1 - All intermediate fields that are needed to parse the correct PTYPE
must be provided (in e.g. 3: Ethernet Type 0x0800 in MAC, IP version
and IP length: 0x45 and protocol: 0x01 (ICMP)).
2 - The last match must provide an offset that guarantees all required
headers are accounted for, even if the last header is not matched.
For example, in #2, the last match is 4 bytes at offset 24 starting
from IP header, so the total is 14 (MAC) + 24 + 4 = 42, which is the
sum of MAC+IP+ICMP headers.

Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Ahmed Zaki and committed by
Tony Nguyen
623122ac 995617dc

+238 -27
+26 -1
drivers/net/ethernet/intel/iavf/iavf.h
··· 33 33 #include <net/udp.h> 34 34 #include <net/tc_act/tc_gact.h> 35 35 #include <net/tc_act/tc_mirred.h> 36 + #include <net/tc_act/tc_skbedit.h> 36 37 37 38 #include "iavf_type.h" 38 39 #include <linux/avf/virtchnl.h> ··· 394 393 VIRTCHNL_VF_OFFLOAD_VLAN_V2) 395 394 #define CRC_OFFLOAD_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \ 396 395 VIRTCHNL_VF_OFFLOAD_CRC) 396 + #define TC_U32_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \ 397 + VIRTCHNL_VF_OFFLOAD_TC_U32) 397 398 #define VLAN_V2_FILTERING_ALLOWED(_a) \ 398 399 (VLAN_V2_ALLOWED((_a)) && \ 399 400 ((_a)->vlan_v2_caps.filtering.filtering_support.outer || \ ··· 440 437 441 438 #define IAVF_MAX_FDIR_FILTERS 128 /* max allowed Flow Director filters */ 442 439 u16 fdir_active_fltr; 440 + u16 raw_fdir_active_fltr; 443 441 struct list_head fdir_list_head; 444 442 spinlock_t fdir_fltr_lock; /* protect the Flow Director filter list */ 445 443 ··· 451 447 /* Must be called with fdir_fltr_lock lock held */ 452 448 static inline bool iavf_fdir_max_reached(struct iavf_adapter *adapter) 453 449 { 454 - return adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS; 450 + return adapter->fdir_active_fltr + adapter->raw_fdir_active_fltr >= 451 + IAVF_MAX_FDIR_FILTERS; 452 + } 453 + 454 + static inline void 455 + iavf_inc_fdir_active_fltr(struct iavf_adapter *adapter, 456 + struct iavf_fdir_fltr *fltr) 457 + { 458 + if (iavf_is_raw_fdir(fltr)) 459 + adapter->raw_fdir_active_fltr++; 460 + else 461 + adapter->fdir_active_fltr++; 462 + } 463 + 464 + static inline void 465 + iavf_dec_fdir_active_fltr(struct iavf_adapter *adapter, 466 + struct iavf_fdir_fltr *fltr) 467 + { 468 + if (iavf_is_raw_fdir(fltr)) 469 + adapter->raw_fdir_active_fltr--; 470 + else 471 + adapter->fdir_active_fltr--; 455 472 } 456 473 457 474 /* Ethtool Private Flags */
+6 -3
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
··· 927 927 928 928 spin_lock_bh(&adapter->fdir_fltr_lock); 929 929 930 - rule = iavf_find_fdir_fltr(adapter, fsp->location); 930 + rule = iavf_find_fdir_fltr(adapter, false, fsp->location); 931 931 if (!rule) { 932 932 ret = -EINVAL; 933 933 goto release_lock; ··· 1072 1072 spin_lock_bh(&adapter->fdir_fltr_lock); 1073 1073 1074 1074 list_for_each_entry(fltr, &adapter->fdir_list_head, list) { 1075 + if (iavf_is_raw_fdir(fltr)) 1076 + continue; 1077 + 1075 1078 if (cnt == cmd->rule_cnt) { 1076 1079 val = -EMSGSIZE; 1077 1080 goto release_lock; ··· 1266 1263 return -EINVAL; 1267 1264 1268 1265 spin_lock_bh(&adapter->fdir_fltr_lock); 1269 - if (iavf_find_fdir_fltr(adapter, fsp->location)) { 1266 + if (iavf_find_fdir_fltr(adapter, false, fsp->location)) { 1270 1267 dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n"); 1271 1268 spin_unlock_bh(&adapter->fdir_fltr_lock); 1272 1269 return -EEXIST; ··· 1310 1307 if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED)) 1311 1308 return -EOPNOTSUPP; 1312 1309 1313 - return iavf_fdir_del_fltr(adapter, fsp->location); 1310 + return iavf_fdir_del_fltr(adapter, false, fsp->location); 1314 1311 } 1315 1312 1316 1313 /**
+20 -9
drivers/net/ethernet/intel/iavf/iavf_fdir.c
··· 796 796 797 797 spin_lock_bh(&adapter->fdir_fltr_lock); 798 798 list_for_each_entry(tmp, &adapter->fdir_list_head, list) { 799 + if (iavf_is_raw_fdir(fltr)) 800 + continue; 801 + 799 802 if (tmp->flow_type != fltr->flow_type) 800 803 continue; 801 804 ··· 820 817 /** 821 818 * iavf_find_fdir_fltr - find FDIR filter 822 819 * @adapter: pointer to the VF adapter structure 823 - * @loc: location to find. 820 + * @is_raw: filter type, is raw (tc u32) or not (ethtool) 821 + * @data: data to ID the filter, type dependent 824 822 * 825 823 * Returns: pointer to Flow Director filter if found or NULL. Lock must be held. 826 824 */ 827 825 struct iavf_fdir_fltr *iavf_find_fdir_fltr(struct iavf_adapter *adapter, 828 - u32 loc) 826 + bool is_raw, u32 data) 829 827 { 830 828 struct iavf_fdir_fltr *rule; 831 829 832 - list_for_each_entry(rule, &adapter->fdir_list_head, list) 833 - if (rule->loc == loc) 830 + list_for_each_entry(rule, &adapter->fdir_list_head, list) { 831 + if ((is_raw && rule->cls_u32_handle == data) || 832 + (!is_raw && rule->loc == data)) 834 833 return rule; 834 + } 835 835 836 836 return NULL; 837 837 } ··· 861 855 } 862 856 863 857 list_for_each_entry(rule, &adapter->fdir_list_head, list) { 858 + if (iavf_is_raw_fdir(fltr)) 859 + break; 860 + 864 861 if (rule->loc >= fltr->loc) 865 862 break; 866 863 parent = rule; ··· 873 864 list_add(&fltr->list, &parent->list); 874 865 else 875 866 list_add(&fltr->list, &adapter->fdir_list_head); 876 - adapter->fdir_active_fltr++; 867 + 868 + iavf_inc_fdir_active_fltr(adapter, fltr); 877 869 878 870 if (adapter->link_up) 879 871 fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST; ··· 891 881 /** 892 882 * iavf_fdir_del_fltr - delete a flow director filter from the list 893 883 * @adapter: pointer to the VF adapter structure 894 - * @loc: location to delete. 884 + * @is_raw: filter type, is raw (tc u32) or not (ethtool) 885 + * @data: data to ID the filter, type dependent 895 886 * 896 887 * Return: 0 on success or negative errno on failure. 897 888 */ 898 - int iavf_fdir_del_fltr(struct iavf_adapter *adapter, u32 loc) 889 + int iavf_fdir_del_fltr(struct iavf_adapter *adapter, bool is_raw, u32 data) 899 890 { 900 891 struct iavf_fdir_fltr *fltr = NULL; 901 892 int err = 0; 902 893 903 894 spin_lock_bh(&adapter->fdir_fltr_lock); 904 - fltr = iavf_find_fdir_fltr(adapter, loc); 895 + fltr = iavf_find_fdir_fltr(adapter, is_raw, data); 905 896 906 897 if (fltr) { 907 898 if (fltr->state == IAVF_FDIR_FLTR_ACTIVE) { 908 899 fltr->state = IAVF_FDIR_FLTR_DEL_REQUEST; 909 900 } else if (fltr->state == IAVF_FDIR_FLTR_INACTIVE) { 910 901 list_del(&fltr->list); 902 + iavf_dec_fdir_active_fltr(adapter, fltr); 911 903 kfree(fltr); 912 - adapter->fdir_active_fltr--; 913 904 fltr = NULL; 914 905 } else { 915 906 err = -EBUSY;
+8 -2
drivers/net/ethernet/intel/iavf/iavf_fdir.h
··· 117 117 118 118 u32 flow_id; 119 119 120 + u32 cls_u32_handle; /* for FDIR added via tc u32 */ 120 121 u32 loc; /* Rule location inside the flow table */ 121 122 u32 q_index; 122 123 123 124 struct virtchnl_fdir_add vc_add_msg; 124 125 }; 126 + 127 + static inline bool iavf_is_raw_fdir(struct iavf_fdir_fltr *fltr) 128 + { 129 + return !fltr->vc_add_msg.rule_cfg.proto_hdrs.count; 130 + } 125 131 126 132 int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter, 127 133 struct iavf_fdir_fltr *fltr); ··· 136 130 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr); 137 131 int iavf_fdir_add_fltr(struct iavf_adapter *adapter, 138 132 struct iavf_fdir_fltr *fltr); 139 - int iavf_fdir_del_fltr(struct iavf_adapter *adapter, u32 loc); 133 + int iavf_fdir_del_fltr(struct iavf_adapter *adapter, bool is_raw, u32 data); 140 134 struct iavf_fdir_fltr *iavf_find_fdir_fltr(struct iavf_adapter *adapter, 141 - u32 loc); 135 + bool is_raw, u32 data); 142 136 #endif /* _IAVF_FDIR_H_ */
+156 -4
drivers/net/ethernet/intel/iavf/iavf_main.c
··· 4013 4013 4014 4014 /** 4015 4015 * iavf_setup_tc_cls_flower - flower classifier offloads 4016 - * @adapter: board private structure 4016 + * @adapter: pointer to iavf adapter structure 4017 4017 * @cls_flower: pointer to flow_cls_offload struct with flow info 4018 4018 */ 4019 4019 static int iavf_setup_tc_cls_flower(struct iavf_adapter *adapter, ··· 4026 4026 return iavf_delete_clsflower(adapter, cls_flower); 4027 4027 case FLOW_CLS_STATS: 4028 4028 return -EOPNOTSUPP; 4029 + default: 4030 + return -EOPNOTSUPP; 4031 + } 4032 + } 4033 + 4034 + /** 4035 + * iavf_add_cls_u32 - Add U32 classifier offloads 4036 + * @adapter: pointer to iavf adapter structure 4037 + * @cls_u32: pointer to tc_cls_u32_offload struct with flow info 4038 + * 4039 + * Return: 0 on success or negative errno on failure. 4040 + */ 4041 + static int iavf_add_cls_u32(struct iavf_adapter *adapter, 4042 + struct tc_cls_u32_offload *cls_u32) 4043 + { 4044 + struct netlink_ext_ack *extack = cls_u32->common.extack; 4045 + struct virtchnl_fdir_rule *rule_cfg; 4046 + struct virtchnl_filter_action *vact; 4047 + struct virtchnl_proto_hdrs *hdrs; 4048 + struct ethhdr *spec_h, *mask_h; 4049 + const struct tc_action *act; 4050 + struct iavf_fdir_fltr *fltr; 4051 + struct tcf_exts *exts; 4052 + unsigned int q_index; 4053 + int i, status = 0; 4054 + int off_base = 0; 4055 + 4056 + if (cls_u32->knode.link_handle) { 4057 + NL_SET_ERR_MSG_MOD(extack, "Linking not supported"); 4058 + return -EOPNOTSUPP; 4059 + } 4060 + 4061 + fltr = kzalloc(sizeof(*fltr), GFP_KERNEL); 4062 + if (!fltr) 4063 + return -ENOMEM; 4064 + 4065 + rule_cfg = &fltr->vc_add_msg.rule_cfg; 4066 + hdrs = &rule_cfg->proto_hdrs; 4067 + hdrs->count = 0; 4068 + 4069 + /* The parser lib at the PF expects the packet starting with MAC hdr */ 4070 + switch (ntohs(cls_u32->common.protocol)) { 4071 + case ETH_P_802_3: 4072 + break; 4073 + case ETH_P_IP: 4074 + spec_h = (struct ethhdr *)hdrs->raw.spec; 4075 + mask_h = (struct ethhdr *)hdrs->raw.mask; 4076 + spec_h->h_proto = htons(ETH_P_IP); 4077 + mask_h->h_proto = htons(0xFFFF); 4078 + off_base += ETH_HLEN; 4079 + break; 4080 + default: 4081 + NL_SET_ERR_MSG_MOD(extack, "Only 802_3 and ip filter protocols are supported"); 4082 + status = -EOPNOTSUPP; 4083 + goto free_alloc; 4084 + } 4085 + 4086 + for (i = 0; i < cls_u32->knode.sel->nkeys; i++) { 4087 + __be32 val, mask; 4088 + int off; 4089 + 4090 + off = off_base + cls_u32->knode.sel->keys[i].off; 4091 + val = cls_u32->knode.sel->keys[i].val; 4092 + mask = cls_u32->knode.sel->keys[i].mask; 4093 + 4094 + if (off >= sizeof(hdrs->raw.spec)) { 4095 + NL_SET_ERR_MSG_MOD(extack, "Input exceeds maximum allowed."); 4096 + status = -EINVAL; 4097 + goto free_alloc; 4098 + } 4099 + 4100 + memcpy(&hdrs->raw.spec[off], &val, sizeof(val)); 4101 + memcpy(&hdrs->raw.mask[off], &mask, sizeof(mask)); 4102 + hdrs->raw.pkt_len = off + sizeof(val); 4103 + } 4104 + 4105 + /* Only one action is allowed */ 4106 + rule_cfg->action_set.count = 1; 4107 + vact = &rule_cfg->action_set.actions[0]; 4108 + exts = cls_u32->knode.exts; 4109 + 4110 + tcf_exts_for_each_action(i, act, exts) { 4111 + /* FDIR queue */ 4112 + if (is_tcf_skbedit_rx_queue_mapping(act)) { 4113 + q_index = tcf_skbedit_rx_queue_mapping(act); 4114 + if (q_index >= adapter->num_active_queues) { 4115 + status = -EINVAL; 4116 + goto free_alloc; 4117 + } 4118 + 4119 + vact->type = VIRTCHNL_ACTION_QUEUE; 4120 + vact->act_conf.queue.index = q_index; 4121 + break; 4122 + } 4123 + 4124 + /* Drop */ 4125 + if (is_tcf_gact_shot(act)) { 4126 + vact->type = VIRTCHNL_ACTION_DROP; 4127 + break; 4128 + } 4129 + 4130 + /* Unsupported action */ 4131 + NL_SET_ERR_MSG_MOD(extack, "Unsupported action."); 4132 + status = -EOPNOTSUPP; 4133 + goto free_alloc; 4134 + } 4135 + 4136 + fltr->vc_add_msg.vsi_id = adapter->vsi.id; 4137 + fltr->cls_u32_handle = cls_u32->knode.handle; 4138 + return iavf_fdir_add_fltr(adapter, fltr); 4139 + 4140 + free_alloc: 4141 + kfree(fltr); 4142 + return status; 4143 + } 4144 + 4145 + /** 4146 + * iavf_del_cls_u32 - Delete U32 classifier offloads 4147 + * @adapter: pointer to iavf adapter structure 4148 + * @cls_u32: pointer to tc_cls_u32_offload struct with flow info 4149 + * 4150 + * Return: 0 on success or negative errno on failure. 4151 + */ 4152 + static int iavf_del_cls_u32(struct iavf_adapter *adapter, 4153 + struct tc_cls_u32_offload *cls_u32) 4154 + { 4155 + return iavf_fdir_del_fltr(adapter, true, cls_u32->knode.handle); 4156 + } 4157 + 4158 + /** 4159 + * iavf_setup_tc_cls_u32 - U32 filter offloads 4160 + * @adapter: pointer to iavf adapter structure 4161 + * @cls_u32: pointer to tc_cls_u32_offload struct with flow info 4162 + * 4163 + * Return: 0 on success or negative errno on failure. 4164 + */ 4165 + static int iavf_setup_tc_cls_u32(struct iavf_adapter *adapter, 4166 + struct tc_cls_u32_offload *cls_u32) 4167 + { 4168 + if (!TC_U32_SUPPORT(adapter) || !FDIR_FLTR_SUPPORT(adapter)) 4169 + return -EOPNOTSUPP; 4170 + 4171 + switch (cls_u32->command) { 4172 + case TC_CLSU32_NEW_KNODE: 4173 + case TC_CLSU32_REPLACE_KNODE: 4174 + return iavf_add_cls_u32(adapter, cls_u32); 4175 + case TC_CLSU32_DELETE_KNODE: 4176 + return iavf_del_cls_u32(adapter, cls_u32); 4029 4177 default: 4030 4178 return -EOPNOTSUPP; 4031 4179 } ··· 4198 4050 switch (type) { 4199 4051 case TC_SETUP_CLSFLOWER: 4200 4052 return iavf_setup_tc_cls_flower(cb_priv, type_data); 4053 + case TC_SETUP_CLSU32: 4054 + return iavf_setup_tc_cls_u32(cb_priv, type_data); 4201 4055 default: 4202 4056 return -EOPNOTSUPP; 4203 4057 } ··· 4482 4332 fdir->state == IAVF_FDIR_FLTR_INACTIVE) { 4483 4333 /* Delete filters not registered in PF */ 4484 4334 list_del(&fdir->list); 4335 + iavf_dec_fdir_active_fltr(adapter, fdir); 4485 4336 kfree(fdir); 4486 - adapter->fdir_active_fltr--; 4487 4337 } else if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING || 4488 4338 fdir->state == IAVF_FDIR_FLTR_DIS_REQUEST || 4489 4339 fdir->state == IAVF_FDIR_FLTR_ACTIVE) { ··· 4993 4843 /* get HW VLAN features that can be toggled */ 4994 4844 hw_vlan_features = iavf_get_netdev_vlan_hw_features(adapter); 4995 4845 4996 - /* Enable cloud filter if ADQ is supported */ 4997 - if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) 4846 + /* Enable HW TC offload if ADQ or tc U32 is supported */ 4847 + if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ || 4848 + TC_U32_SUPPORT(adapter)) 4998 4849 hw_features |= NETIF_F_HW_TC; 4850 + 4999 4851 if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO) 5000 4852 hw_features |= NETIF_F_GSO_UDP_L4; 5001 4853
+17 -8
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
··· 142 142 VIRTCHNL_VF_OFFLOAD_WB_ON_ITR | 143 143 VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 | 144 144 VIRTCHNL_VF_OFFLOAD_ENCAP | 145 + VIRTCHNL_VF_OFFLOAD_TC_U32 | 145 146 VIRTCHNL_VF_OFFLOAD_VLAN_V2 | 146 147 VIRTCHNL_VF_OFFLOAD_CRC | 147 148 VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM | ··· 1962 1961 * list on PF is already cleared after a reset 1963 1962 */ 1964 1963 list_del(&f->list); 1964 + iavf_dec_fdir_active_fltr(adapter, f); 1965 1965 kfree(f); 1966 - adapter->fdir_active_fltr--; 1967 1966 } 1968 1967 } 1969 1968 spin_unlock_bh(&adapter->fdir_fltr_lock); ··· 2136 2135 dev_err(&adapter->pdev->dev, 2137 2136 "%s\n", msg); 2138 2137 list_del(&fdir->list); 2138 + iavf_dec_fdir_active_fltr(adapter, fdir); 2139 2139 kfree(fdir); 2140 - adapter->fdir_active_fltr--; 2141 2140 } 2142 2141 } 2143 2142 spin_unlock_bh(&adapter->fdir_fltr_lock); ··· 2452 2451 list) { 2453 2452 if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING) { 2454 2453 if (add_fltr->status == VIRTCHNL_FDIR_SUCCESS) { 2455 - dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is added\n", 2456 - fdir->loc); 2454 + if (!iavf_is_raw_fdir(fdir)) 2455 + dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is added\n", 2456 + fdir->loc); 2457 + else 2458 + dev_info(&adapter->pdev->dev, "Flow Director filter (raw) for TC handle %x is added\n", 2459 + TC_U32_USERHTID(fdir->cls_u32_handle)); 2457 2460 fdir->state = IAVF_FDIR_FLTR_ACTIVE; 2458 2461 fdir->flow_id = add_fltr->flow_id; 2459 2462 } else { ··· 2465 2460 add_fltr->status); 2466 2461 iavf_print_fdir_fltr(adapter, fdir); 2467 2462 list_del(&fdir->list); 2463 + iavf_dec_fdir_active_fltr(adapter, fdir); 2468 2464 kfree(fdir); 2469 - adapter->fdir_active_fltr--; 2470 2465 } 2471 2466 } 2472 2467 } ··· 2484 2479 if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS || 2485 2480 del_fltr->status == 2486 2481 VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) { 2487 - dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is deleted\n", 2488 - fdir->loc); 2482 + if (!iavf_is_raw_fdir(fdir)) 2483 + dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is deleted\n", 2484 + fdir->loc); 2485 + else 2486 + dev_info(&adapter->pdev->dev, "Flow Director filter (raw) for TC handle %x is deleted\n", 2487 + TC_U32_USERHTID(fdir->cls_u32_handle)); 2489 2488 list_del(&fdir->list); 2489 + iavf_dec_fdir_active_fltr(adapter, fdir); 2490 2490 kfree(fdir); 2491 - adapter->fdir_active_fltr--; 2492 2491 } else { 2493 2492 fdir->state = IAVF_FDIR_FLTR_ACTIVE; 2494 2493 dev_info(&adapter->pdev->dev, "Failed to delete Flow Director filter with status: %d\n",
+4
drivers/net/ethernet/intel/ice/ice_virtchnl.c
··· 461 461 if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF) 462 462 vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_FDIR_PF; 463 463 464 + if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_TC_U32 && 465 + vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_FDIR_PF) 466 + vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_TC_U32; 467 + 464 468 if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) 465 469 vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2; 466 470
+1
include/linux/avf/virtchnl.h
··· 247 247 /* used to negotiate communicating link speeds in Mbps */ 248 248 #define VIRTCHNL_VF_CAP_ADV_LINK_SPEED BIT(7) 249 249 #define VIRTCHNL_VF_OFFLOAD_CRC BIT(10) 250 + #define VIRTCHNL_VF_OFFLOAD_TC_U32 BIT(11) 250 251 #define VIRTCHNL_VF_OFFLOAD_VLAN_V2 BIT(15) 251 252 #define VIRTCHNL_VF_OFFLOAD_VLAN BIT(16) 252 253 #define VIRTCHNL_VF_OFFLOAD_RX_POLLING BIT(17)