@@ -112,6 +112,7 @@ struct mlx5e_hairpin_entry {
112
112
struct list_head flows ;
113
113
114
114
u16 peer_vhca_id ;
115
+ u8 prio ;
115
116
struct mlx5e_hairpin * hp ;
116
117
};
117
118
@@ -333,20 +334,63 @@ static void mlx5e_hairpin_destroy(struct mlx5e_hairpin *hp)
333
334
kvfree (hp );
334
335
}
335
336
337
+ static inline u32 hash_hairpin_info (u16 peer_vhca_id , u8 prio )
338
+ {
339
+ return (peer_vhca_id << 16 | prio );
340
+ }
341
+
336
342
static struct mlx5e_hairpin_entry * mlx5e_hairpin_get (struct mlx5e_priv * priv ,
337
- u16 peer_vhca_id )
343
+ u16 peer_vhca_id , u8 prio )
338
344
{
339
345
struct mlx5e_hairpin_entry * hpe ;
346
+ u32 hash_key = hash_hairpin_info (peer_vhca_id , prio );
340
347
341
348
hash_for_each_possible (priv -> fs .tc .hairpin_tbl , hpe ,
342
- hairpin_hlist , peer_vhca_id ) {
343
- if (hpe -> peer_vhca_id == peer_vhca_id )
349
+ hairpin_hlist , hash_key ) {
350
+ if (hpe -> peer_vhca_id == peer_vhca_id && hpe -> prio == prio )
344
351
return hpe ;
345
352
}
346
353
347
354
return NULL ;
348
355
}
349
356
357
+ #define UNKNOWN_MATCH_PRIO 8
358
+
359
+ static int mlx5e_hairpin_get_prio (struct mlx5e_priv * priv ,
360
+ struct mlx5_flow_spec * spec , u8 * match_prio )
361
+ {
362
+ void * headers_c , * headers_v ;
363
+ u8 prio_val , prio_mask = 0 ;
364
+ bool vlan_present ;
365
+
366
+ #ifdef CONFIG_MLX5_CORE_EN_DCB
367
+ if (priv -> dcbx_dp .trust_state != MLX5_QPTS_TRUST_PCP ) {
368
+ netdev_warn (priv -> netdev ,
369
+ "only PCP trust state supported for hairpin\n" );
370
+ return - EOPNOTSUPP ;
371
+ }
372
+ #endif
373
+ headers_c = MLX5_ADDR_OF (fte_match_param , spec -> match_criteria , outer_headers );
374
+ headers_v = MLX5_ADDR_OF (fte_match_param , spec -> match_value , outer_headers );
375
+
376
+ vlan_present = MLX5_GET (fte_match_set_lyr_2_4 , headers_v , cvlan_tag );
377
+ if (vlan_present ) {
378
+ prio_mask = MLX5_GET (fte_match_set_lyr_2_4 , headers_c , first_prio );
379
+ prio_val = MLX5_GET (fte_match_set_lyr_2_4 , headers_v , first_prio );
380
+ }
381
+
382
+ if (!vlan_present || !prio_mask ) {
383
+ prio_val = UNKNOWN_MATCH_PRIO ;
384
+ } else if (prio_mask != 0x7 ) {
385
+ netdev_warn (priv -> netdev ,
386
+ "masked priority match not supported for hairpin\n" );
387
+ return - EOPNOTSUPP ;
388
+ }
389
+
390
+ * match_prio = prio_val ;
391
+ return 0 ;
392
+ }
393
+
350
394
static int mlx5e_hairpin_flow_add (struct mlx5e_priv * priv ,
351
395
struct mlx5e_tc_flow * flow ,
352
396
struct mlx5e_tc_flow_parse_attr * parse_attr )
@@ -356,6 +400,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
356
400
struct mlx5_core_dev * peer_mdev ;
357
401
struct mlx5e_hairpin_entry * hpe ;
358
402
struct mlx5e_hairpin * hp ;
403
+ u8 match_prio ;
359
404
u16 peer_id ;
360
405
int err ;
361
406
@@ -366,7 +411,10 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
366
411
}
367
412
368
413
peer_id = MLX5_CAP_GEN (peer_mdev , vhca_id );
369
- hpe = mlx5e_hairpin_get (priv , peer_id );
414
+ err = mlx5e_hairpin_get_prio (priv , & parse_attr -> spec , & match_prio );
415
+ if (err )
416
+ return err ;
417
+ hpe = mlx5e_hairpin_get (priv , peer_id , match_prio );
370
418
if (hpe )
371
419
goto attach_flow ;
372
420
@@ -376,6 +424,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
376
424
377
425
INIT_LIST_HEAD (& hpe -> flows );
378
426
hpe -> peer_vhca_id = peer_id ;
427
+ hpe -> prio = match_prio ;
379
428
380
429
params .log_data_size = 15 ;
381
430
params .log_data_size = min_t (u8 , params .log_data_size ,
@@ -390,12 +439,13 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
390
439
goto create_hairpin_err ;
391
440
}
392
441
393
- netdev_dbg (priv -> netdev , "add hairpin: tirn %x rqn %x peer %s sqn %x log data size %d\n" ,
442
+ netdev_dbg (priv -> netdev , "add hairpin: tirn %x rqn %x peer %s sqn %x prio %d log data size %d\n" ,
394
443
hp -> tirn , hp -> pair -> rqn , hp -> pair -> peer_mdev -> priv .name ,
395
- hp -> pair -> sqn , params .log_data_size );
444
+ hp -> pair -> sqn , match_prio , params .log_data_size );
396
445
397
446
hpe -> hp = hp ;
398
- hash_add (priv -> fs .tc .hairpin_tbl , & hpe -> hairpin_hlist , peer_id );
447
+ hash_add (priv -> fs .tc .hairpin_tbl , & hpe -> hairpin_hlist ,
448
+ hash_hairpin_info (peer_id , match_prio ));
399
449
400
450
attach_flow :
401
451
flow -> nic_attr -> hairpin_tirn = hpe -> hp -> tirn ;
0 commit comments