@@ -2241,13 +2241,14 @@ static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
22412241
22422242struct mlx5_fields {
22432243 u8 field ;
2244- u8 size ;
2244+ u8 field_bsize ;
2245+ u32 field_mask ;
22452246 u32 offset ;
22462247 u32 match_offset ;
22472248};
22482249
2249- #define OFFLOAD (fw_field , size , field , off , match_field ) \
2250- {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size , \
2250+ #define OFFLOAD (fw_field , field_bsize , field_mask , field , off , match_field ) \
2251+ {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask , \
22512252 offsetof(struct pedit_headers, field) + (off), \
22522253 MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
22532254
@@ -2265,18 +2266,18 @@ struct mlx5_fields {
22652266})
22662267
22672268static bool cmp_val_mask (void * valp , void * maskp , void * matchvalp ,
2268- void * matchmaskp , int size )
2269+ void * matchmaskp , u8 bsize )
22692270{
22702271 bool same = false;
22712272
2272- switch (size ) {
2273- case sizeof ( u8 ) :
2273+ switch (bsize ) {
2274+ case 8 :
22742275 same = SAME_VAL_MASK (u8 , valp , maskp , matchvalp , matchmaskp );
22752276 break ;
2276- case sizeof ( u16 ) :
2277+ case 16 :
22772278 same = SAME_VAL_MASK (u16 , valp , maskp , matchvalp , matchmaskp );
22782279 break ;
2279- case sizeof ( u32 ) :
2280+ case 32 :
22802281 same = SAME_VAL_MASK (u32 , valp , maskp , matchvalp , matchmaskp );
22812282 break ;
22822283 }
@@ -2285,41 +2286,43 @@ static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
22852286}
22862287
22872288static struct mlx5_fields fields [] = {
2288- OFFLOAD (DMAC_47_16 , 4 , eth .h_dest [0 ], 0 , dmac_47_16 ),
2289- OFFLOAD (DMAC_15_0 , 2 , eth .h_dest [4 ], 0 , dmac_15_0 ),
2290- OFFLOAD (SMAC_47_16 , 4 , eth .h_source [0 ], 0 , smac_47_16 ),
2291- OFFLOAD (SMAC_15_0 , 2 , eth .h_source [4 ], 0 , smac_15_0 ),
2292- OFFLOAD (ETHERTYPE , 2 , eth .h_proto , 0 , ethertype ),
2293- OFFLOAD (FIRST_VID , 2 , vlan .h_vlan_TCI , 0 , first_vid ),
2294-
2295- OFFLOAD (IP_TTL , 1 , ip4 .ttl , 0 , ttl_hoplimit ),
2296- OFFLOAD (SIPV4 , 4 , ip4 .saddr , 0 , src_ipv4_src_ipv6 .ipv4_layout .ipv4 ),
2297- OFFLOAD (DIPV4 , 4 , ip4 .daddr , 0 , dst_ipv4_dst_ipv6 .ipv4_layout .ipv4 ),
2298-
2299- OFFLOAD (SIPV6_127_96 , 4 , ip6 .saddr .s6_addr32 [0 ], 0 ,
2289+ OFFLOAD (DMAC_47_16 , 32 , U32_MAX , eth .h_dest [0 ], 0 , dmac_47_16 ),
2290+ OFFLOAD (DMAC_15_0 , 16 , U16_MAX , eth .h_dest [4 ], 0 , dmac_15_0 ),
2291+ OFFLOAD (SMAC_47_16 , 32 , U32_MAX , eth .h_source [0 ], 0 , smac_47_16 ),
2292+ OFFLOAD (SMAC_15_0 , 16 , U16_MAX , eth .h_source [4 ], 0 , smac_15_0 ),
2293+ OFFLOAD (ETHERTYPE , 16 , U16_MAX , eth .h_proto , 0 , ethertype ),
2294+ OFFLOAD (FIRST_VID , 16 , U16_MAX , vlan .h_vlan_TCI , 0 , first_vid ),
2295+
2296+ OFFLOAD (IP_DSCP , 8 , 0xfc , ip4 .tos , 0 , ip_dscp ),
2297+ OFFLOAD (IP_TTL , 8 , U8_MAX , ip4 .ttl , 0 , ttl_hoplimit ),
2298+ OFFLOAD (SIPV4 , 32 , U32_MAX , ip4 .saddr , 0 , src_ipv4_src_ipv6 .ipv4_layout .ipv4 ),
2299+ OFFLOAD (DIPV4 , 32 , U32_MAX , ip4 .daddr , 0 , dst_ipv4_dst_ipv6 .ipv4_layout .ipv4 ),
2300+
2301+ OFFLOAD (SIPV6_127_96 , 32 , U32_MAX , ip6 .saddr .s6_addr32 [0 ], 0 ,
23002302 src_ipv4_src_ipv6 .ipv6_layout .ipv6 [0 ]),
2301- OFFLOAD (SIPV6_95_64 , 4 , ip6 .saddr .s6_addr32 [1 ], 0 ,
2303+ OFFLOAD (SIPV6_95_64 , 32 , U32_MAX , ip6 .saddr .s6_addr32 [1 ], 0 ,
23022304 src_ipv4_src_ipv6 .ipv6_layout .ipv6 [4 ]),
2303- OFFLOAD (SIPV6_63_32 , 4 , ip6 .saddr .s6_addr32 [2 ], 0 ,
2305+ OFFLOAD (SIPV6_63_32 , 32 , U32_MAX , ip6 .saddr .s6_addr32 [2 ], 0 ,
23042306 src_ipv4_src_ipv6 .ipv6_layout .ipv6 [8 ]),
2305- OFFLOAD (SIPV6_31_0 , 4 , ip6 .saddr .s6_addr32 [3 ], 0 ,
2307+ OFFLOAD (SIPV6_31_0 , 32 , U32_MAX , ip6 .saddr .s6_addr32 [3 ], 0 ,
23062308 src_ipv4_src_ipv6 .ipv6_layout .ipv6 [12 ]),
2307- OFFLOAD (DIPV6_127_96 , 4 , ip6 .daddr .s6_addr32 [0 ], 0 ,
2309+ OFFLOAD (DIPV6_127_96 , 32 , U32_MAX , ip6 .daddr .s6_addr32 [0 ], 0 ,
23082310 dst_ipv4_dst_ipv6 .ipv6_layout .ipv6 [0 ]),
2309- OFFLOAD (DIPV6_95_64 , 4 , ip6 .daddr .s6_addr32 [1 ], 0 ,
2311+ OFFLOAD (DIPV6_95_64 , 32 , U32_MAX , ip6 .daddr .s6_addr32 [1 ], 0 ,
23102312 dst_ipv4_dst_ipv6 .ipv6_layout .ipv6 [4 ]),
2311- OFFLOAD (DIPV6_63_32 , 4 , ip6 .daddr .s6_addr32 [2 ], 0 ,
2313+ OFFLOAD (DIPV6_63_32 , 32 , U32_MAX , ip6 .daddr .s6_addr32 [2 ], 0 ,
23122314 dst_ipv4_dst_ipv6 .ipv6_layout .ipv6 [8 ]),
2313- OFFLOAD (DIPV6_31_0 , 4 , ip6 .daddr .s6_addr32 [3 ], 0 ,
2315+ OFFLOAD (DIPV6_31_0 , 32 , U32_MAX , ip6 .daddr .s6_addr32 [3 ], 0 ,
23142316 dst_ipv4_dst_ipv6 .ipv6_layout .ipv6 [12 ]),
2315- OFFLOAD (IPV6_HOPLIMIT , 1 , ip6 .hop_limit , 0 , ttl_hoplimit ),
2317+ OFFLOAD (IPV6_HOPLIMIT , 8 , U8_MAX , ip6 .hop_limit , 0 , ttl_hoplimit ),
23162318
2317- OFFLOAD (TCP_SPORT , 2 , tcp .source , 0 , tcp_sport ),
2318- OFFLOAD (TCP_DPORT , 2 , tcp .dest , 0 , tcp_dport ),
2319- OFFLOAD (TCP_FLAGS , 1 , tcp .ack_seq , 5 , tcp_flags ),
2319+ OFFLOAD (TCP_SPORT , 16 , U16_MAX , tcp .source , 0 , tcp_sport ),
2320+ OFFLOAD (TCP_DPORT , 16 , U16_MAX , tcp .dest , 0 , tcp_dport ),
2321+ /* in linux iphdr tcp_flags is 8 bits long */
2322+ OFFLOAD (TCP_FLAGS , 8 , U8_MAX , tcp .ack_seq , 5 , tcp_flags ),
23202323
2321- OFFLOAD (UDP_SPORT , 2 , udp .source , 0 , udp_sport ),
2322- OFFLOAD (UDP_DPORT , 2 , udp .dest , 0 , udp_dport ),
2324+ OFFLOAD (UDP_SPORT , 16 , U16_MAX , udp .source , 0 , udp_sport ),
2325+ OFFLOAD (UDP_DPORT , 16 , U16_MAX , udp .dest , 0 , udp_dport ),
23232326};
23242327
23252328/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
@@ -2332,19 +2335,17 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23322335 struct netlink_ext_ack * extack )
23332336{
23342337 struct pedit_headers * set_masks , * add_masks , * set_vals , * add_vals ;
2335- void * headers_c = get_match_headers_criteria (* action_flags ,
2336- & parse_attr -> spec );
2337- void * headers_v = get_match_headers_value (* action_flags ,
2338- & parse_attr -> spec );
23392338 int i , action_size , nactions , max_actions , first , last , next_z ;
2340- void * s_masks_p , * a_masks_p , * vals_p ;
2339+ void * headers_c , * headers_v , * action , * vals_p ;
2340+ u32 * s_masks_p , * a_masks_p , s_mask , a_mask ;
23412341 struct mlx5_fields * f ;
2342- u8 cmd , field_bsize ;
2343- u32 s_mask , a_mask ;
23442342 unsigned long mask ;
23452343 __be32 mask_be32 ;
23462344 __be16 mask_be16 ;
2347- void * action ;
2345+ u8 cmd ;
2346+
2347+ headers_c = get_match_headers_criteria (* action_flags , & parse_attr -> spec );
2348+ headers_v = get_match_headers_value (* action_flags , & parse_attr -> spec );
23482349
23492350 set_masks = & hdrs [0 ].masks ;
23502351 add_masks = & hdrs [1 ].masks ;
@@ -2369,8 +2370,8 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23692370 s_masks_p = (void * )set_masks + f -> offset ;
23702371 a_masks_p = (void * )add_masks + f -> offset ;
23712372
2372- memcpy ( & s_mask , s_masks_p , f -> size ) ;
2373- memcpy ( & a_mask , a_masks_p , f -> size ) ;
2373+ s_mask = * s_masks_p & f -> field_mask ;
2374+ a_mask = * a_masks_p & f -> field_mask ;
23742375
23752376 if (!s_mask && !a_mask ) /* nothing to offload here */
23762377 continue ;
@@ -2399,38 +2400,34 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
23992400 vals_p = (void * )set_vals + f -> offset ;
24002401 /* don't rewrite if we have a match on the same value */
24012402 if (cmp_val_mask (vals_p , s_masks_p , match_val ,
2402- match_mask , f -> size ))
2403+ match_mask , f -> field_bsize ))
24032404 skip = true;
24042405 /* clear to denote we consumed this field */
2405- memset ( s_masks_p , 0 , f -> size ) ;
2406+ * s_masks_p &= ~ f -> field_mask ;
24062407 } else {
2407- u32 zero = 0 ;
2408-
24092408 cmd = MLX5_ACTION_TYPE_ADD ;
24102409 mask = a_mask ;
24112410 vals_p = (void * )add_vals + f -> offset ;
24122411 /* add 0 is no change */
2413- if (! memcmp ( vals_p , & zero , f -> size ) )
2412+ if (( * ( u32 * ) vals_p & f -> field_mask ) == 0 )
24142413 skip = true;
24152414 /* clear to denote we consumed this field */
2416- memset ( a_masks_p , 0 , f -> size ) ;
2415+ * a_masks_p &= ~ f -> field_mask ;
24172416 }
24182417 if (skip )
24192418 continue ;
24202419
2421- field_bsize = f -> size * BITS_PER_BYTE ;
2422-
2423- if (field_bsize == 32 ) {
2420+ if (f -> field_bsize == 32 ) {
24242421 mask_be32 = * (__be32 * )& mask ;
24252422 mask = (__force unsigned long )cpu_to_le32 (be32_to_cpu (mask_be32 ));
2426- } else if (field_bsize == 16 ) {
2423+ } else if (f -> field_bsize == 16 ) {
24272424 mask_be16 = * (__be16 * )& mask ;
24282425 mask = (__force unsigned long )cpu_to_le16 (be16_to_cpu (mask_be16 ));
24292426 }
24302427
2431- first = find_first_bit (& mask , field_bsize );
2432- next_z = find_next_zero_bit (& mask , field_bsize , first );
2433- last = find_last_bit (& mask , field_bsize );
2428+ first = find_first_bit (& mask , f -> field_bsize );
2429+ next_z = find_next_zero_bit (& mask , f -> field_bsize , first );
2430+ last = find_last_bit (& mask , f -> field_bsize );
24342431 if (first < next_z && next_z < last ) {
24352432 NL_SET_ERR_MSG_MOD (extack ,
24362433 "rewrite of few sub-fields isn't supported" );
@@ -2443,16 +2440,22 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
24432440 MLX5_SET (set_action_in , action , field , f -> field );
24442441
24452442 if (cmd == MLX5_ACTION_TYPE_SET ) {
2446- MLX5_SET (set_action_in , action , offset , first );
2443+ int start ;
2444+
2445+ /* if field is bit sized it can start not from first bit */
2446+ start = find_first_bit ((unsigned long * )& f -> field_mask ,
2447+ f -> field_bsize );
2448+
2449+ MLX5_SET (set_action_in , action , offset , first - start );
24472450 /* length is num of bits to be written, zero means length of 32 */
24482451 MLX5_SET (set_action_in , action , length , (last - first + 1 ));
24492452 }
24502453
2451- if (field_bsize == 32 )
2454+ if (f -> field_bsize == 32 )
24522455 MLX5_SET (set_action_in , action , data , ntohl (* (__be32 * )vals_p ) >> first );
2453- else if (field_bsize == 16 )
2456+ else if (f -> field_bsize == 16 )
24542457 MLX5_SET (set_action_in , action , data , ntohs (* (__be16 * )vals_p ) >> first );
2455- else if (field_bsize == 8 )
2458+ else if (f -> field_bsize == 8 )
24562459 MLX5_SET (set_action_in , action , data , * (u8 * )vals_p >> first );
24572460
24582461 action += action_size ;
@@ -3443,6 +3446,12 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
34433446 attr -> action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ;
34443447 }
34453448
3449+ if (!(attr -> action &
3450+ (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP ))) {
3451+ NL_SET_ERR_MSG (extack , "Rule must have at least one forward/drop action" );
3452+ return - EOPNOTSUPP ;
3453+ }
3454+
34463455 if (attr -> split_count > 0 && !mlx5_esw_has_fwd_fdb (priv -> mdev )) {
34473456 NL_SET_ERR_MSG_MOD (extack ,
34483457 "current firmware doesn't support split rule for port mirroring" );
0 commit comments