Skip to content

Commit dd8eff6

Browse files
ffainellidavem330
authored andcommitted
net: dsa: bcm_sf2: Allow matching arbitrary IPv6 masks/lengths
There is no reason why we should limit ourselves to matching only full IPv4 addresses (/32), the same logic applies between the DATA and MASK ports, so just make it more configurable to accept both. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent bc3fc44 commit dd8eff6

File tree

1 file changed

+80
-33
lines changed

1 file changed

+80
-33
lines changed

drivers/net/dsa/bcm_sf2_cfp.c

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -441,17 +441,22 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
441441

442442
static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
443443
const __be32 *ip6_addr, const __be16 port,
444-
unsigned int slice_num)
444+
unsigned int slice_num,
445+
bool mask)
445446
{
446-
u32 reg, tmp, val;
447+
u32 reg, tmp, val, offset;
447448

448449
/* C-Tag [31:24]
449450
* UDF_n_B8 [23:8] (port)
450451
* UDF_n_B7 (upper) [7:0] (addr[15:8])
451452
*/
452453
reg = be32_to_cpu(ip6_addr[3]);
453454
val = (u32)be16_to_cpu(port) << 8 | ((reg >> 8) & 0xff);
454-
core_writel(priv, val, CORE_CFP_DATA_PORT(4));
455+
if (mask)
456+
offset = CORE_CFP_MASK_PORT(4);
457+
else
458+
offset = CORE_CFP_DATA_PORT(4);
459+
core_writel(priv, val, offset);
455460

456461
/* UDF_n_B7 (lower) [31:24] (addr[7:0])
457462
* UDF_n_B6 [23:8] (addr[31:16])
@@ -460,7 +465,11 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
460465
tmp = be32_to_cpu(ip6_addr[2]);
461466
val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 |
462467
((tmp >> 8) & 0xff);
463-
core_writel(priv, val, CORE_CFP_DATA_PORT(3));
468+
if (mask)
469+
offset = CORE_CFP_MASK_PORT(3);
470+
else
471+
offset = CORE_CFP_DATA_PORT(3);
472+
core_writel(priv, val, offset);
464473

465474
/* UDF_n_B5 (lower) [31:24] (addr[39:32])
466475
* UDF_n_B4 [23:8] (addr[63:48])
@@ -469,7 +478,11 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
469478
reg = be32_to_cpu(ip6_addr[1]);
470479
val = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 |
471480
((reg >> 8) & 0xff);
472-
core_writel(priv, val, CORE_CFP_DATA_PORT(2));
481+
if (mask)
482+
offset = CORE_CFP_MASK_PORT(2);
483+
else
484+
offset = CORE_CFP_DATA_PORT(2);
485+
core_writel(priv, val, offset);
473486

474487
/* UDF_n_B3 (lower) [31:24] (addr[71:64])
475488
* UDF_n_B2 [23:8] (addr[95:80])
@@ -478,7 +491,11 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
478491
tmp = be32_to_cpu(ip6_addr[0]);
479492
val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 |
480493
((tmp >> 8) & 0xff);
481-
core_writel(priv, val, CORE_CFP_DATA_PORT(1));
494+
if (mask)
495+
offset = CORE_CFP_MASK_PORT(1);
496+
else
497+
offset = CORE_CFP_DATA_PORT(1);
498+
core_writel(priv, val, offset);
482499

483500
/* UDF_n_B1 (lower) [31:24] (addr[103:96])
484501
* UDF_n_B0 [23:8] (addr[127:112])
@@ -488,23 +505,20 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
488505
*/
489506
reg = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 |
490507
SLICE_NUM(slice_num) | SLICE_VALID;
491-
core_writel(priv, reg, CORE_CFP_DATA_PORT(0));
492-
493-
/* All other UDFs should be matched with the filter */
494-
core_writel(priv, 0x00ffffff, CORE_CFP_MASK_PORT(4));
495-
core_writel(priv, 0xffffffff, CORE_CFP_MASK_PORT(3));
496-
core_writel(priv, 0xffffffff, CORE_CFP_MASK_PORT(2));
497-
core_writel(priv, 0xffffffff, CORE_CFP_MASK_PORT(1));
498-
core_writel(priv, 0xffffff0f, CORE_CFP_MASK_PORT(0));
508+
if (mask)
509+
offset = CORE_CFP_MASK_PORT(0);
510+
else
511+
offset = CORE_CFP_DATA_PORT(0);
512+
core_writel(priv, reg, offset);
499513
}
500514

