Commit 17654d84 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

sfc: add offloading of 'foreign' TC (decap) rules

A 'foreign' rule is one for which the net_dev is not the sfc netdevice
 or any of its representors.  The driver registers indirect flow blocks
 for tunnel netdevs so that it can offload decap rules.  For example:

    tc filter add dev vxlan0 parent ffff: protocol ipv4 flower \
        enc_src_ip 10.1.0.2 enc_dst_ip 10.1.0.1 \
        enc_key_id 1000 enc_dst_port 4789 \
        action tunnel_key unset \
        action mirred egress redirect dev $REPRESENTOR

When notified of a rule like this, register an encap match on the IP
 and dport tuple (creating an Outer Rule table entry) and insert an MAE
 action rule to perform the decapsulation and deliver to the representee.

Moved efx_tc_delete_rule() below efx_tc_flower_release_encap_match() to
 avoid the need for a forward declaration.
Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 746224cd
...@@ -241,6 +241,7 @@ static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps) ...@@ -241,6 +241,7 @@ static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps)
if (outlen < sizeof(outbuf)) if (outlen < sizeof(outbuf))
return -EIO; return -EIO;
caps->match_field_count = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT); caps->match_field_count = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
caps->encap_types = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED);
caps->action_prios = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_ACTION_PRIOS); caps->action_prios = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_ACTION_PRIOS);
return 0; return 0;
} }
...@@ -507,6 +508,25 @@ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, ...@@ -507,6 +508,25 @@ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
} }
#undef CHECK #undef CHECK
int efx_mae_check_encap_type_supported(struct efx_nic *efx, enum efx_encap_type typ)
{
unsigned int bit;
switch (typ & EFX_ENCAP_TYPES_MASK) {
case EFX_ENCAP_TYPE_VXLAN:
bit = MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_LBN;
break;
case EFX_ENCAP_TYPE_GENEVE:
bit = MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_LBN;
break;
default:
return -EOPNOTSUPP;
}
if (efx->tc->caps->encap_types & BIT(bit))
return 0;
return -EOPNOTSUPP;
}
int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt) int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt)
{ {
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(1)); MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(1));
...@@ -766,9 +786,10 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) ...@@ -766,9 +786,10 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
size_t outlen; size_t outlen;
int rc; int rc;
MCDI_POPULATE_DWORD_2(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, MCDI_POPULATE_DWORD_3(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS,
MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push, MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push,
MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop); MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop,
MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap);
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
......
...@@ -70,6 +70,7 @@ void efx_mae_counters_grant_credits(struct work_struct *work); ...@@ -70,6 +70,7 @@ void efx_mae_counters_grant_credits(struct work_struct *work);
struct mae_caps { struct mae_caps {
u32 match_field_count; u32 match_field_count;
u32 encap_types;
u32 action_prios; u32 action_prios;
u8 action_rule_fields[MAE_NUM_FIELDS]; u8 action_rule_fields[MAE_NUM_FIELDS];
u8 outer_rule_fields[MAE_NUM_FIELDS]; u8 outer_rule_fields[MAE_NUM_FIELDS];
...@@ -82,6 +83,8 @@ int efx_mae_match_check_caps(struct efx_nic *efx, ...@@ -82,6 +83,8 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int efx_mae_check_encap_type_supported(struct efx_nic *efx,
enum efx_encap_type typ);
int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
......
This diff is collapsed.
...@@ -28,6 +28,7 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) ...@@ -28,6 +28,7 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr)
struct efx_tc_action_set { struct efx_tc_action_set {
u16 vlan_push:2; u16 vlan_push:2;
u16 vlan_pop:2; u16 vlan_pop:2;
u16 decap:1;
u16 deliver:1; u16 deliver:1;
__be16 vlan_tci[2]; /* TCIs for vlan_push */ __be16 vlan_tci[2]; /* TCIs for vlan_push */
__be16 vlan_proto[2]; /* Ethertypes for vlan_push */ __be16 vlan_proto[2]; /* Ethertypes for vlan_push */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment