Skip to content

Commit 88f30bb

Browse files
DmytroLinkinSaeed Mahameed
authored andcommitted
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 <[email protected]> Reviewed-by: Roi Dayan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 769619e commit 88f30bb

File tree

1 file changed

+62
-60
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core

1 file changed

+62
-60
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,13 +2238,14 @@ static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
22382238

22392239
struct mlx5_fields {
22402240
u8 field;
2241-
u8 size;
2241+
u8 field_bsize;
2242+
u32 field_mask;
22422243
u32 offset;
22432244
u32 match_offset;
22442245
};
22452246

2246-
#define OFFLOAD(fw_field, size, field, off, match_field) \
2247-
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, \
2247+
#define OFFLOAD(fw_field, field_bsize, field_mask, field, off, match_field) \
2248+
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask, \
22482249
offsetof(struct pedit_headers, field) + (off), \
22492250
MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
22502251

@@ -2262,18 +2263,18 @@ struct mlx5_fields {
22622263
})
22632264

22642265
static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
2265-
void *matchmaskp, int size)
2266+
void *matchmaskp, u8 bsize)
22662267
{
22672268
bool same = false;
22682269

2269-
switch (size) {
2270-
case sizeof(u8):
2270+
switch (bsize) {
2271+
case 8:
22712272
same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp);
22722273
break;
2273-
case sizeof(u16):
2274+
case 16:
22742275
same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp);
22752276
break;
2276-
case sizeof(u32):
2277+
case 32:
22772278
same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp);
22782279
break;
22792280
}
@@ -2282,41 +2283,42 @@ static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
22822283
}
22832284

