Skip to content

Commit

Permalink
net: microchip: vcap: Add tc flower keys for lan966x
Browse files Browse the repository at this point in the history
Add the following TC flower filter keys to lan966x for IS2:
- ipv4_addr (sip and dip)
- ipv6_addr (sip and dip)
- control (IPv4 fragments)
- portnum (tcp and udp port numbers)
- basic (L3 and L4 protocol)
- vlan (outer vlan tag info)
- tcp (tcp flags)
- ip (tos field)

As the parsing of these keys is similar between lan966x and sparx5, move
the code in a separate file to be shared by these 2 chips. And put the
specific parsing outside of the common functions.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Horatiu Vultur authored and David S. Miller committed Feb 10, 2023
1 parent 21119e2 commit 47400aa
Show file tree
Hide file tree
Showing 5 changed files with 607 additions and 476 deletions.
138 changes: 110 additions & 28 deletions drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,144 @@
#include "lan966x_main.h"
#include "vcap_api.h"
#include "vcap_api_client.h"
#include "vcap_tc.h"

struct lan966x_tc_flower_parse_usage {
struct flow_cls_offload *f;
struct flow_rule *frule;
struct vcap_rule *vrule;
unsigned int used_keys;
u16 l3_proto;
};
static bool lan966x_tc_is_known_etype(u16 etype)
{
switch (etype) {
case ETH_P_ALL:
case ETH_P_ARP:
case ETH_P_IP:
case ETH_P_IPV6:
return true;
}

static int lan966x_tc_flower_handler_ethaddr_usage(struct lan966x_tc_flower_parse_usage *st)
return false;
}

static int
lan966x_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
{
enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;
enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC;
struct flow_match_eth_addrs match;
struct vcap_u48_key smac, dmac;
struct flow_match_control match;
int err = 0;

flow_rule_match_eth_addrs(st->frule, &match);

if (!is_zero_ether_addr(match.mask->src)) {
vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN);
vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN);
err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac);
flow_rule_match_control(st->frule, &match);
if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_L3_FRAGMENT,
VCAP_BIT_1);
else
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_L3_FRAGMENT,
VCAP_BIT_0);
if (err)
goto out;
}

if (!is_zero_ether_addr(match.mask->dst)) {
vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN);
vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN);
err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac);
if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
if (match.key->flags & FLOW_DIS_FIRST_FRAG)
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_L3_FRAG_OFS_GT0,
VCAP_BIT_0);
else
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_L3_FRAG_OFS_GT0,
VCAP_BIT_1);
if (err)
goto out;
}

st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS);
st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);

return err;

out:
NL_SET_ERR_MSG_MOD(st->f->common.extack, "eth_addr parse error");
NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
return err;
}

static int
lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
{
struct flow_match_basic match;
int err = 0;

flow_rule_match_basic(st->frule, &match);
if (match.mask->n_proto) {
st->l3_proto = be16_to_cpu(match.key->n_proto);
if (!lan966x_tc_is_known_etype(st->l3_proto)) {
err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
st->l3_proto, ~0);
if (err)
goto out;
} else if (st->l3_proto == ETH_P_IP) {
err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
VCAP_BIT_1);
if (err)
goto out;
}
}
if (match.mask->ip_proto) {
st->l4_proto = match.key->ip_proto;

if (st->l4_proto == IPPROTO_TCP) {
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_TCP_IS,
VCAP_BIT_1);
if (err)
goto out;
} else if (st->l4_proto == IPPROTO_UDP) {
err = vcap_rule_add_key_bit(st->vrule,
VCAP_KF_TCP_IS,
VCAP_BIT_0);
if (err)
goto out;
} else {
err = vcap_rule_add_key_u32(st->vrule,
VCAP_KF_L3_IP_PROTO,
st->l4_proto, ~0);
if (err)
goto out;
}
}

st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC);
return err;
out:
NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
return err;
}

static int
(*lan966x_tc_flower_handlers_usage[])(struct lan966x_tc_flower_parse_usage *st) = {
[FLOW_DISSECTOR_KEY_ETH_ADDRS] = lan966x_tc_flower_handler_ethaddr_usage,
lan966x_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)
{
return vcap_tc_flower_handler_vlan_usage(st,
VCAP_KF_8021Q_VID_CLS,
VCAP_KF_8021Q_PCP_CLS);
}

static int
(*lan966x_tc_flower_handlers_usage[])(struct vcap_tc_flower_parse_usage *st) = {
[FLOW_DISSECTOR_KEY_ETH_ADDRS] = vcap_tc_flower_handler_ethaddr_usage,
[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = vcap_tc_flower_handler_ipv4_usage,
[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = vcap_tc_flower_handler_ipv6_usage,
[FLOW_DISSECTOR_KEY_CONTROL] = lan966x_tc_flower_handler_control_usage,
[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,
[FLOW_DISSECTOR_KEY_BASIC] = lan966x_tc_flower_handler_basic_usage,
[FLOW_DISSECTOR_KEY_VLAN] = lan966x_tc_flower_handler_vlan_usage,
[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,
[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage,
[FLOW_DISSECTOR_KEY_IP] = vcap_tc_flower_handler_ip_usage,
};

static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f,
struct vcap_admin *admin,
struct vcap_rule *vrule,
u16 *l3_proto)
{
struct lan966x_tc_flower_parse_usage state = {
.f = f,
struct vcap_tc_flower_parse_usage state = {
.fco = f,
.vrule = vrule,
.l3_proto = ETH_P_ALL,
};
Expand Down
Loading

0 comments on commit 47400aa

Please sign in to comment.