You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
10 KiB
268 lines
10 KiB
From 1d4ac7b4c1c443681ec5bb74e185884e00755ed6 Mon Sep 17 00:00:00 2001
|
|
From: Alaa Hleihel <ahleihel@redhat.com>
|
|
Date: Sun, 10 May 2020 15:04:11 -0400
|
|
Subject: [PATCH 093/312] [netdrv] net/mlx5e: Bit sized fields rewrite support
|
|
|
|
Message-id: <20200510150452.10307-47-ahleihel@redhat.com>
|
|
Patchwork-id: 306670
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.3 BZ 1789380 v2 46/87] net/mlx5e: Bit sized fields rewrite support
|
|
Bugzilla: 1789380
|
|
RH-Acked-by: Kamal Heib <kheib@redhat.com>
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
RH-Acked-by: Jonathan Toppins <jtoppins@redhat.com>
|
|
|
|
Bugzilla: http://bugzilla.redhat.com/1789380
|
|
Upstream: v5.5-rc1
|
|
|
|
commit 88f30bbcbaaa1b124fcc622ff49e3d427da9c96c
|
|
Author: Dmytro Linkin <dmitrolin@mellanox.com>
|
|
Date: Wed Oct 2 07:37:08 2019 +0000
|
|
|
|
net/mlx5e: Bit sized fields rewrite support
|
|
|
|
This patch doesn't change any functionality, but is a pre-step for
|
|
adding support for rewriting of bit-sized fields, like DSCP and ECN
|
|
in IPv4 header, similar fields in IPv6, etc.
|
|
|
|
Signed-off-by: Dmytro Linkin <dmitrolin@mellanox.com>
|
|
Reviewed-by: Roi Dayan <roid@mellanox.com>
|
|
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
|
|
|
|
Signed-off-by: Alaa Hleihel <ahleihel@redhat.com>
|
|
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
|
|
---
|
|
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 122 ++++++++++++------------
|
|
1 file changed, 62 insertions(+), 60 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
index b13e7996ad83..ab6d99d6ba14 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
@@ -2244,13 +2244,14 @@ static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
|
|
|
|
struct mlx5_fields {
|
|
u8 field;
|
|
- u8 size;
|
|
+ u8 field_bsize;
|
|
+ u32 field_mask;
|
|
u32 offset;
|
|
u32 match_offset;
|
|
};
|
|
|
|
-#define OFFLOAD(fw_field, size, field, off, match_field) \
|
|
- {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, \
|
|
+#define OFFLOAD(fw_field, field_bsize, field_mask, field, off, match_field) \
|
|
+ {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask, \
|
|
offsetof(struct pedit_headers, field) + (off), \
|
|
MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
|
|
|
|
@@ -2268,18 +2269,18 @@ struct mlx5_fields {
|
|
})
|
|
|
|
static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
|
|
- void *matchmaskp, int size)
|
|
+ void *matchmaskp, u8 bsize)
|
|
{
|
|
bool same = false;
|
|
|
|
- switch (size) {
|
|
- case sizeof(u8):
|
|
+ switch (bsize) {
|
|
+ case 8:
|
|
same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp);
|
|
break;
|
|
- case sizeof(u16):
|
|
+ case 16:
|
|
same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp);
|
|
break;
|
|
- case sizeof(u32):
|
|
+ case 32:
|
|
same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp);
|
|
break;
|
|
}
|
|
@@ -2288,41 +2289,42 @@ static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
|
|
}
|
|
|
|
static struct mlx5_fields fields[] = {
|
|
- OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0, dmac_47_16),
|
|
- OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0, dmac_15_0),
|
|
- OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0, smac_47_16),
|
|
- OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0, smac_15_0),
|
|
- OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0, ethertype),
|
|
- OFFLOAD(FIRST_VID, 2, vlan.h_vlan_TCI, 0, first_vid),
|
|
-
|
|
- OFFLOAD(IP_TTL, 1, ip4.ttl, 0, ttl_hoplimit),
|
|
- OFFLOAD(SIPV4, 4, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
|
|
- OFFLOAD(DIPV4, 4, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
|
|
-
|
|
- OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0,
|
|
+ OFFLOAD(DMAC_47_16, 32, U32_MAX, eth.h_dest[0], 0, dmac_47_16),
|
|
+ OFFLOAD(DMAC_15_0, 16, U16_MAX, eth.h_dest[4], 0, dmac_15_0),
|
|
+ OFFLOAD(SMAC_47_16, 32, U32_MAX, eth.h_source[0], 0, smac_47_16),
|
|
+ OFFLOAD(SMAC_15_0, 16, U16_MAX, eth.h_source[4], 0, smac_15_0),
|
|
+ OFFLOAD(ETHERTYPE, 16, U16_MAX, eth.h_proto, 0, ethertype),
|
|
+ OFFLOAD(FIRST_VID, 16, U16_MAX, vlan.h_vlan_TCI, 0, first_vid),
|
|
+
|
|
+ OFFLOAD(IP_TTL, 8, U8_MAX, ip4.ttl, 0, ttl_hoplimit),
|
|
+ OFFLOAD(SIPV4, 32, U32_MAX, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
|
|
+ OFFLOAD(DIPV4, 32, U32_MAX, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
|
|
+
|
|
+ OFFLOAD(SIPV6_127_96, 32, U32_MAX, ip6.saddr.s6_addr32[0], 0,
|
|
src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
|
|
- OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0,
|
|
+ OFFLOAD(SIPV6_95_64, 32, U32_MAX, ip6.saddr.s6_addr32[1], 0,
|
|
src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
|
|
- OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0,
|
|
+ OFFLOAD(SIPV6_63_32, 32, U32_MAX, ip6.saddr.s6_addr32[2], 0,
|
|
src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
|
|
- OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0,
|
|
+ OFFLOAD(SIPV6_31_0, 32, U32_MAX, ip6.saddr.s6_addr32[3], 0,
|
|
src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
|
|
- OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0,
|
|
+ OFFLOAD(DIPV6_127_96, 32, U32_MAX, ip6.daddr.s6_addr32[0], 0,
|
|
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
|
|
- OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0,
|
|
+ OFFLOAD(DIPV6_95_64, 32, U32_MAX, ip6.daddr.s6_addr32[1], 0,
|
|
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
|
|
- OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0,
|
|
+ OFFLOAD(DIPV6_63_32, 32, U32_MAX, ip6.daddr.s6_addr32[2], 0,
|
|
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
|
|
- OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0,
|
|
+ OFFLOAD(DIPV6_31_0, 32, U32_MAX, ip6.daddr.s6_addr32[3], 0,
|
|
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
|
|
- OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0, ttl_hoplimit),
|
|
+ OFFLOAD(IPV6_HOPLIMIT, 8, U8_MAX, ip6.hop_limit, 0, ttl_hoplimit),
|
|
|
|
- OFFLOAD(TCP_SPORT, 2, tcp.source, 0, tcp_sport),
|
|
- OFFLOAD(TCP_DPORT, 2, tcp.dest, 0, tcp_dport),
|
|
- OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5, tcp_flags),
|
|
+ OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source, 0, tcp_sport),
|
|
+ OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest, 0, tcp_dport),
|
|
+ /* in linux iphdr tcp_flags is 8 bits long */
|
|
+ OFFLOAD(TCP_FLAGS, 8, U8_MAX, tcp.ack_seq, 5, tcp_flags),
|
|
|
|
- OFFLOAD(UDP_SPORT, 2, udp.source, 0, udp_sport),
|
|
- OFFLOAD(UDP_DPORT, 2, udp.dest, 0, udp_dport),
|
|
+ OFFLOAD(UDP_SPORT, 16, U16_MAX, udp.source, 0, udp_sport),
|
|
+ OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest, 0, udp_dport),
|
|
};
|
|
|
|
/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
|
|
@@ -2335,19 +2337,17 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|
struct netlink_ext_ack *extack)
|
|
{
|
|
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
|
|
- void *headers_c = get_match_headers_criteria(*action_flags,
|
|
- &parse_attr->spec);
|
|
- void *headers_v = get_match_headers_value(*action_flags,
|
|
- &parse_attr->spec);
|
|
int i, action_size, nactions, max_actions, first, last, next_z;
|
|
- void *s_masks_p, *a_masks_p, *vals_p;
|
|
+ void *headers_c, *headers_v, *action, *vals_p;
|
|
+ u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
|
|
struct mlx5_fields *f;
|
|
- u8 cmd, field_bsize;
|
|
- u32 s_mask, a_mask;
|
|
unsigned long mask;
|
|
__be32 mask_be32;
|
|
__be16 mask_be16;
|
|
- void *action;
|
|
+ u8 cmd;
|
|
+
|
|
+ headers_c = get_match_headers_criteria(*action_flags, &parse_attr->spec);
|
|
+ headers_v = get_match_headers_value(*action_flags, &parse_attr->spec);
|
|
|
|
set_masks = &hdrs[0].masks;
|
|
add_masks = &hdrs[1].masks;
|
|
@@ -2372,8 +2372,8 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|
s_masks_p = (void *)set_masks + f->offset;
|
|
a_masks_p = (void *)add_masks + f->offset;
|
|
|
|
- memcpy(&s_mask, s_masks_p, f->size);
|
|
- memcpy(&a_mask, a_masks_p, f->size);
|
|
+ s_mask = *s_masks_p & f->field_mask;
|
|
+ a_mask = *a_masks_p & f->field_mask;
|
|
|
|
if (!s_mask && !a_mask) /* nothing to offload here */
|
|
continue;
|
|
@@ -2402,38 +2402,34 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|
vals_p = (void *)set_vals + f->offset;
|
|
/* don't rewrite if we have a match on the same value */
|
|
if (cmp_val_mask(vals_p, s_masks_p, match_val,
|
|
- match_mask, f->size))
|
|
+ match_mask, f->field_bsize))
|
|
skip = true;
|
|
/* clear to denote we consumed this field */
|
|
- memset(s_masks_p, 0, f->size);
|
|
+ *s_masks_p &= ~f->field_mask;
|
|
} else {
|
|
- u32 zero = 0;
|
|
-
|
|
cmd = MLX5_ACTION_TYPE_ADD;
|
|
mask = a_mask;
|
|
vals_p = (void *)add_vals + f->offset;
|
|
/* add 0 is no change */
|
|
- if (!memcmp(vals_p, &zero, f->size))
|
|
+ if ((*(u32 *)vals_p & f->field_mask) == 0)
|
|
skip = true;
|
|
/* clear to denote we consumed this field */
|
|
- memset(a_masks_p, 0, f->size);
|
|
+ *a_masks_p &= ~f->field_mask;
|
|
}
|
|
if (skip)
|
|
continue;
|
|
|
|
- field_bsize = f->size * BITS_PER_BYTE;
|
|
-
|
|
- if (field_bsize == 32) {
|
|
+ if (f->field_bsize == 32) {
|
|
mask_be32 = *(__be32 *)&mask;
|
|
mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
|
|
- } else if (field_bsize == 16) {
|
|
+ } else if (f->field_bsize == 16) {
|
|
mask_be16 = *(__be16 *)&mask;
|
|
mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
|
|
}
|
|
|
|
- first = find_first_bit(&mask, field_bsize);
|
|
- next_z = find_next_zero_bit(&mask, field_bsize, first);
|
|
- last = find_last_bit(&mask, field_bsize);
|
|
+ first = find_first_bit(&mask, f->field_bsize);
|
|
+ next_z = find_next_zero_bit(&mask, f->field_bsize, first);
|
|
+ last = find_last_bit(&mask, f->field_bsize);
|
|
if (first < next_z && next_z < last) {
|
|
NL_SET_ERR_MSG_MOD(extack,
|
|
"rewrite of few sub-fields isn't supported");
|
|
@@ -2446,16 +2442,22 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|
MLX5_SET(set_action_in, action, field, f->field);
|
|
|
|
if (cmd == MLX5_ACTION_TYPE_SET) {
|
|
- MLX5_SET(set_action_in, action, offset, first);
|
|
+ int start;
|
|
+
|
|
+ /* if field is bit sized it can start not from first bit */
|
|
+ start = find_first_bit((unsigned long *)&f->field_mask,
|
|
+ f->field_bsize);
|
|
+
|
|
+ MLX5_SET(set_action_in, action, offset, first - start);
|
|
/* length is num of bits to be written, zero means length of 32 */
|
|
MLX5_SET(set_action_in, action, length, (last - first + 1));
|
|
}
|
|
|
|
- if (field_bsize == 32)
|
|
+ if (f->field_bsize == 32)
|
|
MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
|
|
- else if (field_bsize == 16)
|
|
+ else if (f->field_bsize == 16)
|
|
MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
|
|
- else if (field_bsize == 8)
|
|
+ else if (f->field_bsize == 8)
|
|
MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
|
|
|
|
action += action_size;
|
|
--
|
|
2.13.6
|
|
|