Commit 4ab95646 authored by Henry Tieman's avatar Henry Tieman Committed by Jeff Kirsher

ice: Support displaying ntuple rules

Add functionality for ethtool --show-ntuple, allowing for filters to be
displayed when set functionality is added. Add statistics related to
Flow Director matches and status.
Signed-off-by: default avatarHenry Tieman <henry.w.tieman@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 148beb61
......@@ -525,6 +525,11 @@ static inline struct ice_vsi *ice_get_ctrl_vsi(struct ice_pf *pf)
return pf->vsi[pf->ctrl_vsi_idx];
}
#define ICE_FD_STAT_CTR_BLOCK_COUNT 256
#define ICE_FD_STAT_PF_IDX(base_idx) \
((base_idx) * ICE_FD_STAT_CTR_BLOCK_COUNT)
#define ICE_FD_SB_STAT_IDX(base_idx) ICE_FD_STAT_PF_IDX(base_idx)
int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);
int ice_vsi_setup_rx_rings(struct ice_vsi *vsi);
int ice_vsi_open_ctrl(struct ice_vsi *vsi);
......@@ -552,6 +557,10 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup);
const char *ice_stat_str(enum ice_status stat_err);
const char *ice_aq_str(enum ice_aq_err aq_err);
void ice_vsi_manage_fdir(struct ice_vsi *vsi, bool ena);
int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd);
int
ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,
u32 *rule_locs);
void ice_fdir_release_flows(struct ice_hw *hw);
int ice_fdir_create_dflt_rules(struct ice_pf *pf);
int ice_open(struct net_device *netdev);
......
......@@ -130,6 +130,8 @@ static const struct ice_stats ice_gstrings_pf_stats[] = {
ICE_PF_STAT("illegal_bytes.nic", stats.illegal_bytes),
ICE_PF_STAT("mac_local_faults.nic", stats.mac_local_faults),
ICE_PF_STAT("mac_remote_faults.nic", stats.mac_remote_faults),
ICE_PF_STAT("fdir_sb_match.nic", stats.fd_sb_match),
ICE_PF_STAT("fdir_sb_status.nic", stats.fd_sb_status),
};
static const u32 ice_regs_dump_list[] = {
......@@ -2558,12 +2560,27 @@ ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
int ret = -EOPNOTSUPP;
struct ice_hw *hw;
hw = &vsi->back->hw;
switch (cmd->cmd) {
case ETHTOOL_GRXRINGS:
cmd->data = vsi->rss_size;
ret = 0;
break;
case ETHTOOL_GRXCLSRLCNT:
cmd->rule_cnt = hw->fdir_active_fltr;
/* report total rule count */
cmd->data = ice_get_fdir_cnt_all(hw);
ret = 0;
break;
case ETHTOOL_GRXCLSRULE:
ret = ice_get_ethtool_fdir_entry(hw, cmd);
break;
case ETHTOOL_GRXCLSRLALL:
ret = ice_get_fdir_fltr_ids(hw, cmd, (u32 *)rule_locs);
break;
case ETHTOOL_GRXFH:
ice_get_rss_hash_opt(vsi, cmd);
ret = 0;
......
......@@ -12,6 +12,167 @@
*/
#define TNL_SEG_CNT(_TNL_) ((_TNL_) + 1)
/**
* ice_fltr_to_ethtool_flow - convert filter type values to ethtool
* flow type values
* @flow: filter type to be converted
*
* Returns the corresponding ethtool flow type.
*/
static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow)
{
switch (flow) {
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
return TCP_V4_FLOW;
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
return UDP_V4_FLOW;
case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
return SCTP_V4_FLOW;
case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
return IPV4_USER_FLOW;
default:
/* 0 is undefined ethtool flow */
return 0;
}
}
/**
* ice_ethtool_flow_to_fltr - convert ethtool flow type to filter enum
* @eth: Ethtool flow type to be converted
*
* Returns flow enum
*/
static enum ice_fltr_ptype ice_ethtool_flow_to_fltr(int eth)
{
switch (eth) {
case TCP_V4_FLOW:
return ICE_FLTR_PTYPE_NONF_IPV4_TCP;
case UDP_V4_FLOW:
return ICE_FLTR_PTYPE_NONF_IPV4_UDP;
case SCTP_V4_FLOW:
return ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
case IPV4_USER_FLOW:
return ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
default:
return ICE_FLTR_PTYPE_NONF_NONE;
}
}
/**
* ice_get_ethtool_fdir_entry - fill ethtool structure with fdir filter data
* @hw: hardware structure that contains filter list
* @cmd: ethtool command data structure to receive the filter data
*
* Returns 0 on success and -EINVAL on failure
*/
int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd)
{
struct ethtool_rx_flow_spec *fsp;
struct ice_fdir_fltr *rule;
int ret = 0;
u16 idx;
fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
mutex_lock(&hw->fdir_fltr_lock);
rule = ice_fdir_find_fltr_by_idx(hw, fsp->location);
if (!rule || fsp->location != rule->fltr_id) {
ret = -EINVAL;
goto release_lock;
}
fsp->flow_type = ice_fltr_to_ethtool_flow(rule->flow_type);
memset(&fsp->m_u, 0, sizeof(fsp->m_u));
memset(&fsp->m_ext, 0, sizeof(fsp->m_ext));
switch (fsp->flow_type) {
case IPV4_USER_FLOW:
fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
fsp->h_u.usr_ip4_spec.proto = 0;
fsp->h_u.usr_ip4_spec.l4_4_bytes = rule->ip.l4_header;
fsp->h_u.usr_ip4_spec.tos = rule->ip.tos;
fsp->h_u.usr_ip4_spec.ip4src = rule->ip.src_ip;
fsp->h_u.usr_ip4_spec.ip4dst = rule->ip.dst_ip;
fsp->m_u.usr_ip4_spec.ip4src = rule->mask.src_ip;
fsp->m_u.usr_ip4_spec.ip4dst = rule->mask.dst_ip;
fsp->m_u.usr_ip4_spec.ip_ver = 0xFF;
fsp->m_u.usr_ip4_spec.proto = 0;
fsp->m_u.usr_ip4_spec.l4_4_bytes = rule->mask.l4_header;
fsp->m_u.usr_ip4_spec.tos = rule->mask.tos;
break;
case TCP_V4_FLOW:
case UDP_V4_FLOW:
case SCTP_V4_FLOW:
fsp->h_u.tcp_ip4_spec.psrc = rule->ip.src_port;
fsp->h_u.tcp_ip4_spec.pdst = rule->ip.dst_port;
fsp->h_u.tcp_ip4_spec.ip4src = rule->ip.src_ip;
fsp->h_u.tcp_ip4_spec.ip4dst = rule->ip.dst_ip;
fsp->m_u.tcp_ip4_spec.psrc = rule->mask.src_port;
fsp->m_u.tcp_ip4_spec.pdst = rule->mask.dst_port;
fsp->m_u.tcp_ip4_spec.ip4src = rule->mask.src_ip;
fsp->m_u.tcp_ip4_spec.ip4dst = rule->mask.dst_ip;
break;
default:
break;
}
if (rule->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT)
fsp->ring_cookie = RX_CLS_FLOW_DISC;
else
fsp->ring_cookie = rule->q_index;
idx = ice_ethtool_flow_to_fltr(fsp->flow_type);
if (idx == ICE_FLTR_PTYPE_NONF_NONE) {
dev_err(ice_hw_to_dev(hw), "Missing input index for flow_type %d\n",
rule->flow_type);
ret = -EINVAL;
}
release_lock:
mutex_unlock(&hw->fdir_fltr_lock);
return ret;
}
/**
* ice_get_fdir_fltr_ids - fill buffer with filter IDs of active filters
* @hw: hardware structure containing the filter list
* @cmd: ethtool command data structure
* @rule_locs: ethtool array passed in from OS to receive filter IDs
*
* Returns 0 as expected for success by ethtool
*/
int
ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct ice_fdir_fltr *f_rule;
unsigned int cnt = 0;
int val = 0;
/* report total rule count */
cmd->data = ice_get_fdir_cnt_all(hw);
mutex_lock(&hw->fdir_fltr_lock);
list_for_each_entry(f_rule, &hw->fdir_list_head, fltr_node) {
if (cnt == cmd->rule_cnt) {
val = -EMSGSIZE;
goto release_lock;
}
rule_locs[cnt] = f_rule->fltr_id;
cnt++;
}
release_lock:
mutex_unlock(&hw->fdir_fltr_lock);
if (!val)
cmd->rule_cnt = cnt;
return val;
}
/**
* ice_fdir_get_hw_prof - return the ice_fd_hw_proc associated with a flow
* @hw: hardware structure containing the filter list
......
......@@ -52,3 +52,36 @@ ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
cntr_id);
}
/**
* ice_get_fdir_cnt_all - get the number of Flow Director filters
* @hw: hardware data structure
*
* Returns the number of filters available on device
*/
int ice_get_fdir_cnt_all(struct ice_hw *hw)
{
return hw->func_caps.fd_fltr_guar + hw->func_caps.fd_fltr_best_effort;
}
/**
* ice_fdir_find_by_idx - find filter with idx
* @hw: pointer to hardware structure
* @fltr_idx: index to find.
*
* Returns pointer to filter if found or null
*/
struct ice_fdir_fltr *
ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
{
struct ice_fdir_fltr *rule;
list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
/* rule ID found in the list */
if (fltr_idx == rule->fltr_id)
return rule;
if (fltr_idx < rule->fltr_id)
break;
}
return NULL;
}
......@@ -3,10 +3,57 @@
#ifndef _ICE_FDIR_H_
#define _ICE_FDIR_H_
enum ice_fltr_prgm_desc_dest {
ICE_FLTR_PRGM_DESC_DEST_DROP_PKT,
ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX,
};
struct ice_fdir_v4 {
__be32 dst_ip;
__be32 src_ip;
__be16 dst_port;
__be16 src_port;
__be32 l4_header;
__be32 sec_parm_idx; /* security parameter index */
u8 tos;
u8 ip_ver;
u8 proto;
};
struct ice_fdir_extra {
u8 dst_mac[ETH_ALEN]; /* dest MAC address */
u32 usr_def[2]; /* user data */
__be16 vlan_type; /* VLAN ethertype */
__be16 vlan_tag; /* VLAN tag info */
};
struct ice_fdir_fltr {
struct list_head fltr_node;
enum ice_fltr_ptype flow_type;
struct ice_fdir_v4 ip;
struct ice_fdir_v4 mask;
struct ice_fdir_extra ext_data;
struct ice_fdir_extra ext_mask;
/* filter control */
u16 q_index;
u16 dest_vsi;
u8 dest_ctl;
u8 fltr_status;
u16 cnt_index;
u32 fltr_id;
};
enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id);
enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id);
enum ice_status
ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr);
enum ice_status
ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr);
int ice_get_fdir_cnt_all(struct ice_hw *hw);
struct ice_fdir_fltr *
ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx);
#endif /* _ICE_FDIR_H_ */
......@@ -344,6 +344,7 @@
#define GLPRT_TDOLD(_i) (0x00381280 + ((_i) * 8))
#define GLPRT_UPRCL(_i) (0x00381300 + ((_i) * 8))
#define GLPRT_UPTCL(_i) (0x003811C0 + ((_i) * 8))
#define GLSTAT_FD_CNT0L(_i) (0x003A0000 + ((_i) * 8))
#define GLV_BPRCL(_i) (0x003B6000 + ((_i) * 8))
#define GLV_BPTCL(_i) (0x0030E000 + ((_i) * 8))
#define GLV_GORCL(_i) (0x003B0000 + ((_i) * 8))
......
......@@ -4281,6 +4281,7 @@ void ice_update_pf_stats(struct ice_pf *pf)
{
struct ice_hw_port_stats *prev_ps, *cur_ps;
struct ice_hw *hw = &pf->hw;
u16 fd_ctr_base;
u8 port;
port = hw->port_info->lport;
......@@ -4369,6 +4370,12 @@ void ice_update_pf_stats(struct ice_pf *pf)
ice_stat_update40(hw, GLPRT_PTC9522L(port), pf->stat_prev_loaded,
&prev_ps->tx_size_big, &cur_ps->tx_size_big);
fd_ctr_base = hw->fd_ctr_base;
ice_stat_update40(hw,
GLSTAT_FD_CNT0L(ICE_FD_SB_STAT_IDX(fd_ctr_base)),
pf->stat_prev_loaded, &prev_ps->fd_sb_match,
&cur_ps->fd_sb_match);
ice_stat_update32(hw, GLPRT_LXONRXC(port), pf->stat_prev_loaded,
&prev_ps->link_xon_rx, &cur_ps->link_xon_rx);
......@@ -4412,6 +4419,8 @@ void ice_update_pf_stats(struct ice_pf *pf)
ice_stat_update32(hw, GLPRT_RJC(port), pf->stat_prev_loaded,
&prev_ps->rx_jabber, &cur_ps->rx_jabber);
cur_ps->fd_sb_status = test_bit(ICE_FLAG_FD_ENA, pf->flags) ? 1 : 0;
pf->stat_prev_loaded = true;
}
......
......@@ -691,6 +691,9 @@ struct ice_hw_port_stats {
u64 tx_size_1023; /* ptc1023 */
u64 tx_size_1522; /* ptc1522 */
u64 tx_size_big; /* ptc9522 */
/* flow director stats */
u32 fd_sb_status;
u64 fd_sb_match;
};
/* Checksum and Shadow RAM pointers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment