nfp: support vepa mode in HW bridge
authorYinjun Zhang <yinjun.zhang@corigine.com>
Fri, 24 Jun 2022 07:38:15 +0000 (09:38 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 28 Jun 2022 05:06:59 +0000 (22:06 -0700)
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>
drivers/net/ethernet/netronome/nfp/nfd3/rings.c
drivers/net/ethernet/netronome/nfp/nfdk/rings.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h

index f31eabd..f65851e 100644 (file)
@@ -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 |       \
index f4d94ae..222ee0e 100644 (file)
@@ -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 |       \
index 57f284e..0991fc1 100644 (file)
@@ -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 ?
index 8892a94..9007675 100644 (file)
@@ -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 */