Commit 1cf3fe1c authored by David S. Miller's avatar David S. Miller

Merge branch 'macsec-vlan'

Emeel Hakim says:

====================
Support MACsec VLAN

This patch series introduces support for hardware (HW) offload MACsec
devices with VLAN configuration. The patches address both scenarios
where the VLAN header is both the inner and outer header for MACsec.

The changes include:

1. Adding MACsec offload operation for VLAN.
2. Considering VLAN when accessing MACsec net device.
3. Currently offloading MACsec when it's configured over VLAN with
current MACsec TX steering rules would wrongly insert the MACsec sec tag
after inserting the VLAN header. This resulted in an ETHERNET | SECTAG |
VLAN packet when ETHERNET | VLAN | SECTAG is configured. The patche
handles this issue when configuring steering rules.
4. Adding MACsec rx_handler change support in case of a marked skb and a
mismatch on the dst MAC address.

Please review these changes and let me know if you have any feedback or
concerns.

Updates since v1:
- Consult vlan_features when adding NETIF_F_HW_MACSEC.
- Allow grep for the functions.
- Add helper function to get the macsec operation to allow the compiler
  to make some choice.

Updates since v2:
- Don't use macros to allow direct navigattion from mdo functions to its
  implementation.
- Make the vlan_get_macsec_ops argument a const.
- Check if the specific mdo function is available before calling it.
- Enable NETIF_F_HW_MACSEC by default when the lower device has it enabled
  and in case the lower device currently has NETIF_F_HW_MACSEC but disabled
  let the new vlan device also have it disabled.

Updates since v3:
- Split patch ("vlan: Add MACsec offload operations for VLAN interface")
  to prevent mixing generic vlan code changes with driver changes.
- Add mdo_open, stop and stats to support drivers which have those.
- Don't fail if macsec offload operations are available but a specific
  function is not, to support drivers which does not implement all
  macsec offload operations.
- Don't call find_rx_sc twice in the same loop, instead save the result
  in a parameter and re-use it.
- Completely remove _BUILD_VLAN_MACSEC_MDO macro, to prevent returning
  from a macro.
- Reorder the functions inside struct macsec_ops to match the struct
  decleration.

 Updates since v4:
 - Change subject line of ("macsec: Add MACsec rx_handler change support") and adapt commit message.
 - Don't separate the new check in patch ("macsec: Add MACsec rx_handler change support")
   from the previous if/else if.
 - Drop"_found" from the parameter naming "rx_sc_found" and move the definition to
   the relevant block.
 - Remove "{}" since not needed around a single line.

 Updates since v5:
 - Consider promiscuous mode case.

 Updates since v6:
 - Use IS_ENABLED instead of checking for ifdef.
 - Don't add inline keywork in c files, let the compiler make its own decisions.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e2598dbd 7661351a
......@@ -4,6 +4,7 @@
#include <linux/mlx5/device.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/xarray.h>
#include <linux/if_vlan.h>
#include "en.h"
#include "lib/aso.h"
......@@ -348,12 +349,21 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec,
sa->macsec_rule = NULL;
}
static struct mlx5e_priv *macsec_netdev_priv(const struct net_device *dev)
{
#if IS_ENABLED(CONFIG_VLAN_8021Q)
if (is_vlan_dev(dev))
return netdev_priv(vlan_dev_priv(dev)->real_dev);
#endif
return netdev_priv(dev);
}
static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
struct mlx5e_macsec_sa *sa,
bool encrypt,
bool is_tx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
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;
......@@ -427,7 +437,7 @@ static int macsec_rx_sa_active_update(struct macsec_context *ctx,
struct mlx5e_macsec_sa *rx_sa,
bool active)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec *macsec = priv->macsec;
int err = 0;
......@@ -508,9 +518,9 @@ static void update_macsec_epn(struct mlx5e_macsec_sa *sa, const struct macsec_ke
static int mlx5e_macsec_add_txsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
const struct macsec_secy *secy = ctx->secy;
struct mlx5e_macsec_device *macsec_device;
struct mlx5_core_dev *mdev = priv->mdev;
......@@ -583,9 +593,9 @@ static int mlx5e_macsec_add_txsa(struct macsec_context *ctx)
static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
u8 assoc_num = ctx->sa.assoc_num;
struct mlx5e_macsec_sa *tx_sa;
......@@ -645,7 +655,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
static int mlx5e_macsec_del_txsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
u8 assoc_num = ctx->sa.assoc_num;
struct mlx5e_macsec_sa *tx_sa;
......@@ -696,7 +706,7 @@ static u32 mlx5e_macsec_get_sa_from_hashtable(struct rhashtable *sci_hash, sci_t
static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx)
{
struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc;
struct mlx5e_macsec_device *macsec_device;
struct mlx5e_macsec_rx_sc *rx_sc;
......@@ -776,7 +786,7 @@ static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx)
static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc;
struct mlx5e_macsec_device *macsec_device;
struct mlx5e_macsec_rx_sc *rx_sc;
......@@ -854,7 +864,7 @@ static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec
static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
struct mlx5e_macsec_rx_sc *rx_sc;
struct mlx5e_macsec *macsec;
......@@ -890,8 +900,8 @@ static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
struct mlx5_core_dev *mdev = priv->mdev;
u8 assoc_num = ctx->sa.assoc_num;
......@@ -976,8 +986,8 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
u8 assoc_num = ctx->sa.assoc_num;
struct mlx5e_macsec_rx_sc *rx_sc;
......@@ -1033,7 +1043,7 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
sci_t sci = ctx->sa.rx_sa->sc->sci;
struct mlx5e_macsec_rx_sc *rx_sc;
......@@ -1085,7 +1095,7 @@ static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx)
static int mlx5e_macsec_add_secy(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct net_device *dev = ctx->secy->netdev;
const struct net_device *netdev = ctx->netdev;
struct mlx5e_macsec_device *macsec_device;
......@@ -1137,7 +1147,7 @@ static int mlx5e_macsec_add_secy(struct macsec_context *ctx)
static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
struct mlx5e_macsec_device *macsec_device)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct net_device *dev = ctx->secy->netdev;
struct mlx5e_macsec *macsec = priv->macsec;
struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
......@@ -1184,8 +1194,8 @@ static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
*/
static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
const struct net_device *dev = ctx->secy->netdev;
struct mlx5e_macsec_device *macsec_device;
struct mlx5e_macsec_sa *tx_sa;
......@@ -1240,7 +1250,7 @@ static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
{
struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5e_macsec_device *macsec_device;
struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
struct mlx5e_macsec_sa *tx_sa;
......@@ -1741,7 +1751,7 @@ void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
{
struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
u32 macsec_meta_data = be32_to_cpu(cqe->ft_metadata);
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_priv *priv = macsec_netdev_priv(netdev);
struct mlx5e_macsec_rx_sc *rx_sc;
struct mlx5e_macsec *macsec;
u32 fs_id;
......
......@@ -4,6 +4,7 @@
#include <net/macsec.h>
#include <linux/netdevice.h>
#include <linux/mlx5/qp.h>
#include <linux/if_vlan.h>
#include "fs_core.h"
#include "en/fs.h"
#include "en_accel/macsec_fs.h"
......@@ -508,6 +509,8 @@ static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs,
macsec_fs_tx_ft_put(macsec_fs);
}
#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1
static union mlx5e_macsec_rule *
macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
const struct macsec_context *macsec_ctx,
......@@ -553,6 +556,10 @@ macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC;
reformat_params.size = reformat_size;
reformat_params.data = reformatbf;
if (is_vlan_dev(macsec_ctx->netdev))
reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES;
flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev,
&reformat_params,
MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
......
......@@ -5109,6 +5109,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
netdev->vlan_features |= NETIF_F_SG;
netdev->vlan_features |= NETIF_F_HW_CSUM;
netdev->vlan_features |= NETIF_F_HW_MACSEC;
netdev->vlan_features |= NETIF_F_GRO;
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
......
......@@ -1021,8 +1021,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
* the SecTAG, so we have to deduce which port to deliver to.
*/
if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
if (md_dst && md_dst->type == METADATA_MACSEC &&
(!find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci)))
struct macsec_rx_sc *rx_sc = NULL;
if (md_dst && md_dst->type == METADATA_MACSEC)
rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci);
if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc)
continue;
if (ether_addr_equal_64bits(hdr->h_dest,
......@@ -1047,7 +1051,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
nskb->pkt_type = PACKET_MULTICAST;
__netif_rx(nskb);
} else if (rx_sc || ndev->flags & IFF_PROMISC) {
skb->dev = ndev;
skb->pkt_type = PACKET_HOST;
ret = RX_HANDLER_ANOTHER;
goto out;
}
continue;
}
......
......@@ -26,6 +26,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <net/arp.h>
#include <net/macsec.h>
#include "vlan.h"
#include "vlanproc.h"
......@@ -572,6 +573,9 @@ static int vlan_dev_init(struct net_device *dev)
NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
NETIF_F_ALL_FCOE;
if (real_dev->vlan_features & NETIF_F_HW_MACSEC)
dev->hw_features |= NETIF_F_HW_MACSEC;
dev->features |= dev->hw_features | NETIF_F_LLTX;
netif_inherit_tso_max(dev, real_dev);
if (dev->features & NETIF_F_VLAN_FEATURES)
......@@ -803,6 +807,241 @@ static int vlan_dev_fill_forward_path(struct net_device_path_ctx *ctx,
return 0;
}
#if IS_ENABLED(CONFIG_MACSEC)
static const struct macsec_ops *vlan_get_macsec_ops(const struct macsec_context *ctx)
{
return vlan_dev_priv(ctx->netdev)->real_dev->macsec_ops;
}
static int vlan_macsec_offload(int (* const func)(struct macsec_context *),
struct macsec_context *ctx)
{
if (unlikely(!func))
return 0;
return (*func)(ctx);
}
static int vlan_macsec_dev_open(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_dev_open, ctx);
}
static int vlan_macsec_dev_stop(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_dev_stop, ctx);
}
static int vlan_macsec_add_secy(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_add_secy, ctx);
}
static int vlan_macsec_upd_secy(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_upd_secy, ctx);
}
static int vlan_macsec_del_secy(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_del_secy, ctx);
}
static int vlan_macsec_add_rxsc(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_add_rxsc, ctx);
}
static int vlan_macsec_upd_rxsc(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_upd_rxsc, ctx);
}
static int vlan_macsec_del_rxsc(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_del_rxsc, ctx);
}
static int vlan_macsec_add_rxsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_add_rxsa, ctx);
}
static int vlan_macsec_upd_rxsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_upd_rxsa, ctx);
}
static int vlan_macsec_del_rxsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_del_rxsa, ctx);
}
static int vlan_macsec_add_txsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_add_txsa, ctx);
}
static int vlan_macsec_upd_txsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_upd_txsa, ctx);
}
static int vlan_macsec_del_txsa(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_del_txsa, ctx);
}
static int vlan_macsec_get_dev_stats(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_get_dev_stats, ctx);
}
static int vlan_macsec_get_tx_sc_stats(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_get_tx_sc_stats, ctx);
}
static int vlan_macsec_get_tx_sa_stats(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_get_tx_sa_stats, ctx);
}
static int vlan_macsec_get_rx_sc_stats(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_get_rx_sc_stats, ctx);
}
static int vlan_macsec_get_rx_sa_stats(struct macsec_context *ctx)
{
const struct macsec_ops *ops = vlan_get_macsec_ops(ctx);
if (!ops)
return -EOPNOTSUPP;
return vlan_macsec_offload(ops->mdo_get_rx_sa_stats, ctx);
}
static const struct macsec_ops macsec_offload_ops = {
/* Device wide */
.mdo_dev_open = vlan_macsec_dev_open,
.mdo_dev_stop = vlan_macsec_dev_stop,
/* SecY */
.mdo_add_secy = vlan_macsec_add_secy,
.mdo_upd_secy = vlan_macsec_upd_secy,
.mdo_del_secy = vlan_macsec_del_secy,
/* Security channels */
.mdo_add_rxsc = vlan_macsec_add_rxsc,
.mdo_upd_rxsc = vlan_macsec_upd_rxsc,
.mdo_del_rxsc = vlan_macsec_del_rxsc,
/* Security associations */
.mdo_add_rxsa = vlan_macsec_add_rxsa,
.mdo_upd_rxsa = vlan_macsec_upd_rxsa,
.mdo_del_rxsa = vlan_macsec_del_rxsa,
.mdo_add_txsa = vlan_macsec_add_txsa,
.mdo_upd_txsa = vlan_macsec_upd_txsa,
.mdo_del_txsa = vlan_macsec_del_txsa,
/* Statistics */
.mdo_get_dev_stats = vlan_macsec_get_dev_stats,
.mdo_get_tx_sc_stats = vlan_macsec_get_tx_sc_stats,
.mdo_get_tx_sa_stats = vlan_macsec_get_tx_sa_stats,
.mdo_get_rx_sc_stats = vlan_macsec_get_rx_sc_stats,
.mdo_get_rx_sa_stats = vlan_macsec_get_rx_sa_stats,
};
#endif
static const struct ethtool_ops vlan_ethtool_ops = {
.get_link_ksettings = vlan_ethtool_get_link_ksettings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
......@@ -869,6 +1108,9 @@ void vlan_setup(struct net_device *dev)
dev->priv_destructor = vlan_dev_free;
dev->ethtool_ops = &vlan_ethtool_ops;
#if IS_ENABLED(CONFIG_MACSEC)
dev->macsec_ops = &macsec_offload_ops;
#endif
dev->min_mtu = 0;
dev->max_mtu = ETH_MAX_MTU;
......
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