501515
static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
502516
unsigned int port_num,
503517
unsigned int queue_num,
504518
struct ethtool_rx_flow_spec *fs)
505519
{
520+
struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec;
506521
unsigned int slice_num, rule_index[2];
507-
struct ethtool_tcpip6_spec *v6_spec;
508522
const struct cfp_udf_layout *layout;
509523
u8 ip_proto, ip_frag;
510524
int ret = 0;
@@ -515,10 +529,12 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
515529
case TCP_V6_FLOW:
516530
ip_proto = IPPROTO_TCP;
517531
v6_spec = &fs->h_u.tcp_ip6_spec;
532+
v6_m_spec = &fs->m_u.tcp_ip6_spec;
518533
break;
519534
case UDP_V6_FLOW:
520535
ip_proto = IPPROTO_UDP;
521536
v6_spec = &fs->h_u.udp_ip6_spec;
537+
v6_m_spec = &fs->m_u.udp_ip6_spec;
522538
break;
523539
default:
524540
return -EINVAL;
@@ -606,7 +622,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
606622
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
607623

608624
/* Slice the IPv6 source address and port */
609-
bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc, slice_num);
625+
bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc,
626+
slice_num, false);
627+
bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc,
628+
slice_num, true);
610629

611630
/* Insert into TCAM now because we need to insert a second rule */
612631
bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]);
@@ -663,7 +682,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
663682
/* Mask all */
664683
core_writel(priv, 0, CORE_CFP_MASK_PORT(5));
665684

666-
bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num);
685+
bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num,
686+
false);
687+
bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst,
688+
SLICE_NUM_MASK, true);
667689

