linux/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c

// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2018-2023, Intel Corporation. */

/* flow director ethtool support for ice */

#include "ice.h"
#include "ice_lib.h"
#include "ice_fdir.h"
#include "ice_flow.h"

static struct in6_addr full_ipv6_addr_mask =;

static struct in6_addr zero_ipv6_addr_mask =;

/* calls to ice_flow_add_prof require the number of segments in the array
 * for segs_cnt. In this code that is one more than the index.
 */
#define TNL_SEG_CNT(_TNL_)

/**
 * 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)
{}

/**
 * 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)
{}

/**
 * ice_is_mask_valid - check mask field set
 * @mask: full mask to check
 * @field: field for which mask should be valid
 *
 * If the mask is fully set return true. If it is not valid for field return
 * false.
 */
static bool ice_is_mask_valid(u64 mask, u64 field)
{}

/**
 * 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)
{}

/**
 * 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)
{}

/**
 * ice_fdir_remap_entries - update the FDir entries in profile
 * @prof: FDir structure pointer
 * @tun: tunneled or non-tunneled packet
 * @idx: FDir entry index
 */
static void
ice_fdir_remap_entries(struct ice_fd_hw_prof *prof, int tun, int idx)
{}

/**
 * ice_fdir_rem_adq_chnl - remove an ADQ channel from HW filter rules
 * @hw: hardware structure containing filter list
 * @vsi_idx: VSI handle
 */
void ice_fdir_rem_adq_chnl(struct ice_hw *hw, u16 vsi_idx)
{}

/**
 * ice_fdir_get_hw_prof - return the ice_fd_hw_proc associated with a flow
 * @hw: hardware structure containing the filter list
 * @blk: hardware block
 * @flow: FDir flow type to release
 */
static struct ice_fd_hw_prof *
ice_fdir_get_hw_prof(struct ice_hw *hw, enum ice_block blk, int flow)
{}

/**
 * ice_fdir_erase_flow_from_hw - remove a flow from the HW profile tables
 * @hw: hardware structure containing the filter list
 * @blk: hardware block
 * @flow: FDir flow type to release
 */
static void
ice_fdir_erase_flow_from_hw(struct ice_hw *hw, enum ice_block blk, int flow)
{}

/**
 * ice_fdir_rem_flow - release the ice_flow structures for a filter type
 * @hw: hardware structure containing the filter list
 * @blk: hardware block
 * @flow_type: FDir flow type to release
 */
static void
ice_fdir_rem_flow(struct ice_hw *hw, enum ice_block blk,
		  enum ice_fltr_ptype flow_type)
{}

/**
 * ice_fdir_release_flows - release all flows in use for later replay
 * @hw: pointer to HW instance
 */
void ice_fdir_release_flows(struct ice_hw *hw)
{}

/**
 * ice_fdir_replay_flows - replay HW Flow Director filter info
 * @hw: pointer to HW instance
 */
void ice_fdir_replay_flows(struct ice_hw *hw)
{}

/**
 * ice_parse_rx_flow_user_data - deconstruct user-defined data
 * @fsp: pointer to ethtool Rx flow specification
 * @data: pointer to userdef data structure for storage
 *
 * Returns 0 on success, negative error value on failure
 */
static int
ice_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,
			    struct ice_rx_flow_userdef *data)
{}

/**
 * ice_fdir_num_avail_fltr - return the number of unused flow director filters
 * @hw: pointer to hardware structure
 * @vsi: software VSI structure
 *
 * There are 2 filter pools: guaranteed and best effort(shared). Each VSI can
 * use filters from either pool. The guaranteed pool is divided between VSIs.
 * The best effort filter pool is common to all VSIs and is a device shared
 * resource pool. The number of filters available to this VSI is the sum of
 * the VSIs guaranteed filter pool and the global available best effort
 * filter pool.
 *
 * Returns the number of available flow director filters to this VSI
 */
int ice_fdir_num_avail_fltr(struct ice_hw *hw, struct ice_vsi *vsi)
{}

/**
 * ice_fdir_alloc_flow_prof - allocate FDir flow profile structure(s)
 * @hw: HW structure containing the FDir flow profile structure(s)
 * @flow: flow type to allocate the flow profile for
 *
 * Allocate the fdir_prof and fdir_prof[flow] if not already created. Return 0
 * on success and negative on error.
 */
static int
ice_fdir_alloc_flow_prof(struct ice_hw *hw, enum ice_fltr_ptype flow)
{}

/**
 * ice_fdir_prof_vsi_idx - find or insert a vsi_idx in structure
 * @prof: pointer to flow director HW profile
 * @vsi_idx: vsi_idx to locate
 *
 * return the index of the vsi_idx. if vsi_idx is not found insert it
 * into the vsi_h table.
 */
