linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
   3
   4#include <linux/if_bridge.h>
   5#include <linux/list.h>
   6#include <net/arp.h>
   7#include <net/gre.h>
   8#include <net/lag.h>
   9#include <net/ndisc.h>
  10#include <net/ip6_tunnel.h>
  11
  12#include "spectrum.h"
  13#include "spectrum_ipip.h"
  14#include "spectrum_span.h"
  15#include "spectrum_switchdev.h"
  16
  17int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
  18{
  19        int i;
  20
  21        if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
  22                return -EIO;
  23
  24        mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
  25                                                          MAX_SPAN);
  26        mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
  27                                         sizeof(struct mlxsw_sp_span_entry),
  28                                         GFP_KERNEL);
  29        if (!mlxsw_sp->span.entries)
  30                return -ENOMEM;
  31
  32        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
  33                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
  34
  35                INIT_LIST_HEAD(&curr->bound_ports_list);
  36                curr->id = i;
  37        }
  38
  39        return 0;
  40}
  41
  42void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
  43{
  44        int i;
  45
  46        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
  47                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
  48
  49                WARN_ON_ONCE(!list_empty(&curr->bound_ports_list));
  50        }
  51        kfree(mlxsw_sp->span.entries);
  52}
  53
  54static int
  55mlxsw_sp_span_entry_phys_parms(const struct net_device *to_dev,
  56                               struct mlxsw_sp_span_parms *sparmsp)
  57{
  58        sparmsp->dest_port = netdev_priv(to_dev);
  59        return 0;
  60}
  61
  62static int
  63mlxsw_sp_span_entry_phys_configure(struct mlxsw_sp_span_entry *span_entry,
  64                                   struct mlxsw_sp_span_parms sparms)
  65{
  66        struct mlxsw_sp_port *dest_port = sparms.dest_port;
  67        struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
  68        u8 local_port = dest_port->local_port;
  69        char mpat_pl[MLXSW_REG_MPAT_LEN];
  70        int pa_id = span_entry->id;
  71
  72        /* Create a new port analayzer entry for local_port. */
  73        mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
  74                            MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
  75
  76        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
  77}
  78
  79static void
  80mlxsw_sp_span_entry_deconfigure_common(struct mlxsw_sp_span_entry *span_entry,
  81                                       enum mlxsw_reg_mpat_span_type span_type)
  82{
  83        struct mlxsw_sp_port *dest_port = span_entry->parms.dest_port;
  84        struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
  85        u8 local_port = dest_port->local_port;
  86        char mpat_pl[MLXSW_REG_MPAT_LEN];
  87        int pa_id = span_entry->id;
  88
  89        mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false, span_type);
  90        mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
  91}
  92
  93static void
  94mlxsw_sp_span_entry_phys_deconfigure(struct mlxsw_sp_span_entry *span_entry)
  95{
  96        mlxsw_sp_span_entry_deconfigure_common(span_entry,
  97                                            MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
  98}
  99
 100static const
 101struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_phys = {
 102        .can_handle = mlxsw_sp_port_dev_check,
 103        .parms = mlxsw_sp_span_entry_phys_parms,
 104        .configure = mlxsw_sp_span_entry_phys_configure,
 105        .deconfigure = mlxsw_sp_span_entry_phys_deconfigure,
 106};
 107
 108static int mlxsw_sp_span_dmac(struct neigh_table *tbl,
 109                              const void *pkey,
 110                              struct net_device *dev,
 111                              unsigned char dmac[ETH_ALEN])
 112{
 113        struct neighbour *neigh = neigh_lookup(tbl, pkey, dev);
 114        int err = 0;
 115
 116        if (!neigh) {
 117                neigh = neigh_create(tbl, pkey, dev);
 118                if (IS_ERR(neigh))
 119                        return PTR_ERR(neigh);
 120        }
 121
 122        neigh_event_send(neigh, NULL);
 123
 124        read_lock_bh(&neigh->lock);
 125        if ((neigh->nud_state & NUD_VALID) && !neigh->dead)
 126                memcpy(dmac, neigh->ha, ETH_ALEN);
 127        else
 128                err = -ENOENT;
 129        read_unlock_bh(&neigh->lock);
 130
 131        neigh_release(neigh);
 132        return err;
 133}
 134
 135static int
 136mlxsw_sp_span_entry_unoffloadable(struct mlxsw_sp_span_parms *sparmsp)
 137{
 138        sparmsp->dest_port = NULL;
 139        return 0;
 140}
 141
 142static struct net_device *
 143mlxsw_sp_span_entry_bridge_8021q(const struct net_device *br_dev,
 144                                 unsigned char *dmac,
 145                                 u16 *p_vid)
 146{
 147        struct bridge_vlan_info vinfo;
 148        struct net_device *edev;
 149        u16 vid = *p_vid;
 150
 151        if (!vid && WARN_ON(br_vlan_get_pvid(br_dev, &vid)))
 152                return NULL;
 153        if (!vid ||
 154            br_vlan_get_info(br_dev, vid, &vinfo) ||
 155            !(vinfo.flags & BRIDGE_VLAN_INFO_BRENTRY))
 156                return NULL;
 157
 158        edev = br_fdb_find_port(br_dev, dmac, vid);
 159        if (!edev)
 160                return NULL;
 161
 162        if (br_vlan_get_info(edev, vid, &vinfo))
 163                return NULL;
 164        if (vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED)
 165                *p_vid = 0;
 166        else
 167                *p_vid = vid;
 168        return edev;
 169}
 170
 171static struct net_device *
 172mlxsw_sp_span_entry_bridge_8021d(const struct net_device *br_dev,
 173                                 unsigned char *dmac)
 174{
 175        return br_fdb_find_port(br_dev, dmac, 0);
 176}
 177
 178static struct net_device *
 179mlxsw_sp_span_entry_bridge(const struct net_device *br_dev,
 180                           unsigned char dmac[ETH_ALEN],
 181                           u16 *p_vid)
 182{
 183        struct mlxsw_sp_bridge_port *bridge_port;
 184        enum mlxsw_reg_spms_state spms_state;
 185        struct net_device *dev = NULL;
 186        struct mlxsw_sp_port *port;
 187        u8 stp_state;
 188
 189        if (br_vlan_enabled(br_dev))
 190                dev = mlxsw_sp_span_entry_bridge_8021q(br_dev, dmac, p_vid);
 191        else if (!*p_vid)
 192                dev = mlxsw_sp_span_entry_bridge_8021d(br_dev, dmac);
 193        if (!dev)
 194                return NULL;
 195
 196        port = mlxsw_sp_port_dev_lower_find(dev);
 197        if (!port)
 198                return NULL;
 199
 200        bridge_port = mlxsw_sp_bridge_port_find(port->mlxsw_sp->bridge, dev);
 201        if (!bridge_port)
 202                return NULL;
 203
 204        stp_state = mlxsw_sp_bridge_port_stp_state(bridge_port);
 205        spms_state = mlxsw_sp_stp_spms_state(stp_state);
 206        if (spms_state != MLXSW_REG_SPMS_STATE_FORWARDING)
 207                return NULL;
 208
 209        return dev;
 210}
 211
 212static struct net_device *
 213mlxsw_sp_span_entry_vlan(const struct net_device *vlan_dev,
 214                         u16 *p_vid)
 215{
 216        *p_vid = vlan_dev_vlan_id(vlan_dev);
 217        return vlan_dev_real_dev(vlan_dev);
 218}
 219
 220static struct net_device *
 221mlxsw_sp_span_entry_lag(struct net_device *lag_dev)
 222{
 223        struct net_device *dev;
 224        struct list_head *iter;
 225
 226        netdev_for_each_lower_dev(lag_dev, dev, iter)
 227                if (netif_carrier_ok(dev) &&
 228                    net_lag_port_dev_txable(dev) &&
 229                    mlxsw_sp_port_dev_check(dev))
 230                        return dev;
 231
 232        return NULL;
 233}
 234
 235static __maybe_unused int
 236mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *edev,
 237                                        union mlxsw_sp_l3addr saddr,
 238                                        union mlxsw_sp_l3addr daddr,
 239                                        union mlxsw_sp_l3addr gw,
 240                                        __u8 ttl,
 241                                        struct neigh_table *tbl,
 242                                        struct mlxsw_sp_span_parms *sparmsp)
 243{
 244        unsigned char dmac[ETH_ALEN];
 245        u16 vid = 0;
 246
 247        if (mlxsw_sp_l3addr_is_zero(gw))
 248                gw = daddr;
 249
 250        if (!edev || mlxsw_sp_span_dmac(tbl, &gw, edev, dmac))
 251                goto unoffloadable;
 252
 253        if (is_vlan_dev(edev))
 254                edev = mlxsw_sp_span_entry_vlan(edev, &vid);
 255
 256        if (netif_is_bridge_master(edev)) {
 257                edev = mlxsw_sp_span_entry_bridge(edev, dmac, &vid);
 258                if (!edev)
 259                        goto unoffloadable;
 260        }
 261
 262        if (is_vlan_dev(edev)) {
 263                if (vid || !(edev->flags & IFF_UP))
 264                        goto unoffloadable;
 265                edev = mlxsw_sp_span_entry_vlan(edev, &vid);
 266        }
 267
 268        if (netif_is_lag_master(edev)) {
 269                if (!(edev->flags & IFF_UP))
 270                        goto unoffloadable;
 271                edev = mlxsw_sp_span_entry_lag(edev);
 272                if (!edev)
 273                        goto unoffloadable;
 274        }
 275
 276        if (!mlxsw_sp_port_dev_check(edev))
 277                goto unoffloadable;
 278
 279        sparmsp->dest_port = netdev_priv(edev);
 280        sparmsp->ttl = ttl;
 281        memcpy(sparmsp->dmac, dmac, ETH_ALEN);
 282        memcpy(sparmsp->smac, edev->dev_addr, ETH_ALEN);
 283        sparmsp->saddr = saddr;
 284        sparmsp->daddr = daddr;
 285        sparmsp->vid = vid;
 286        return 0;
 287
 288unoffloadable:
 289        return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 290}
 291
 292#if IS_ENABLED(CONFIG_NET_IPGRE)
 293static struct net_device *
 294mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
 295                            __be32 *saddrp, __be32 *daddrp)
 296{
 297        struct ip_tunnel *tun = netdev_priv(to_dev);
 298        struct net_device *dev = NULL;
 299        struct ip_tunnel_parm parms;
 300        struct rtable *rt = NULL;
 301        struct flowi4 fl4;
 302
 303        /* We assume "dev" stays valid after rt is put. */
 304        ASSERT_RTNL();
 305
 306        parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
 307        ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
 308                            0, 0, parms.link, tun->fwmark, 0);
 309
 310        rt = ip_route_output_key(tun->net, &fl4);
 311        if (IS_ERR(rt))
 312                return NULL;
 313
 314        if (rt->rt_type != RTN_UNICAST)
 315                goto out;
 316
 317        dev = rt->dst.dev;
 318        *saddrp = fl4.saddr;
 319        if (rt->rt_gw_family == AF_INET)
 320                *daddrp = rt->rt_gw4;
 321        /* can not offload if route has an IPv6 gateway */
 322        else if (rt->rt_gw_family == AF_INET6)
 323                dev = NULL;
 324
 325out:
 326        ip_rt_put(rt);
 327        return dev;
 328}
 329
 330static int
 331mlxsw_sp_span_entry_gretap4_parms(const struct net_device *to_dev,
 332                                  struct mlxsw_sp_span_parms *sparmsp)
 333{
 334        struct ip_tunnel_parm tparm = mlxsw_sp_ipip_netdev_parms4(to_dev);
 335        union mlxsw_sp_l3addr saddr = { .addr4 = tparm.iph.saddr };
 336        union mlxsw_sp_l3addr daddr = { .addr4 = tparm.iph.daddr };
 337        bool inherit_tos = tparm.iph.tos & 0x1;
 338        bool inherit_ttl = !tparm.iph.ttl;
 339        union mlxsw_sp_l3addr gw = daddr;
 340        struct net_device *l3edev;
 341
 342        if (!(to_dev->flags & IFF_UP) ||
 343            /* Reject tunnels with GRE keys, checksums, etc. */
 344            tparm.i_flags || tparm.o_flags ||
 345            /* Require a fixed TTL and a TOS copied from the mirrored packet. */
 346            inherit_ttl || !inherit_tos ||
 347            /* A destination address may not be "any". */
 348            mlxsw_sp_l3addr_is_zero(daddr))
 349                return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 350
 351        l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
 352        return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
 353                                                       tparm.iph.ttl,
 354                                                       &arp_tbl, sparmsp);
 355}
 356
 357static int
 358mlxsw_sp_span_entry_gretap4_configure(struct mlxsw_sp_span_entry *span_entry,
 359                                      struct mlxsw_sp_span_parms sparms)
 360{
 361        struct mlxsw_sp_port *dest_port = sparms.dest_port;
 362        struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
 363        u8 local_port = dest_port->local_port;
 364        char mpat_pl[MLXSW_REG_MPAT_LEN];
 365        int pa_id = span_entry->id;
 366
 367        /* Create a new port analayzer entry for local_port. */
 368        mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
 369                            MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
 370        mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
 371        mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
 372                                    MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
 373                                    sparms.dmac, !!sparms.vid);
 374        mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(mpat_pl,
 375                                              sparms.ttl, sparms.smac,
 376                                              be32_to_cpu(sparms.saddr.addr4),
 377                                              be32_to_cpu(sparms.daddr.addr4));
 378
 379        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
 380}
 381
 382static void
 383mlxsw_sp_span_entry_gretap4_deconfigure(struct mlxsw_sp_span_entry *span_entry)
 384{
 385        mlxsw_sp_span_entry_deconfigure_common(span_entry,
 386                                        MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
 387}
 388
 389static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap4 = {
 390        .can_handle = netif_is_gretap,
 391        .parms = mlxsw_sp_span_entry_gretap4_parms,
 392        .configure = mlxsw_sp_span_entry_gretap4_configure,
 393        .deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure,
 394};
 395#endif
 396
 397#if IS_ENABLED(CONFIG_IPV6_GRE)
 398static struct net_device *
 399mlxsw_sp_span_gretap6_route(const struct net_device *to_dev,
 400                            struct in6_addr *saddrp,
 401                            struct in6_addr *daddrp)
 402{
 403        struct ip6_tnl *t = netdev_priv(to_dev);
 404        struct flowi6 fl6 = t->fl.u.ip6;
 405        struct net_device *dev = NULL;
 406        struct dst_entry *dst;
 407        struct rt6_info *rt6;
 408
 409        /* We assume "dev" stays valid after dst is released. */
 410        ASSERT_RTNL();
 411
 412        fl6.flowi6_mark = t->parms.fwmark;
 413        if (!ip6_tnl_xmit_ctl(t, &fl6.saddr, &fl6.daddr))
 414                return NULL;
 415
 416        dst = ip6_route_output(t->net, NULL, &fl6);
 417        if (!dst || dst->error)
 418                goto out;
 419
 420        rt6 = container_of(dst, struct rt6_info, dst);
 421
 422        dev = dst->dev;
 423        *saddrp = fl6.saddr;
 424        *daddrp = rt6->rt6i_gateway;
 425
 426out:
 427        dst_release(dst);
 428        return dev;
 429}
 430
 431static int
 432mlxsw_sp_span_entry_gretap6_parms(const struct net_device *to_dev,
 433                                  struct mlxsw_sp_span_parms *sparmsp)
 434{
 435        struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(to_dev);
 436        bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS;
 437        union mlxsw_sp_l3addr saddr = { .addr6 = tparm.laddr };
 438        union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr };
 439        bool inherit_ttl = !tparm.hop_limit;
 440        union mlxsw_sp_l3addr gw = daddr;
 441        struct net_device *l3edev;
 442
 443        if (!(to_dev->flags & IFF_UP) ||
 444            /* Reject tunnels with GRE keys, checksums, etc. */
 445            tparm.i_flags || tparm.o_flags ||
 446            /* Require a fixed TTL and a TOS copied from the mirrored packet. */
 447            inherit_ttl || !inherit_tos ||
 448            /* A destination address may not be "any". */
 449            mlxsw_sp_l3addr_is_zero(daddr))
 450                return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 451
 452        l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6);
 453        return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
 454                                                       tparm.hop_limit,
 455                                                       &nd_tbl, sparmsp);
 456}
 457
 458static int
 459mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry,
 460                                      struct mlxsw_sp_span_parms sparms)
 461{
 462        struct mlxsw_sp_port *dest_port = sparms.dest_port;
 463        struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
 464        u8 local_port = dest_port->local_port;
 465        char mpat_pl[MLXSW_REG_MPAT_LEN];
 466        int pa_id = span_entry->id;
 467
 468        /* Create a new port analayzer entry for local_port. */
 469        mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
 470                            MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
 471        mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
 472        mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
 473                                    MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
 474                                    sparms.dmac, !!sparms.vid);
 475        mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac,
 476                                              sparms.saddr.addr6,
 477                                              sparms.daddr.addr6);
 478
 479        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
 480}
 481
 482static void
 483mlxsw_sp_span_entry_gretap6_deconfigure(struct mlxsw_sp_span_entry *span_entry)
 484{
 485        mlxsw_sp_span_entry_deconfigure_common(span_entry,
 486                                        MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
 487}
 488
 489static const
 490struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap6 = {
 491        .can_handle = netif_is_ip6gretap,
 492        .parms = mlxsw_sp_span_entry_gretap6_parms,
 493        .configure = mlxsw_sp_span_entry_gretap6_configure,
 494        .deconfigure = mlxsw_sp_span_entry_gretap6_deconfigure,
 495};
 496#endif
 497
 498static bool
 499mlxsw_sp_span_vlan_can_handle(const struct net_device *dev)
 500{
 501        return is_vlan_dev(dev) &&
 502               mlxsw_sp_port_dev_check(vlan_dev_real_dev(dev));
 503}
 504
 505static int
 506mlxsw_sp_span_entry_vlan_parms(const struct net_device *to_dev,
 507                               struct mlxsw_sp_span_parms *sparmsp)
 508{
 509        struct net_device *real_dev;
 510        u16 vid;
 511
 512        if (!(to_dev->flags & IFF_UP))
 513                return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 514
 515        real_dev = mlxsw_sp_span_entry_vlan(to_dev, &vid);
 516        sparmsp->dest_port = netdev_priv(real_dev);
 517        sparmsp->vid = vid;
 518        return 0;
 519}
 520
 521static int
 522mlxsw_sp_span_entry_vlan_configure(struct mlxsw_sp_span_entry *span_entry,
 523                                   struct mlxsw_sp_span_parms sparms)
 524{
 525        struct mlxsw_sp_port *dest_port = sparms.dest_port;
 526        struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
 527        u8 local_port = dest_port->local_port;
 528        char mpat_pl[MLXSW_REG_MPAT_LEN];
 529        int pa_id = span_entry->id;
 530
 531        mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
 532                            MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH);
 533        mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
 534
 535        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
 536}
 537
 538static void
 539mlxsw_sp_span_entry_vlan_deconfigure(struct mlxsw_sp_span_entry *span_entry)
 540{
 541        mlxsw_sp_span_entry_deconfigure_common(span_entry,
 542                                        MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH);
 543}
 544
 545static const
 546struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_vlan = {
 547        .can_handle = mlxsw_sp_span_vlan_can_handle,
 548        .parms = mlxsw_sp_span_entry_vlan_parms,
 549        .configure = mlxsw_sp_span_entry_vlan_configure,
 550        .deconfigure = mlxsw_sp_span_entry_vlan_deconfigure,
 551};
 552
 553static const
 554struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = {
 555        &mlxsw_sp_span_entry_ops_phys,
 556#if IS_ENABLED(CONFIG_NET_IPGRE)
 557        &mlxsw_sp_span_entry_ops_gretap4,
 558#endif
 559#if IS_ENABLED(CONFIG_IPV6_GRE)
 560        &mlxsw_sp_span_entry_ops_gretap6,
 561#endif
 562        &mlxsw_sp_span_entry_ops_vlan,
 563};
 564
 565static int
 566mlxsw_sp_span_entry_nop_parms(const struct net_device *to_dev,
 567                              struct mlxsw_sp_span_parms *sparmsp)
 568{
 569        return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 570}
 571
 572static int
 573mlxsw_sp_span_entry_nop_configure(struct mlxsw_sp_span_entry *span_entry,
 574                                  struct mlxsw_sp_span_parms sparms)
 575{
 576        return 0;
 577}
 578
 579static void
 580mlxsw_sp_span_entry_nop_deconfigure(struct mlxsw_sp_span_entry *span_entry)
 581{
 582}
 583
 584static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_nop = {
 585        .parms = mlxsw_sp_span_entry_nop_parms,
 586        .configure = mlxsw_sp_span_entry_nop_configure,
 587        .deconfigure = mlxsw_sp_span_entry_nop_deconfigure,
 588};
 589
 590static void
 591mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
 592                              struct mlxsw_sp_span_entry *span_entry,
 593                              struct mlxsw_sp_span_parms sparms)
 594{
 595        if (sparms.dest_port) {
 596                if (sparms.dest_port->mlxsw_sp != mlxsw_sp) {
 597                        netdev_err(span_entry->to_dev, "Cannot mirror to %s, which belongs to a different mlxsw instance",
 598                                   sparms.dest_port->dev->name);
 599                        sparms.dest_port = NULL;
 600                } else if (span_entry->ops->configure(span_entry, sparms)) {
 601                        netdev_err(span_entry->to_dev, "Failed to offload mirror to %s",
 602                                   sparms.dest_port->dev->name);
 603                        sparms.dest_port = NULL;
 604                }
 605        }
 606
 607        span_entry->parms = sparms;
 608}
 609
 610static void
 611mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp_span_entry *span_entry)
 612{
 613        if (span_entry->parms.dest_port)
 614                span_entry->ops->deconfigure(span_entry);
 615}
 616
 617static struct mlxsw_sp_span_entry *
 618mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
 619                           const struct net_device *to_dev,
 620                           const struct mlxsw_sp_span_entry_ops *ops,
 621                           struct mlxsw_sp_span_parms sparms)
 622{
 623        struct mlxsw_sp_span_entry *span_entry = NULL;
 624        int i;
 625
 626        /* find a free entry to use */
 627        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 628                if (!mlxsw_sp->span.entries[i].ref_count) {
 629                        span_entry = &mlxsw_sp->span.entries[i];
 630                        break;
 631                }
 632        }
 633        if (!span_entry)
 634                return NULL;
 635
 636        span_entry->ops = ops;
 637        span_entry->ref_count = 1;
 638        span_entry->to_dev = to_dev;
 639        mlxsw_sp_span_entry_configure(mlxsw_sp, span_entry, sparms);
 640
 641        return span_entry;
 642}
 643
 644static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp_span_entry *span_entry)
 645{
 646        mlxsw_sp_span_entry_deconfigure(span_entry);
 647}
 648
 649struct mlxsw_sp_span_entry *
 650mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
 651                                 const struct net_device *to_dev)
 652{
 653        int i;
 654
 655        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 656                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
 657
 658                if (curr->ref_count && curr->to_dev == to_dev)
 659                        return curr;
 660        }
 661        return NULL;
 662}
 663
 664void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
 665                                    struct mlxsw_sp_span_entry *span_entry)
 666{
 667        mlxsw_sp_span_entry_deconfigure(span_entry);
 668        span_entry->ops = &mlxsw_sp_span_entry_ops_nop;
 669}
 670
 671static struct mlxsw_sp_span_entry *
 672mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
 673{
 674        int i;
 675
 676        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 677                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
 678
 679                if (curr->ref_count && curr->id == span_id)
 680                        return curr;
 681        }
 682        return NULL;
 683}
 684
 685static struct mlxsw_sp_span_entry *
 686mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp,
 687                        const struct net_device *to_dev,
 688                        const struct mlxsw_sp_span_entry_ops *ops,
 689                        struct mlxsw_sp_span_parms sparms)
 690{
 691        struct mlxsw_sp_span_entry *span_entry;
 692
 693        span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, to_dev);
 694        if (span_entry) {
 695                /* Already exists, just take a reference */
 696                span_entry->ref_count++;
 697                return span_entry;
 698        }
 699
 700        return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev, ops, sparms);
 701}
 702
 703static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
 704                                   struct mlxsw_sp_span_entry *span_entry)
 705{
 706        WARN_ON(!span_entry->ref_count);
 707        if (--span_entry->ref_count == 0)
 708                mlxsw_sp_span_entry_destroy(span_entry);
 709        return 0;
 710}
 711
 712static bool mlxsw_sp_span_is_egress_mirror(struct mlxsw_sp_port *port)
 713{
 714        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
 715        struct mlxsw_sp_span_inspected_port *p;
 716        int i;
 717
 718        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 719                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
 720
 721                list_for_each_entry(p, &curr->bound_ports_list, list)
 722                        if (p->local_port == port->local_port &&
 723                            p->type == MLXSW_SP_SPAN_EGRESS)
 724                                return true;
 725        }
 726
 727        return false;
 728}
 729
 730static int mlxsw_sp_span_mtu_to_buffsize(const struct mlxsw_sp *mlxsw_sp,
 731                                         int mtu)
 732{
 733        return mlxsw_sp_bytes_cells(mlxsw_sp, mtu * 5 / 2) + 1;
 734}
 735
 736int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu)
 737{
 738        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
 739        char sbib_pl[MLXSW_REG_SBIB_LEN];
 740        int err;
 741
 742        /* If port is egress mirrored, the shared buffer size should be
 743         * updated according to the mtu value
 744         */
 745        if (mlxsw_sp_span_is_egress_mirror(port)) {
 746                u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp, mtu);
 747
 748                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
 749                err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 750                if (err) {
 751                        netdev_err(port->dev, "Could not update shared buffer for mirroring\n");
 752                        return err;
 753                }
 754        }
 755
 756        return 0;
 757}
 758
 759static struct mlxsw_sp_span_inspected_port *
 760mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_span_entry *span_entry,
 761                                    enum mlxsw_sp_span_type type,
 762                                    struct mlxsw_sp_port *port,
 763                                    bool bind)
 764{
 765        struct mlxsw_sp_span_inspected_port *p;
 766
 767        list_for_each_entry(p, &span_entry->bound_ports_list, list)
 768                if (type == p->type &&
 769                    port->local_port == p->local_port &&
 770                    bind == p->bound)
 771                        return p;
 772        return NULL;
 773}
 774
 775static int
 776mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
 777                                  struct mlxsw_sp_span_entry *span_entry,
 778                                  enum mlxsw_sp_span_type type,
 779                                  bool bind)
 780{
 781        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
 782        char mpar_pl[MLXSW_REG_MPAR_LEN];
 783        int pa_id = span_entry->id;
 784
 785        /* bind the port to the SPAN entry */
 786        mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
 787                            (enum mlxsw_reg_mpar_i_e)type, bind, pa_id);
 788        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
 789}
 790
 791static int
 792mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
 793                                 struct mlxsw_sp_span_entry *span_entry,
 794                                 enum mlxsw_sp_span_type type,
 795                                 bool bind)
 796{
 797        struct mlxsw_sp_span_inspected_port *inspected_port;
 798        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
 799        char sbib_pl[MLXSW_REG_SBIB_LEN];
 800        int i;
 801        int err;
 802
 803        /* A given (source port, direction) can only be bound to one analyzer,
 804         * so if a binding is requested, check for conflicts.
 805         */
 806        if (bind)
 807                for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 808                        struct mlxsw_sp_span_entry *curr =
 809                                &mlxsw_sp->span.entries[i];
 810
 811                        if (mlxsw_sp_span_entry_bound_port_find(curr, type,
 812                                                                port, bind))
 813                                return -EEXIST;
 814                }
 815
 816        /* if it is an egress SPAN, bind a shared buffer to it */
 817        if (type == MLXSW_SP_SPAN_EGRESS) {
 818                u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp,
 819                                                             port->dev->mtu);
 820
 821                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
 822                err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 823                if (err) {
 824                        netdev_err(port->dev, "Could not create shared buffer for mirroring\n");
 825                        return err;
 826                }
 827        }
 828
 829        if (bind) {
 830                err = mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
 831                                                        true);
 832                if (err)
 833                        goto err_port_bind;
 834        }
 835
 836        inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
 837        if (!inspected_port) {
 838                err = -ENOMEM;
 839                goto err_inspected_port_alloc;
 840        }
 841        inspected_port->local_port = port->local_port;
 842        inspected_port->type = type;
 843        inspected_port->bound = bind;
 844        list_add_tail(&inspected_port->list, &span_entry->bound_ports_list);
 845
 846        return 0;
 847
 848err_inspected_port_alloc:
 849        if (bind)
 850                mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
 851                                                  false);
 852err_port_bind:
 853        if (type == MLXSW_SP_SPAN_EGRESS) {
 854                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
 855                mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 856        }
 857        return err;
 858}
 859
 860static void
 861mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
 862                                 struct mlxsw_sp_span_entry *span_entry,
 863                                 enum mlxsw_sp_span_type type,
 864                                 bool bind)
 865{
 866        struct mlxsw_sp_span_inspected_port *inspected_port;
 867        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
 868        char sbib_pl[MLXSW_REG_SBIB_LEN];
 869
 870        inspected_port = mlxsw_sp_span_entry_bound_port_find(span_entry, type,
 871                                                             port, bind);
 872        if (!inspected_port)
 873                return;
 874
 875        if (bind)
 876                mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
 877                                                  false);
 878        /* remove the SBIB buffer if it was egress SPAN */
 879        if (type == MLXSW_SP_SPAN_EGRESS) {
 880                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
 881                mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 882        }
 883
 884        mlxsw_sp_span_entry_put(mlxsw_sp, span_entry);
 885
 886        list_del(&inspected_port->list);
 887        kfree(inspected_port);
 888}
 889
 890static const struct mlxsw_sp_span_entry_ops *
 891mlxsw_sp_span_entry_ops(struct mlxsw_sp *mlxsw_sp,
 892                        const struct net_device *to_dev)
 893{
 894        size_t i;
 895
 896        for (i = 0; i < ARRAY_SIZE(mlxsw_sp_span_entry_types); ++i)
 897                if (mlxsw_sp_span_entry_types[i]->can_handle(to_dev))
 898                        return mlxsw_sp_span_entry_types[i];
 899
 900        return NULL;
 901}
 902
 903int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
 904                             const struct net_device *to_dev,
 905                             enum mlxsw_sp_span_type type, bool bind,
 906                             int *p_span_id)
 907{
 908        struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
 909        const struct mlxsw_sp_span_entry_ops *ops;
 910        struct mlxsw_sp_span_parms sparms = {NULL};
 911        struct mlxsw_sp_span_entry *span_entry;
 912        int err;
 913
 914        ops = mlxsw_sp_span_entry_ops(mlxsw_sp, to_dev);
 915        if (!ops) {
 916                netdev_err(to_dev, "Cannot mirror to %s", to_dev->name);
 917                return -EOPNOTSUPP;
 918        }
 919
 920        err = ops->parms(to_dev, &sparms);
 921        if (err)
 922                return err;
 923
 924        span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev, ops, sparms);
 925        if (!span_entry)
 926                return -ENOBUFS;
 927
 928        netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
 929                   span_entry->id);
 930
 931        err = mlxsw_sp_span_inspected_port_add(from, span_entry, type, bind);
 932        if (err)
 933                goto err_port_bind;
 934
 935        *p_span_id = span_entry->id;
 936        return 0;
 937
 938err_port_bind:
 939        mlxsw_sp_span_entry_put(mlxsw_sp, span_entry);
 940        return err;
 941}
 942
 943void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
 944                              enum mlxsw_sp_span_type type, bool bind)
 945{
 946        struct mlxsw_sp_span_entry *span_entry;
 947
 948        span_entry = mlxsw_sp_span_entry_find_by_id(from->mlxsw_sp, span_id);
 949        if (!span_entry) {
 950                netdev_err(from->dev, "no span entry found\n");
 951                return;
 952        }
 953
 954        netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
 955                   span_entry->id);
 956        mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
 957}
 958
 959void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
 960{
 961        int i;
 962        int err;
 963
 964        ASSERT_RTNL();
 965        for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
 966                struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
 967                struct mlxsw_sp_span_parms sparms = {NULL};
 968
 969                if (!curr->ref_count)
 970                        continue;
 971
 972                err = curr->ops->parms(curr->to_dev, &sparms);
 973                if (err)
 974                        continue;
 975
 976                if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
 977                        mlxsw_sp_span_entry_deconfigure(curr);
 978                        mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
 979                }
 980        }
 981}
 982