Commit 2cc88bbc authored by David S. Miller's avatar David S. Miller

Merge branch 'sfc-pedit-offloads'

Pieter Jansen van Vuuren says:

====================
sfc: introduce eth, ipv4 and ipv6 pedit offloads

This set introduces mac source and destination pedit set action offloads.
It also adds offload for ipv4 ttl and ipv6 hop limit pedit set action as
well pedit add actions that would result in the same semantics as
decrementing the ttl and hop limit.

v2:
- fix 'efx_tc_mangle' kdoc which was orphaned when adding 'efx_tc_pedit_add'.
- add description of 'match' in 'efx_tc_mangle' kdoc.
- correct some inconsistent kdoc indentation.

v1: https://lore.kernel.org/netdev/20230823111725.28090-1-pieter.jansen-van-vuuren@amd.com/
====================
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b32add2d e8e0bd60
...@@ -1219,6 +1219,71 @@ int efx_mae_enumerate_mports(struct efx_nic *efx) ...@@ -1219,6 +1219,71 @@ int efx_mae_enumerate_mports(struct efx_nic *efx)
return rc; return rc;
} }
/**
* efx_mae_allocate_pedit_mac() - allocate pedit MAC address in HW.
* @efx: NIC we're installing a pedit MAC address on
* @ped: pedit MAC action to be installed
*
* Attempts to install @ped in HW and populates its id with an index of this
* entry in the firmware MAC address table on success.
*
* Return: negative value on error, 0 in success.
*/
int efx_mae_allocate_pedit_mac(struct efx_nic *efx,
struct efx_tc_mac_pedit_action *ped)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN);
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN);
size_t outlen;
int rc;
BUILD_BUG_ON(MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_LEN !=
sizeof(ped->h_addr));
memcpy(MCDI_PTR(inbuf, MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR), ped->h_addr,
sizeof(ped->h_addr));
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_ALLOC, inbuf, sizeof(inbuf),
outbuf, sizeof(outbuf), &outlen);
if (rc)
return rc;
if (outlen < sizeof(outbuf))
return -EIO;
ped->fw_id = MCDI_DWORD(outbuf, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID);
return 0;
}
/**
* efx_mae_free_pedit_mac() - free pedit MAC address in HW.
* @efx: NIC we're installing a pedit MAC address on
* @ped: pedit MAC action that needs to be freed
*
* Frees @ped in HW, check that firmware did not free a different one and clears
* the id (which denotes the index of the entry in the MAC address table).
*/
void efx_mae_free_pedit_mac(struct efx_nic *efx,
struct efx_tc_mac_pedit_action *ped)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1));
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1));
size_t outlen;
int rc;
MCDI_SET_DWORD(inbuf, MAE_MAC_ADDR_FREE_IN_MAC_ID, ped->fw_id);
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_FREE, inbuf,
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
if (rc || outlen < sizeof(outbuf))
return;
/* FW freed a different ID than we asked for, should also never happen.
* Warn because it means we've now got a different idea to the FW of
* what MAC addresses exist, which could cause mayhem later.
*/
if (WARN_ON(MCDI_DWORD(outbuf, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) != ped->fw_id))
return;
/* We're probably about to free @ped, but let's just make sure its
* fw_id is blatted so that it won't look valid if it leaks out.
*/
ped->fw_id = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL;
}
int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
{ {
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
...@@ -1226,15 +1291,27 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) ...@@ -1226,15 +1291,27 @@ 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_3(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, MCDI_POPULATE_DWORD_4(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); MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap,
MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL,
act->do_ttl_dec);
if (act->src_mac)
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
act->src_mac->fw_id);
else
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);
if (act->dst_mac)
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
act->dst_mac->fw_id);
else
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
if (act->count && !WARN_ON(!act->count->cnt)) if (act->count && !WARN_ON(!act->count->cnt))
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID,
act->count->cnt->fw_id); act->count->cnt->fw_id);
......
...@@ -103,6 +103,10 @@ int efx_mae_update_encap_md(struct efx_nic *efx, ...@@ -103,6 +103,10 @@ int efx_mae_update_encap_md(struct efx_nic *efx,
int efx_mae_free_encap_md(struct efx_nic *efx, int efx_mae_free_encap_md(struct efx_nic *efx,
struct efx_tc_encap_action *encap); struct efx_tc_encap_action *encap);
int efx_mae_allocate_pedit_mac(struct efx_nic *efx,
struct efx_tc_mac_pedit_action *ped);
void efx_mae_free_pedit_mac(struct efx_nic *efx,
struct efx_tc_mac_pedit_action *ped);
int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act);
int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id);
......
This diff is collapsed.
...@@ -18,6 +18,23 @@ ...@@ -18,6 +18,23 @@
#define IS_ALL_ONES(v) (!(typeof (v))~(v)) #define IS_ALL_ONES(v) (!(typeof (v))~(v))
/**
* struct efx_tc_mac_pedit_action - mac pedit action fields
*
* @h_addr: mac address field of ethernet header
* @linkage: rhashtable reference
* @ref: reference count
* @fw_id: index of this entry in firmware MAC address table
*
* MAC address edits are indirected through a table in the hardware
*/
struct efx_tc_mac_pedit_action {
u8 h_addr[ETH_ALEN];
struct rhash_head linkage;
refcount_t ref;
u32 fw_id; /* index of this entry in firmware MAC address table */
};
static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr)
{ {
return !memchr_inv(addr, 0xff, sizeof(*addr)); return !memchr_inv(addr, 0xff, sizeof(*addr));
...@@ -25,20 +42,45 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) ...@@ -25,20 +42,45 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr)
struct efx_tc_encap_action; /* see tc_encap_actions.h */ struct efx_tc_encap_action; /* see tc_encap_actions.h */
/**
* struct efx_tc_action_set - collection of tc action fields
*
* @vlan_push: the number of vlan headers to push
* @vlan_pop: the number of vlan headers to pop
* @decap: used to indicate a tunnel header decapsulation should take place
* @do_ttl_dec: used to indicate IP TTL / Hop Limit should be decremented
* @deliver: used to indicate a deliver action should take place
* @vlan_tci: tci fields for vlan push actions
* @vlan_proto: ethernet types for vlan push actions
* @count: counter mapping
* @encap_md: encap entry in tc_encap_ht table
* @encap_user: linked list of encap users (encap_md->users)
* @user: owning action-set-list. Only populated if @encap_md is; used by efx_tc_update_encap() fallback handling
* @count_user: linked list of counter users (counter->users)
* @dest_mport: destination mport
* @src_mac: source mac entry in tc_mac_ht table
* @dst_mac: destination mac entry in tc_mac_ht table
* @fw_id: index of this entry in firmware actions table
* @list: linked list of tc actions
*
*/
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 decap:1;
u16 do_ttl_dec:1;
u16 deliver:1; u16 deliver:1;
__be16 vlan_tci[2]; /* TCIs for vlan_push */ __be16 vlan_tci[2];
__be16 vlan_proto[2]; /* Ethertypes for vlan_push */ __be16 vlan_proto[2];
struct efx_tc_counter_index *count; struct efx_tc_counter_index *count;
struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ struct efx_tc_encap_action *encap_md;
struct list_head encap_user; /* entry on encap_md->users list */ struct list_head encap_user;
struct efx_tc_action_set_list *user; /* Only populated if encap_md */ struct efx_tc_action_set_list *user;
struct list_head count_user; /* entry on counter->users list, if encap */ struct list_head count_user;
u32 dest_mport; u32 dest_mport;
u32 fw_id; /* index of this entry in firmware actions table */ struct efx_tc_mac_pedit_action *src_mac;
struct efx_tc_mac_pedit_action *dst_mac;
u32 fw_id;
struct list_head list; struct list_head list;
}; };
...@@ -220,6 +262,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ ...@@ -220,6 +262,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */
* @counter_ht: Hashtable of TC counters (FW IDs and counter values) * @counter_ht: Hashtable of TC counters (FW IDs and counter values)
* @counter_id_ht: Hashtable mapping TC counter cookies to counters * @counter_id_ht: Hashtable mapping TC counter cookies to counters
* @encap_ht: Hashtable of TC encap actions * @encap_ht: Hashtable of TC encap actions
* @mac_ht: Hashtable of MAC address entries (for pedits)
* @encap_match_ht: Hashtable of TC encap matches * @encap_match_ht: Hashtable of TC encap matches
* @match_action_ht: Hashtable of TC match-action rules * @match_action_ht: Hashtable of TC match-action rules
* @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules * @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules
...@@ -257,6 +300,7 @@ struct efx_tc_state { ...@@ -257,6 +300,7 @@ struct efx_tc_state {
struct rhashtable counter_ht; struct rhashtable counter_ht;
struct rhashtable counter_id_ht; struct rhashtable counter_id_ht;
struct rhashtable encap_ht; struct rhashtable encap_ht;
struct rhashtable mac_ht;
struct rhashtable encap_match_ht; struct rhashtable encap_match_ht;
struct rhashtable match_action_ht; struct rhashtable match_action_ht;
struct rhashtable lhs_rule_ht; struct rhashtable lhs_rule_ht;
......
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