Skip to content

Commit 9ba0e56

Browse files
vikasbrcmkuba-moo
authored andcommitted
bnxt_en: Enhance ethtool ntuple support for ip flows besides TCP/UDP
Enable flow type ipv4/ipv6 1) for protocols ICMPV4 and ICMPV6. 2) for wildcard match. Wildcard matches to TCP/UDP/ICMP. Note that, IPPROTO_RAW(255) i.e. a reserved protocol considered for a wildcard. Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com> Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com> Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Link: https://lore.kernel.org/r/20240205223202.25341-6-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent c8d129c commit 9ba0e56

File tree

4 files changed

+113
-18
lines changed

4 files changed

+113
-18
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8891,6 +8891,10 @@ static int bnxt_hwrm_cfa_adv_flow_mgnt_qcaps(struct bnxt *bp)
88918891
CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RFS_RING_TBL_IDX_V2_SUPPORTED)
88928892
bp->fw_cap |= BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2;
88938893

8894+
if (flags &
8895+
CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_EXT_IP_PROTO_SUPPORTED)
8896+
bp->fw_cap |= BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO;
8897+
88948898
hwrm_cfa_adv_qcaps_exit:
88958899
hwrm_req_drop(bp, req);
88968900
return rc;

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,6 +2302,7 @@ struct bnxt {
23022302
#define BNXT_FW_CAP_PRE_RESV_VNICS BIT_ULL(35)
23032303
#define BNXT_FW_CAP_BACKING_STORE_V2 BIT_ULL(36)
23042304
#define BNXT_FW_CAP_VNIC_TUNNEL_TPA BIT_ULL(37)
2305+
#define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(38)
23052306

23062307
u32 fw_dbg_cap;
23072308

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 106 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,28 +1130,50 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
11301130
fkeys = &fltr->fkeys;
11311131
fmasks = &fltr->fmasks;
11321132
if (fkeys->basic.n_proto == htons(ETH_P_IP)) {
1133-
if (fkeys->basic.ip_proto == IPPROTO_TCP)
1133+
if (fkeys->basic.ip_proto == IPPROTO_ICMP ||
1134+
fkeys->basic.ip_proto == IPPROTO_RAW) {
1135+
fs->flow_type = IP_USER_FLOW;
1136+
fs->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
1137+
if (fkeys->basic.ip_proto == IPPROTO_ICMP)
1138+
fs->h_u.usr_ip4_spec.proto = IPPROTO_ICMP;
1139+
else
1140+
fs->h_u.usr_ip4_spec.proto = IPPROTO_RAW;
1141+
fs->m_u.usr_ip4_spec.proto = BNXT_IP_PROTO_FULL_MASK;
1142+
} else if (fkeys->basic.ip_proto == IPPROTO_TCP) {
11341143
fs->flow_type = TCP_V4_FLOW;
1135-
else if (fkeys->basic.ip_proto == IPPROTO_UDP)
1144+
} else if (fkeys->basic.ip_proto == IPPROTO_UDP) {
11361145
fs->flow_type = UDP_V4_FLOW;
1137-
else
1146+
} else {
11381147
goto fltr_err;
1148+
}
11391149

11401150
fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src;
11411151
fs->m_u.tcp_ip4_spec.ip4src = fmasks->addrs.v4addrs.src;
11421152
fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst;
11431153
fs->m_u.tcp_ip4_spec.ip4dst = fmasks->addrs.v4addrs.dst;
1144-
fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
1145-
fs->m_u.tcp_ip4_spec.psrc = fmasks->ports.src;
1146-
fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
1147-
fs->m_u.tcp_ip4_spec.pdst = fmasks->ports.dst;
1154+
if (fs->flow_type == TCP_V4_FLOW ||
1155+
fs->flow_type == UDP_V4_FLOW) {
1156+
fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
1157+
fs->m_u.tcp_ip4_spec.psrc = fmasks->ports.src;
1158+
fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
1159+
fs->m_u.tcp_ip4_spec.pdst = fmasks->ports.dst;
1160+
}
11481161
} else {
1149-
if (fkeys->basic.ip_proto == IPPROTO_TCP)
1162+
if (fkeys->basic.ip_proto == IPPROTO_ICMPV6 ||
1163+
fkeys->basic.ip_proto == IPPROTO_RAW) {
1164+
fs->flow_type = IPV6_USER_FLOW;
1165+
if (fkeys->basic.ip_proto == IPPROTO_ICMPV6)
1166+
fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_ICMPV6;
1167+
else
1168+
fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_RAW;
1169+
fs->m_u.usr_ip6_spec.l4_proto = BNXT_IP_PROTO_FULL_MASK;
1170+
} else if (fkeys->basic.ip_proto == IPPROTO_TCP) {
11501171
fs->flow_type = TCP_V6_FLOW;
1151-
else if (fkeys->basic.ip_proto == IPPROTO_UDP)
1172+
} else if (fkeys->basic.ip_proto == IPPROTO_UDP) {
11521173
fs->flow_type = UDP_V6_FLOW;
1153-
else
1174+
} else {
11541175
goto fltr_err;
1176+
}
11551177

11561178
*(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6src[0] =
11571179
fkeys->addrs.v6addrs.src;
@@ -1161,10 +1183,13 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
11611183
fkeys->addrs.v6addrs.dst;
11621184
*(struct in6_addr *)&fs->m_u.tcp_ip6_spec.ip6dst[0] =
11631185
fmasks->addrs.v6addrs.dst;
1164-
fs->h_u.tcp_ip6_spec.psrc = fkeys->ports.src;
1165-
fs->m_u.tcp_ip6_spec.psrc = fmasks->ports.src;
1166-
fs->h_u.tcp_ip6_spec.pdst = fkeys->ports.dst;
1167-
fs->m_u.tcp_ip6_spec.pdst = fmasks->ports.dst;
1186+
if (fs->flow_type == TCP_V6_FLOW ||
1187+
fs->flow_type == UDP_V6_FLOW) {
1188+
fs->h_u.tcp_ip6_spec.psrc = fkeys->ports.src;
1189+
fs->m_u.tcp_ip6_spec.psrc = fmasks->ports.src;
1190+
fs->h_u.tcp_ip6_spec.pdst = fkeys->ports.dst;
1191+
fs->m_u.tcp_ip6_spec.pdst = fmasks->ports.dst;
1192+
}
11681193
}
11691194

11701195
fs->ring_cookie = fltr->base.rxq;
@@ -1228,6 +1253,28 @@ static int bnxt_add_l2_cls_rule(struct bnxt *bp,
12281253
return rc;
12291254
}
12301255

1256+
static bool bnxt_verify_ntuple_ip4_flow(struct ethtool_usrip4_spec *ip_spec,
1257+
struct ethtool_usrip4_spec *ip_mask)
1258+
{
1259+
if (ip_mask->l4_4_bytes || ip_mask->tos ||
1260+
ip_spec->ip_ver != ETH_RX_NFC_IP4 ||
1261+
ip_mask->proto != BNXT_IP_PROTO_FULL_MASK ||
1262+
(ip_spec->proto != IPPROTO_RAW && ip_spec->proto != IPPROTO_ICMP))
1263+
return false;
1264+
return true;
1265+
}
1266+
1267+
static bool bnxt_verify_ntuple_ip6_flow(struct ethtool_usrip6_spec *ip_spec,
1268+
struct ethtool_usrip6_spec *ip_mask)
1269+
{
1270+
if (ip_mask->l4_4_bytes || ip_mask->tclass ||
1271+
ip_mask->l4_proto != BNXT_IP_PROTO_FULL_MASK ||
1272+
(ip_spec->l4_proto != IPPROTO_RAW &&
1273+
ip_spec->l4_proto != IPPROTO_ICMPV6))
1274+
return false;
1275+
return true;
1276+
}
1277+
12311278
static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
12321279
struct ethtool_rx_flow_spec *fs)
12331280
{
@@ -1247,6 +1294,18 @@ static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
12471294
if ((flow_type & (FLOW_MAC_EXT | FLOW_EXT)) || vf)
12481295
return -EOPNOTSUPP;
12491296

1297+
if (flow_type == IP_USER_FLOW) {
1298+
if (!bnxt_verify_ntuple_ip4_flow(&fs->h_u.usr_ip4_spec,
1299+
&fs->m_u.usr_ip4_spec))
1300+
return -EOPNOTSUPP;
1301+
}
1302+
1303+
if (flow_type == IPV6_USER_FLOW) {
1304+
if (!bnxt_verify_ntuple_ip6_flow(&fs->h_u.usr_ip6_spec,
1305+
&fs->m_u.usr_ip6_spec))
1306+
return -EOPNOTSUPP;
1307+
}
1308+
12501309
new_fltr = kzalloc(sizeof(*new_fltr), GFP_KERNEL);
12511310
if (!new_fltr)
12521311
return -ENOMEM;
@@ -1259,6 +1318,18 @@ static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
12591318

12601319
rc = -EOPNOTSUPP;
12611320
switch (flow_type) {
1321+
case IP_USER_FLOW: {
1322+
struct ethtool_usrip4_spec *ip_spec = &fs->h_u.usr_ip4_spec;
1323+
struct ethtool_usrip4_spec *ip_mask = &fs->m_u.usr_ip4_spec;
1324+
1325+
fkeys->basic.ip_proto = ip_spec->proto;
1326+
fkeys->basic.n_proto = htons(ETH_P_IP);
1327+
fkeys->addrs.v4addrs.src = ip_spec->ip4src;
1328+
fmasks->addrs.v4addrs.src = ip_mask->ip4src;
1329+
fkeys->addrs.v4addrs.dst = ip_spec->ip4dst;
1330+
fmasks->addrs.v4addrs.dst = ip_mask->ip4dst;
1331+
break;
1332+
}
12621333
case TCP_V4_FLOW:
12631334
case UDP_V4_FLOW: {
12641335
struct ethtool_tcpip4_spec *ip_spec = &fs->h_u.tcp_ip4_spec;
@@ -1278,6 +1349,18 @@ static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
12781349
fmasks->ports.dst = ip_mask->pdst;
12791350
break;
12801351
}
1352+
case IPV6_USER_FLOW: {
1353+
struct ethtool_usrip6_spec *ip_spec = &fs->h_u.usr_ip6_spec;
1354+
struct ethtool_usrip6_spec *ip_mask = &fs->m_u.usr_ip6_spec;
1355+
1356+
fkeys->basic.ip_proto = ip_spec->l4_proto;
1357+
fkeys->basic.n_proto = htons(ETH_P_IPV6);
1358+
fkeys->addrs.v6addrs.src = *(struct in6_addr *)&ip_spec->ip6src;
1359+
fmasks->addrs.v6addrs.src = *(struct in6_addr *)&ip_mask->ip6src;
1360+
fkeys->addrs.v6addrs.dst = *(struct in6_addr *)&ip_spec->ip6dst;
1361+
fmasks->addrs.v6addrs.dst = *(struct in6_addr *)&ip_mask->ip6dst;
1362+
break;
1363+
}
12811364
case TCP_V6_FLOW:
12821365
case UDP_V6_FLOW: {
12831366
struct ethtool_tcpip6_spec *ip_spec = &fs->h_u.tcp_ip6_spec;
@@ -1349,6 +1432,15 @@ static int bnxt_srxclsrlins(struct bnxt *bp, struct ethtool_rxnfc *cmd)
13491432
if (fs->location != RX_CLS_LOC_ANY)
13501433
return -EINVAL;
13511434

1435+
flow_type = fs->flow_type;
1436+
if ((flow_type == IP_USER_FLOW ||
1437+
flow_type == IPV6_USER_FLOW) &&
1438+
!(bp->fw_cap & BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO))
1439+
return -EOPNOTSUPP;
1440+
if (flow_type & (FLOW_MAC_EXT | FLOW_RSS))
1441+
return -EINVAL;
1442+
flow_type &= ~FLOW_EXT;
1443+
13521444
ring = ethtool_get_flow_spec_ring(fs->ring_cookie);
13531445
vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie);
13541446
if (BNXT_VF(bp) && vf)
@@ -1358,10 +1450,6 @@ static int bnxt_srxclsrlins(struct bnxt *bp, struct ethtool_rxnfc *cmd)
13581450
if (!vf && ring >= bp->rx_nr_rings)
13591451
return -EINVAL;
13601452

1361-
flow_type = fs->flow_type;
1362-
if (flow_type & (FLOW_MAC_EXT | FLOW_RSS))
1363-
return -EINVAL;
1364-
flow_type &= ~FLOW_EXT;
13651453
if (flow_type == ETHER_FLOW)
13661454
rc = bnxt_add_l2_cls_rule(bp, fs);
13671455
else

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct bnxt_led_cfg {
4343

4444
#define BNXT_PXP_REG_LEN 0x3110
4545

46+
#define BNXT_IP_PROTO_FULL_MASK 0xFF
47+
4648
extern const struct ethtool_ops bnxt_ethtool_ops;
4749

4850
u32 bnxt_get_rxfh_indir_size(struct net_device *dev);

0 commit comments

Comments
 (0)