Commit be801411 authored by Yinjun Zhang's avatar Yinjun Zhang Committed by Jakub Kicinski
Browse files

nfp: support vepa mode in HW bridge



Add support for VEPA mode of HW bridge.
The default remains VEB mode.
The mode may be configured using ndo_bridge_setlink,
and inspected using ndo_bridge_getlink.

Signed-off-by: default avatarYinjun Zhang <yinjun.zhang@corigine.com>
Reviewed-by: default avatarLouis Peens <louis.peens@corigine.com>
Signed-off-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 63769819
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -251,6 +251,7 @@ nfp_nfd3_print_tx_descs(struct seq_file *file,
	 NFP_NET_CFG_CTRL_CTAG_FILTER | NFP_NET_CFG_CTRL_CMSG_DATA |	\
	 NFP_NET_CFG_CTRL_RINGCFG | NFP_NET_CFG_CTRL_RSS |		\
	 NFP_NET_CFG_CTRL_IRQMOD | NFP_NET_CFG_CTRL_TXRWB |		\
	 NFP_NET_CFG_CTRL_VEPA |					\
	 NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE |		\
	 NFP_NET_CFG_CTRL_BPF | NFP_NET_CFG_CTRL_LSO2 |			\
	 NFP_NET_CFG_CTRL_RSS2 | NFP_NET_CFG_CTRL_CSUM_COMPLETE |	\
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ nfp_nfdk_print_tx_descs(struct seq_file *file,
	 NFP_NET_CFG_CTRL_GATHER | NFP_NET_CFG_CTRL_LSO |		\
	 NFP_NET_CFG_CTRL_CTAG_FILTER | NFP_NET_CFG_CTRL_CMSG_DATA |	\
	 NFP_NET_CFG_CTRL_RINGCFG | NFP_NET_CFG_CTRL_IRQMOD |		\
	 NFP_NET_CFG_CTRL_TXRWB |					\
	 NFP_NET_CFG_CTRL_TXRWB | NFP_NET_CFG_CTRL_VEPA |		\
	 NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE |		\
	 NFP_NET_CFG_CTRL_BPF | NFP_NET_CFG_CTRL_LSO2 |			\
	 NFP_NET_CFG_CTRL_RSS2 | NFP_NET_CFG_CTRL_CSUM_COMPLETE |	\
+70 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/ethtool.h>
#include <linux/log2.h>
#include <linux/if_vlan.h>
#include <linux/if_bridge.h>
#include <linux/random.h>
#include <linux/vmalloc.h>
#include <linux/ktime.h>
@@ -1892,6 +1893,69 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
	return 0;
}

static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
				  struct net_device *dev, u32 filter_mask,
				  int nlflags)
{
	struct nfp_net *nn = netdev_priv(dev);
	u16 mode;

	if (!(nn->cap & NFP_NET_CFG_CTRL_VEPA))
		return -EOPNOTSUPP;

	mode = (nn->dp.ctrl & NFP_NET_CFG_CTRL_VEPA) ?
	       BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;

	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0,
				       nlflags, filter_mask, NULL);
}

static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
				  u16 flags, struct netlink_ext_ack *extack)
{
	struct nfp_net *nn = netdev_priv(dev);
	struct nlattr *attr, *br_spec;
	int rem, err;
	u32 new_ctrl;
	u16 mode;

	if (!(nn->cap & NFP_NET_CFG_CTRL_VEPA))
		return -EOPNOTSUPP;

	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
	if (!br_spec)
		return -EINVAL;

	nla_for_each_nested(attr, br_spec, rem) {
		if (nla_type(attr) != IFLA_BRIDGE_MODE)
			continue;

		if (nla_len(attr) < sizeof(mode))
			return -EINVAL;

		new_ctrl = nn->dp.ctrl;
		mode = nla_get_u16(attr);
		if (mode == BRIDGE_MODE_VEPA)
			new_ctrl |= NFP_NET_CFG_CTRL_VEPA;
		else if (mode == BRIDGE_MODE_VEB)
			new_ctrl &= ~NFP_NET_CFG_CTRL_VEPA;
		else
			return -EOPNOTSUPP;

		if (new_ctrl == nn->dp.ctrl)
			return 0;

		nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl);
		err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
		if (!err)
			nn->dp.ctrl = new_ctrl;

		return err;
	}

	return -EINVAL;
}