static u16
ice_fdir_prof_vsi_idx(struct ice_fd_hw_prof *prof, int vsi_idx)
{}

/**
 * ice_fdir_set_hw_fltr_rule - Configure HW tables to generate a FDir rule
 * @pf: pointer to the PF structure
 * @seg: protocol header description pointer
 * @flow: filter enum
 * @tun: FDir segment to program
 */
static int
ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,
			  enum ice_fltr_ptype flow, enum ice_fd_hw_seg tun)
{}

/**
 * ice_set_init_fdir_seg
 * @seg: flow segment for programming
 * @l3_proto: ICE_FLOW_SEG_HDR_IPV4 or ICE_FLOW_SEG_HDR_IPV6
 * @l4_proto: ICE_FLOW_SEG_HDR_TCP or ICE_FLOW_SEG_HDR_UDP
 *
 * Set the configuration for perfect filters to the provided flow segment for
 * programming the HW filter. This is to be called only when initializing
 * filters as this function it assumes no filters exist.
 */
static int
ice_set_init_fdir_seg(struct ice_flow_seg_info *seg,
		      enum ice_flow_seg_hdr l3_proto,
		      enum ice_flow_seg_hdr l4_proto)
{}

/**
 * ice_create_init_fdir_rule
 * @pf: PF structure
 * @flow: filter enum
 *
 * Return error value or 0 on success.
 */
static int
ice_create_init_fdir_rule(struct ice_pf *pf, enum ice_fltr_ptype flow)
{}

/**
 * ice_set_fdir_ip4_seg
 * @seg: flow segment for programming
 * @tcp_ip4_spec: mask data from ethtool
 * @l4_proto: Layer 4 protocol to program
 * @perfect_fltr: only valid on success; returns true if perfect filter,
 *		  false if not
 *
 * Set the mask data into the flow segment to be used to program HW
 * table based on provided L4 protocol for IPv4
 */
static int
ice_set_fdir_ip4_seg(struct ice_flow_seg_info *seg,
		     struct ethtool_tcpip4_spec *tcp_ip4_spec,
		     enum ice_flow_seg_hdr l4_proto, bool *perfect_fltr)
{}

/**
 * ice_set_fdir_ip4_usr_seg
 * @seg: flow segment for programming
 * @usr_ip4_spec: ethtool userdef packet offset
 * @perfect_fltr: only valid on success; returns true if perfect filter,
 *		  false if not
 *
 * Set the offset data into the flow segment to be used to program HW
 * table for IPv4
 */
static int
ice_set_fdir_ip4_usr_seg(struct ice_flow_seg_info *seg,
			 struct ethtool_usrip4_spec *usr_ip4_spec,
			 bool *perfect_fltr)
{}

/**
 * ice_set_fdir_ip6_seg
 * @seg: flow segment for programming
 * @tcp_ip6_spec: mask data from ethtool
 * @l4_proto: Layer 4 protocol to program
 * @perfect_fltr: only valid on success; returns true if perfect filter,
 *		  false if not
 *
 * Set the mask data into the flow segment to be used to program HW
 * table based on provided L4 protocol for IPv6
 */
static int
ice_set_fdir_ip6_seg(struct ice_flow_seg_info *seg,
		     struct ethtool_tcpip6_spec *tcp_ip6_spec,
		     enum ice_flow_seg_hdr l4_proto, bool *perfect_fltr)
{}

/**
 * ice_set_fdir_ip6_usr_seg
 * @seg: flow segment for programming
 * @usr_ip6_spec: ethtool userdef packet offset
 * @perfect_fltr: only valid on success; returns true if perfect filter,
 *		  false if not
 *
 * Set the offset data into the flow segment to be used to program HW
 * table for IPv6
 */
static int
ice_set_fdir_ip6_usr_seg(struct ice_flow_seg_info *seg,
			 struct ethtool_usrip6_spec *usr_ip6_spec,
			 bool *perfect_fltr)
{}

/**
 * ice_fdir_vlan_valid - validate VLAN data for Flow Director rule
 * @dev: network interface device structure
 * @fsp: pointer to ethtool Rx flow specification
 *
 * Return: true if vlan data is valid, false otherwise
 */
static bool ice_fdir_vlan_valid(struct device *dev,
				struct ethtool_rx_flow_spec *fsp)
{}

/**
 * ice_set_ether_flow_seg - set address and protocol segments for ether flow
 * @dev: network interface device structure
 * @seg: flow segment for programming
 * @eth_spec: mask data from ethtool
 *
 * Return: 0 on success and errno in case of error.
 */
static int ice_set_ether_flow_seg(struct device *dev,
				  struct ice_flow_seg_info *seg,
				  struct ethhdr *eth_spec)
{}