22842285
static struct mlx5_fields fields[] = {
2285-
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0, dmac_47_16),
2286-
OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0, dmac_15_0),
2287-
OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0, smac_47_16),
2288-
OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0, smac_15_0),
2289-
OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0, ethertype),
2290-
OFFLOAD(FIRST_VID, 2, vlan.h_vlan_TCI, 0, first_vid),
2291-
2292-
OFFLOAD(IP_TTL, 1, ip4.ttl, 0, ttl_hoplimit),
2293-
OFFLOAD(SIPV4, 4, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
2294-
OFFLOAD(DIPV4, 4, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2295-
2296-
OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0,
2286+
OFFLOAD(DMAC_47_16, 32, U32_MAX, eth.h_dest[0], 0, dmac_47_16),
2287+
OFFLOAD(DMAC_15_0, 16, U16_MAX, eth.h_dest[4], 0, dmac_15_0),
2288+
OFFLOAD(SMAC_47_16, 32, U32_MAX, eth.h_source[0], 0, smac_47_16),
2289+
OFFLOAD(SMAC_15_0, 16, U16_MAX, eth.h_source[4], 0, smac_15_0),
2290+
OFFLOAD(ETHERTYPE, 16, U16_MAX, eth.h_proto, 0, ethertype),
2291+
OFFLOAD(FIRST_VID, 16, U16_MAX, vlan.h_vlan_TCI, 0, first_vid),
2292+
2293+
OFFLOAD(IP_TTL, 8, U8_MAX, ip4.ttl, 0, ttl_hoplimit),
2294+
OFFLOAD(SIPV4, 32, U32_MAX, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
2295+
OFFLOAD(DIPV4, 32, U32_MAX, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2296+
2297+
OFFLOAD(SIPV6_127_96, 32, U32_MAX, ip6.saddr.s6_addr32[0], 0,
22972298
src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
2298-
OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0,
2299+
OFFLOAD(SIPV6_95_64, 32, U32_MAX, ip6.saddr.s6_addr32[1], 0,
22992300
src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
2300-
OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0,
2301+
OFFLOAD(SIPV6_63_32, 32, U32_MAX, ip6.saddr.s6_addr32[2], 0,
23012302
src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
2302-
OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0,
2303+
OFFLOAD(SIPV6_31_0, 32, U32_MAX, ip6.saddr.s6_addr32[3], 0,
23032304
src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
2304-
OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0,
2305+
OFFLOAD(DIPV6_127_96, 32, U32_MAX, ip6.daddr.s6_addr32[0], 0,
23052306
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
2306-
OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0,
2307+
OFFLOAD(DIPV6_95_64, 32, U32_MAX, ip6.daddr.s6_addr32[1], 0,
23072308
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
2308-
OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0,
2309+
OFFLOAD(DIPV6_63_32, 32, U32_MAX, ip6.daddr.s6_addr32[2], 0,
23092310
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
2310-
OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0,
2311+
OFFLOAD(DIPV6_31_0, 32, U32_MAX, ip6.daddr.s6_addr32[3], 0,
23112312
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
2312-
OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0, ttl_hoplimit),
2313+
OFFLOAD(IPV6_HOPLIMIT, 8, U8_MAX, ip6.hop_limit, 0, ttl_hoplimit),
23132314

2314-
OFFLOAD(TCP_SPORT, 2, tcp.source, 0, tcp_sport),
2315-
OFFLOAD(TCP_DPORT, 2, tcp.dest, 0, tcp_dport),
2316-
OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5, tcp_flags),
2315+
OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source, 0, tcp_sport),
2316+
OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest, 0, tcp_dport),
2317+
/* in linux iphdr tcp_flags is 8 bits long */
2318+
OFFLOAD(TCP_FLAGS, 8, U8_MAX, tcp.ack_seq, 5, tcp_flags),
23172319

2318-
OFFLOAD(UDP_SPORT, 2, udp.source, 0, udp_sport),
2319-
OFFLOAD(UDP_DPORT, 2, udp.dest, 0, udp_dport),
2320+
OFFLOAD(UDP_SPORT, 16, U16_MAX, udp.source, 0, udp_sport),
2321+
OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest, 0, udp_dport),
23202322
};
23212323

23222324
/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
@@ -2329,19 +2331,17 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23292331
struct netlink_ext_ack *extack)
23302332
{
23312333
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
2332-
void *headers_c = get_match_headers_criteria(*action_flags,
2333-
&parse_attr->spec);
2334-
void *headers_v = get_match_headers_value(*action_flags,
2335-
&parse_attr->spec);
23362334
int i, action_size, nactions, max_actions, first, last, next_z;
2337-
void *s_masks_p, *a_masks_p, *vals_p;
2335+
void *headers_c, *headers_v, *action, *vals_p;
2336+
u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
23382337
struct mlx5_fields *f;
2339-
u8 cmd, field_bsize;
2340-
u32 s_mask, a_mask;
23412338
unsigned long mask;
23422339
__be32 mask_be32;
23432340
__be16 mask_be16;
2344-
void *action;
2341+
u8 cmd;
2342+
2343+
headers_c = get_match_headers_criteria(*action_flags, &parse_attr->spec);
2344+
headers_v = get_match_headers_value(*action_flags, &parse_attr->spec);
23452345

23462346
set_masks = &hdrs[0].masks;
23472347
add_masks = &hdrs[1].masks;
@@ -2366,8 +2366,8 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23662366
s_masks_p = (void *)set_masks + f->offset;
23672367
a_masks_p = (void *)add_masks + f->offset;
23682368

2369-
memcpy(&s_mask, s_masks_p, f->size);
2370-
memcpy(&a_mask, a_masks_p, f->size);
2369+
s_mask = *s_masks_p & f->field_mask;
2370+
a_mask = *a_masks_p & f->field_mask;
23712371

23722372
if (!s_mask && !a_mask) /* nothing to offload here */
23732373
continue;
@@ -2396,38 +2396,34 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23962396
vals_p = (void *)set_vals + f->offset;
23972397
/* don't rewrite if we have a match on the same value */
23982398
if (cmp_val_mask(vals_p, s_masks_p, match_val,
2399-
match_mask, f->size))
2399+
match_mask, f->field_bsize))
24002400
skip = true;
24012401
/* clear to denote we consumed this field */
2402-
memset(s_masks_p, 0, f->size);
2402+
*s_masks_p &= ~f->field_mask;
24032403
} else {
2404-
u32 zero = 0;
2405-
24062404
cmd = MLX5_ACTION_TYPE_ADD;
24072405
mask = a_mask;
24082406
vals_p = (void *)add_vals + f->offset;
24092407
/* add 0 is no change */
2410-
if (!memcmp(vals_p, &zero, f->size))
2408+
if ((*(u32 *)vals_p & f->field_mask) == 0)
24112409
skip = true;
24122410
/* clear to denote we consumed this field */
2413-
memset(a_masks_p, 0, f->size);
2411+
*a_masks_p &= ~f->field_mask;
24142412
}
24152413
if (skip)
24162414
continue;
24172415

2418-
field_bsize = f->size * BITS_PER_BYTE;
2419-
2420-
if (field_bsize == 32) {
2416+
if (f->field_bsize == 32) {
24212417
mask_be32 = *(__be32 *)&mask;
24222418
mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
2423-
} else if (field_bsize == 16) {
2419+
} else if (f->field_bsize == 16) {
24242420
mask_be16 = *(__be16 *)&mask;
24252421
mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
24262422
}
24272423

2428-
first = find_first_bit(&mask, field_bsize);
2429-
next_z = find_next_zero_bit(&mask, field_bsize, first);
2430-
last = find_last_bit(&mask, field_bsize);
2424+
first = find_first_bit(&mask, f->field_bsize);
2425+
next_z = find_next_zero_bit(&mask, f->field_bsize, first);
2426+
last = find_last_bit(&mask, f->field_bsize);
24312427
if (first < next_z && next_z < last) {
24322428
NL_SET_ERR_MSG_MOD(extack,
24332429
"rewrite of few sub-fields isn't supported");
@@ -2440,16 +2436,22 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
24402436
MLX5_SET(set_action_in, action, field, f->field);
24412437

24422438
if (cmd == MLX5_ACTION_TYPE_SET) {
2443-
MLX5_SET(set_action_in, action, offset, first);
2439+
int start;
2440+
2441+
/* if field is bit sized it can start not from first bit */
2442+
start = find_first_bit((unsigned long *)&f->field_mask,
2443+
f->field_bsize);
2444+
2445+
MLX5_SET(set_action_in, action, offset, first - start);
24442446
/* length is num of bits to be written, zero means length of 32 */
24452447
MLX5_SET(set_action_in, action, length, (last - first + 1));
24462448
}
24472449

2448-
if (field_bsize == 32)
2450+
if (f->field_bsize == 32)
24492451
MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
2450-
else if (field_bsize == 16)
2452+
else if (f->field_bsize == 16)
24512453
MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
2452-
else if (field_bsize == 8)
2454+
else if (f->field_bsize == 8)
24532455
MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
24542456

24552457
action += action_size;

0 commit comments

Comments
 (0)