|
@@ -62,6 +62,9 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {
|
|
|
I40E_NETDEV_STAT(rx_crc_errors),
|
|
|
};
|
|
|
|
|
|
+static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
|
|
|
+ struct ethtool_rxnfc *cmd, bool add);
|
|
|
+
|
|
|
/* These PF_STATs might look like duplicates of some NETDEV_STATs,
|
|
|
* but they are separate. This device supports Virtualization, and
|
|
|
* as such might have several netdevs supporting VMDq and FCoE going
|
|
@@ -1111,6 +1114,84 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * i40e_get_ethtool_fdir_all - Populates the rule count of a command
|
|
|
+ * @pf: Pointer to the physical function struct
|
|
|
+ * @cmd: The command to get or set Rx flow classification rules
|
|
|
+ * @rule_locs: Array of used rule locations
|
|
|
+ *
|
|
|
+ * This function populates both the total and actual rule count of
|
|
|
+ * the ethtool flow classification command
|
|
|
+ *
|
|
|
+ * Returns 0 on success or -EMSGSIZE if entry not found
|
|
|
+ **/
|
|
|
+static int i40e_get_ethtool_fdir_all(struct i40e_pf *pf,
|
|
|
+ struct ethtool_rxnfc *cmd,
|
|
|
+ u32 *rule_locs)
|
|
|
+{
|
|
|
+ struct i40e_fdir_filter *rule;
|
|
|
+ struct hlist_node *node2;
|
|
|
+ int cnt = 0;
|
|
|
+
|
|
|
+ /* report total rule count */
|
|
|
+ cmd->data = pf->hw.fdir_shared_filter_count +
|
|
|
+ pf->fdir_pf_filter_count;
|
|
|
+
|
|
|
+ hlist_for_each_entry_safe(rule, node2,
|
|
|
+ &pf->fdir_filter_list, fdir_node) {
|
|
|
+ if (cnt == cmd->rule_cnt)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ rule_locs[cnt] = rule->fd_id;
|
|
|
+ cnt++;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd->rule_cnt = cnt;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * i40e_get_ethtool_fdir_entry - Look up a filter based on Rx flow
|
|
|
+ * @pf: Pointer to the physical function struct
|
|
|
+ * @cmd: The command to get or set Rx flow classification rules
|
|
|
+ *
|
|
|
+ * This function looks up a filter based on the Rx flow classification
|
|
|
+ * command and fills the flow spec info for it if found
|
|
|
+ *
|
|
|
+ * Returns 0 on success or -EINVAL if filter not found
|
|
|
+ **/
|
|
|
+static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
|
|
|
+ struct ethtool_rxnfc *cmd)
|
|
|
+{
|
|
|
+ struct ethtool_rx_flow_spec *fsp =
|
|
|
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
|
|
|
+ struct i40e_fdir_filter *rule = NULL;
|
|
|
+ struct hlist_node *node2;
|
|
|
+
|
|
|
+ /* report total rule count */
|
|
|
+ cmd->data = pf->hw.fdir_shared_filter_count +
|
|
|
+ pf->fdir_pf_filter_count;
|
|
|
+
|
|
|
+ hlist_for_each_entry_safe(rule, node2,
|
|
|
+ &pf->fdir_filter_list, fdir_node) {
|
|
|
+ if (fsp->location <= rule->fd_id)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!rule || fsp->location != rule->fd_id)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ fsp->flow_type = rule->flow_type;
|
|
|
+ fsp->h_u.tcp_ip4_spec.psrc = rule->src_port;
|
|
|
+ fsp->h_u.tcp_ip4_spec.pdst = rule->dst_port;
|
|
|
+ fsp->h_u.tcp_ip4_spec.ip4src = rule->src_ip[0];
|
|
|
+ fsp->h_u.tcp_ip4_spec.ip4dst = rule->dst_ip[0];
|
|
|
+ fsp->ring_cookie = rule->q_index;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* i40e_get_rxnfc - command to get RX flow classification rules
|
|
|
* @netdev: network interface device structure
|
|
@@ -1135,15 +1216,15 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
|
|
|
ret = i40e_get_rss_hash_opts(pf, cmd);
|
|
|
break;
|
|
|
case ETHTOOL_GRXCLSRLCNT:
|
|
|
- cmd->rule_cnt = 10;
|
|
|
+ cmd->rule_cnt = pf->fdir_pf_active_filters;
|
|
|
ret = 0;
|
|
|
break;
|
|
|
case ETHTOOL_GRXCLSRULE:
|
|
|
- ret = 0;
|
|
|
+ ret = i40e_get_ethtool_fdir_entry(pf, cmd);
|
|
|
break;
|
|
|
case ETHTOOL_GRXCLSRLALL:
|
|
|
- cmd->data = 500;
|
|
|
- ret = 0;
|
|
|
+ ret = i40e_get_ethtool_fdir_all(pf, cmd, rule_locs);
|
|
|
+ break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -1274,289 +1355,158 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#define IP_HEADER_OFFSET 14
|
|
|
-#define I40E_UDPIP_DUMMY_PACKET_LEN 42
|
|
|
/**
|
|
|
- * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 Flow Director filters for
|
|
|
- * a specific flow spec
|
|
|
- * @vsi: pointer to the targeted VSI
|
|
|
- * @fd_data: the flow director data required from the FDir descriptor
|
|
|
- * @ethtool_rx_flow_spec: the flow spec
|
|
|
- * @add: true adds a filter, false removes it
|
|
|
+ * i40e_update_ethtool_fdir_entry - Updates the fdir filter entry
|
|
|
+ * @vsi: Pointer to the targeted VSI
|
|
|
+ * @input: The filter to update or NULL to indicate deletion
|
|
|
+ * @sw_idx: Software index to the filter
|
|
|
+ * @cmd: The command to get or set Rx flow classification rules
|
|
|
*
|
|
|
- * Returns 0 if the filters were successfully added or removed
|
|
|
+ * This function updates (or deletes) a Flow Director entry from
|
|
|
+ * the hlist of the corresponding PF
|
|
|
+ *
|
|
|
+ * Returns 0 on success
|
|
|
**/
|
|
|
-static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
|
|
|
- struct i40e_fdir_data *fd_data,
|
|
|
- struct ethtool_rx_flow_spec *fsp, bool add)
|
|
|
+static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi,
|
|
|
+ struct i40e_fdir_filter *input,
|
|
|
+ u16 sw_idx,
|
|
|
+ struct ethtool_rxnfc *cmd)
|
|
|
{
|
|
|
+ struct i40e_fdir_filter *rule, *parent;
|
|
|
struct i40e_pf *pf = vsi->back;
|
|
|
- struct udphdr *udp;
|
|
|
- struct iphdr *ip;
|
|
|
- bool err = false;
|
|
|
- int ret;
|
|
|
- int i;
|
|
|
- char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
|
|
|
- 0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11,
|
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
- 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
-
|
|
|
- memcpy(fd_data->raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
|
|
|
-
|
|
|
- ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
|
|
|
- udp = (struct udphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
|
|
|
- + sizeof(struct iphdr));
|
|
|
+ struct hlist_node *node2;
|
|
|
+ int err = -EINVAL;
|
|
|
|
|
|
- ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
|
|
|
- ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst;
|
|
|
- udp->source = fsp->h_u.tcp_ip4_spec.psrc;
|
|
|
- udp->dest = fsp->h_u.tcp_ip4_spec.pdst;
|
|
|
+ parent = NULL;
|
|
|
+ rule = NULL;
|
|
|
|
|
|
- for (i = I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP;
|
|
|
- i <= I40E_FILTER_PCTYPE_NONF_IPV4_UDP; i++) {
|
|
|
- fd_data->pctype = i;
|
|
|
- ret = i40e_program_fdir_filter(fd_data, pf, add);
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter command send failed for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- err = true;
|
|
|
- } else {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter OK for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- }
|
|
|
+ hlist_for_each_entry_safe(rule, node2,
|
|
|
+ &pf->fdir_filter_list, fdir_node) {
|
|
|
+ /* hash found, or no matching entry */
|
|
|
+ if (rule->fd_id >= sw_idx)
|
|
|
+ break;
|
|
|
+ parent = rule;
|
|
|
}
|
|
|
|
|
|
- return err ? -EOPNOTSUPP : 0;
|
|
|
-}
|
|
|
-
|
|
|
-#define I40E_TCPIP_DUMMY_PACKET_LEN 54
|
|
|
-/**
|
|
|
- * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 Flow Director filters for
|
|
|
- * a specific flow spec
|
|
|
- * @vsi: pointer to the targeted VSI
|
|
|
- * @fd_data: the flow director data required from the FDir descriptor
|
|
|
- * @ethtool_rx_flow_spec: the flow spec
|
|
|
- * @add: true adds a filter, false removes it
|
|
|
- *
|
|
|
- * Returns 0 if the filters were successfully added or removed
|
|
|
- **/
|
|
|
-static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
|
|
|
- struct i40e_fdir_data *fd_data,
|
|
|
- struct ethtool_rx_flow_spec *fsp, bool add)
|
|
|
-{
|
|
|
- struct i40e_pf *pf = vsi->back;
|
|
|
- struct tcphdr *tcp;
|
|
|
- struct iphdr *ip;
|
|
|
- bool err = false;
|
|
|
- int ret;
|
|
|
- /* Dummy packet */
|
|
|
- char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
|
|
|
- 0x45, 0, 0, 0x28, 0, 0, 0x40, 0, 0x40, 0x6,
|
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
- 0x80, 0x11, 0x0, 0x72, 0, 0, 0, 0};
|
|
|
-
|
|
|
- memcpy(fd_data->raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
|
|
|
-
|
|
|
- ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
|
|
|
- tcp = (struct tcphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
|
|
|
- + sizeof(struct iphdr));
|
|
|
-
|
|
|
- ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst;
|
|
|
- tcp->dest = fsp->h_u.tcp_ip4_spec.pdst;
|
|
|
- ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
|
|
|
- tcp->source = fsp->h_u.tcp_ip4_spec.psrc;
|
|
|
-
|
|
|
- if (add) {
|
|
|
- if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
|
|
|
- dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
|
|
|
- pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
|
|
|
+ /* if there is an old rule occupying our place remove it */
|
|
|
+ if (rule && (rule->fd_id == sw_idx)) {
|
|
|
+ if (!input || (rule->fd_id != input->fd_id)) {
|
|
|
+ cmd->fs.flow_type = rule->flow_type;
|
|
|
+ err = i40e_add_del_fdir_ethtool(vsi, cmd, false);
|
|
|
}
|
|
|
+
|
|
|
+ hlist_del(&rule->fdir_node);
|
|
|
+ kfree(rule);
|
|
|
+ pf->fdir_pf_active_filters--;
|
|
|
}
|
|
|
|
|
|
- fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN;
|
|
|
- ret = i40e_program_fdir_filter(fd_data, pf, add);
|
|
|
+ /* If no input this was a delete, err should be 0 if a rule was
|
|
|
+ * successfully found and removed from the list else -EINVAL
|
|
|
+ */
|
|
|
+ if (!input)
|
|
|
+ return err;
|
|
|
|
|
|
- if (ret) {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter command send failed for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- err = true;
|
|
|
- } else {
|
|
|
- dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- }
|
|
|
+ /* initialize node and set software index */
|
|
|
+ INIT_HLIST_NODE(&input->fdir_node);
|
|
|
|
|
|
- fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
|
|
|
+ /* add filter to the list */
|
|
|
+ if (parent)
|
|
|
+ hlist_add_after(&parent->fdir_node, &input->fdir_node);
|
|
|
+ else
|
|
|
+ hlist_add_head(&input->fdir_node,
|
|
|
+ &pf->fdir_filter_list);
|
|
|
|
|
|
- ret = i40e_program_fdir_filter(fd_data, pf, add);
|
|
|
- if (ret) {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter command send failed for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- err = true;
|
|
|
- } else {
|
|
|
- dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- }
|
|
|
+ /* update counts */
|
|
|
+ pf->fdir_pf_active_filters++;
|
|
|
|
|
|
- return err ? -EOPNOTSUPP : 0;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
|
|
|
- * a specific flow spec
|
|
|
- * @vsi: pointer to the targeted VSI
|
|
|
- * @fd_data: the flow director data required from the FDir descriptor
|
|
|
- * @ethtool_rx_flow_spec: the flow spec
|
|
|
- * @add: true adds a filter, false removes it
|
|
|
+ * i40e_del_fdir_entry - Deletes a Flow Director filter entry
|
|
|
+ * @vsi: Pointer to the targeted VSI
|
|
|
+ * @cmd: The command to get or set Rx flow classification rules
|
|
|
*
|
|
|
- * Returns 0 if the filters were successfully added or removed
|
|
|
- **/
|
|
|
-static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
|
|
|
- struct i40e_fdir_data *fd_data,
|
|
|
- struct ethtool_rx_flow_spec *fsp, bool add)
|
|
|
-{
|
|
|
- return -EOPNOTSUPP;
|
|
|
-}
|
|
|
-
|
|
|
-#define I40E_IP_DUMMY_PACKET_LEN 34
|
|
|
-/**
|
|
|
- * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
|
|
|
- * a specific flow spec
|
|
|
- * @vsi: pointer to the targeted VSI
|
|
|
- * @fd_data: the flow director data required for the FDir descriptor
|
|
|
- * @fsp: the ethtool flow spec
|
|
|
- * @add: true adds a filter, false removes it
|
|
|
+ * The function removes a Flow Director filter entry from the
|
|
|
+ * hlist of the corresponding PF
|
|
|
*
|
|
|
- * Returns 0 if the filters were successfully added or removed
|
|
|
- **/
|
|
|
-static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
|
|
|
- struct i40e_fdir_data *fd_data,
|
|
|
- struct ethtool_rx_flow_spec *fsp, bool add)
|
|
|
+ * Returns 0 on success
|
|
|
+ */
|
|
|
+static int i40e_del_fdir_entry(struct i40e_vsi *vsi,
|
|
|
+ struct ethtool_rxnfc *cmd)
|
|
|
{
|
|
|
+ struct ethtool_rx_flow_spec *fsp =
|
|
|
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
|
|
|
struct i40e_pf *pf = vsi->back;
|
|
|
- struct iphdr *ip;
|
|
|
- bool err = false;
|
|
|
- int ret;
|
|
|
- int i;
|
|
|
- char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
|
|
|
- 0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10,
|
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
+ int ret = 0;
|
|
|
|
|
|
- memcpy(fd_data->raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
|
|
|
- ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
|
|
|
-
|
|
|
- ip->saddr = fsp->h_u.usr_ip4_spec.ip4src;
|
|
|
- ip->daddr = fsp->h_u.usr_ip4_spec.ip4dst;
|
|
|
- ip->protocol = fsp->h_u.usr_ip4_spec.proto;
|
|
|
-
|
|
|
- for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
|
|
|
- i <= I40E_FILTER_PCTYPE_FRAG_IPV4; i++) {
|
|
|
- fd_data->pctype = i;
|
|
|
- ret = i40e_program_fdir_filter(fd_data, pf, add);
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter command send failed for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- err = true;
|
|
|
- } else {
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Filter OK for PCTYPE %d (ret = %d)\n",
|
|
|
- fd_data->pctype, ret);
|
|
|
- }
|
|
|
- }
|
|
|
+ ret = i40e_update_ethtool_fdir_entry(vsi, NULL, fsp->location, cmd);
|
|
|
|
|
|
- return err ? -EOPNOTSUPP : 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * i40e_add_del_fdir_ethtool - Add/Remove Flow Director filters for
|
|
|
- * a specific flow spec based on their protocol
|
|
|
+ * i40e_add_del_fdir_ethtool - Add/Remove Flow Director filters
|
|
|
* @vsi: pointer to the targeted VSI
|
|
|
* @cmd: command to get or set RX flow classification rules
|
|
|
* @add: true adds a filter, false removes it
|
|
|
*
|
|
|
- * Returns 0 if the filters were successfully added or removed
|
|
|
+ * Add/Remove Flow Director filters for a specific flow spec based on their
|
|
|
+ * protocol. Returns 0 if the filters were successfully added or removed.
|
|
|
**/
|
|
|
static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
|
|
|
- struct ethtool_rxnfc *cmd, bool add)
|
|
|
+ struct ethtool_rxnfc *cmd, bool add)
|
|
|
{
|
|
|
- struct i40e_fdir_data fd_data;
|
|
|
- int ret = -EINVAL;
|
|
|
+ struct ethtool_rx_flow_spec *fsp;
|
|
|
+ struct i40e_fdir_filter *input;
|
|
|
struct i40e_pf *pf;
|
|
|
- struct ethtool_rx_flow_spec *fsp =
|
|
|
- (struct ethtool_rx_flow_spec *)&cmd->fs;
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
if (!vsi)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
|
|
|
pf = vsi->back;
|
|
|
|
|
|
- if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
|
|
|
- (fsp->ring_cookie >= vsi->num_queue_pairs))
|
|
|
+ if (fsp->location >= (pf->hw.func_caps.fd_filters_best_effort +
|
|
|
+ pf->hw.func_caps.fd_filters_guaranteed)) {
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- /* Populate the Flow Director that we have at the moment
|
|
|
- * and allocate the raw packet buffer for the calling functions
|
|
|
- */
|
|
|
- fd_data.raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_LOOKUP,
|
|
|
- GFP_KERNEL);
|
|
|
+ if ((fsp->ring_cookie >= vsi->num_queue_pairs) && add)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- if (!fd_data.raw_packet) {
|
|
|
- dev_info(&pf->pdev->dev, "Could not allocate memory\n");
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
+ input = kzalloc(sizeof(*input), GFP_KERNEL);
|
|
|
|
|
|
- fd_data.q_index = fsp->ring_cookie;
|
|
|
- fd_data.flex_off = 0;
|
|
|
- fd_data.pctype = 0;
|
|
|
- fd_data.dest_vsi = vsi->id;
|
|
|
- fd_data.dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
|
|
|
- fd_data.fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
|
|
|
- fd_data.cnt_index = 0;
|
|
|
- fd_data.fd_id = 0;
|
|
|
+ if (!input)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- switch (fsp->flow_type & ~FLOW_EXT) {
|
|
|
- case TCP_V4_FLOW:
|
|
|
- ret = i40e_add_del_fdir_tcpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case UDP_V4_FLOW:
|
|
|
- ret = i40e_add_del_fdir_udpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case SCTP_V4_FLOW:
|
|
|
- ret = i40e_add_del_fdir_sctpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case IPV4_FLOW:
|
|
|
- ret = i40e_add_del_fdir_ipv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case IP_USER_FLOW:
|
|
|
- switch (fsp->h_u.usr_ip4_spec.proto) {
|
|
|
- case IPPROTO_TCP:
|
|
|
- ret = i40e_add_del_fdir_tcpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case IPPROTO_UDP:
|
|
|
- ret = i40e_add_del_fdir_udpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- case IPPROTO_SCTP:
|
|
|
- ret = i40e_add_del_fdir_sctpv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- default:
|
|
|
- ret = i40e_add_del_fdir_ipv4(vsi, &fd_data, fsp, add);
|
|
|
- break;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- dev_info(&pf->pdev->dev, "Could not specify spec type\n");
|
|
|
- ret = -EINVAL;
|
|
|
+ input->fd_id = fsp->location;
|
|
|
+
|
|
|
+ input->q_index = fsp->ring_cookie;
|
|
|
+ input->flex_off = 0;
|
|
|
+ input->pctype = 0;
|
|
|
+ input->dest_vsi = vsi->id;
|
|
|
+ input->dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
|
|
|
+ input->fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
|
|
|
+ input->cnt_index = 0;
|
|
|
+ input->flow_type = fsp->flow_type;
|
|
|
+ input->ip4_proto = fsp->h_u.usr_ip4_spec.proto;
|
|
|
+ input->src_port = fsp->h_u.tcp_ip4_spec.psrc;
|
|
|
+ input->dst_port = fsp->h_u.tcp_ip4_spec.pdst;
|
|
|
+ input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
|
|
|
+ input->dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
|
|
|
+
|
|
|
+ ret = i40e_add_del_fdir(vsi, input, add);
|
|
|
+ if (ret) {
|
|
|
+ kfree(input);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- kfree(fd_data.raw_packet);
|
|
|
- fd_data.raw_packet = NULL;
|
|
|
+ if (!ret && add)
|
|
|
+ i40e_update_ethtool_fdir_entry(vsi, input, fsp->location, NULL);
|
|
|
+ else
|
|
|
+ kfree(input);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -1583,7 +1533,7 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
|
|
|
ret = i40e_add_del_fdir_ethtool(vsi, cmd, true);
|
|
|
break;
|
|
|
case ETHTOOL_SRXCLSRLDEL:
|
|
|
- ret = i40e_add_del_fdir_ethtool(vsi, cmd, false);
|
|
|
+ ret = i40e_del_fdir_entry(vsi, cmd);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|