Commit fd2a6b71 authored by Dan Nowlin's avatar Dan Nowlin Committed by Tony Nguyen

ice: create advanced switch recipe

These changes introduce code for creating advanced recipes for the
switch in hardware.

There are a couple of recipes already defined in the HW. They apply to
matching on basic protocol headers, like MAC, VLAN, MACVLAN,
ethertype or direction (promiscuous), etc.. If the user wants to match on
other protocol headers (eg. ip address, src/dst port etc.) or different
variation of already supported protocols, there is a need to create
new, more complex recipe. That new recipe is referred as
'advanced recipe', and the filtering rule created on top of that recipe
is called 'advanced rule'.

One recipe can have up to 5 words, but the first word is always reserved
for match on switch id, so the driver can define up to 4 words for one
recipe. To support recipes with more words up to 5 recipes can be
chained, so 20 words can be programmed for look up.

Input for adding recipe function is a list of protocols to support. Based
on this list correct profile is being chosen. Correct profile means
that it contains all protocol types from a list. Each profile have up to
48 field vector words and each of this word have protocol id and offset.
These two fields need to match with input data for adding recipe
function. If the correct profile can't be found the function returns an
error.

The next step after finding the correct profile is grouping words into
groups. One group can have up to 4 words. This is done to simplify
sending recipes to HW (because recipe also can have up to 4 words).

In case of chaining (so when look up consists of more than 4 words) last
recipe will always have results from the previous recipes used as words.

A recipe to profile map is used to store information about which profile
is associate with this recipe. This map is an array of 64 elements (max
number of recipes) and each element is a 256 bits bitmap (max number of
profiles)

