16
16
#include <linux/netdevice.h>
17
17
#include <net/dsa.h>
18
18
#include <linux/bitmap.h>
19
+ #include <net/flow_offload.h>
19
20
20
21
#include "bcm_sf2.h"
21
22
#include "bcm_sf2_regs.h"
@@ -257,7 +258,8 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
257
258
}
258
259
259
260
static void bcm_sf2_cfp_slice_ipv4 (struct bcm_sf2_priv * priv ,
260
- struct ethtool_tcpip4_spec * v4_spec ,
261
+ struct flow_dissector_key_ipv4_addrs * addrs ,
262
+ struct flow_dissector_key_ports * ports ,
261
263
unsigned int slice_num ,
262
264
bool mask )
263
265
{
@@ -278,7 +280,7 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
278
280
* UDF_n_A6 [23:8]
279
281
* UDF_n_A5 [7:0]
280
282
*/
281
- reg = be16_to_cpu (v4_spec -> pdst ) >> 8 ;
283
+ reg = be16_to_cpu (ports -> dst ) >> 8 ;
282
284
if (mask )
283
285
offset = CORE_CFP_MASK_PORT (3 );
284
286
else
@@ -289,9 +291,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
289
291
* UDF_n_A4 [23:8]
290
292
* UDF_n_A3 [7:0]
291
293
*/
292
- reg = (be16_to_cpu (v4_spec -> pdst ) & 0xff ) << 24 |
293
- (u32 )be16_to_cpu (v4_spec -> psrc ) << 8 |
294
- (be32_to_cpu (v4_spec -> ip4dst ) & 0x0000ff00 ) >> 8 ;
294
+ reg = (be16_to_cpu (ports -> dst ) & 0xff ) << 24 |
295
+ (u32 )be16_to_cpu (ports -> src ) << 8 |
296
+ (be32_to_cpu (addrs -> dst ) & 0x0000ff00 ) >> 8 ;
295
297
if (mask )
296
298
offset = CORE_CFP_MASK_PORT (2 );
297
299
else
@@ -302,9 +304,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
302
304
* UDF_n_A2 [23:8]
303
305
* UDF_n_A1 [7:0]
304
306
*/
305
- reg = (u32 )(be32_to_cpu (v4_spec -> ip4dst ) & 0xff ) << 24 |
306
- (u32 )(be32_to_cpu (v4_spec -> ip4dst ) >> 16 ) << 8 |
307
- (be32_to_cpu (v4_spec -> ip4src ) & 0x0000ff00 ) >> 8 ;
307
+ reg = (u32 )(be32_to_cpu (addrs -> dst ) & 0xff ) << 24 |
308
+ (u32 )(be32_to_cpu (addrs -> dst ) >> 16 ) << 8 |
309
+ (be32_to_cpu (addrs -> src ) & 0x0000ff00 ) >> 8 ;
308
310
if (mask )
309
311
offset = CORE_CFP_MASK_PORT (1 );
310
312
else
@@ -317,8 +319,8 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
317
319
* Slice ID [3:2]
318
320
* Slice valid [1:0]
319
321
*/
320
- reg = (u32 )(be32_to_cpu (v4_spec -> ip4src ) & 0xff ) << 24 |
321
- (u32 )(be32_to_cpu (v4_spec -> ip4src ) >> 16 ) << 8 |
322
+ reg = (u32 )(be32_to_cpu (addrs -> src ) & 0xff ) << 24 |
323
+ (u32 )(be32_to_cpu (addrs -> src ) >> 16 ) << 8 |
322
324
SLICE_NUM (slice_num ) | SLICE_VALID ;
323
325
if (mask )
324
326
offset = CORE_CFP_MASK_PORT (0 );
@@ -332,9 +334,13 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
332
334
unsigned int queue_num ,
333
335
struct ethtool_rx_flow_spec * fs )
334
336
{
335
- struct ethtool_tcpip4_spec * v4_spec , * v4_m_spec ;
337
+ struct ethtool_rx_flow_spec_input input = {} ;
336
338
const struct cfp_udf_layout * layout ;
337
339
unsigned int slice_num , rule_index ;
340
+ struct ethtool_rx_flow_rule * flow ;
341
+ struct flow_match_ipv4_addrs ipv4 ;
342
+ struct flow_match_ports ports ;
343
+ struct flow_match_ip ip ;
338
344
u8 ip_proto , ip_frag ;
339
345
u8 num_udf ;
340
346
u32 reg ;
@@ -343,13 +349,9 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
343
349
switch (fs -> flow_type & ~FLOW_EXT ) {
344
350
case TCP_V4_FLOW :
345
351
ip_proto = IPPROTO_TCP ;
346
- v4_spec = & fs -> h_u .tcp_ip4_spec ;
347
- v4_m_spec = & fs -> m_u .tcp_ip4_spec ;
348
352
break ;
349
353
case UDP_V4_FLOW :
350
354
ip_proto = IPPROTO_UDP ;
351
- v4_spec = & fs -> h_u .udp_ip4_spec ;
352
- v4_m_spec = & fs -> m_u .udp_ip4_spec ;
353
355
break ;
354
356
default :
355
357
return - EINVAL ;
@@ -367,11 +369,22 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
367
369
if (rule_index > bcm_sf2_cfp_rule_size (priv ))
368
370
return - ENOSPC ;
369
371
372
+ input .fs = fs ;
373
+ flow = ethtool_rx_flow_rule_create (& input );
374
+ if (IS_ERR (flow ))
375
+ return PTR_ERR (flow );
376
+
377
+ flow_rule_match_ipv4_addrs (flow -> rule , & ipv4 );
378
+ flow_rule_match_ports (flow -> rule , & ports );
379
+ flow_rule_match_ip (flow -> rule , & ip );
380
+
370
381
layout = & udf_tcpip4_layout ;
371
382
/* We only use one UDF slice for now */
372
383
slice_num = bcm_sf2_get_slice_number (layout , 0 );
373
- if (slice_num == UDF_NUM_SLICES )
374
- return - EINVAL ;
384
+ if (slice_num == UDF_NUM_SLICES ) {
385
+ ret = - EINVAL ;
386
+ goto out_err_flow_rule ;
387
+ }
375
388
376
389
num_udf = bcm_sf2_get_num_udf_slices (layout -> udfs [slice_num ].slices );
377
390
@@ -398,7 +411,7 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
398
411
* Reserved [1]
399
412
* UDF_Valid[8] [0]
400
413
*/
401
- core_writel (priv , v4_spec -> tos << IPTOS_SHIFT |
414
+ core_writel (priv , ip . key -> tos << IPTOS_SHIFT |
402
415
ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
403
416
udf_upper_bits (num_udf ),
404
417
CORE_CFP_DATA_PORT (6 ));
@@ -417,23 +430,23 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
417
430
core_writel (priv , udf_lower_bits (num_udf ) << 24 , CORE_CFP_MASK_PORT (5 ));
418
431
419
432
/* Program the match and the mask */
420
- bcm_sf2_cfp_slice_ipv4 (priv , v4_spec , slice_num , false);
421
- bcm_sf2_cfp_slice_ipv4 (priv , v4_m_spec , SLICE_NUM_MASK , true);
433
+ bcm_sf2_cfp_slice_ipv4 (priv , ipv4 . key , ports . key , slice_num , false);
434
+ bcm_sf2_cfp_slice_ipv4 (priv , ipv4 . mask , ports . mask , SLICE_NUM_MASK , true);
422
435
423
436
/* Insert into TCAM now */
424
437
bcm_sf2_cfp_rule_addr_set (priv , rule_index );
425
438
426
439
ret = bcm_sf2_cfp_op (priv , OP_SEL_WRITE | TCAM_SEL );
427
440
if (ret ) {
428
441
pr_err ("TCAM entry at addr %d failed\n" , rule_index );
429
- return ret ;
442
+ goto out_err_flow_rule ;
430
443
}
431
444
432
445
/* Insert into Action and policer RAMs now */
433
446
ret = bcm_sf2_cfp_act_pol_set (priv , rule_index , port_num ,
434
447
queue_num , true);
435
448
if (ret )
436
- return ret ;
449
+ goto out_err_flow_rule ;
437
450
438
451
/* Turn on CFP for this rule now */
439
452
reg = core_readl (priv , CORE_CFP_CTL_REG );
@@ -446,6 +459,10 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
446
459
fs -> location = rule_index ;
447
460
448
461
return 0 ;
462
+
463
+ out_err_flow_rule :
464
+ ethtool_rx_flow_rule_destroy (flow );
465
+ return ret ;
449
466
}
450
467
451
468
static void bcm_sf2_cfp_slice_ipv6 (struct bcm_sf2_priv * priv ,
@@ -582,8 +599,12 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
582
599
struct ethtool_rx_flow_spec * fs )
583
600
{
584
601
struct ethtool_tcpip6_spec * v6_spec , * v6_m_spec ;
602
+ struct ethtool_rx_flow_spec_input input = {};
585
603
unsigned int slice_num , rule_index [2 ];
586
604
const struct cfp_udf_layout * layout ;
605
+ struct ethtool_rx_flow_rule * flow ;
606
+ struct flow_match_ipv6_addrs ipv6 ;
607
+ struct flow_match_ports ports ;
587
608
u8 ip_proto , ip_frag ;
588
609
int ret = 0 ;
589
610
u8 num_udf ;
@@ -645,6 +666,15 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
645
666
goto out_err ;
646
667
}
647
668
669
+ input .fs = fs ;
670
+ flow = ethtool_rx_flow_rule_create (& input );
671
+ if (IS_ERR (flow )) {
672
+ ret = PTR_ERR (flow );
673
+ goto out_err ;
674
+ }
675
+ flow_rule_match_ipv6_addrs (flow -> rule , & ipv6 );
676
+ flow_rule_match_ports (flow -> rule , & ports );
677
+
648
678
/* Apply the UDF layout for this filter */
649
679
bcm_sf2_cfp_udf_set (priv , layout , slice_num );
650
680
@@ -688,31 +718,31 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
688
718
core_writel (priv , udf_lower_bits (num_udf ) << 24 , CORE_CFP_MASK_PORT (5 ));
689
719
690
720
/* Slice the IPv6 source address and port */
691
- bcm_sf2_cfp_slice_ipv6 (priv , v6_spec -> ip6src , v6_spec -> psrc ,
692
- slice_num , false);
693
- bcm_sf2_cfp_slice_ipv6 (priv , v6_m_spec -> ip6src , v6_m_spec -> psrc ,
694
- SLICE_NUM_MASK , true);
721
+ bcm_sf2_cfp_slice_ipv6 (priv , ipv6 . key -> src . in6_u . u6_addr32 ,
722
+ ports . key -> src , slice_num , false);
723
+ bcm_sf2_cfp_slice_ipv6 (priv , ipv6 . mask -> src . in6_u . u6_addr32 ,
724
+ ports . mask -> src , SLICE_NUM_MASK , true);
695
725
696
726
/* Insert into TCAM now because we need to insert a second rule */
697
727
bcm_sf2_cfp_rule_addr_set (priv , rule_index [0 ]);
698
728
699
729
ret = bcm_sf2_cfp_op (priv , OP_SEL_WRITE | TCAM_SEL );
700
730
if (ret ) {
701
731
pr_err ("TCAM entry at addr %d failed\n" , rule_index [0 ]);
702
- goto out_err ;
732
+ goto out_err_flow_rule ;
703
733
}
704
734
705
735
/* Insert into Action and policer RAMs now */
706
736
ret = bcm_sf2_cfp_act_pol_set (priv , rule_index [0 ], port_num ,
707
737
queue_num , false);
708
738
if (ret )
709
- goto out_err ;
739
+ goto out_err_flow_rule ;
710
740
711
741
/* Now deal with the second slice to chain this rule */
712
742
slice_num = bcm_sf2_get_slice_number (layout , slice_num + 1 );
713
743
if (slice_num == UDF_NUM_SLICES ) {
714
744
ret = - EINVAL ;
715
- goto out_err ;
745
+ goto out_err_flow_rule ;
716
746
}
717
747
718
748
num_udf = bcm_sf2_get_num_udf_slices (layout -> udfs [slice_num ].slices );
@@ -748,18 +778,18 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
748
778
/* Mask all */
749
779
core_writel (priv , 0 , CORE_CFP_MASK_PORT (5 ));
750
780
751
- bcm_sf2_cfp_slice_ipv6 (priv , v6_spec -> ip6dst , v6_spec -> pdst , slice_num ,
752
- false);
753
- bcm_sf2_cfp_slice_ipv6 (priv , v6_m_spec -> ip6dst , v6_m_spec -> pdst ,
754
- SLICE_NUM_MASK , true);
781
+ bcm_sf2_cfp_slice_ipv6 (priv , ipv6 . key -> dst . in6_u . u6_addr32 ,
782
+ ports . key -> dst , slice_num , false);
783
+ bcm_sf2_cfp_slice_ipv6 (priv , ipv6 . mask -> dst . in6_u . u6_addr32 ,
784
+ ports . key -> dst , SLICE_NUM_MASK , true);
755
785
756
786
/* Insert into TCAM now */
757
787
bcm_sf2_cfp_rule_addr_set (priv , rule_index [1 ]);
758
788
759
789
ret = bcm_sf2_cfp_op (priv , OP_SEL_WRITE | TCAM_SEL );
760
790
if (ret ) {
761
791
pr_err ("TCAM entry at addr %d failed\n" , rule_index [1 ]);
762
- goto out_err ;
792
+ goto out_err_flow_rule ;
763
793
}
764
794
765
795
/* Insert into Action and policer RAMs now, set chain ID to
@@ -768,7 +798,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
768
798
ret = bcm_sf2_cfp_act_pol_set (priv , rule_index [1 ], port_num ,
769
799
queue_num , true);
770
800
if (ret )
771
- goto out_err ;
801
+ goto out_err_flow_rule ;
772
802
773
803
/* Turn on CFP for this rule now */
774
804
reg = core_readl (priv , CORE_CFP_CTL_REG );
@@ -784,6 +814,8 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
784
814
785
815
return ret ;
786
816
817
+ out_err_flow_rule :
818
+ ethtool_rx_flow_rule_destroy (flow );
787
819
out_err :
788
820
clear_bit (rule_index [1 ], priv -> cfp .used );
789
821
return ret ;
0 commit comments