#define ICE_FLOW_FLD_SZ_ICMP_CODE 1
#define ICE_FLOW_FLD_SZ_ARP_OPER 2
#define ICE_FLOW_FLD_SZ_GRE_KEYID 4
+#define ICE_FLOW_FLD_SZ_GTP_TEID 4
+#define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2
/* Protocol header fields are extracted at the word boundaries as word-sized
* values. Specify the displacement value of some non-word-aligned fields needed
enum ice_flow_seg_hdr hdr;
s16 off; /* Offset from start of a protocol header, in bits */
u16 size; /* Size of fields in bits */
+ u16 mask; /* 16-bit mask for field */
};
#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
.hdr = _hdr, \
- .off = _offset_bytes * BITS_PER_BYTE, \
- .size = _size_bytes * BITS_PER_BYTE, \
+ .off = (_offset_bytes) * BITS_PER_BYTE, \
+ .size = (_size_bytes) * BITS_PER_BYTE, \
+ .mask = 0, \
+}
+
+#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
+ .hdr = _hdr, \
+ .off = (_offset_bytes) * BITS_PER_BYTE, \
+ .size = (_size_bytes) * BITS_PER_BYTE, \
+ .mask = _mask, \
}
/* Table containing properties of supported protocol header fields */
/* GRE */
/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
+ /* GTP */
+ /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
+ ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
+ ICE_FLOW_FLD_SZ_GTP_TEID),
+ /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
+ ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
+ ICE_FLOW_FLD_SZ_GTP_TEID),
+ /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
+ ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
+ ICE_FLOW_FLD_SZ_GTP_TEID),
+ /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
+ ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
+ ICE_FLOW_FLD_SZ_GTP_TEID),
+ /* PPPOE */
+ /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
+ ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
+ ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
};
/* Bitmaps indicating relevant packet types for a particular protocol header
static const u32 ice_ptypes_mac_ofos[] = {
0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
- 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
+ 0x000B0F0F, 0x00003000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_ipv4_ofos[] = {
0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x0003000F, 0x00000000, 0x00000000, 0x00000000,
+ 0x0003000F, 0x000FC000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_ipv4_il[] = {
0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
0x0007700E, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x000FF800, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_ipv6_ofos[] = {
0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
- 0x00080F00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00080F00, 0x03F00000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_ipv6_il[] = {
0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
0x03B80770, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_udp_il[] = {
0x81000000, 0x20204040, 0x04081010, 0x80810102,
0x00204040, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00410000, 0x10842000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
/* Packet types for packets with an Innermost/Last TCP header */
static const u32 ice_ptypes_tcp_il[] = {
- 0x04000000, 0x80810102, 0x10204040, 0x42040408,
+ 0x04000000, 0x80810102, 0x10204040, 0x02040408,
0x00810102, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00820000, 0x21084000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_sctp_il[] = {
0x08000000, 0x01020204, 0x20408081, 0x04080810,
0x01020204, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x01040000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
static const u32 ice_ptypes_icmp_il[] = {
0x00000000, 0x02040408, 0x40810102, 0x08101020,
0x02040408, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x42108000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
+/* Packet types for GTPC */
+static const u32 ice_ptypes_gtpc[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000180, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Packet types for GTPC with TEID */
+static const u32 ice_ptypes_gtpc_tid[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000060, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Packet types for GTPU */
+static const u32 ice_ptypes_gtpu[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Packet types for pppoe */
+static const u32 ice_ptypes_pppoe[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
/* Manage parameters and info. used during the creation of a flow profile */
struct ice_flow_prof_params {
enum ice_block blk;
* This will give us the direction flags.
*/
struct ice_fv_word es[ICE_MAX_FV_WORDS];
-
+ u16 mask[ICE_MAX_FV_WORDS];
ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
};
-/**
- * ice_is_pow2 - check if integer value is a power of 2
- * @val: unsigned integer to be validated
- */
-static bool ice_is_pow2(u64 val)
-{
- return (val && !(val & (val - 1)));
-}
+#define ICE_FLOW_RSS_HDRS_INNER_MASK \
+ (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
+ ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
#define ICE_FLOW_SEG_HDRS_L2_MASK \
(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
#define ICE_FLOW_SEG_HDRS_L3_MASK \
- (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
+ (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
+ ICE_FLOW_SEG_HDR_ARP)
#define ICE_FLOW_SEG_HDRS_L4_MASK \
(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
ICE_FLOW_SEG_HDR_SCTP)
static enum ice_status
ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
{
- const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
- ICE_FLOW_SEG_HDRS_L3_MASK |
- ICE_FLOW_SEG_HDRS_L4_MASK);
u8 i;
for (i = 0; i < segs_cnt; i++) {
- /* No header specified */
- if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
- return ICE_ERR_PARAM;
-
/* Multiple L3 headers */
if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
!ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
(const ice_bitmap_t *)ice_ptypes_mac_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
}
if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
}
if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
ice_and_bitmap(params->ptypes, params->ptypes,
(const ice_bitmap_t *)ice_ptypes_arp_of,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
+ }
+
+ if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
+ src = (const ice_bitmap_t *)ice_ptypes_pppoe;
+ ice_and_bitmap(params->ptypes, params->ptypes, src,
+ ICE_FLOW_PTYPE_MAX);
}
if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
(const ice_bitmap_t *)ice_ptypes_ipv4_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
(const ice_bitmap_t *)ice_ptypes_ipv6_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
}
if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
(const ice_bitmap_t *)ice_ptypes_icmp_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
} else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
src = (const ice_bitmap_t *)ice_ptypes_udp_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
ice_and_bitmap(params->ptypes, params->ptypes,
(const ice_bitmap_t *)ice_ptypes_tcp_il,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
ice_and_bitmap(params->ptypes, params->ptypes, src,
ICE_FLOW_PTYPE_MAX);
- hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
if (!i) {
src = (const ice_bitmap_t *)ice_ptypes_gre_of;
ice_and_bitmap(params->ptypes, params->ptypes,
src, ICE_FLOW_PTYPE_MAX);
}
- hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
+ } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
+ if (!i) {
+ src = (const ice_bitmap_t *)ice_ptypes_gtpc;
+ ice_and_bitmap(params->ptypes, params->ptypes,
+ src, ICE_FLOW_PTYPE_MAX);
+ }
+ } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
+ if (!i) {
+ src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
+ ice_and_bitmap(params->ptypes, params->ptypes,
+ src, ICE_FLOW_PTYPE_MAX);
+ }
+ } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
+ if (!i) {
+ src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+ ice_and_bitmap(params->ptypes, params->ptypes,
+ src, ICE_FLOW_PTYPE_MAX);
+ }
}
}
* ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
* @hw: pointer to the HW struct
* @params: information about the flow to be processed
- * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
+ * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
*
* This function will allocate an extraction sequence entries for a DWORD size
* chunk of the packet flags.
struct ice_flow_fld_info *flds;
u16 cnt, ese_bits, i;
s16 adj = 0;
+ u16 mask;
u16 off;
flds = params->prof->segs[seg].fields;
break;
case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
- prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
+ prot_id = ICE_PROT_UDP_IL_OR_S;
break;
case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
prot_id = ICE_PROT_SCTP_IL;
break;
+ case ICE_FLOW_FIELD_IDX_GTPC_TEID:
+ case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
+ case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
+ case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
+ /* GTP is accessed through UDP OF protocol */
+ prot_id = ICE_PROT_UDP_OF;
+ break;
+ case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
+ prot_id = ICE_PROT_PPPOE;
+ break;
case ICE_FLOW_FIELD_IDX_ARP_SIP:
case ICE_FLOW_FIELD_IDX_ARP_DIP:
case ICE_FLOW_FIELD_IDX_ARP_SHA:
/* Fill in the extraction sequence entries needed for this field */
off = flds[fld].xtrct.off;
+ mask = ice_flds_info[fld].mask;
for (i = 0; i < cnt; i++) {
/* Only consume an extraction sequence entry if there is no
* sibling field associated with this field or the sibling entry
params->es[idx].prot_id = prot_id;
params->es[idx].off = off;
+ params->mask[idx] = mask;
params->es_cnt++;
}
/* For ACL, we also need to extract the direction bit (Rx,Tx) data from
* packet flags
*/
- if (params->blk == ICE_BLK_ACL)
- ice_flow_xtract_pkt_flags(hw, params,
- ICE_RX_MDID_PKT_FLAGS_15_0);
+ if (params->blk == ICE_BLK_ACL) {
+ status = ice_flow_xtract_pkt_flags(hw, params,
+ ICE_RX_MDID_PKT_FLAGS_15_0);
+ if (status)
+ return status;
+ }
for (i = 0; i < params->prof->segs_cnt; i++) {
u64 match = params->prof->segs[i].match;
#define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
#define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
+#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
/**
* ice_flow_find_prof_conds - Find a profile matching headers and conditions
enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
u8 segs_cnt, u16 vsi_handle, u32 conds)
{
- struct ice_flow_prof *p;
+ struct ice_flow_prof *p, *prof = NULL;
+ ice_acquire_lock(&hw->fl_profs_locks[blk]);
LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
- if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
+ if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
+ segs_cnt && segs_cnt == p->segs_cnt) {
u8 i;
/* Check for profile-VSI association if specified */
break;
/* A match is found if all segments are matched */
- if (i == segs_cnt)
- return p;
+ if (i == segs_cnt) {
+ prof = p;
+ break;
+ }
}
}
+ ice_release_lock(&hw->fl_profs_locks[blk]);
- return NULL;
+ return prof;
}
/**
{
struct ice_flow_prof *p;
- ice_acquire_lock(&hw->fl_profs_locks[blk]);
p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
- ice_release_lock(&hw->fl_profs_locks[blk]);
return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
}
}
/**
- * ice_flow_rem_entry_sync - Remove a flow entry
+ * ice_dealloc_flow_entry - Deallocate flow entry memory
* @hw: pointer to the HW struct
* @entry: flow entry to be removed
*/
-static enum ice_status
-ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+static void
+ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
{
if (!entry)
- return ICE_ERR_BAD_PTR;
-
- LIST_DEL(&entry->l_entry);
+ return;
if (entry->entry)
ice_free(hw, entry->entry);
}
ice_free(hw, entry);
+}
+
+/**
+ * ice_flow_rem_entry_sync - Remove a flow entry
+ * @hw: pointer to the HW struct
+ * @entry: flow entry to be removed
+ */
+static enum ice_status
+ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+{
+ if (!entry)
+ return ICE_ERR_BAD_PTR;
+
+ LIST_DEL(&entry->l_entry);
+
+ ice_dealloc_flow_entry(hw, entry);
return ICE_SUCCESS;
}
}
/* Add a HW profile for this flow profile */
- status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
+ status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
+ params.es, params.mask);
if (status) {
ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
goto out;
return status;
}
+/**
+ * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
+ * @hw: pointer to the hardware structure
+ * @blk: classification stage
+ * @vsi_handle: software VSI handle
+ * @vsig: target VSI group
+ *
+ * Assumption: the caller has already verified that the VSI to
+ * be added has the same characteristics as the VSIG and will
+ * thereby have access to all resources added to that VSIG.
+ */
+enum ice_status
+ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
+ u16 vsig)
+{
+ enum ice_status status;
+
+ if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
+ return ICE_ERR_PARAM;
+
+ ice_acquire_lock(&hw->fl_profs_locks[blk]);
+ status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
+ vsig);
+ ice_release_lock(&hw->fl_profs_locks[blk]);
+
+ return status;
+}
+
/**
* ice_flow_assoc_prof - associate a VSI with a flow profile
* @hw: pointer to the hardware structure
goto out;
}
- ice_acquire_lock(&prof->entries_lock);
- LIST_ADD(&e->l_entry, &prof->entries);
- ice_release_lock(&prof->entries_lock);
+ if (blk != ICE_BLK_ACL) {
+ /* ACL will handle the entry management */
+ ice_acquire_lock(&prof->entries_lock);
+ LIST_ADD(&e->l_entry, &prof->entries);
+ ice_release_lock(&prof->entries_lock);
+ }
*entry_h = ICE_FLOW_ENTRY_HNDL(e);
seg->raws_cnt++;
}
+#define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
+(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
+
#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
ICE_FLOW_SEG_HDR_SCTP)
#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
- (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
+ (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
+ ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
/**
}
ICE_FLOW_SET_HDRS(segs, flow_hdr);
- if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
+ if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
+ ~ICE_FLOW_RSS_HDRS_INNER_MASK)
return ICE_ERR_PARAM;
val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
- if (!ice_is_pow2(val))
+ if (val && !ice_is_pow2(val))
return ICE_ERR_CFG;
val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
if (!ice_is_vsi_valid(hw, vsi_handle))
return ICE_ERR_PARAM;
+ if (LIST_EMPTY(&hw->fl_profs[blk]))
+ return ICE_SUCCESS;
+
ice_acquire_lock(&hw->fl_profs_locks[blk]);
LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
l_entry) {
rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
+ rss_cfg->symm = prof->cfg.symm;
ice_set_bit(vsi_handle, rss_cfg->vsis);
LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
#define ICE_FLOW_PROF_HASH_S 0
#define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
#define ICE_FLOW_PROF_HDR_S 32
-#define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
+#define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
+#define ICE_FLOW_PROF_ENCAP_S 63
+#define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
+
+#define ICE_RSS_OUTER_HEADERS 1
+#define ICE_RSS_INNER_HEADERS 2
-#define ICE_FLOW_GEN_PROFID(hash, hdr) \
+/* Flow profile ID format:
+ * [0:31] - Packet match fields
+ * [32:62] - Protocol header
+ * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
+ */
+#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
- (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
+ (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
+ ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
+
+static void
+ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
+{
+ u32 s = ((src % 4) << 3); /* byte shift */
+ u32 v = dst | 0x80; /* value to program */
+ u8 i = src / 4; /* register index */
+ u32 reg;
+
+ reg = rd32(hw, GLQF_HSYMM(prof_id, i));
+ reg = (reg & ~(0xff << s)) | (v << s);
+ wr32(hw, GLQF_HSYMM(prof_id, i), reg);
+}
+
+static void
+ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
+{
+ int fv_last_word =
+ ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ ice_rss_config_xor_word(hw, prof_id,
+ /* Yes, field vector in GLQF_HSYMM and
+ * GLQF_HINSET is inversed!
+ */
+ fv_last_word - (src + i),
+ fv_last_word - (dst + i));
+ ice_rss_config_xor_word(hw, prof_id,
+ fv_last_word - (dst + i),
+ fv_last_word - (src + i));
+ }
+}
+
+static void
+ice_rss_update_symm(struct ice_hw *hw,
+ struct ice_flow_prof *prof)
+{
+ struct ice_prof_map *map;
+ u8 prof_id, m;
+
+ map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
+ prof_id = map->prof_id;
+
+ /* clear to default */
+ for (m = 0; m < 6; m++)
+ wr32(hw, GLQF_HSYMM(prof_id, m), 0);
+ if (prof->cfg.symm) {
+ struct ice_flow_seg_info *seg =
+ &prof->segs[prof->segs_cnt - 1];
+
+ struct ice_flow_seg_xtrct *ipv4_src =
+ &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
+ struct ice_flow_seg_xtrct *ipv4_dst =
+ &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
+ struct ice_flow_seg_xtrct *ipv6_src =
+ &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
+ struct ice_flow_seg_xtrct *ipv6_dst =
+ &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
+
+ struct ice_flow_seg_xtrct *tcp_src =
+ &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
+ struct ice_flow_seg_xtrct *tcp_dst =
+ &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
+
+ struct ice_flow_seg_xtrct *udp_src =
+ &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
+ struct ice_flow_seg_xtrct *udp_dst =
+ &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
+
+ struct ice_flow_seg_xtrct *sctp_src =
+ &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
+ struct ice_flow_seg_xtrct *sctp_dst =
+ &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
+
+ /* xor IPv4 */
+ if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
+ ice_rss_config_xor(hw, prof_id,
+ ipv4_src->idx, ipv4_dst->idx, 2);
+
+ /* xor IPv6 */
+ if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
+ ice_rss_config_xor(hw, prof_id,
+ ipv6_src->idx, ipv6_dst->idx, 8);
+
+ /* xor TCP */
+ if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
+ ice_rss_config_xor(hw, prof_id,
+ tcp_src->idx, tcp_dst->idx, 1);
+
+ /* xor UDP */
+ if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
+ ice_rss_config_xor(hw, prof_id,
+ udp_src->idx, udp_dst->idx, 1);
+
+ /* xor SCTP */
+ if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
+ ice_rss_config_xor(hw, prof_id,
+ sctp_src->idx, sctp_dst->idx, 1);
+ }
+}
/**
* ice_add_rss_cfg_sync - add an RSS configuration
* @vsi_handle: software VSI handle
* @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
* @addl_hdrs: protocol header fields
+ * @segs_cnt: packet segment count
+ * @symm: symmetric hash enable/disable
*
* Assumption: lock has already been acquired for RSS list
*/
static enum ice_status
ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
- u32 addl_hdrs)
+ u32 addl_hdrs, u8 segs_cnt, bool symm)
{
const enum ice_block blk = ICE_BLK_RSS;
struct ice_flow_prof *prof = NULL;
struct ice_flow_seg_info *segs;
enum ice_status status = ICE_SUCCESS;
- segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
+ if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
+ return ICE_ERR_PARAM;
+
+ segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
+ sizeof(*segs));
if (!segs)
return ICE_ERR_NO_MEMORY;
/* Construct the packet segment info from the hashed fields */
- status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
+ status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
+ addl_hdrs);
if (status)
goto exit;
* and has the input VSI associated to it. If found, no further
* operations required and exit.
*/
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
+ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
vsi_handle,
ICE_FLOW_FIND_PROF_CHK_FLDS |
ICE_FLOW_FIND_PROF_CHK_VSI);
- if (prof)
- goto exit;
+ if (prof) {
+ if (prof->cfg.symm == symm)
+ goto exit;
+ prof->cfg.symm = symm;
+ goto update_symm;
+ }
/* Check if a flow profile exists with the same protocol headers and
* associated with the input VSI. If so disasscociate the VSI from
* this profile. The VSI will be added to a new profile created with
* the protocol header and new hash field configuration.
*/
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
+ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
if (prof) {
status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
/* Remove profile if it has no VSIs associated */
if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
- status = ice_flow_rem_prof_sync(hw, blk, prof);
+ status = ice_flow_rem_prof(hw, blk, prof->id);
if (status)
goto exit;
}
/* Search for a profile that has same match fields only. If this
* exists then associate the VSI to this profile.
*/
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
+ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
vsi_handle,
ICE_FLOW_FIND_PROF_CHK_FLDS);
if (prof) {
- status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
- if (!status)
- status = ice_add_rss_list(hw, vsi_handle, prof);
+ if (prof->cfg.symm == symm) {
+ status = ice_flow_assoc_prof(hw, blk, prof,
+ vsi_handle);
+ if (!status)
+ status = ice_add_rss_list(hw, vsi_handle,
+ prof);
+ } else {
+ /* if a profile exist but with different symmetric
+ * requirement, just return error.
+ */
+ status = ICE_ERR_NOT_SUPPORTED;
+ }
goto exit;
}
* segment information.
*/
status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
- ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
- segs, 1, NULL, 0, &prof);
+ ICE_FLOW_GEN_PROFID(hashed_flds,
+ segs[segs_cnt - 1].hdrs,
+ segs_cnt),
+ segs, segs_cnt, NULL, 0, &prof);
if (status)
goto exit;
* be removed.
*/
if (status) {
- ice_flow_rem_prof_sync(hw, blk, prof);
+ ice_flow_rem_prof(hw, blk, prof->id);
goto exit;
}
status = ice_add_rss_list(hw, vsi_handle, prof);
+ prof->cfg.symm = symm;
+ if (!symm)
+ goto exit;
+
+update_symm:
+ ice_rss_update_symm(hw, prof);
+
exit:
ice_free(hw, segs);
return status;
* @vsi_handle: software VSI handle
* @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
* @addl_hdrs: protocol header fields
+ * @symm: symmetric hash enable/disable
*
* This function will generate a flow profile based on fields associated with
* the input fields to hash on, the flow type and use the VSI number to add
*/
enum ice_status
ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
- u32 addl_hdrs)
+ u32 addl_hdrs, bool symm)
{
enum ice_status status;
return ICE_ERR_PARAM;
ice_acquire_lock(&hw->rss_locks);
- status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
+ status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
+ ICE_RSS_OUTER_HEADERS, symm);
+ if (!status)
+ status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
+ addl_hdrs, ICE_RSS_INNER_HEADERS,
+ symm);
ice_release_lock(&hw->rss_locks);
return status;
* @vsi_handle: software VSI handle
* @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
* @addl_hdrs: Protocol header fields within a packet segment
+ * @segs_cnt: packet segment count
*
* Assumption: lock has already been acquired for RSS list
*/
static enum ice_status
ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
- u32 addl_hdrs)
+ u32 addl_hdrs, u8 segs_cnt)
{
const enum ice_block blk = ICE_BLK_RSS;
struct ice_flow_seg_info *segs;
struct ice_flow_prof *prof;
enum ice_status status;
- segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
+ segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
+ sizeof(*segs));
if (!segs)
return ICE_ERR_NO_MEMORY;
/* Construct the packet segment info from the hashed fields */
- status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
+ status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
+ addl_hdrs);
if (status)
goto out;
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
+ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
vsi_handle,
ICE_FLOW_FIND_PROF_CHK_FLDS);
if (!prof) {
ice_rem_rss_list(hw, vsi_handle, prof);
if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
- status = ice_flow_rem_prof_sync(hw, blk, prof);
+ status = ice_flow_rem_prof(hw, blk, prof->id);
out:
ice_free(hw, segs);
return status;
}
-/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
- * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
- * convert its values to their appropriate flow L3, L4 values.
- */
-#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
-#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
-#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
-#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
- (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
- ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
-
-#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
-#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
-#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
-#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
- (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
- ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
-
-#define ICE_FLOW_MAX_CFG 10
-
-/**
- * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
- *
- * This function will take the hash bitmap provided by the AVF driver via a
- * message, convert it to ICE-compatible values, and configure RSS flow
- * profiles.
- */
-enum ice_status
-ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
-{
- enum ice_status status = ICE_SUCCESS;
- u64 hash_flds;
-
- if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
- !ice_is_vsi_valid(hw, vsi_handle))
- return ICE_ERR_PARAM;
-
- /* Make sure no unsupported bits are specified */
- if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
- ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
- return ICE_ERR_CFG;
-
- hash_flds = avf_hash;
-
- /* Always create an L3 RSS configuration for any L4 RSS configuration */
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
- hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
-
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
- hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
-
- /* Create the corresponding RSS configuration for each valid hash bit */
- while (hash_flds) {
- u64 rss_hash = ICE_HASH_INVALID;
-
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
- if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4;
- hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_TCP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_UDP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
- } else if (hash_flds &
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_SCTP_PORT;
- hash_flds &=
- ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
- }
- } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
- if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6;
- hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_TCP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_UDP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
- } else if (hash_flds &
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_SCTP_PORT;
- hash_flds &=
- ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
- }
- }
-
- if (rss_hash == ICE_HASH_INVALID)
- return ICE_ERR_OUT_OF_RANGE;
-
- status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
- ICE_FLOW_SEG_HDR_NONE);
- if (status)
- break;
- }
-
- return status;
-}
-
/**
* ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
* @hw: pointer to the hardware structure
return ICE_ERR_PARAM;
ice_acquire_lock(&hw->rss_locks);
- status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
+ status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
+ ICE_RSS_OUTER_HEADERS);
+ if (!status)
+ status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
+ addl_hdrs, ICE_RSS_INNER_HEADERS);
ice_release_lock(&hw->rss_locks);
return status;
if (ice_is_bit_set(r->vsis, vsi_handle)) {
status = ice_add_rss_cfg_sync(hw, vsi_handle,
r->hashed_flds,
- r->packet_hdr);
+ r->packet_hdr,
+ ICE_RSS_OUTER_HEADERS,
+ r->symm);
+ if (status)
+ break;
+ status = ice_add_rss_cfg_sync(hw, vsi_handle,
+ r->hashed_flds,
+ r->packet_hdr,
+ ICE_RSS_INNER_HEADERS,
+ r->symm);
if (status)
break;
}