const struct net_device_ops nfp_nfd3_netdev_ops = {
	.ndo_init		= nfp_app_ndo_init,
	.ndo_uninit		= nfp_app_ndo_uninit,
@@ -1919,6 +1983,8 @@ const struct net_device_ops nfp_nfd3_netdev_ops = {
	.ndo_bpf		= nfp_net_xdp,
	.ndo_xsk_wakeup		= nfp_net_xsk_wakeup,
	.ndo_get_devlink_port	= nfp_devlink_get_devlink_port,
	.ndo_bridge_getlink     = nfp_net_bridge_getlink,
	.ndo_bridge_setlink     = nfp_net_bridge_setlink,
};

const struct net_device_ops nfp_nfdk_netdev_ops = {
@@ -1946,6 +2012,8 @@ const struct net_device_ops nfp_nfdk_netdev_ops = {
	.ndo_get_phys_port_name	= nfp_net_get_phys_port_name,
	.ndo_bpf		= nfp_net_xdp,
	.ndo_get_devlink_port	= nfp_devlink_get_devlink_port,
	.ndo_bridge_getlink     = nfp_net_bridge_getlink,
	.ndo_bridge_setlink     = nfp_net_bridge_setlink,
};

static int nfp_udp_tunnel_sync(struct net_device *netdev, unsigned int table)
@@ -1993,7 +2061,7 @@ void nfp_net_info(struct nfp_net *nn)
		nn->fw_ver.extend, nn->fw_ver.class,
		nn->fw_ver.major, nn->fw_ver.minor,
		nn->max_mtu);
	nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
	nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
		nn->cap,
		nn->cap & NFP_NET_CFG_CTRL_PROMISC  ? "PROMISC "  : "",
		nn->cap & NFP_NET_CFG_CTRL_L2BC     ? "L2BCFILT " : "",
@@ -2012,6 +2080,7 @@ void nfp_net_info(struct nfp_net *nn)
		nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO ? "AUTOMASK " : "",
		nn->cap & NFP_NET_CFG_CTRL_IRQMOD   ? "IRQMOD "   : "",
		nn->cap & NFP_NET_CFG_CTRL_TXRWB    ? "TXRWB "    : "",
		nn->cap & NFP_NET_CFG_CTRL_VEPA     ? "VEPA "     : "",
		nn->cap & NFP_NET_CFG_CTRL_VXLAN    ? "VXLAN "    : "",
		nn->cap & NFP_NET_CFG_CTRL_NVGRE    ? "NVGRE "	  : "",
		nn->cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ?
+1 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@
#define   NFP_NET_CFG_CTRL_IRQMOD	  (0x1 << 18) /* Interrupt moderation */
#define   NFP_NET_CFG_CTRL_MSIXAUTO	  (0x1 << 20) /* MSI-X auto-masking */
#define   NFP_NET_CFG_CTRL_TXRWB	  (0x1 << 21) /* Write-back of TX ring*/
#define   NFP_NET_CFG_CTRL_VEPA		  (0x1 << 22) /* Enable VEPA mode */
#define   NFP_NET_CFG_CTRL_VXLAN	  (0x1 << 24) /* VXLAN tunnel support */
#define   NFP_NET_CFG_CTRL_NVGRE	  (0x1 << 25) /* NVGRE tunnel support */
#define   NFP_NET_CFG_CTRL_BPF		  (0x1 << 27) /* BPF offload capable */