Commit 456bfd9d authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/nex

t-queue

Tony Nguyen says:

====================
100GbE Intel Wired LAN Driver Updates 2022-06-30

This series contains updates to ice driver only.

Martyna adds support for VLAN related TC switchdev filters and reworks
dummy packet implementation of VLANs to enable dynamic header insertion to
allow for more rule types.

Lu Wei utilizes eth_broadcast_addr() helper over an open coded version.

Ziyang Xuan removes unneeded NULL checks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 023e79db afa64629
......@@ -447,11 +447,9 @@ void ice_deinit_lag(struct ice_pf *pf)
if (lag->pf)
ice_unregister_lag_handler(lag);
if (lag->upper_netdev)
dev_put(lag->upper_netdev);
dev_put(lag->upper_netdev);
if (lag->peer_netdev)
dev_put(lag->peer_netdev);
dev_put(lag->peer_netdev);
kfree(lag);
......
......@@ -43,6 +43,8 @@ enum ice_protocol_type {
ICE_NVGRE,
ICE_GTP,
ICE_GTP_NO_PAY,
ICE_VLAN_EX,
ICE_VLAN_IN,
ICE_VXLAN_GPE,
ICE_SCTP_IL,
ICE_PROTOCOL_LAST
......@@ -109,13 +111,18 @@ enum ice_prot_id {
#define ICE_GRE_OF_HW 64
#define ICE_UDP_OF_HW 52 /* UDP Tunnels */
#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel type */
#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
#define ICE_MDID_SIZE 2
#define ICE_TUN_FLAG_MDID 21
#define ICE_TUN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_TUN_FLAG_MDID)
#define ICE_TUN_FLAG_MASK 0xFF
#define ICE_VLAN_FLAG_MDID 20
#define ICE_VLAN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_VLAN_FLAG_MDID)
#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
#define ICE_TUN_FLAG_FV_IND 2
/* Mapping of software defined protocol ID to hardware defined protocol ID */
......
......@@ -31,16 +31,16 @@ static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
0x81, 0, 0, 0};
enum {
ICE_PKT_VLAN = BIT(0),
ICE_PKT_OUTER_IPV6 = BIT(1),
ICE_PKT_TUN_GTPC = BIT(2),
ICE_PKT_TUN_GTPU = BIT(3),
ICE_PKT_TUN_NVGRE = BIT(4),
ICE_PKT_TUN_UDP = BIT(5),
ICE_PKT_INNER_IPV6 = BIT(6),
ICE_PKT_INNER_TCP = BIT(7),
ICE_PKT_INNER_UDP = BIT(8),
ICE_PKT_GTP_NOPAY = BIT(9),
ICE_PKT_OUTER_IPV6 = BIT(0),
ICE_PKT_TUN_GTPC = BIT(1),
ICE_PKT_TUN_GTPU = BIT(2),
ICE_PKT_TUN_NVGRE = BIT(3),
ICE_PKT_TUN_UDP = BIT(4),
ICE_PKT_INNER_IPV6 = BIT(5),
ICE_PKT_INNER_TCP = BIT(6),
ICE_PKT_INNER_UDP = BIT(7),
ICE_PKT_GTP_NOPAY = BIT(8),
ICE_PKT_KMALLOC = BIT(9),
};
struct ice_dummy_pkt_offsets {
......@@ -53,22 +53,42 @@ struct ice_dummy_pkt_profile {
const u8 *pkt;
u32 match;
u16 pkt_len;
u16 offsets_len;
};
#define ICE_DECLARE_PKT_OFFSETS(type) \
static const struct ice_dummy_pkt_offsets \
#define ICE_DECLARE_PKT_OFFSETS(type) \
static const struct ice_dummy_pkt_offsets \
ice_dummy_##type##_packet_offsets[]
#define ICE_DECLARE_PKT_TEMPLATE(type) \
#define ICE_DECLARE_PKT_TEMPLATE(type) \
static const u8 ice_dummy_##type##_packet[]
#define ICE_PKT_PROFILE(type, m) { \
.match = (m), \
.pkt = ice_dummy_##type##_packet, \
.pkt_len = sizeof(ice_dummy_##type##_packet), \
.offsets = ice_dummy_##type##_packet_offsets, \
#define ICE_PKT_PROFILE(type, m) { \
.match = (m), \
.pkt = ice_dummy_##type##_packet, \
.pkt_len = sizeof(ice_dummy_##type##_packet), \
.offsets = ice_dummy_##type##_packet_offsets, \
.offsets_len = sizeof(ice_dummy_##type##_packet_offsets), \
}
ICE_DECLARE_PKT_OFFSETS(vlan) = {
{ ICE_VLAN_OFOS, 12 },
};
ICE_DECLARE_PKT_TEMPLATE(vlan) = {
0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
};
ICE_DECLARE_PKT_OFFSETS(qinq) = {
{ ICE_VLAN_EX, 12 },
{ ICE_VLAN_IN, 16 },
};
ICE_DECLARE_PKT_TEMPLATE(qinq) = {
0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
};
ICE_DECLARE_PKT_OFFSETS(gre_tcp) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_ETYPE_OL, 12 },
......@@ -506,38 +526,6 @@ ICE_DECLARE_PKT_TEMPLATE(udp) = {
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* offset info for MAC + VLAN + IPv4 + UDP dummy packet */
ICE_DECLARE_PKT_OFFSETS(vlan_udp) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_VLAN_OFOS, 12 },
{ ICE_ETYPE_OL, 16 },
{ ICE_IPV4_OFOS, 18 },
{ ICE_UDP_ILOS, 38 },
{ ICE_PROTOCOL_LAST, 0 },
};
/* C-tag (801.1Q), IPv4:UDP dummy packet */
ICE_DECLARE_PKT_TEMPLATE(vlan_udp) = {
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
0x08, 0x00, /* ICE_ETYPE_OL 16 */
0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 18 */
0x00, 0x01, 0x00, 0x00,
0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 38 */
0x00, 0x08, 0x00, 0x00,
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* offset info for MAC + IPv4 + TCP dummy packet */
ICE_DECLARE_PKT_OFFSETS(tcp) = {
{ ICE_MAC_OFOS, 0 },
......@@ -570,41 +558,6 @@ ICE_DECLARE_PKT_TEMPLATE(tcp) = {
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* offset info for MAC + VLAN (C-tag, 802.1Q) + IPv4 + TCP dummy packet */
ICE_DECLARE_PKT_OFFSETS(vlan_tcp) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_VLAN_OFOS, 12 },
{ ICE_ETYPE_OL, 16 },
{ ICE_IPV4_OFOS, 18 },
{ ICE_TCP_IL, 38 },
{ ICE_PROTOCOL_LAST, 0 },
};
/* C-tag (801.1Q), IPv4:TCP dummy packet */
ICE_DECLARE_PKT_TEMPLATE(vlan_tcp) = {
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
0x08, 0x00, /* ICE_ETYPE_OL 16 */
0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 18 */
0x00, 0x01, 0x00, 0x00,
0x00, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 38 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
ICE_DECLARE_PKT_OFFSETS(tcp_ipv6) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_ETYPE_OL, 12 },
......@@ -640,46 +593,6 @@ ICE_DECLARE_PKT_TEMPLATE(tcp_ipv6) = {
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* C-tag (802.1Q): IPv6 + TCP */
ICE_DECLARE_PKT_OFFSETS(vlan_tcp_ipv6) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_VLAN_OFOS, 12 },
{ ICE_ETYPE_OL, 16 },
{ ICE_IPV6_OFOS, 18 },
{ ICE_TCP_IL, 58 },
{ ICE_PROTOCOL_LAST, 0 },
};
/* C-tag (802.1Q), IPv6 + TCP dummy packet */
ICE_DECLARE_PKT_TEMPLATE(vlan_tcp_ipv6) = {
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
0x86, 0xDD, /* ICE_ETYPE_OL 16 */
0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 58 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* IPv6 + UDP */
ICE_DECLARE_PKT_OFFSETS(udp_ipv6) = {
{ ICE_MAC_OFOS, 0 },
......@@ -717,43 +630,6 @@ ICE_DECLARE_PKT_TEMPLATE(udp_ipv6) = {
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* C-tag (802.1Q): IPv6 + UDP */
ICE_DECLARE_PKT_OFFSETS(vlan_udp_ipv6) = {
{ ICE_MAC_OFOS, 0 },
{ ICE_VLAN_OFOS, 12 },
{ ICE_ETYPE_OL, 16 },
{ ICE_IPV6_OFOS, 18 },
{ ICE_UDP_ILOS, 58 },
{ ICE_PROTOCOL_LAST, 0 },
};
/* C-tag (802.1Q), IPv6 + UDP dummy packet */
ICE_DECLARE_PKT_TEMPLATE(vlan_udp_ipv6) = {
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x81, 0x00, 0x00, 0x00,/* ICE_VLAN_OFOS 12 */
0x86, 0xDD, /* ICE_ETYPE_OL 16 */
0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
0x00, 0x08, 0x11, 0x00, /* Next header UDP */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 58 */
0x00, 0x08, 0x00, 0x00,
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_tcp) = {
{ ICE_MAC_OFOS, 0 },
......@@ -1271,14 +1147,9 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
ICE_PKT_INNER_IPV6),
ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP),
ICE_PKT_PROFILE(vlan_udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP |
ICE_PKT_VLAN),
ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP),
ICE_PKT_PROFILE(vlan_udp, ICE_PKT_INNER_UDP | ICE_PKT_VLAN),
ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP),
ICE_PKT_PROFILE(vlan_tcp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_VLAN),
ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6),
ICE_PKT_PROFILE(vlan_tcp, ICE_PKT_VLAN),
ICE_PKT_PROFILE(tcp, 0),
};
......@@ -4609,6 +4480,8 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
{ ICE_NVGRE, { 0, 2, 4, 6 } },
{ ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } },
{ ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
{ ICE_VLAN_EX, { 2, 0 } },
{ ICE_VLAN_IN, { 2, 0 } },
};
static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
......@@ -4629,6 +4502,8 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
{ ICE_NVGRE, ICE_GRE_OF_HW },
{ ICE_GTP, ICE_UDP_OF_HW },
{ ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW },
{ ICE_VLAN_EX, ICE_VLAN_OF_HW },
{ ICE_VLAN_IN, ICE_VLAN_OL_HW },
};
/**
......@@ -5313,10 +5188,11 @@ static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
* ice_add_special_words - Add words that are not protocols, such as metadata
* @rinfo: other information regarding the rule e.g. priority and action info
* @lkup_exts: lookup word structure
* @dvm_ena: is double VLAN mode enabled
*/
static int
ice_add_special_words(struct ice_adv_rule_info *rinfo,
struct ice_prot_lkup_ext *lkup_exts)
struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena)
{
u16 mask;
......@@ -5335,6 +5211,19 @@ ice_add_special_words(struct ice_adv_rule_info *rinfo,
}
}
if (rinfo->vlan_type != 0 && dvm_ena) {
if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
u8 word = lkup_exts->n_val_words++;
lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF;
lkup_exts->field_mask[word] =
ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK;
} else {
return -ENOSPC;
}
}
return 0;
}
......@@ -5454,7 +5343,7 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
/* Create any special protocol/offset pairs, such as looking at tunnel
* bits by extracting metadata
*/
status = ice_add_special_words(rinfo, lkup_exts);
status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw));
if (status)
goto err_free_lkup_exts;
......@@ -5554,6 +5443,79 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
return status;
}
/**
* ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt
*
* @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added
* @num_vlan: number of VLAN tags
*/
static struct ice_dummy_pkt_profile *
ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt,
u32 num_vlan)
{
struct ice_dummy_pkt_profile *profile;
struct ice_dummy_pkt_offsets *offsets;
u32 buf_len, off, etype_off, i;
u8 *pkt;
if (num_vlan < 1 || num_vlan > 2)
return ERR_PTR(-EINVAL);
off = num_vlan * VLAN_HLEN;
buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) +
dummy_pkt->offsets_len;
offsets = kzalloc(buf_len, GFP_KERNEL);
if (!offsets)
return ERR_PTR(-ENOMEM);
offsets[0] = dummy_pkt->offsets[0];
if (num_vlan == 2) {
offsets[1] = ice_dummy_qinq_packet_offsets[0];
offsets[2] = ice_dummy_qinq_packet_offsets[1];
} else if (num_vlan == 1) {
offsets[1] = ice_dummy_vlan_packet_offsets[0];
}
for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) {
offsets[i + num_vlan].type = dummy_pkt->offsets[i].type;
offsets[i + num_vlan].offset =
dummy_pkt->offsets[i].offset + off;
}
offsets[i + num_vlan] = dummy_pkt->offsets[i];
etype_off = dummy_pkt->offsets[1].offset;
buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) +
dummy_pkt->pkt_len;
pkt = kzalloc(buf_len, GFP_KERNEL);
if (!pkt) {
kfree(offsets);
return ERR_PTR(-ENOMEM);
}
memcpy(pkt, dummy_pkt->pkt, etype_off);
memcpy(pkt + etype_off,
num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet,
off);
memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off,
dummy_pkt->pkt_len - etype_off);
profile = kzalloc(sizeof(*profile), GFP_KERNEL);
if (!profile) {
kfree(offsets);
kfree(pkt);
return ERR_PTR(-ENOMEM);
}
profile->offsets = offsets;
profile->pkt = pkt;
profile->pkt_len = buf_len;
profile->match |= ICE_PKT_KMALLOC;
return profile;
}
/**
* ice_find_dummy_packet - find dummy packet
*
......@@ -5569,7 +5531,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
enum ice_sw_tunnel_type tun_type)
{
const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
u32 match = 0;
u32 match = 0, vlan_count = 0;
u16 i;
switch (tun_type) {
......@@ -5597,8 +5559,11 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
match |= ICE_PKT_INNER_TCP;
else if (lkups[i].type == ICE_IPV6_OFOS)
match |= ICE_PKT_OUTER_IPV6;
else if (lkups[i].type == ICE_VLAN_OFOS)
match |= ICE_PKT_VLAN;
else if (lkups[i].type == ICE_VLAN_OFOS ||
lkups[i].type == ICE_VLAN_EX)
vlan_count++;
else if (lkups[i].type == ICE_VLAN_IN)
vlan_count++;
else if (lkups[i].type == ICE_ETYPE_OL &&
lkups[i].h_u.ethertype.ethtype_id ==
cpu_to_be16(ICE_IPV6_ETHER_ID) &&
......@@ -5620,6 +5585,9 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
while (ret->match && (match & ret->match) != ret->match)
ret++;
if (vlan_count != 0)
ret = ice_dummy_packet_add_vlan(ret, vlan_count);
return ret;
}
......@@ -5678,6 +5646,8 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
len = sizeof(struct ice_ethtype_hdr);
break;
case ICE_VLAN_OFOS:
case ICE_VLAN_EX:
case ICE_VLAN_IN:
len = sizeof(struct ice_vlan_hdr);
break;
case ICE_IPV4_OFOS:
......@@ -5782,6 +5752,36 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
return -EIO;
}
/**
* ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
* @vlan_type: VLAN tag type
* @pkt: dummy packet to fill in
* @offsets: offset info for the dummy packet
*/
static int
ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
const struct ice_dummy_pkt_offsets *offsets)
{
u16 i;
/* Find VLAN header and insert VLAN TPID */
for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
if (offsets[i].type == ICE_VLAN_OFOS ||
offsets[i].type == ICE_VLAN_EX) {
struct ice_vlan_hdr *hdr;
u16 offset;
offset = offsets[i].offset;
hdr = (struct ice_vlan_hdr *)&pkt[offset];
hdr->type = cpu_to_be16(vlan_type);
return 0;
}
}
return -EIO;
}
/**
* ice_find_adv_rule_entry - Search a rule entry
* @hw: pointer to the hardware structure
......@@ -5817,6 +5817,7 @@ ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
}
if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
rinfo->tun_type == list_itr->rule_info.tun_type &&
rinfo->vlan_type == list_itr->rule_info.vlan_type &&
lkups_matched)
return list_itr;
}
......@@ -5993,16 +5994,22 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
/* locate a dummy packet */
profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
if (IS_ERR(profile))
return PTR_ERR(profile);
if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
rinfo->sw_act.fltr_act == ICE_DROP_PACKET))
return -EIO;
rinfo->sw_act.fltr_act == ICE_DROP_PACKET)) {
status = -EIO;
goto free_pkt_profile;
}
vsi_handle = rinfo->sw_act.vsi_handle;
if (!ice_is_vsi_valid(hw, vsi_handle))
return -EINVAL;
if (!ice_is_vsi_valid(hw, vsi_handle)) {
status = -EINVAL;
goto free_pkt_profile;
}
if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
rinfo->sw_act.fwd_id.hw_vsi_id =
......@@ -6012,7 +6019,7 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
if (status)
return status;
goto free_pkt_profile;
m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
if (m_entry) {
/* we have to add VSI to VSI_LIST and increment vsi_count.
......@@ -6031,12 +6038,14 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
}
return status;
goto free_pkt_profile;
}
rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
if (!s_rule)
return -ENOMEM;
if (!s_rule) {
status = -ENOMEM;
goto free_pkt_profile;
}
if (!rinfo->flags_info.act_valid) {
act |= ICE_SINGLE_ACT_LAN_ENABLE;
act |= ICE_SINGLE_ACT_LB_ENABLE;
......@@ -6105,6 +6114,14 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
goto err_ice_add_adv_rule;
}
if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) {
status = ice_fill_adv_packet_vlan(rinfo->vlan_type,
s_rule->hdr_data,
profile->offsets);
if (status)
goto err_ice_add_adv_rule;
}
status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
NULL);
......@@ -6150,6 +6167,13 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
kfree(s_rule);
free_pkt_profile:
if (profile->match & ICE_PKT_KMALLOC) {
kfree(profile->offsets);
kfree(profile->pkt);
kfree(profile);
}
return status;
}
......@@ -6342,7 +6366,7 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
/* Create any special protocol/offset pairs, such as looking at tunnel
* bits by extracting metadata
*/
status = ice_add_special_words(rinfo, &lkup_exts);
status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw));
if (status)
return status;
......
......@@ -192,6 +192,7 @@ struct ice_adv_rule_info {
u32 priority;
u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */
u16 fltr_rule_id;
u16 vlan_type;
struct ice_adv_rule_flags_info flags_info;
};
......
......@@ -50,6 +50,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
if (flags & ICE_TC_FLWR_FIELD_VLAN)
lkups_cnt++;
/* is CVLAN specified? */
if (flags & ICE_TC_FLWR_FIELD_CVLAN)
lkups_cnt++;
/* are IPv[4|6] fields specified? */
if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 | ICE_TC_FLWR_FIELD_SRC_IPV4 |
ICE_TC_FLWR_FIELD_DEST_IPV6 | ICE_TC_FLWR_FIELD_SRC_IPV6))
......@@ -134,6 +138,18 @@ ice_sw_type_from_tunnel(enum ice_tunnel_type type)
}
}
static u16 ice_check_supported_vlan_tpid(u16 vlan_tpid)
{
switch (vlan_tpid) {
case ETH_P_8021Q:
case ETH_P_8021AD:
case ETH_P_QINQ1:
return vlan_tpid;
default:
return 0;
}
}
static int
ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
struct ice_adv_lkup_elem *list)
......@@ -269,8 +285,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
{
struct ice_tc_flower_lyr_2_4_hdrs *headers = &tc_fltr->outer_headers;
bool inner = false;
u16 vlan_tpid = 0;
int i = 0;
rule_info->vlan_type = vlan_tpid;
rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type);
if (tc_fltr->tunnel_type != TNL_LAST) {
i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list);
......@@ -311,12 +330,26 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
/* copy VLAN info */
if (flags & ICE_TC_FLWR_FIELD_VLAN) {
list[i].type = ICE_VLAN_OFOS;
vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
rule_info->vlan_type =
ice_check_supported_vlan_tpid(vlan_tpid);
if (flags & ICE_TC_FLWR_FIELD_CVLAN)
list[i].type = ICE_VLAN_EX;
else
list[i].type = ICE_VLAN_OFOS;
list[i].h_u.vlan_hdr.vlan = headers->vlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xFFFF);
i++;
}
if (flags & ICE_TC_FLWR_FIELD_CVLAN) {
list[i].type = ICE_VLAN_IN;
list[i].h_u.vlan_hdr.vlan = headers->cvlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xFFFF);
i++;
}
/* copy L3 (IPv[4|6]: src, dest) address */
if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 |
ICE_TC_FLWR_FIELD_SRC_IPV4)) {
......@@ -945,6 +978,7 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_VLAN) |
BIT(FLOW_DISSECTOR_KEY_CVLAN) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
......@@ -1060,6 +1094,34 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
cpu_to_be16(match.key->vlan_id & VLAN_VID_MASK);
if (match.mask->vlan_priority)
headers->vlan_hdr.vlan_prio = match.key->vlan_priority;
if (match.mask->vlan_tpid)
headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid;
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
struct flow_match_vlan match;
if (!ice_is_dvm_ena(&vsi->back->hw)) {
NL_SET_ERR_MSG_MOD(fltr->extack, "Double VLAN mode is not enabled");
return -EINVAL;
}
flow_rule_match_cvlan(rule, &match);
if (match.mask->vlan_id) {
if (match.mask->vlan_id == VLAN_VID_MASK) {
fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN;
} else {
NL_SET_ERR_MSG_MOD(fltr->extack,
"Bad CVLAN mask");
return -EINVAL;
}
}
headers->cvlan_hdr.vlan_id =
cpu_to_be16(match.key->vlan_id & VLAN_VID_MASK);
if (match.mask->vlan_priority)
headers->cvlan_hdr.vlan_prio = match.key->vlan_priority;
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
......@@ -1194,7 +1256,7 @@ ice_handle_tclass_action(struct ice_vsi *vsi,
ICE_TC_FLWR_FIELD_ENC_DST_MAC)) {
ether_addr_copy(fltr->outer_headers.l2_key.dst_mac,
vsi->netdev->dev_addr);
memset(fltr->outer_headers.l2_mask.dst_mac, 0xff, ETH_ALEN);
eth_broadcast_addr(fltr->outer_headers.l2_mask.dst_mac);
}
/* validate specified dest MAC address, make sure either it belongs to
......
......@@ -23,6 +23,7 @@
#define ICE_TC_FLWR_FIELD_ENC_DST_MAC BIT(16)
#define ICE_TC_FLWR_FIELD_ETH_TYPE_ID BIT(17)
#define ICE_TC_FLWR_FIELD_ENC_OPTS BIT(18)
#define ICE_TC_FLWR_FIELD_CVLAN BIT(19)
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
......@@ -40,6 +41,7 @@ struct ice_tc_flower_action {
struct ice_tc_vlan_hdr {
__be16 vlan_id; /* Only last 12 bits valid */
u16 vlan_prio; /* Only last 3 bits valid (valid values: 0..7) */
__be16 vlan_tpid;
};
struct ice_tc_l2_hdr {
......@@ -81,6 +83,7 @@ struct ice_tc_flower_lyr_2_4_hdrs {
struct ice_tc_l2_hdr l2_key;
struct ice_tc_l2_hdr l2_mask;
struct ice_tc_vlan_hdr vlan_hdr;
struct ice_tc_vlan_hdr cvlan_hdr;
/* L3 (IPv4[6]) layer fields with their mask */
struct ice_tc_l3_hdr l3_key;
struct ice_tc_l3_hdr l3_mask;
......
......@@ -199,7 +199,6 @@ static bool ice_is_dvm_supported(struct ice_hw *hw)
#define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2
#define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2
#define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1
#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
{
/* Update recipe ICE_SW_LKUP_VLAN to filter based on the
......
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