/**
 * ice_set_fdir_vlan_seg - set vlan segments for ether flow
 * @seg: flow segment for programming
 * @ext_masks: masks for additional RX flow fields
 *
 * Return: 0 on success and errno in case of error.
 */
static int
ice_set_fdir_vlan_seg(struct ice_flow_seg_info *seg,
		      struct ethtool_flow_ext *ext_masks)
{}

/**
 * ice_cfg_fdir_xtrct_seq - Configure extraction sequence for the given filter
 * @pf: PF structure
 * @fsp: pointer to ethtool Rx flow specification
 * @user: user defined data from flow specification
 *
 * Returns 0 on success.
 */
static int
ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
		       struct ice_rx_flow_userdef *user)
{}

/**
 * ice_update_per_q_fltr
 * @vsi: ptr to VSI
 * @q_index: queue index
 * @inc: true to increment or false to decrement per queue filter count
 *
 * This function is used to keep track of per queue sideband filters
 */
static void ice_update_per_q_fltr(struct ice_vsi *vsi, u32 q_index, bool inc)
{}

/**
 * ice_fdir_write_fltr - send a flow director filter to the hardware
 * @pf: PF data structure
 * @input: filter structure
 * @add: true adds filter and false removed filter
 * @is_tun: true adds inner filter on tunnel and false outer headers
 *
 * returns 0 on success and negative value on error
 */
int
ice_fdir_write_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, bool add,
		    bool is_tun)
{}

/**
 * ice_fdir_write_all_fltr - send a flow director filter to the hardware
 * @pf: PF data structure
 * @input: filter structure
 * @add: true adds filter and false removed filter
 *
 * returns 0 on success and negative value on error
 */
static int
ice_fdir_write_all_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input,
			bool add)
{}

/**
 * ice_fdir_replay_fltrs - replay filters from the HW filter list
 * @pf: board private structure
 */
void ice_fdir_replay_fltrs(struct ice_pf *pf)
{}

/**
 * ice_fdir_create_dflt_rules - create default perfect filters
 * @pf: PF data structure
 *
 * Returns 0 for success or error.
 */
int ice_fdir_create_dflt_rules(struct ice_pf *pf)
{}

/**
 * ice_fdir_del_all_fltrs - Delete all flow director filters
 * @vsi: the VSI being changed
 *
 * This function needs to be called while holding hw->fdir_fltr_lock
 */
void ice_fdir_del_all_fltrs(struct ice_vsi *vsi)
{}

/**
 * ice_vsi_manage_fdir - turn on/off flow director
 * @vsi: the VSI being changed
 * @ena: boolean value indicating if this is an enable or disable request
 */
void ice_vsi_manage_fdir(struct ice_vsi *vsi, bool ena)
{}

/**
 * ice_fdir_do_rem_flow - delete flow and possibly add perfect flow
 * @pf: PF structure
 * @flow_type: FDir flow type to release
 */
static void
ice_fdir_do_rem_flow(struct ice_pf *pf, enum ice_fltr_ptype flow_type)
{}

/**
 * ice_fdir_update_list_entry - add or delete a filter from the filter list
 * @pf: PF structure
 * @input: filter structure
 * @fltr_idx: ethtool index of filter to modify
 *
 * returns 0 on success and negative on errors
 */
static int
ice_fdir_update_list_entry(struct ice_pf *pf, struct ice_fdir_fltr *input,
			   int fltr_idx)
{}

/**
 * ice_del_fdir_ethtool - delete Flow Director filter
 * @vsi: pointer to target VSI
 * @cmd: command to add or delete Flow Director filter
 *
 * Returns 0 on success and negative values for failure
 */
int ice_del_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
{}

/**
 * ice_update_ring_dest_vsi - update dest ring and dest VSI
 * @vsi: pointer to target VSI
 * @dest_vsi: ptr to dest VSI index
 * @ring: ptr to dest ring
 *
 * This function updates destination VSI and queue if user specifies
 * target queue which falls in channel's (aka ADQ) queue region
 */
static void
ice_update_ring_dest_vsi(struct ice_vsi *vsi, u16 *dest_vsi, u32 *ring)
{}

/**
 * ice_set_fdir_input_set - Set the input set for Flow Director
 * @vsi: pointer to target VSI
 * @fsp: pointer to ethtool Rx flow specification
 * @input: filter structure
 */
static int
ice_set_fdir_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,
		       struct ice_fdir_fltr *input)
{}

/**
 * ice_add_fdir_ethtool - Add/Remove Flow Director filter
 * @vsi: pointer to target VSI
 * @cmd: command to add or delete Flow Director filter
 *
 * Returns 0 on success and negative values for failure
 */
int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
{}