Leon Romanovsky says:

====================
mlx5 MACsec RoCEv2 support

From Patrisious:

This series extends previously added MACsec offload support
to cover RoCE traffic either.

In order to achieve that, we need configure MACsec with offload between
the two endpoints, like below:

REMOTE_MAC=10:70:fd:43:71:c0

* ip addr add 1.1.1.1/16 dev eth2
* ip link set dev eth2 up
* ip link add link eth2 macsec0 type macsec encrypt on
* ip macsec offload macsec0 mac
* ip macsec add macsec0 tx sa 0 pn 1 on key 00 dffafc8d7b9a43d5b9a3dfbbf6a30c16
* ip macsec add macsec0 rx port 1 address $REMOTE_MAC
* ip macsec add macsec0 rx port 1 address $REMOTE_MAC sa 0 pn 1 on key 01 ead3664f508eb06c40ac7104cdae4ce5
* ip addr add 10.1.0.1/16 dev macsec0
* ip link set dev macsec0 up

And in a similar manner on the other machine, while noting the keys order
would be reversed and the MAC address of the other machine.

RDMA traffic is separated through relevant GID entries and in case
of IP ambiguity issue - meaning we have a physical GIDs and a MACsec
GIDs with the same IP/GID, we disable our physical GID in order
to force the user to only use the MACsec GID.

v0: https://lore.kernel.org/netdev/20230813064703.574082-1-leon@kernel.org/

* 'mlx5-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux:
  RDMA/mlx5: Handles RoCE MACsec steering rules addition and deletion
  net/mlx5: Add RoCE MACsec steering infrastructure in core
  net/mlx5: Configure MACsec steering for ingress RoCEv2 traffic
  net/mlx5: Configure MACsec steering for egress RoCEv2 traffic
  IB/core: Reorder GID delete code for RoCE
  net/mlx5: Add MACsec priorities in RDMA namespaces
  RDMA/mlx5: Implement MACsec gid addition and deletion
  net/mlx5: Maintain fs_id xarray per MACsec device inside macsec steering
  net/mlx5: Remove netdevice from MACsec steering
  net/mlx5e: Move MACsec flow steering and statistics database from ethernet to core
  net/mlx5e: Rename MACsec flow steering functions/parameters to suit core naming style
  net/mlx5: Remove dependency of macsec flow steering on ethernet
  net/mlx5e: Move MACsec flow steering operations to be used as core library
  macsec: add functions to get macsec real netdevice and check offload
====================

Link: https://lore.kernel.org/r/20230821073833.59042-1-leon@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2023-08-24 11:32:17 -07:00
commit 3c5066c6b0
26 changed files with 3118 additions and 1631 deletions

View File

@ -400,6 +400,9 @@ static void del_gid(struct ib_device *ib_dev, u32 port,
table->data_vec[ix] = NULL;
write_unlock_irq(&table->rwlock);
if (rdma_cap_roce_gid_table(ib_dev, port))
ib_dev->ops.del_gid(&entry->attr, &entry->context);
ndev_storage = entry->ndev_storage;
if (ndev_storage) {
entry->ndev_storage = NULL;
@ -407,9 +410,6 @@ static void del_gid(struct ib_device *ib_dev, u32 port,
call_rcu(&ndev_storage->rcu_head, put_gid_ndev);
}
if (rdma_cap_roce_gid_table(ib_dev, port))
ib_dev->ops.del_gid(&entry->attr, &entry->context);
put_gid_entry_locked(entry);
}

View File

@ -28,3 +28,4 @@ mlx5_ib-$(CONFIG_INFINIBAND_USER_ACCESS) += devx.o \
fs.o \
qos.o \
std_types.o
mlx5_ib-$(CONFIG_MLX5_MACSEC) += macsec.o

View File

@ -0,0 +1,364 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
#include "macsec.h"
#include <linux/mlx5/macsec.h>
struct mlx5_reserved_gids {
int macsec_index;
const struct ib_gid_attr *physical_gid;
};
struct mlx5_roce_gids {
struct list_head roce_gid_list_entry;
u16 gid_idx;
union {
struct sockaddr_in sockaddr_in;
struct sockaddr_in6 sockaddr_in6;
} addr;
};
struct mlx5_macsec_device {
struct list_head macsec_devices_list_entry;
void *macdev;
struct list_head macsec_roce_gids;
struct list_head tx_rules_list;
struct list_head rx_rules_list;
};
static void cleanup_macsec_device(struct mlx5_macsec_device *macsec_device)
{
if (!list_empty(&macsec_device->tx_rules_list) ||
!list_empty(&macsec_device->rx_rules_list) ||
!list_empty(&macsec_device->macsec_roce_gids))
return;
list_del(&macsec_device->macsec_devices_list_entry);
kfree(macsec_device);
}
static struct mlx5_macsec_device *get_macsec_device(void *macdev,
struct list_head *macsec_devices_list)
{
struct mlx5_macsec_device *iter, *macsec_device = NULL;
list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) {
if (iter->macdev == macdev) {
macsec_device = iter;
break;
}
}
if (macsec_device)
return macsec_device;
macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL);
if (!macsec_device)
return NULL;
macsec_device->macdev = macdev;
INIT_LIST_HEAD(&macsec_device->tx_rules_list);
INIT_LIST_HEAD(&macsec_device->rx_rules_list);
INIT_LIST_HEAD(&macsec_device->macsec_roce_gids);
list_add(&macsec_device->macsec_devices_list_entry, macsec_devices_list);
return macsec_device;
}
static void mlx5_macsec_del_roce_gid(struct mlx5_macsec_device *macsec_device, u16 gid_idx)
{
struct mlx5_roce_gids *current_gid, *next_gid;
list_for_each_entry_safe(current_gid, next_gid, &macsec_device->macsec_roce_gids,
roce_gid_list_entry)
if (current_gid->gid_idx == gid_idx) {
list_del(&current_gid->roce_gid_list_entry);
kfree(current_gid);
}
}
static void mlx5_macsec_save_roce_gid(struct mlx5_macsec_device *macsec_device,
const struct sockaddr *addr, u16 gid_idx)
{
struct mlx5_roce_gids *roce_gids;
roce_gids = kzalloc(sizeof(*roce_gids), GFP_KERNEL);
if (!roce_gids)
return;
roce_gids->gid_idx = gid_idx;
if (addr->sa_family == AF_INET)
memcpy(&roce_gids->addr.sockaddr_in, addr, sizeof(roce_gids->addr.sockaddr_in));
else
memcpy(&roce_gids->addr.sockaddr_in6, addr, sizeof(roce_gids->addr.sockaddr_in6));
list_add_tail(&roce_gids->roce_gid_list_entry, &macsec_device->macsec_roce_gids);
}
static void handle_macsec_gids(struct list_head *macsec_devices_list,
struct mlx5_macsec_event_data *data)
{
struct mlx5_macsec_device *macsec_device;
struct mlx5_roce_gids *gid;
macsec_device = get_macsec_device(data->macdev, macsec_devices_list);
if (!macsec_device)
return;
list_for_each_entry(gid, &macsec_device->macsec_roce_gids, roce_gid_list_entry) {
mlx5_macsec_add_roce_sa_rules(data->fs_id, (struct sockaddr *)&gid->addr,
gid->gid_idx, &macsec_device->tx_rules_list,
&macsec_device->rx_rules_list, data->macsec_fs,
data->is_tx);
}
}
static void del_sa_roce_rule(struct list_head *macsec_devices_list,
struct mlx5_macsec_event_data *data)
{
struct mlx5_macsec_device *macsec_device;
macsec_device = get_macsec_device(data->macdev, macsec_devices_list);
WARN_ON(!macsec_device);
mlx5_macsec_del_roce_sa_rules(data->fs_id, data->macsec_fs,
&macsec_device->tx_rules_list,
&macsec_device->rx_rules_list, data->is_tx);
}
static int macsec_event(struct notifier_block *nb, unsigned long event, void *data)
{
struct mlx5_macsec *macsec = container_of(nb, struct mlx5_macsec, blocking_events_nb);
mutex_lock(&macsec->lock);
switch (event) {
case MLX5_DRIVER_EVENT_MACSEC_SA_ADDED:
handle_macsec_gids(&macsec->macsec_devices_list, data);
break;
case MLX5_DRIVER_EVENT_MACSEC_SA_DELETED:
del_sa_roce_rule(&macsec->macsec_devices_list, data);
break;
default:
mutex_unlock(&macsec->lock);
return NOTIFY_DONE;
}
mutex_unlock(&macsec->lock);
return NOTIFY_OK;
}
void mlx5r_macsec_event_register(struct mlx5_ib_dev *dev)
{
if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
return;
}
dev->macsec.blocking_events_nb.notifier_call = macsec_event;
blocking_notifier_chain_register(&dev->mdev->macsec_nh,
&dev->macsec.blocking_events_nb);
}
void mlx5r_macsec_event_unregister(struct mlx5_ib_dev *dev)
{
if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
return;
}
blocking_notifier_chain_unregister(&dev->mdev->macsec_nh,
&dev->macsec.blocking_events_nb);
}
int mlx5r_macsec_init_gids_and_devlist(struct mlx5_ib_dev *dev)
{
int i, j, max_gids;
if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
return 0;
}
max_gids = MLX5_CAP_ROCE(dev->mdev, roce_address_table_size);
for (i = 0; i < dev->num_ports; i++) {
dev->port[i].reserved_gids = kcalloc(max_gids,
sizeof(*dev->port[i].reserved_gids),
GFP_KERNEL);
if (!dev->port[i].reserved_gids)
goto err;
for (j = 0; j < max_gids; j++)
dev->port[i].reserved_gids[j].macsec_index = -1;
}
INIT_LIST_HEAD(&dev->macsec.macsec_devices_list);
mutex_init(&dev->macsec.lock);
return 0;
err:
while (i >= 0) {
kfree(dev->port[i].reserved_gids);
i--;
}
return -ENOMEM;
}
void mlx5r_macsec_dealloc_gids(struct mlx5_ib_dev *dev)
{
int i;
if (!mlx5_is_macsec_roce_supported(dev->mdev))
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
for (i = 0; i < dev->num_ports; i++)
kfree(dev->port[i].reserved_gids);
mutex_destroy(&dev->macsec.lock);
}
int mlx5r_add_gid_macsec_operations(const struct ib_gid_attr *attr)
{
struct mlx5_ib_dev *dev = to_mdev(attr->device);
struct mlx5_macsec_device *macsec_device;
const struct ib_gid_attr *physical_gid;
struct mlx5_reserved_gids *mgids;
struct net_device *ndev;
int ret = 0;
union {
struct sockaddr_in sockaddr_in;
struct sockaddr_in6 sockaddr_in6;
} addr;
if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
return 0;
if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
return 0;
}
rcu_read_lock();
ndev = rcu_dereference(attr->ndev);
if (!ndev) {
rcu_read_unlock();
return -ENODEV;
}
if (!netif_is_macsec(ndev) || !macsec_netdev_is_offloaded(ndev)) {
rcu_read_unlock();
return 0;
}
dev_hold(ndev);
rcu_read_unlock();
mutex_lock(&dev->macsec.lock);
macsec_device = get_macsec_device(ndev, &dev->macsec.macsec_devices_list);
if (!macsec_device) {
ret = -ENOMEM;
goto dev_err;
}
physical_gid = rdma_find_gid(attr->device, &attr->gid,
attr->gid_type, NULL);
if (!IS_ERR(physical_gid)) {
ret = set_roce_addr(to_mdev(physical_gid->device),
physical_gid->port_num,
physical_gid->index, NULL,
physical_gid);
if (ret)
goto gid_err;
mgids = &dev->port[attr->port_num - 1].reserved_gids[physical_gid->index];
mgids->macsec_index = attr->index;
mgids->physical_gid = physical_gid;
}
/* Proceed with adding steering rules, regardless if there was gid ambiguity or not.*/
rdma_gid2ip((struct sockaddr *)&addr, &attr->gid);
ret = mlx5_macsec_add_roce_rule(ndev, (struct sockaddr *)&addr, attr->index,
&macsec_device->tx_rules_list,
&macsec_device->rx_rules_list, dev->mdev->macsec_fs);
if (ret && !IS_ERR(physical_gid))
goto rule_err;
mlx5_macsec_save_roce_gid(macsec_device, (struct sockaddr *)&addr, attr->index);
dev_put(ndev);
mutex_unlock(&dev->macsec.lock);
return ret;
rule_err:
set_roce_addr(to_mdev(physical_gid->device), physical_gid->port_num,
physical_gid->index, &physical_gid->gid, physical_gid);
mgids->macsec_index = -1;
gid_err:
rdma_put_gid_attr(physical_gid);
cleanup_macsec_device(macsec_device);
dev_err:
dev_put(ndev);
mutex_unlock(&dev->macsec.lock);
return ret;
}
void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr)
{
struct mlx5_ib_dev *dev = to_mdev(attr->device);
struct mlx5_macsec_device *macsec_device;
struct mlx5_reserved_gids *mgids;
struct net_device *ndev;
int i, max_gids;
if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
return;
if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
return;
}
mgids = &dev->port[attr->port_num - 1].reserved_gids[attr->index];
if (mgids->macsec_index != -1) { /* Checking if physical gid has ambiguous IP */
rdma_put_gid_attr(mgids->physical_gid);
mgids->macsec_index = -1;
return;
}
rcu_read_lock();
ndev = rcu_dereference(attr->ndev);
if (!ndev) {
rcu_read_unlock();
return;
}
if (!netif_is_macsec(ndev) || !macsec_netdev_is_offloaded(ndev)) {
rcu_read_unlock();
return;
}
dev_hold(ndev);
rcu_read_unlock();
mutex_lock(&dev->macsec.lock);
max_gids = MLX5_CAP_ROCE(dev->mdev, roce_address_table_size);
for (i = 0; i < max_gids; i++) { /* Checking if macsec gid has ambiguous IP */
mgids = &dev->port[attr->port_num - 1].reserved_gids[i];
if (mgids->macsec_index == attr->index) {
const struct ib_gid_attr *physical_gid = mgids->physical_gid;
set_roce_addr(to_mdev(physical_gid->device),
physical_gid->port_num,
physical_gid->index,
&physical_gid->gid, physical_gid);
rdma_put_gid_attr(physical_gid);
mgids->macsec_index = -1;
break;
}
}
macsec_device = get_macsec_device(ndev, &dev->macsec.macsec_devices_list);
mlx5_macsec_del_roce_rule(attr->index, dev->mdev->macsec_fs,
&macsec_device->tx_rules_list, &macsec_device->rx_rules_list);
mlx5_macsec_del_roce_gid(macsec_device, attr->index);
cleanup_macsec_device(macsec_device);
dev_put(ndev);
mutex_unlock(&dev->macsec.lock);
}

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
#ifndef __MLX5_MACSEC_H__
#define __MLX5_MACSEC_H__
#include <net/macsec.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_addr.h>
#include "mlx5_ib.h"
#ifdef CONFIG_MLX5_MACSEC
struct mlx5_reserved_gids;
int mlx5r_add_gid_macsec_operations(const struct ib_gid_attr *attr);
void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr);
int mlx5r_macsec_init_gids_and_devlist(struct mlx5_ib_dev *dev);
void mlx5r_macsec_dealloc_gids(struct mlx5_ib_dev *dev);
void mlx5r_macsec_event_register(struct mlx5_ib_dev *dev);
void mlx5r_macsec_event_unregister(struct mlx5_ib_dev *dev);
#else
static inline int mlx5r_add_gid_macsec_operations(const struct ib_gid_attr *attr) { return 0; }
static inline void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr) {}
static inline int mlx5r_macsec_init_gids_and_devlist(struct mlx5_ib_dev *dev) { return 0; }
static inline void mlx5r_macsec_dealloc_gids(struct mlx5_ib_dev *dev) {}
static inline void mlx5r_macsec_event_register(struct mlx5_ib_dev *dev) {}
static inline void mlx5r_macsec_event_unregister(struct mlx5_ib_dev *dev) {}
#endif
#endif /* __MLX5_MACSEC_H__ */

View File

@ -46,6 +46,7 @@
#include <rdma/uverbs_ioctl.h>
#include <rdma/mlx5_user_ioctl_verbs.h>
#include <rdma/mlx5_user_ioctl_cmds.h>
#include "macsec.h"
#define UVERBS_MODULE_NAME mlx5_ib
#include <rdma/uverbs_named_ioctl.h>
@ -564,9 +565,9 @@ out:
return err;
}
static int set_roce_addr(struct mlx5_ib_dev *dev, u32 port_num,
unsigned int index, const union ib_gid *gid,
const struct ib_gid_attr *attr)
int set_roce_addr(struct mlx5_ib_dev *dev, u32 port_num,
unsigned int index, const union ib_gid *gid,
const struct ib_gid_attr *attr)
{
enum ib_gid_type gid_type;
u16 vlan_id = 0xffff;
@ -607,6 +608,12 @@ static int set_roce_addr(struct mlx5_ib_dev *dev, u32 port_num,
static int mlx5_ib_add_gid(const struct ib_gid_attr *attr,
__always_unused void **context)
{
int ret;
ret = mlx5r_add_gid_macsec_operations(attr);
if (ret)
return ret;
return set_roce_addr(to_mdev(attr->device), attr->port_num,
attr->index, &attr->gid, attr);
}
@ -614,8 +621,15 @@ static int mlx5_ib_add_gid(const struct ib_gid_attr *attr,
static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
__always_unused void **context)
{
return set_roce_addr(to_mdev(attr->device), attr->port_num,
attr->index, NULL, attr);
int ret;
ret = set_roce_addr(to_mdev(attr->device), attr->port_num,
attr->index, NULL, attr);
if (ret)
return ret;
mlx5r_del_gid_macsec_operations(attr);
return 0;
}
__be16 mlx5_get_roce_udp_sport_min(const struct mlx5_ib_dev *dev,
@ -3644,13 +3658,13 @@ static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
mutex_destroy(&dev->cap_mask_mutex);
WARN_ON(!xa_empty(&dev->sig_mrs));
WARN_ON(!bitmap_empty(dev->dm.memic_alloc_pages, MLX5_MAX_MEMIC_PAGES));
mlx5r_macsec_dealloc_gids(dev);
}
static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
{
struct mlx5_core_dev *mdev = dev->mdev;
int err;
int i;
int err, i;
dev->ib_dev.node_type = RDMA_NODE_IB_CA;
dev->ib_dev.local_dma_lkey = 0 /* not supported for now */;
@ -3670,10 +3684,14 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
if (err)
return err;
err = mlx5_ib_init_multiport_master(dev);
err = mlx5r_macsec_init_gids_and_devlist(dev);
if (err)
return err;
err = mlx5_ib_init_multiport_master(dev);
if (err)
goto err;
err = set_has_smi_cap(dev);
if (err)
goto err_mp;
@ -3697,7 +3715,8 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
spin_lock_init(&dev->dm.lock);
dev->dm.dev = mdev;
return 0;
err:
mlx5r_macsec_dealloc_gids(dev);
err_mp:
mlx5_ib_cleanup_multiport_master(dev);
return err;
@ -4106,11 +4125,15 @@ static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
{
dev->mdev_events.notifier_call = mlx5_ib_event;
mlx5_notifier_register(dev->mdev, &dev->mdev_events);
mlx5r_macsec_event_register(dev);
return 0;
}
static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev)
{
mlx5r_macsec_event_unregister(dev);
mlx5_notifier_unregister(dev->mdev, &dev->mdev_events);
}

View File

@ -26,6 +26,7 @@
#include "srq.h"
#include "qp.h"
#include "macsec.h"
#define mlx5_ib_dbg(_dev, format, arg...) \
dev_dbg(&(_dev)->ib_dev.dev, "%s:%d:(pid %d): " format, __func__, \
@ -870,6 +871,9 @@ struct mlx5_ib_port {
struct mlx5_ib_dbg_cc_params *dbg_cc_params;
struct mlx5_roce roce;
struct mlx5_eswitch_rep *rep;
#ifdef CONFIG_MLX5_MACSEC
struct mlx5_reserved_gids *reserved_gids;
#endif
};
struct mlx5_ib_dbg_param {
@ -1086,6 +1090,12 @@ struct mlx5_special_mkeys {
__be32 terminate_scatter_list_mkey;
};
struct mlx5_macsec {
struct mutex lock; /* Protects mlx5_macsec internal contexts */
struct list_head macsec_devices_list;
struct notifier_block blocking_events_nb;
};
struct mlx5_ib_dev {
struct ib_device ib_dev;
struct mlx5_core_dev *mdev;
@ -1145,6 +1155,10 @@ struct mlx5_ib_dev {
u16 pkey_table_len;
u8 lag_ports;
struct mlx5_special_mkeys mkeys;
#ifdef CONFIG_MLX5_MACSEC
struct mlx5_macsec macsec;
#endif
};
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
@ -1648,4 +1662,7 @@ static inline bool mlx5_umem_needs_ats(struct mlx5_ib_dev *dev,
return access_flags & IB_ACCESS_RELAXED_ORDERING;
}
int set_roce_addr(struct mlx5_ib_dev *dev, u32 port_num,
unsigned int index, const union ib_gid *gid,
const struct ib_gid_attr *attr);
#endif /* MLX5_IB_H */

View File

@ -140,7 +140,7 @@ config MLX5_CORE_IPOIB
help
MLX5 IPoIB offloads & acceleration support.
config MLX5_EN_MACSEC
config MLX5_MACSEC
bool "Connect-X support for MACSec offload"
depends on MLX5_CORE_EN
depends on MACSEC

View File

@ -98,7 +98,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib
#
mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o
mlx5_core-$(CONFIG_MLX5_EN_MACSEC) += en_accel/macsec.o en_accel/macsec_fs.o \
mlx5_core-$(CONFIG_MLX5_MACSEC) += en_accel/macsec.o lib/macsec_fs.o \
en_accel/macsec_stats.o
mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \

View File

@ -917,7 +917,7 @@ struct mlx5e_priv {
const struct mlx5e_profile *profile;
void *ppriv;
#ifdef CONFIG_MLX5_EN_MACSEC
#ifdef CONFIG_MLX5_MACSEC
struct mlx5e_macsec *macsec;
#endif
#ifdef CONFIG_MLX5_EN_IPSEC

View File

@ -138,7 +138,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
}
#endif
#ifdef CONFIG_MLX5_EN_MACSEC
#ifdef CONFIG_MLX5_MACSEC
if (unlikely(mlx5e_macsec_skb_is_offload(skb))) {
struct mlx5e_priv *priv = netdev_priv(dev);
@ -173,7 +173,7 @@ static inline void mlx5e_accel_tx_eseg(struct mlx5e_priv *priv,
mlx5e_ipsec_tx_build_eseg(priv, skb, eseg);
#endif
#ifdef CONFIG_MLX5_EN_MACSEC
#ifdef CONFIG_MLX5_MACSEC
if (unlikely(mlx5e_macsec_skb_is_offload(skb)))
mlx5e_macsec_tx_build_eseg(priv->macsec, skb, eseg);
#endif

View File

@ -10,7 +10,6 @@
#include "lib/aso.h"
#include "lib/crypto.h"
#include "en_accel/macsec.h"
#include "en_accel/macsec_fs.h"
#define MLX5_MACSEC_EPN_SCOPE_MID 0x80000000L
#define MLX5E_MACSEC_ASO_CTX_SZ MLX5_ST_SZ_BYTES(macsec_aso)
@ -66,9 +65,7 @@ struct mlx5e_macsec_sa {
ssci_t ssci;
salt_t salt;
struct rhash_head hash;
u32 fs_id;
union mlx5e_macsec_rule *macsec_rule;
union mlx5_macsec_rule *macsec_rule;
struct rcu_head rcu_head;
struct mlx5e_macsec_epn_state epn_state;
};
@ -106,14 +103,6 @@ struct mlx5e_macsec_aso {
u32 pdn;
};
static const struct rhashtable_params rhash_sci = {
.key_len = sizeof_field(struct mlx5e_macsec_sa, sci),
.key_offset = offsetof(struct mlx5e_macsec_sa, sci),
.head_offset = offsetof(struct mlx5e_macsec_sa, hash),
.automatic_shrinking = true,
.min_size = 1,
};
struct mlx5e_macsec_device {
const struct net_device *netdev;
struct mlx5e_macsec_sa *tx_sa[MACSEC_NUM_AN];
@ -125,20 +114,13 @@ struct mlx5e_macsec_device {
struct mlx5e_macsec {
struct list_head macsec_device_list_head;
int num_of_devices;
struct mlx5e_macsec_fs *macsec_fs;
struct mutex lock; /* Protects mlx5e_macsec internal contexts */
/* Tx sci -> fs id mapping handling */
struct rhashtable sci_hash; /* sci -> mlx5e_macsec_sa */
/* Rx fs_id -> rx_sc mapping */
struct xarray sc_xarray;
struct mlx5_core_dev *mdev;
/* Stats manage */
struct mlx5e_macsec_stats stats;
/* ASO */
struct mlx5e_macsec_aso aso;
@ -330,36 +312,30 @@ static void mlx5e_macsec_destroy_object(struct mlx5_core_dev *mdev, u32 macsec_o
static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec,
struct mlx5e_macsec_sa *sa,
bool is_tx)
bool is_tx, struct net_device *netdev, u32 fs_id)
{
int action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT :
MLX5_ACCEL_MACSEC_ACTION_DECRYPT;
if ((is_tx) && sa->fs_id) {
/* Make sure ongoing datapath readers sees a valid SA */
rhashtable_remove_fast(&macsec->sci_hash, &sa->hash, rhash_sci);
sa->fs_id = 0;
}
if (!sa->macsec_rule)
return;
mlx5e_macsec_fs_del_rule(macsec->macsec_fs, sa->macsec_rule, action);
mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action, netdev,
fs_id);
mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id);
sa->macsec_rule = NULL;
}
static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
struct mlx5e_macsec_sa *sa,
bool encrypt,
bool is_tx)
bool encrypt, bool is_tx, u32 *fs_id)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec *macsec = priv->macsec;
struct mlx5_macsec_rule_attrs rule_attrs;
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5_macsec_obj_attrs obj_attrs;
union mlx5e_macsec_rule *macsec_rule;
union mlx5_macsec_rule *macsec_rule;
int err;
obj_attrs.next_pn = sa->next_pn;
@ -387,7 +363,7 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT :
MLX5_ACCEL_MACSEC_ACTION_DECRYPT;
macsec_rule = mlx5e_macsec_fs_add_rule(macsec->macsec_fs, ctx, &rule_attrs, &sa->fs_id);
macsec_rule = mlx5_macsec_fs_add_rule(mdev->macsec_fs, ctx, &rule_attrs, fs_id);
if (!macsec_rule) {
err = -ENOMEM;
goto destroy_macsec_object;
@ -395,16 +371,8 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
sa->macsec_rule = macsec_rule;
if (is_tx) {
err = rhashtable_insert_fast(&macsec->sci_hash, &sa->hash, rhash_sci);
if (err)
goto destroy_macsec_object_and_rule;
}
return 0;
destroy_macsec_object_and_rule:
mlx5e_macsec_cleanup_sa(macsec, sa, is_tx);
destroy_macsec_object:
mlx5e_macsec_destroy_object(mdev, sa->macsec_obj_id);
@ -426,7 +394,7 @@ mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head *list, sci_t sci)
static int macsec_rx_sa_active_update(struct macsec_context *ctx,
struct mlx5e_macsec_sa *rx_sa,
bool active)
bool active, u32 *fs_id)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec *macsec = priv->macsec;
@ -437,11 +405,11 @@ static int macsec_rx_sa_active_update(struct macsec_context *ctx,
rx_sa->active = active;
if (!active) {
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, *fs_id);
return 0;
}
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false);
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, fs_id);
if (err)
rx_sa->active = false;
@ -563,7 +531,7 @@ static int mlx5e_macsec_add_txsa(struct macsec_context *ctx)
!tx_sa->active)
goto out;
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true);
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL);
if (err)
goto destroy_encryption_key;
@ -627,7 +595,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
goto out;
if (ctx_tx_sa->active) {
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true);
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL);
if (err)
goto out;
} else {
@ -636,7 +604,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
goto out;
}
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
}
out:
mutex_unlock(&macsec->lock);
@ -669,7 +637,7 @@ static int mlx5e_macsec_del_txsa(struct macsec_context *ctx)
goto out;
}
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
kfree_rcu_mightsleep(tx_sa);
macsec_device->tx_sa[assoc_num] = NULL;
@ -680,20 +648,6 @@ out:
return err;
}
static u32 mlx5e_macsec_get_sa_from_hashtable(struct rhashtable *sci_hash, sci_t *sci)
{
struct mlx5e_macsec_sa *macsec_sa;
u32 fs_id = 0;
rcu_read_lock();
macsec_sa = rhashtable_lookup(sci_hash, sci, rhash_sci);
if (macsec_sa)
fs_id = macsec_sa->fs_id;
rcu_read_unlock();
return fs_id;
}
static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx)
{
struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
@ -813,7 +767,8 @@ static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
if (!rx_sa)
continue;
err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active);
err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active,
&rx_sc->sc_xarray_element->fs_id);
if (err)
goto out;
}
@ -824,7 +779,8 @@ out:
return err;
}
static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc)
static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc,
struct net_device *netdev)
{
struct mlx5e_macsec_sa *rx_sa;
int i;
@ -834,7 +790,8 @@ static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec
if (!rx_sa)
continue;
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, netdev,
rx_sc->sc_xarray_element->fs_id);
mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
kfree(rx_sa);
@ -882,7 +839,7 @@ static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
goto out;
}
macsec_del_rxsc_ctx(macsec, rx_sc);
macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
out:
mutex_unlock(&macsec->lock);
@ -941,7 +898,6 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
rx_sa->next_pn = ctx_rx_sa->next_pn;
rx_sa->sci = sci;
rx_sa->assoc_num = assoc_num;
rx_sa->fs_id = rx_sc->sc_xarray_element->fs_id;
if (ctx->secy->xpn)
update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves,
@ -958,7 +914,7 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
goto out;
//TODO - add support for both authentication and encryption flows
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false);
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, &rx_sc->sc_xarray_element->fs_id);
if (err)
goto destroy_encryption_key;
@ -1025,7 +981,8 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
goto out;
}
err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active);
err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active,
&rx_sc->sc_xarray_element->fs_id);
out:
mutex_unlock(&macsec->lock);
@ -1073,7 +1030,8 @@ static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx)
goto out;
}
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev,
rx_sc->sc_xarray_element->fs_id);
mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
kfree(rx_sa);
rx_sc->rx_sa[assoc_num] = NULL;
@ -1154,7 +1112,8 @@ static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
if (!rx_sa || !rx_sa->macsec_rule)
continue;
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev,
rx_sc->sc_xarray_element->fs_id);
}
}
@ -1165,7 +1124,8 @@ static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
continue;
if (rx_sa->active) {
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false);
err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false,
&rx_sc->sc_xarray_element->fs_id);
if (err)
goto out;
}
@ -1218,7 +1178,7 @@ static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
if (!tx_sa)
continue;
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
}
for (i = 0; i < MACSEC_NUM_AN; ++i) {
@ -1227,7 +1187,7 @@ static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
continue;
if (tx_sa->assoc_num == tx_sc->encoding_sa && tx_sa->active) {
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true);
err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL);
if (err)
goto out;
}
@ -1265,7 +1225,7 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
if (!tx_sa)
continue;
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
kfree(tx_sa);
macsec_device->tx_sa[i] = NULL;
@ -1273,7 +1233,7 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
list = &macsec_device->macsec_rx_sc_list_head;
list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element)
macsec_del_rxsc_ctx(macsec, rx_sc);
macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
kfree(macsec_device->dev_addr);
macsec_device->dev_addr = NULL;
@ -1647,50 +1607,6 @@ static void mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso *aso, struct mlx5_c
mlx5_core_dealloc_pd(mdev, aso->pdn);
}
bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev)
{
if (!(MLX5_CAP_GEN_64(mdev, general_obj_types) &
MLX5_GENERAL_OBJ_TYPES_CAP_MACSEC_OFFLOAD))
return false;
if (!MLX5_CAP_GEN(mdev, log_max_dek))
return false;
if (!MLX5_CAP_MACSEC(mdev, log_max_macsec_offload))
return false;
if (!MLX5_CAP_FLOWTABLE_NIC_RX(mdev, macsec_decrypt) ||
!MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_remove_macsec))
return false;
if (!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, macsec_encrypt) ||
!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_macsec))
return false;
if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_encrypt) &&
!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_encrypt))
return false;
if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_decrypt) &&
!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_decrypt))
return false;
return true;
}
void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats)
{
mlx5e_macsec_fs_get_stats_fill(macsec->macsec_fs, macsec_stats);
}
struct mlx5e_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec)
{
if (!macsec)
return NULL;
return &macsec->stats;
}
static const struct macsec_ops macsec_offload_ops = {
.mdo_add_txsa = mlx5e_macsec_add_txsa,
.mdo_upd_txsa = mlx5e_macsec_upd_txsa,
@ -1711,7 +1627,8 @@ bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb
struct metadata_dst *md_dst = skb_metadata_dst(skb);
u32 fs_id;
fs_id = mlx5e_macsec_get_sa_from_hashtable(&macsec->sci_hash, &md_dst->u.macsec_info.sci);
fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
&md_dst->u.macsec_info.sci);
if (!fs_id)
goto err_out;
@ -1729,7 +1646,8 @@ void mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec *macsec,
struct metadata_dst *md_dst = skb_metadata_dst(skb);
u32 fs_id;
fs_id = mlx5e_macsec_get_sa_from_hashtable(&macsec->sci_hash, &md_dst->u.macsec_info.sci);
fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
&md_dst->u.macsec_info.sci);
if (!fs_id)
return;
@ -1782,7 +1700,7 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv)
{
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_macsec *macsec = NULL;
struct mlx5e_macsec_fs *macsec_fs;
struct mlx5_macsec_fs *macsec_fs;
int err;
if (!mlx5e_is_macsec_device(priv->mdev)) {
@ -1797,13 +1715,6 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv)
INIT_LIST_HEAD(&macsec->macsec_device_list_head);
mutex_init(&macsec->lock);
err = rhashtable_init(&macsec->sci_hash, &rhash_sci);
if (err) {
mlx5_core_err(mdev, "MACsec offload: Failed to init SCI hash table, err=%d\n",
err);
goto err_hash;
}
err = mlx5e_macsec_aso_init(&macsec->aso, priv->mdev);
if (err) {
mlx5_core_err(mdev, "MACsec offload: Failed to init aso, err=%d\n", err);
@ -1822,13 +1733,13 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv)
macsec->mdev = mdev;
macsec_fs = mlx5e_macsec_fs_init(mdev, priv->netdev);
macsec_fs = mlx5_macsec_fs_init(mdev);
if (!macsec_fs) {
err = -ENOMEM;
goto err_out;
}
macsec->macsec_fs = macsec_fs;
mdev->macsec_fs = macsec_fs;
macsec->nb.notifier_call = macsec_obj_change_event;
mlx5_notifier_register(mdev, &macsec->nb);
@ -1842,8 +1753,6 @@ err_out:
err_wq:
mlx5e_macsec_aso_cleanup(&macsec->aso, priv->mdev);
err_aso:
rhashtable_destroy(&macsec->sci_hash);
err_hash:
kfree(macsec);
priv->macsec = NULL;
return err;
@ -1858,10 +1767,9 @@ void mlx5e_macsec_cleanup(struct mlx5e_priv *priv)
return;
mlx5_notifier_unregister(mdev, &macsec->nb);
mlx5e_macsec_fs_cleanup(macsec->macsec_fs);
mlx5_macsec_fs_cleanup(mdev->macsec_fs);
destroy_workqueue(macsec->wq);
mlx5e_macsec_aso_cleanup(&macsec->aso, mdev);
rhashtable_destroy(&macsec->sci_hash);
mutex_destroy(&macsec->lock);
kfree(macsec);
}

View File

@ -4,32 +4,16 @@
#ifndef __MLX5_EN_ACCEL_MACSEC_H__
#define __MLX5_EN_ACCEL_MACSEC_H__
#ifdef CONFIG_MLX5_EN_MACSEC
#ifdef CONFIG_MLX5_MACSEC
#include <linux/mlx5/driver.h>
#include <net/macsec.h>
#include <net/dst_metadata.h>
/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */
#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */
#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX
#define MLX5_MACSEC_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x1)
#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata) ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK)
#include "lib/macsec_fs.h"
struct mlx5e_priv;
struct mlx5e_macsec;
struct mlx5e_macsec_stats {
u64 macsec_rx_pkts;
u64 macsec_rx_bytes;
u64 macsec_rx_pkts_drop;
u64 macsec_rx_bytes_drop;
u64 macsec_tx_pkts;
u64 macsec_tx_bytes;
u64 macsec_tx_pkts_drop;
u64 macsec_tx_bytes_drop;
};
void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv);
int mlx5e_macsec_init(struct mlx5e_priv *priv);
void mlx5e_macsec_cleanup(struct mlx5e_priv *priv);
@ -52,9 +36,6 @@ static inline bool mlx5e_macsec_is_rx_flow(struct mlx5_cqe64 *cqe)
void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
struct mlx5_cqe64 *cqe);
bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev);
void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats);
struct mlx5e_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec);
#else
@ -67,7 +48,6 @@ static inline void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
struct sk_buff *skb,
struct mlx5_cqe64 *cqe)
{}
static inline bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) { return false; }
#endif /* CONFIG_MLX5_EN_MACSEC */
#endif /* CONFIG_MLX5_MACSEC */
#endif /* __MLX5_ACCEL_EN_MACSEC_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#ifndef __MLX5_MACSEC_STEERING_H__
#define __MLX5_MACSEC_STEERING_H__
#ifdef CONFIG_MLX5_EN_MACSEC
#include "en_accel/macsec.h"
#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16
struct mlx5e_macsec_fs;
union mlx5e_macsec_rule;
struct mlx5_macsec_rule_attrs {
sci_t sci;
u32 macsec_obj_id;
u8 assoc_num;
int action;
};
enum mlx5_macsec_action {
MLX5_ACCEL_MACSEC_ACTION_ENCRYPT,
MLX5_ACCEL_MACSEC_ACTION_DECRYPT,
};
void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs);
struct mlx5e_macsec_fs *
mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev);
union mlx5e_macsec_rule *
mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs,
const struct macsec_context *ctx,
struct mlx5_macsec_rule_attrs *attrs,
u32 *sa_fs_id);
void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs,
union mlx5e_macsec_rule *macsec_rule,
int action);
void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats);
#endif
#endif /* __MLX5_MACSEC_STEERING_H__ */