668690
/* Insert into TCAM now */
669691
bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]);
@@ -932,49 +954,61 @@ static int bcm_sf2_cfp_ipv4_rule_get(struct bcm_sf2_priv *priv, int port,
932954

933955
static int bcm_sf2_cfp_unslice_ipv6(struct bcm_sf2_priv *priv,
934956
__be32 *ip6_addr, __be16 *port,
935-
__be32 *ip6_mask, __be16 *port_mask)
957+
bool mask)
936958
{
937-
u32 reg, tmp;
959+
u32 reg, tmp, offset;
938960

939961
/* C-Tag [31:24]
940962
* UDF_n_B8 [23:8] (port)
941963
* UDF_n_B7 (upper) [7:0] (addr[15:8])
942964
*/
943-
reg = core_readl(priv, CORE_CFP_DATA_PORT(4));
965+
if (mask)
966+
offset = CORE_CFP_MASK_PORT(4);
967+
else
968+
offset = CORE_CFP_DATA_PORT(4);
969+
reg = core_readl(priv, offset);
944970
*port = cpu_to_be32(reg) >> 8;
945-
*port_mask = cpu_to_be16(~0);
946971
tmp = (u32)(reg & 0xff) << 8;
947972

948973
/* UDF_n_B7 (lower) [31:24] (addr[7:0])
949974
* UDF_n_B6 [23:8] (addr[31:16])
950975
* UDF_n_B5 (upper) [7:0] (addr[47:40])
951976
*/
952-
reg = core_readl(priv, CORE_CFP_DATA_PORT(3));
977+
if (mask)
978+
offset = CORE_CFP_MASK_PORT(3);
979+
else
980+
offset = CORE_CFP_DATA_PORT(3);
981+
reg = core_readl(priv, offset);
953982
tmp |= (reg >> 24) & 0xff;
954983
tmp |= (u32)((reg >> 8) << 16);
955-
ip6_mask[3] = cpu_to_be32(~0);
956984
ip6_addr[3] = cpu_to_be32(tmp);
957985
tmp = (u32)(reg & 0xff) << 8;
958986

959987
/* UDF_n_B5 (lower) [31:24] (addr[39:32])
960988
* UDF_n_B4 [23:8] (addr[63:48])
961989
* UDF_n_B3 (upper) [7:0] (addr[79:72])
962990
*/
963-
reg = core_readl(priv, CORE_CFP_DATA_PORT(2));
991+
if (mask)
992+
offset = CORE_CFP_MASK_PORT(2);
993+
else
994+
offset = CORE_CFP_DATA_PORT(2);
995+
reg = core_readl(priv, offset);
964996
tmp |= (reg >> 24) & 0xff;
965997
tmp |= (u32)((reg >> 8) << 16);
966-
ip6_mask[2] = cpu_to_be32(~0);
967998
ip6_addr[2] = cpu_to_be32(tmp);
968999
tmp = (u32)(reg & 0xff) << 8;
9691000

9701001
/* UDF_n_B3 (lower) [31:24] (addr[71:64])
9711002
* UDF_n_B2 [23:8] (addr[95:80])
9721003
* UDF_n_B1 (upper) [7:0] (addr[111:104])
9731004
*/
974-
reg = core_readl(priv, CORE_CFP_DATA_PORT(1));
1005+
if (mask)
1006+
offset = CORE_CFP_MASK_PORT(1);
1007+
else
1008+
offset = CORE_CFP_DATA_PORT(1);
1009+
reg = core_readl(priv, offset);
9751010
tmp |= (reg >> 24) & 0xff;
9761011
tmp |= (u32)((reg >> 8) << 16);
977-
ip6_mask[1] = cpu_to_be32(~0);
9781012
ip6_addr[1] = cpu_to_be32(tmp);
9791013
tmp = (u32)(reg & 0xff) << 8;
9801014

@@ -984,13 +1018,16 @@ static int bcm_sf2_cfp_unslice_ipv6(struct bcm_sf2_priv *priv,
9841018
* Slice ID [3:2]
9851019
* Slice valid [1:0]
9861020
*/
987-
reg = core_readl(priv, CORE_CFP_DATA_PORT(0));
1021+
if (mask)
1022+
offset = CORE_CFP_MASK_PORT(0);
1023+
else
1024+
offset = CORE_CFP_DATA_PORT(0);
1025+
reg = core_readl(priv, offset);
9881026
tmp |= (reg >> 24) & 0xff;
9891027
tmp |= (u32)((reg >> 8) << 16);
990-
ip6_mask[0] = cpu_to_be32(~0);
9911028
ip6_addr[0] = cpu_to_be32(tmp);
9921029

993-
if (!(reg & SLICE_VALID))
1030+
if (!mask && !(reg & SLICE_VALID))
9941031
return -EINVAL;
9951032

9961033
return 0;
@@ -1012,7 +1049,12 @@ static int bcm_sf2_cfp_ipv6_rule_get(struct bcm_sf2_priv *priv, int port,
10121049

10131050
/* Read the second half first */
10141051
ret = bcm_sf2_cfp_unslice_ipv6(priv, v6_spec->ip6dst, &v6_spec->pdst,
1015-
v6_m_spec->ip6dst, &v6_m_spec->pdst);
1052+
false);
1053+
if (ret)
1054+
return ret;
1055+
1056+
ret = bcm_sf2_cfp_unslice_ipv6(priv, v6_m_spec->ip6dst,
1057+
&v6_m_spec->pdst, true);
10161058
if (ret)
10171059
return ret;
10181060

@@ -1043,8 +1085,13 @@ static int bcm_sf2_cfp_ipv6_rule_get(struct bcm_sf2_priv *priv, int port,
10431085
return -EINVAL;
10441086
}
10451087

1046-
return bcm_sf2_cfp_unslice_ipv6(priv, v6_spec->ip6src, &v6_spec->psrc,
1047-
v6_m_spec->ip6src, &v6_m_spec->psrc);
1088+
ret = bcm_sf2_cfp_unslice_ipv6(priv, v6_spec->ip6src, &v6_spec->psrc,
1089+
false);
1090+
if (ret)
1091+
return ret;
1092+
1093+
return bcm_sf2_cfp_unslice_ipv6(priv, v6_m_spec->ip6src,
1094+
&v6_m_spec->psrc, true);
10481095
}
10491096

10501097
static int bcm_sf2_cfp_rule_get(struct bcm_sf2_priv *priv, int port,

0 commit comments

Comments
 (0)