Profile to recipe map is used to store information about which recipe is
associate with this profile. This map is an array of 256 elements (max
number of profiles) and each element is a 64 bits bitmap (max number of
recipes)
Signed-off-by: default avatarDan Nowlin <dan.nowlin@intel.com>
Signed-off-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Tested-by: default avatarSandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 450052a4
......@@ -735,7 +735,7 @@ static void ice_release_global_cfg_lock(struct ice_hw *hw)
*
* This function will request ownership of the change lock.
*/
static enum ice_status
enum ice_status
ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access)
{
return ice_acquire_res(hw, ICE_CHANGE_LOCK_RES_ID, access,
......@@ -748,7 +748,7 @@ ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access)
*
* This function will release the change lock using the proper Admin Command.
*/
static void ice_release_change_lock(struct ice_hw *hw)
void ice_release_change_lock(struct ice_hw *hw)
{
ice_release_res(hw, ICE_CHANGE_LOCK_RES_ID);
}
......@@ -2105,6 +2105,35 @@ int ice_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table,
return 0;
}
/**
* ice_find_prot_off - find prot ID and offset pair, based on prof and FV index
* @hw: pointer to the hardware structure
* @blk: hardware block
* @prof: profile ID
* @fv_idx: field vector word index
* @prot: variable to receive the protocol ID
* @off: variable to receive the protocol offset
*/
enum ice_status
ice_find_prot_off(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 fv_idx,
u8 *prot, u16 *off)
{
struct ice_fv_word *fv_ext;
if (prof >= hw->blk[blk].es.count)
return ICE_ERR_PARAM;
if (fv_idx >= hw->blk[blk].es.fvw)
return ICE_ERR_PARAM;
fv_ext = hw->blk[blk].es.t + (prof * hw->blk[blk].es.fvw);
*prot = fv_ext[fv_idx].prot_id;
*off = fv_ext[fv_idx].off;
return 0;
}
/* PTG Management */
/**
......
......@@ -18,6 +18,12 @@
#define ICE_PKG_CNT 4
enum ice_status
ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access);
void ice_release_change_lock(struct ice_hw *hw);
enum ice_status
ice_find_prot_off(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 fv_idx,
u8 *prot, u16 *off);
void
ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type type,
unsigned long *bm);
......
......@@ -3,6 +3,44 @@
#ifndef _ICE_PROTOCOL_TYPE_H_
#define _ICE_PROTOCOL_TYPE_H_
#define ICE_IPV6_ADDR_LENGTH 16
/* Each recipe can match up to 5 different fields. Fields to match can be meta-
* data, values extracted from packet headers, or results from other recipes.
* One of the 5 fields is reserved for matching the switch ID. So, up to 4
* recipes can provide intermediate results to another one through chaining,
* e.g. recipes 0, 1, 2, and 3 can provide intermediate results to recipe 4.
*/
#define ICE_NUM_WORDS_RECIPE 4
/* Max recipes that can be chained */
#define ICE_MAX_CHAIN_RECIPE 5
/* 1 word reserved for switch ID from allowed 5 words.
* So a recipe can have max 4 words. And you can chain 5 such recipes
* together. So maximum words that can be programmed for look up is 5 * 4.
*/
#define ICE_MAX_CHAIN_WORDS (ICE_NUM_WORDS_RECIPE * ICE_MAX_CHAIN_RECIPE)
/* Field vector index corresponding to chaining */
#define ICE_CHAIN_FV_INDEX_START 47
enum ice_protocol_type {
ICE_MAC_OFOS = 0,
ICE_MAC_IL,
ICE_ETYPE_OL,
ICE_VLAN_OFOS,
ICE_IPV4_OFOS,
ICE_IPV4_IL,
ICE_IPV6_OFOS,
ICE_IPV6_IL,
ICE_TCP_IL,
ICE_UDP_OF,
ICE_UDP_ILOS,
ICE_SCTP_IL,
ICE_PROTOCOL_LAST
};
/* Decoders for ice_prot_id:
* - F: First
* - I: Inner
......@@ -35,4 +73,135 @@ enum ice_prot_id {
ICE_PROT_META_ID = 255, /* when offset == metadata */
ICE_PROT_INVALID = 255 /* when offset == ICE_FV_OFFSET_INVAL */
};
#define ICE_MAC_OFOS_HW 1
#define ICE_MAC_IL_HW 4
#define ICE_ETYPE_OL_HW 9
#define ICE_VLAN_OF_HW 16
#define ICE_VLAN_OL_HW 17
#define ICE_IPV4_OFOS_HW 32
#define ICE_IPV4_IL_HW 33
#define ICE_IPV6_OFOS_HW 40
#define ICE_IPV6_IL_HW 41
#define ICE_TCP_IL_HW 49
#define ICE_UDP_ILOS_HW 53
#define ICE_UDP_OF_HW 52 /* UDP Tunnels */
#define ICE_TUN_FLAG_FV_IND 2
/* Mapping of software defined protocol ID to hardware defined protocol ID */
struct ice_protocol_entry {
enum ice_protocol_type type;
u8 protocol_id;
};
struct ice_ether_hdr {
u8 dst_addr[ETH_ALEN];
u8 src_addr[ETH_ALEN];
};
struct ice_ethtype_hdr {
__be16 ethtype_id;
};
struct ice_ether_vlan_hdr {
u8 dst_addr[ETH_ALEN];
u8 src_addr[ETH_ALEN];
__be32 vlan_id;
};
struct ice_vlan_hdr {
__be16 type;
__be16 vlan;
};
struct ice_ipv4_hdr {
u8 version;
u8 tos;
__be16 total_length;
__be16 id;
__be16 frag_off;
u8 time_to_live;
u8 protocol;
__be16 check;
__be32 src_addr;
__be32 dst_addr;
};
struct ice_ipv6_hdr {
__be32 be_ver_tc_flow;
__be16 payload_len;
u8 next_hdr;
u8 hop_limit;
u8 src_addr[ICE_IPV6_ADDR_LENGTH];
u8 dst_addr[ICE_IPV6_ADDR_LENGTH];
};
struct ice_sctp_hdr {
__be16 src_port;
__be16 dst_port;
__be32 verification_tag;
__be32 check;
};
struct ice_l4_hdr {
__be16 src_port;
__be16 dst_port;
__be16 len;
__be16 check;
};
union ice_prot_hdr {
struct ice_ether_hdr eth_hdr;
struct ice_ethtype_hdr ethertype;
struct ice_vlan_hdr vlan_hdr;
struct ice_ipv4_hdr ipv4_hdr;
struct ice_ipv6_hdr ipv6_hdr;
struct ice_l4_hdr l4_hdr;
struct ice_sctp_hdr sctp_hdr;
};
/* This is mapping table entry that maps every word within a given protocol
* structure to the real byte offset as per the specification of that
* protocol header.
* for e.g. dst address is 3 words in ethertype header and corresponding bytes
* are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
*/
struct ice_prot_ext_tbl_entry {
enum ice_protocol_type prot_type;
/* Byte offset into header of given protocol type */
u8 offs[sizeof(union ice_prot_hdr)];
};
/* Extractions to be looked up for a given recipe */
struct ice_prot_lkup_ext {
u16 prot_type;
u8 n_val_words;
/* create a buffer to hold max words per recipe */
u16 field_off[ICE_MAX_CHAIN_WORDS];
u16 field_mask[ICE_MAX_CHAIN_WORDS];
struct ice_fv_word fv_words[ICE_MAX_CHAIN_WORDS];
/* Indicate field offsets that have field vector indices assigned */
DECLARE_BITMAP(done, ICE_MAX_CHAIN_WORDS);
};
struct ice_pref_recipe_group {
u8 n_val_pairs; /* Number of valid pairs */
struct ice_fv_word pairs[ICE_NUM_WORDS_RECIPE];
u16 mask[ICE_NUM_WORDS_RECIPE];
};
struct ice_recp_grp_entry {
struct list_head l_entry;
#define ICE_INVAL_CHAIN_IND 0xFF
u16 rid;
u8 chain_idx;
u16 fv_idx[ICE_NUM_WORDS_RECIPE];
u16 fv_mask[ICE_NUM_WORDS_RECIPE];
struct ice_pref_recipe_group r_group;
};
#endif /* _ICE_PROTOCOL_TYPE_H_ */
This diff is collapsed.
......@@ -125,30 +125,110 @@ struct ice_fltr_info {
u8 lan_en; /* Indicate if packet can be forwarded to the uplink */
};
struct ice_adv_lkup_elem {
enum ice_protocol_type type;
union ice_prot_hdr h_u; /* Header values */
union ice_prot_hdr m_u; /* Mask of header values to match */
};
struct ice_sw_act_ctrl {
/* Source VSI for LOOKUP_TX or source port for LOOKUP_RX */
u16 src;
u16 flag;
enum ice_sw_fwd_act_type fltr_act;
/* Depending on filter action */
union {
/* This is a queue ID in case of ICE_FWD_TO_Q and starting
* queue ID in case of ICE_FWD_TO_QGRP.
*/
u16 q_id:11;
u16 vsi_id:10;
u16 hw_vsi_id:10;
u16 vsi_list_id:10;
} fwd_id;
/* software VSI handle */
u16 vsi_handle;
u8 qgrp_size;
};
struct ice_rule_query_data {
/* Recipe ID for which the requested rule was added */
u16 rid;
/* Rule ID that was added or is supposed to be removed */
u16 rule_id;
/* vsi_handle for which Rule was added or is supposed to be removed */
u16 vsi_handle;
};
struct ice_adv_rule_info {
struct ice_sw_act_ctrl sw_act;
u32 priority;
u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */
u16 fltr_rule_id;
};
/* A collection of one or more four word recipe */
struct ice_sw_recipe {
struct list_head l_entry;
/* For a chained recipe the root recipe is what should be used for
* programming rules
*/
u8 is_root;
u8 root_rid;
u8 recp_created;
/* To protect modification of filt_rule list
* defined below
/* Number of extraction words */
u8 n_ext_words;
/* Protocol ID and Offset pair (extraction word) to describe the
* recipe
*/
struct mutex filt_rule_lock;
struct ice_fv_word ext_words[ICE_MAX_CHAIN_WORDS];
u16 word_masks[ICE_MAX_CHAIN_WORDS];
/* if this recipe is a collection of other recipe */
u8 big_recp;
/* if this recipe is part of another bigger recipe then chain index
* corresponding to this recipe
*/
u8 chain_idx;
/* if this recipe is a collection of other recipe then count of other
* recipes and recipe IDs of those recipes
*/
u8 n_grp_count;
/* Bit map specifying the IDs associated with this group of recipe */
DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
/* List of type ice_fltr_mgmt_list_entry */
/* List of type ice_fltr_mgmt_list_entry or adv_rule */
u8 adv_rule;
struct list_head filt_rules;
struct list_head filt_replay_rules;
/* linked list of type recipe_list_entry */
struct list_head rg_list;
/* linked list of type ice_sw_fv_list_entry*/
struct mutex filt_rule_lock; /* protect filter rule structure */
/* Profiles this recipe should be associated with */
struct list_head fv_list;
struct ice_aqc_recipe_data_elem *r_buf;
u8 recp_count;
u8 root_rid;
u8 num_profs;
u8 *prof_ids;
/* recipe bitmap: what all recipes makes this recipe */
DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
/* Profiles this recipe is associated with */
u8 num_profs, *prof_ids;
/* Bit map for possible result indexes */
DECLARE_BITMAP(res_idxs, ICE_MAX_FV_WORDS);
/* This allows user to specify the recipe priority.
* For now, this becomes 'fwd_priority' when recipe
* is created, usually recipes can have 'fwd' and 'join'
* priority.
*/
u8 priority;
struct list_head rg_list;
/* AQ buffer associated with this recipe */
struct ice_aqc_recipe_data_elem *root_buf;
/* This struct saves the fv_words for a given lookup */
struct ice_prot_lkup_ext lkup_exts;
};
/* Bookkeeping structure to hold bitmap of VSIs corresponding to VSI list ID */
......
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