View File

@ -8,14 +8,14 @@
#include "en_accel/macsec.h"
static const struct counter_desc mlx5e_macsec_hw_stats_desc[] = {
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_pkts) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_bytes) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_pkts_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_bytes_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_pkts) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_bytes) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_pkts_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_bytes_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_pkts) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_bytes) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_pkts_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_bytes_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_pkts) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_bytes) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_pkts_drop) },
{ MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_bytes_drop) },
};
#define NUM_MACSEC_HW_COUNTERS ARRAY_SIZE(mlx5e_macsec_hw_stats_desc)
@ -52,6 +52,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(macsec_hw)
static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(macsec_hw)
{
struct mlx5_macsec_fs *macsec_fs;
int i;
if (!priv->macsec)
@ -60,9 +61,10 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(macsec_hw)
if (!mlx5e_is_macsec_device(priv->mdev))
return idx;
mlx5e_macsec_get_stats_fill(priv->macsec, mlx5e_macsec_get_stats(priv->macsec));
macsec_fs = priv->mdev->macsec_fs;
mlx5_macsec_fs_get_stats_fill(macsec_fs, mlx5_macsec_fs_get_stats(macsec_fs));
for (i = 0; i < NUM_MACSEC_HW_COUNTERS; i++)
data[idx++] = MLX5E_READ_CTR64_CPU(mlx5e_macsec_get_stats(priv->macsec),
data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_macsec_fs_get_stats(macsec_fs),
mlx5e_macsec_hw_stats_desc,
i);

View File

@ -2502,7 +2502,7 @@ mlx5e_stats_grp_t mlx5e_nic_stats_grps[] = {
&MLX5E_STATS_GRP(per_port_buff_congest),
&MLX5E_STATS_GRP(ptp),
&MLX5E_STATS_GRP(qos),
#ifdef CONFIG_MLX5_EN_MACSEC
#ifdef CONFIG_MLX5_MACSEC
&MLX5E_STATS_GRP(macsec_hw),
#endif
};

View File

@ -975,6 +975,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions);
table_type = FS_FT_ESW_INGRESS_ACL;
break;
case MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC:
case MLX5_FLOW_NAMESPACE_RDMA_TX:
max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions);
table_type = FS_FT_RDMA_TX;

View File

@ -107,7 +107,7 @@
LEFTOVERS_NUM_PRIOS)
#define KERNEL_RX_MACSEC_NUM_PRIOS 1
#define KERNEL_RX_MACSEC_NUM_LEVELS 2
#define KERNEL_RX_MACSEC_NUM_LEVELS 3
#define KERNEL_RX_MACSEC_MIN_LEVEL (BY_PASS_MIN_LEVEL + KERNEL_RX_MACSEC_NUM_PRIOS)
#define ETHTOOL_PRIO_NUM_LEVELS 1
@ -224,6 +224,7 @@ static struct init_tree_node egress_root_fs = {
enum {
RDMA_RX_IPSEC_PRIO,
RDMA_RX_MACSEC_PRIO,
RDMA_RX_COUNTERS_PRIO,
RDMA_RX_BYPASS_PRIO,
RDMA_RX_KERNEL_PRIO,
@ -237,9 +238,13 @@ enum {
#define RDMA_RX_KERNEL_MIN_LEVEL (RDMA_RX_BYPASS_MIN_LEVEL + 1)
#define RDMA_RX_COUNTERS_MIN_LEVEL (RDMA_RX_KERNEL_MIN_LEVEL + 2)
#define RDMA_RX_MACSEC_NUM_PRIOS 1
#define RDMA_RX_MACSEC_PRIO_NUM_LEVELS 2
#define RDMA_RX_MACSEC_MIN_LEVEL (RDMA_RX_COUNTERS_MIN_LEVEL + RDMA_RX_MACSEC_NUM_PRIOS)
static struct init_tree_node rdma_rx_root_fs = {
.type = FS_TYPE_NAMESPACE,
.ar_size = 4,
.ar_size = 5,
.children = (struct init_tree_node[]) {
[RDMA_RX_IPSEC_PRIO] =
ADD_PRIO(0, RDMA_RX_IPSEC_MIN_LEVEL, 0,
@ -247,6 +252,12 @@ static struct init_tree_node rdma_rx_root_fs = {
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(RDMA_RX_IPSEC_NUM_PRIOS,
RDMA_RX_IPSEC_NUM_LEVELS))),
[RDMA_RX_MACSEC_PRIO] =
ADD_PRIO(0, RDMA_RX_MACSEC_MIN_LEVEL, 0,
FS_CHAINING_CAPS,
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(RDMA_RX_MACSEC_NUM_PRIOS,
RDMA_RX_MACSEC_PRIO_NUM_LEVELS))),
[RDMA_RX_COUNTERS_PRIO] =
ADD_PRIO(0, RDMA_RX_COUNTERS_MIN_LEVEL, 0,
FS_CHAINING_CAPS,
@ -270,6 +281,7 @@ static struct init_tree_node rdma_rx_root_fs = {
enum {
RDMA_TX_COUNTERS_PRIO,
RDMA_TX_IPSEC_PRIO,
RDMA_TX_MACSEC_PRIO,
RDMA_TX_BYPASS_PRIO,
};
@ -280,9 +292,13 @@ enum {
#define RDMA_TX_IPSEC_PRIO_NUM_LEVELS 1
#define RDMA_TX_IPSEC_MIN_LEVEL (RDMA_TX_COUNTERS_MIN_LEVEL + RDMA_TX_IPSEC_NUM_PRIOS)
#define RDMA_TX_MACSEC_NUM_PRIOS 1
#define RDMA_TX_MACESC_PRIO_NUM_LEVELS 1
#define RDMA_TX_MACSEC_MIN_LEVEL (RDMA_TX_COUNTERS_MIN_LEVEL + RDMA_TX_MACSEC_NUM_PRIOS)
static struct init_tree_node rdma_tx_root_fs = {
.type = FS_TYPE_NAMESPACE,
.ar_size = 3,
.ar_size = 4,
.children = (struct init_tree_node[]) {
[RDMA_TX_COUNTERS_PRIO] =
ADD_PRIO(0, RDMA_TX_COUNTERS_MIN_LEVEL, 0,
@ -296,7 +312,12 @@ static struct init_tree_node rdma_tx_root_fs = {
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(RDMA_TX_IPSEC_NUM_PRIOS,
RDMA_TX_IPSEC_PRIO_NUM_LEVELS))),
[RDMA_TX_MACSEC_PRIO] =
ADD_PRIO(0, RDMA_TX_MACSEC_MIN_LEVEL, 0,
FS_CHAINING_CAPS,
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(RDMA_TX_MACSEC_NUM_PRIOS,
RDMA_TX_MACESC_PRIO_NUM_LEVELS))),
[RDMA_TX_BYPASS_PRIO] =
ADD_PRIO(0, RDMA_TX_BYPASS_MIN_LEVEL, 0,
FS_CHAINING_CAPS_RDMA_TX,
@ -2466,6 +2487,14 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
root_ns = steering->rdma_tx_root_ns;
prio = RDMA_TX_IPSEC_PRIO;
break;
case MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC:
root_ns = steering->rdma_rx_root_ns;
prio = RDMA_RX_MACSEC_PRIO;
break;
case MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC:
root_ns = steering->rdma_tx_root_ns;
prio = RDMA_TX_MACSEC_PRIO;
break;
default: /* Must be NIC RX */
WARN_ON(!is_nic_rx_ns(type));
root_ns = steering->root_ns;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#ifndef __MLX5_MACSEC_STEERING_H__
#define __MLX5_MACSEC_STEERING_H__
#ifdef CONFIG_MLX5_MACSEC
/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */
#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */
#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX
#define MLX5_MACSEC_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x1)
#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata) ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK)
#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16
struct mlx5_macsec_fs;
union mlx5_macsec_rule;
struct mlx5_macsec_rule_attrs {
sci_t sci;
u32 macsec_obj_id;
u8 assoc_num;
int action;
};
struct mlx5_macsec_stats {
u64 macsec_rx_pkts;
u64 macsec_rx_bytes;
u64 macsec_rx_pkts_drop;
u64 macsec_rx_bytes_drop;
u64 macsec_tx_pkts;
u64 macsec_tx_bytes;
u64 macsec_tx_pkts_drop;
u64 macsec_tx_bytes_drop;
};
enum mlx5_macsec_action {
MLX5_ACCEL_MACSEC_ACTION_ENCRYPT,
MLX5_ACCEL_MACSEC_ACTION_DECRYPT,
};
void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs);
struct mlx5_macsec_fs *
mlx5_macsec_fs_init(struct mlx5_core_dev *mdev);
union mlx5_macsec_rule *
mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs,
const struct macsec_context *ctx,
struct mlx5_macsec_rule_attrs *attrs,
u32 *sa_fs_id);
void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs,
union mlx5_macsec_rule *macsec_rule,
int action, void *macdev, u32 sa_fs_id);
void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats);
struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec_fs);
u32 mlx5_macsec_fs_get_fs_id_from_hashtable(struct mlx5_macsec_fs *macsec_fs, sci_t *sci);
#endif
#endif /* __MLX5_MACSEC_STEERING_H__ */

View File

@ -4229,6 +4229,18 @@ static struct net *macsec_get_link_net(const struct net_device *dev)
return dev_net(macsec_priv(dev)->real_dev);
}
struct net_device *macsec_get_real_dev(const struct net_device *dev)
{
return macsec_priv(dev)->real_dev;
}
EXPORT_SYMBOL_GPL(macsec_get_real_dev);
bool macsec_netdev_is_offloaded(struct net_device *dev)
{
return macsec_is_offloaded(macsec_priv(dev));
}
EXPORT_SYMBOL_GPL(macsec_netdev_is_offloaded);
static size_t macsec_get_size(const struct net_device *dev)
{
return nla_total_size_64bit(8) + /* IFLA_MACSEC_SCI */

View File

@ -364,6 +364,8 @@ enum mlx5_event {
enum mlx5_driver_event {
MLX5_DRIVER_EVENT_TYPE_TRAP = 0,
MLX5_DRIVER_EVENT_UPLINK_NETDEV,
MLX5_DRIVER_EVENT_MACSEC_SA_ADDED,
MLX5_DRIVER_EVENT_MACSEC_SA_DELETED,
};
enum {

View File

@ -727,7 +727,6 @@ struct mlx5_fw_tracer;
struct mlx5_vxlan;
struct mlx5_geneve;
struct mlx5_hv_vhca;
struct mlx5_thermal;
#define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev) (MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity))
#define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev))
@ -809,6 +808,11 @@ struct mlx5_core_dev {
struct mlx5_hwmon *hwmon;
u64 num_block_tc;
u64 num_block_ipsec;
#ifdef CONFIG_MLX5_MACSEC
struct mlx5_macsec_fs *macsec_fs;
/* MACsec notifier chain to sync MACsec core and IB database */
struct blocking_notifier_head macsec_nh;
#endif
};
struct mlx5_db {
@ -1322,6 +1326,52 @@ static inline bool mlx5_get_roce_state(struct mlx5_core_dev *dev)
return mlx5_is_roce_on(dev);
}
#ifdef CONFIG_MLX5_MACSEC
static inline bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev)
{
if (!(MLX5_CAP_GEN_64(mdev, general_obj_types) &
MLX5_GENERAL_OBJ_TYPES_CAP_MACSEC_OFFLOAD))
return false;
if (!MLX5_CAP_GEN(mdev, log_max_dek))
return false;
if (!MLX5_CAP_MACSEC(mdev, log_max_macsec_offload))
return false;
if (!MLX5_CAP_FLOWTABLE_NIC_RX(mdev, macsec_decrypt) ||
!MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_remove_macsec))
return false;
if (!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, macsec_encrypt) ||
!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_macsec))
return false;
if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_encrypt) &&
!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_encrypt))
return false;
if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_decrypt) &&
!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_decrypt))
return false;
return true;
}
#define NIC_RDMA_BOTH_DIRS_CAPS (MLX5_FT_NIC_RX_2_NIC_RX_RDMA | MLX5_FT_NIC_TX_RDMA_2_NIC_TX)
static inline bool mlx5_is_macsec_roce_supported(struct mlx5_core_dev *mdev)
{
if (((MLX5_CAP_GEN_2(mdev, flow_table_type_2_type) &
NIC_RDMA_BOTH_DIRS_CAPS) != NIC_RDMA_BOTH_DIRS_CAPS) ||
!MLX5_CAP_FLOWTABLE_RDMA_TX(mdev, max_modify_header_actions) ||
!mlx5e_is_macsec_device(mdev) || !mdev->macsec_fs)
return false;
return true;
}
#endif
enum {
MLX5_OCTWORD = 16,
};

