diff options
author | Yinjun Zhang <yinjun.zhang@corigine.com> | 2022-06-24 10:38:15 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-06-28 08:06:59 +0300 |
commit | be80141108bc043c71f5fffdfefa75b1e3e6f441 (patch) | |
tree | 784fc1602a58726713b1ccdf742dafdce1e71b02 /drivers/net/ethernet/netronome/nfp/nfp_net_common.c | |
parent | 63769819079d87dc322fefaf981589e227de2978 (diff) | |
download | linux-be80141108bc043c71f5fffdfefa75b1e3e6f441.tar.xz |
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: Yinjun Zhang <yinjun.zhang@corigine.com>
Reviewed-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/netronome/nfp/nfp_net_common.c')
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 57f284eefeb3..0991fc122998 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -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 ? |