View File

@ -105,6 +105,8 @@ enum mlx5_flow_namespace_type {
MLX5_FLOW_NAMESPACE_RDMA_TX_COUNTERS,
MLX5_FLOW_NAMESPACE_RDMA_RX_IPSEC,
MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC,
MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC,
MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC,
};
enum {

View File

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
#ifndef MLX5_MACSEC_H
#define MLX5_MACSEC_H
#ifdef CONFIG_MLX5_MACSEC
struct mlx5_macsec_event_data {
struct mlx5_macsec_fs *macsec_fs;
void *macdev;
u32 fs_id;
bool is_tx;
};
int mlx5_macsec_add_roce_rule(void *macdev, const struct sockaddr *addr, u16 gid_idx,
struct list_head *tx_rules_list, struct list_head *rx_rules_list,
struct mlx5_macsec_fs *macsec_fs);
void mlx5_macsec_del_roce_rule(u16 gid_idx, struct mlx5_macsec_fs *macsec_fs,
struct list_head *tx_rules_list, struct list_head *rx_rules_list);
void mlx5_macsec_add_roce_sa_rules(u32 fs_id, const struct sockaddr *addr, u16 gid_idx,
struct list_head *tx_rules_list,
struct list_head *rx_rules_list,
struct mlx5_macsec_fs *macsec_fs, bool is_tx);
void mlx5_macsec_del_roce_sa_rules(u32 fs_id, struct mlx5_macsec_fs *macsec_fs,
struct list_head *tx_rules_list,
struct list_head *rx_rules_list, bool is_tx);
#endif
#endif /* MLX5_MACSEC_H */

View File

@ -312,6 +312,8 @@ static inline bool macsec_send_sci(const struct macsec_secy *secy)
return tx_sc->send_sci ||
(secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb);
}
struct net_device *macsec_get_real_dev(const struct net_device *dev);
bool macsec_netdev_is_offloaded(struct net_device *dev);
static inline void *macsec_netdev_priv(const struct net_device *dev)
{