linux/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/* Copyright (c) 2020 Mellanox Technologies. */
   3
   4#include <net/dst_metadata.h>
   5#include <linux/netdevice.h>
   6#include <linux/list.h>
   7#include <linux/rculist.h>
   8#include <linux/rtnetlink.h>
   9#include <linux/workqueue.h>
  10#include <linux/spinlock.h>
  11#include "tc.h"
  12#include "neigh.h"
  13#include "en_rep.h"
  14#include "eswitch.h"
  15#include "lib/fs_chains.h"
  16#include "en/tc_ct.h"
  17#include "en/mapping.h"
  18#include "en/tc_tun.h"
  19#include "lib/port_tun.h"
  20
  21struct mlx5e_rep_indr_block_priv {
  22        struct net_device *netdev;
  23        struct mlx5e_rep_priv *rpriv;
  24
  25        struct list_head list;
  26};
  27
  28int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
  29                                 struct mlx5e_encap_entry *e)
  30{
  31        struct mlx5e_rep_priv *rpriv = priv->ppriv;
  32        struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
  33        struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
  34        struct mlx5e_neigh_hash_entry *nhe;
  35        int err;
  36
  37        err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type);
  38        if (err)
  39                return err;
  40
  41        mutex_lock(&rpriv->neigh_update.encap_lock);
  42        nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
  43        if (!nhe) {
  44                err = mlx5e_rep_neigh_entry_create(priv, e, &nhe);
  45                if (err) {
  46                        mutex_unlock(&rpriv->neigh_update.encap_lock);
  47                        mlx5_tun_entropy_refcount_dec(tun_entropy,
  48                                                      e->reformat_type);
  49                        return err;
  50                }
  51        }
  52
  53        e->nhe = nhe;
  54        spin_lock(&nhe->encap_list_lock);
  55        list_add_rcu(&e->encap_list, &nhe->encap_list);
  56        spin_unlock(&nhe->encap_list_lock);
  57
  58        mutex_unlock(&rpriv->neigh_update.encap_lock);
  59
  60        return 0;
  61}
  62
  63void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
  64                                  struct mlx5e_encap_entry *e)
  65{
  66        struct mlx5e_rep_priv *rpriv = priv->ppriv;
  67        struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
  68        struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
  69
  70        if (!e->nhe)
  71                return;
  72
  73        spin_lock(&e->nhe->encap_list_lock);
  74        list_del_rcu(&e->encap_list);
  75        spin_unlock(&e->nhe->encap_list_lock);
  76
  77        mlx5e_rep_neigh_entry_release(e->nhe);
  78        e->nhe = NULL;
  79        mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type);
  80}
  81
  82void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
  83                            struct mlx5e_encap_entry *e,
  84                            bool neigh_connected,
  85                            unsigned char ha[ETH_ALEN])
  86{
  87        struct ethhdr *eth = (struct ethhdr *)e->encap_header;
  88        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
  89        bool encap_connected;
  90        LIST_HEAD(flow_list);
  91
  92        ASSERT_RTNL();
  93
  94        /* wait for encap to be fully initialized */
  95        wait_for_completion(&e->res_ready);
  96
  97        mutex_lock(&esw->offloads.encap_tbl_lock);
  98        encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID);
  99        if (e->compl_result < 0 || (encap_connected == neigh_connected &&
 100                                    ether_addr_equal(e->h_dest, ha)))
 101                goto unlock;
 102
 103        mlx5e_take_all_encap_flows(e, &flow_list);
 104
 105        if ((e->flags & MLX5_ENCAP_ENTRY_VALID) &&
 106            (!neigh_connected || !ether_addr_equal(e->h_dest, ha)))
 107                mlx5e_tc_encap_flows_del(priv, e, &flow_list);
 108
 109        if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
 110                struct net_device *route_dev;
 111
 112                ether_addr_copy(e->h_dest, ha);
 113                ether_addr_copy(eth->h_dest, ha);
 114                /* Update the encap source mac, in case that we delete
 115                 * the flows when encap source mac changed.
 116                 */
 117                route_dev = __dev_get_by_index(dev_net(priv->netdev), e->route_dev_ifindex);
 118                if (route_dev)
 119                        ether_addr_copy(eth->h_source, route_dev->dev_addr);
 120
 121                mlx5e_tc_encap_flows_add(priv, e, &flow_list);
 122        }
 123unlock:
 124        mutex_unlock(&esw->offloads.encap_tbl_lock);
 125        mlx5e_put_encap_flow_list(priv, &flow_list);
 126}
 127
 128static int
 129mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
 130                              struct flow_cls_offload *cls_flower, int flags)
 131{
 132        switch (cls_flower->command) {
 133        case FLOW_CLS_REPLACE:
 134                return mlx5e_configure_flower(priv->netdev, priv, cls_flower,
 135                                              flags);
 136        case FLOW_CLS_DESTROY:
 137                return mlx5e_delete_flower(priv->netdev, priv, cls_flower,
 138                                           flags);
 139        case FLOW_CLS_STATS:
 140                return mlx5e_stats_flower(priv->netdev, priv, cls_flower,
 141                                          flags);
 142        default:
 143                return -EOPNOTSUPP;
 144        }
 145}
 146
 147static
 148int mlx5e_rep_setup_tc_cls_matchall(struct mlx5e_priv *priv,
 149                                    struct tc_cls_matchall_offload *ma)
 150{
 151        switch (ma->command) {
 152        case TC_CLSMATCHALL_REPLACE:
 153                return mlx5e_tc_configure_matchall(priv, ma);
 154        case TC_CLSMATCHALL_DESTROY:
 155                return mlx5e_tc_delete_matchall(priv, ma);
 156        case TC_CLSMATCHALL_STATS:
 157                mlx5e_tc_stats_matchall(priv, ma);
 158                return 0;
 159        default:
 160                return -EOPNOTSUPP;
 161        }
 162}
 163
 164static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
 165                                 void *cb_priv)
 166{
 167        unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD);
 168        struct mlx5e_priv *priv = cb_priv;
 169
 170        switch (type) {
 171        case TC_SETUP_CLSFLOWER:
 172                return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags);
 173        case TC_SETUP_CLSMATCHALL:
 174                return mlx5e_rep_setup_tc_cls_matchall(priv, type_data);
 175        default:
 176                return -EOPNOTSUPP;
 177        }
 178}
 179
 180static int mlx5e_rep_setup_ft_cb(enum tc_setup_type type, void *type_data,
 181                                 void *cb_priv)
 182{
 183        struct flow_cls_offload tmp, *f = type_data;
 184        struct mlx5e_priv *priv = cb_priv;
 185        struct mlx5_eswitch *esw;
 186        unsigned long flags;
 187        int err;
 188
 189        flags = MLX5_TC_FLAG(INGRESS) |
 190                MLX5_TC_FLAG(ESW_OFFLOAD) |
 191                MLX5_TC_FLAG(FT_OFFLOAD);
 192        esw = priv->mdev->priv.eswitch;
 193
 194        switch (type) {
 195        case TC_SETUP_CLSFLOWER:
 196                memcpy(&tmp, f, sizeof(*f));
 197
 198                if (!mlx5_chains_prios_supported(esw_chains(esw)))
 199                        return -EOPNOTSUPP;
 200
 201                /* Re-use tc offload path by moving the ft flow to the
 202                 * reserved ft chain.
 203                 *
 204                 * FT offload can use prio range [0, INT_MAX], so we normalize
 205                 * it to range [1, mlx5_esw_chains_get_prio_range(esw)]
 206                 * as with tc, where prio 0 isn't supported.
 207                 *
 208                 * We only support chain 0 of FT offload.
 209                 */
 210                if (tmp.common.prio >= mlx5_chains_get_prio_range(esw_chains(esw)))
 211                        return -EOPNOTSUPP;
 212                if (tmp.common.chain_index != 0)
 213                        return -EOPNOTSUPP;
 214
 215                tmp.common.chain_index = mlx5_chains_get_nf_ft_chain(esw_chains(esw));
 216                tmp.common.prio++;
 217                err = mlx5e_rep_setup_tc_cls_flower(priv, &tmp, flags);
 218                memcpy(&f->stats, &tmp.stats, sizeof(f->stats));
 219                return err;
 220        default:
 221                return -EOPNOTSUPP;
 222        }
 223}
 224
 225static LIST_HEAD(mlx5e_rep_block_tc_cb_list);
 226static LIST_HEAD(mlx5e_rep_block_ft_cb_list);
 227int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
 228                       void *type_data)
 229{
 230        struct mlx5e_priv *priv = netdev_priv(dev);
 231        struct flow_block_offload *f = type_data;
 232
 233        f->unlocked_driver_cb = true;
 234
 235        switch (type) {
 236        case TC_SETUP_BLOCK:
 237                return flow_block_cb_setup_simple(type_data,
 238                                                  &mlx5e_rep_block_tc_cb_list,
 239                                                  mlx5e_rep_setup_tc_cb,
 240                                                  priv, priv, true);
 241        case TC_SETUP_FT:
 242                return flow_block_cb_setup_simple(type_data,
 243                                                  &mlx5e_rep_block_ft_cb_list,
 244                                                  mlx5e_rep_setup_ft_cb,
 245                                                  priv, priv, true);
 246        default:
 247                return -EOPNOTSUPP;
 248        }
 249}
 250
 251int mlx5e_rep_tc_init(struct mlx5e_rep_priv *rpriv)
 252{
 253        struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
 254        int err;
 255
 256        mutex_init(&uplink_priv->unready_flows_lock);
 257        INIT_LIST_HEAD(&uplink_priv->unready_flows);
 258
 259        /* init shared tc flow table */
 260        err = mlx5e_tc_esw_init(&uplink_priv->tc_ht);
 261        return err;
 262}
 263
 264void mlx5e_rep_tc_cleanup(struct mlx5e_rep_priv *rpriv)
 265{
 266        /* delete shared tc flow table */
 267        mlx5e_tc_esw_cleanup(&rpriv->uplink_priv.tc_ht);
 268        mutex_destroy(&rpriv->uplink_priv.unready_flows_lock);
 269}
 270
 271void mlx5e_rep_tc_enable(struct mlx5e_priv *priv)
 272{
 273        struct mlx5e_rep_priv *rpriv = priv->ppriv;
 274
 275        INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
 276                  mlx5e_tc_reoffload_flows_work);
 277}
 278
 279void mlx5e_rep_tc_disable(struct mlx5e_priv *priv)
 280{
 281        struct mlx5e_rep_priv *rpriv = priv->ppriv;
 282
 283        cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
 284}
 285
 286int mlx5e_rep_tc_event_port_affinity(struct mlx5e_priv *priv)
 287{
 288        struct mlx5e_rep_priv *rpriv = priv->ppriv;
 289
 290        queue_work(priv->wq, &rpriv->uplink_priv.reoffload_flows_work);
 291
 292        return NOTIFY_OK;
 293}
 294
 295static struct mlx5e_rep_indr_block_priv *
 296mlx5e_rep_indr_block_priv_lookup(struct mlx5e_rep_priv *rpriv,
 297                                 struct net_device *netdev)
 298{
 299        struct mlx5e_rep_indr_block_priv *cb_priv;
 300
 301        /* All callback list access should be protected by RTNL. */
 302        ASSERT_RTNL();
 303
 304        list_for_each_entry(cb_priv,
 305                            &rpriv->uplink_priv.tc_indr_block_priv_list,
 306                            list)
 307                if (cb_priv->netdev == netdev)
 308                        return cb_priv;
 309
 310        return NULL;
 311}
 312
 313static int
 314mlx5e_rep_indr_offload(struct net_device *netdev,
 315                       struct flow_cls_offload *flower,
 316                       struct mlx5e_rep_indr_block_priv *indr_priv,
 317                       unsigned long flags)
 318{
 319        struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev);
 320        int err = 0;
 321
 322        switch (flower->command) {
 323        case FLOW_CLS_REPLACE:
 324                err = mlx5e_configure_flower(netdev, priv, flower, flags);
 325                break;
 326        case FLOW_CLS_DESTROY:
 327                err = mlx5e_delete_flower(netdev, priv, flower, flags);
 328                break;
 329        case FLOW_CLS_STATS:
 330                err = mlx5e_stats_flower(netdev, priv, flower, flags);
 331                break;
 332        default:
 333                err = -EOPNOTSUPP;
 334        }
 335
 336        return err;
 337}
 338
 339static int mlx5e_rep_indr_setup_tc_cb(enum tc_setup_type type,
 340                                      void *type_data, void *indr_priv)
 341{
 342        unsigned long flags = MLX5_TC_FLAG(EGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD);
 343        struct mlx5e_rep_indr_block_priv *priv = indr_priv;
 344
 345        switch (type) {
 346        case TC_SETUP_CLSFLOWER:
 347                return mlx5e_rep_indr_offload(priv->netdev, type_data, priv,
 348                                              flags);
 349        default:
 350                return -EOPNOTSUPP;
 351        }
 352}
 353
 354static int mlx5e_rep_indr_setup_ft_cb(enum tc_setup_type type,
 355                                      void *type_data, void *indr_priv)
 356{
 357        struct mlx5e_rep_indr_block_priv *priv = indr_priv;
 358        struct flow_cls_offload *f = type_data;
 359        struct flow_cls_offload tmp;
 360        struct mlx5e_priv *mpriv;
 361        struct mlx5_eswitch *esw;
 362        unsigned long flags;
 363        int err;
 364
 365        mpriv = netdev_priv(priv->rpriv->netdev);
 366        esw = mpriv->mdev->priv.eswitch;
 367
 368        flags = MLX5_TC_FLAG(EGRESS) |
 369                MLX5_TC_FLAG(ESW_OFFLOAD) |
 370                MLX5_TC_FLAG(FT_OFFLOAD);
 371
 372        switch (type) {
 373        case TC_SETUP_CLSFLOWER:
 374                memcpy(&tmp, f, sizeof(*f));
 375
 376                /* Re-use tc offload path by moving the ft flow to the
 377                 * reserved ft chain.
 378                 *
 379                 * FT offload can use prio range [0, INT_MAX], so we normalize
 380                 * it to range [1, mlx5_esw_chains_get_prio_range(esw)]
 381                 * as with tc, where prio 0 isn't supported.
 382                 *
 383                 * We only support chain 0 of FT offload.
 384                 */
 385                if (!mlx5_chains_prios_supported(esw_chains(esw)) ||
 386                    tmp.common.prio >= mlx5_chains_get_prio_range(esw_chains(esw)) ||
 387                    tmp.common.chain_index)
 388                        return -EOPNOTSUPP;
 389
 390                tmp.common.chain_index = mlx5_chains_get_nf_ft_chain(esw_chains(esw));
 391                tmp.common.prio++;
 392                err = mlx5e_rep_indr_offload(priv->netdev, &tmp, priv, flags);
 393                memcpy(&f->stats, &tmp.stats, sizeof(f->stats));
 394                return err;
 395        default:
 396                return -EOPNOTSUPP;
 397        }
 398}
 399
 400static void mlx5e_rep_indr_block_unbind(void *cb_priv)
 401{
 402        struct mlx5e_rep_indr_block_priv *indr_priv = cb_priv;
 403
 404        list_del(&indr_priv->list);
 405        kfree(indr_priv);
 406}
 407
 408static LIST_HEAD(mlx5e_block_cb_list);
 409
 410static int
 411mlx5e_rep_indr_setup_block(struct net_device *netdev, struct Qdisc *sch,
 412                           struct mlx5e_rep_priv *rpriv,
 413                           struct flow_block_offload *f,
 414                           flow_setup_cb_t *setup_cb,
 415                           void *data,
 416                           void (*cleanup)(struct flow_block_cb *block_cb))
 417{
 418        struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
 419        struct mlx5e_rep_indr_block_priv *indr_priv;
 420        struct flow_block_cb *block_cb;
 421
 422        if (!mlx5e_tc_tun_device_to_offload(priv, netdev) &&
 423            !(is_vlan_dev(netdev) && vlan_dev_real_dev(netdev) == rpriv->netdev))
 424                return -EOPNOTSUPP;
 425
 426        if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
 427                return -EOPNOTSUPP;
 428
 429        f->unlocked_driver_cb = true;
 430        f->driver_block_list = &mlx5e_block_cb_list;
 431
 432        switch (f->command) {
 433        case FLOW_BLOCK_BIND:
 434                indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
 435                if (indr_priv)
 436                        return -EEXIST;
 437
 438                indr_priv = kmalloc(sizeof(*indr_priv), GFP_KERNEL);
 439                if (!indr_priv)
 440                        return -ENOMEM;
 441
 442                indr_priv->netdev = netdev;
 443                indr_priv->rpriv = rpriv;
 444                list_add(&indr_priv->list,
 445                         &rpriv->uplink_priv.tc_indr_block_priv_list);
 446
 447                block_cb = flow_indr_block_cb_alloc(setup_cb, indr_priv, indr_priv,
 448                                                    mlx5e_rep_indr_block_unbind,
 449                                                    f, netdev, sch, data, rpriv,
 450                                                    cleanup);
 451                if (IS_ERR(block_cb)) {
 452                        list_del(&indr_priv->list);
 453                        kfree(indr_priv);
 454                        return PTR_ERR(block_cb);
 455                }
 456                flow_block_cb_add(block_cb, f);
 457                list_add_tail(&block_cb->driver_list, &mlx5e_block_cb_list);
 458
 459                return 0;
 460        case FLOW_BLOCK_UNBIND:
 461                indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
 462                if (!indr_priv)
 463                        return -ENOENT;
 464
 465                block_cb = flow_block_cb_lookup(f->block, setup_cb, indr_priv);
 466                if (!block_cb)
 467                        return -ENOENT;
 468
 469                flow_indr_block_cb_remove(block_cb, f);
 470                list_del(&block_cb->driver_list);
 471                return 0;
 472        default:
 473                return -EOPNOTSUPP;
 474        }
 475        return 0;
 476}
 477
 478static
 479int mlx5e_rep_indr_setup_cb(struct net_device *netdev, struct Qdisc *sch, void *cb_priv,
 480                            enum tc_setup_type type, void *type_data,
 481                            void *data,
 482                            void (*cleanup)(struct flow_block_cb *block_cb))
 483{
 484        switch (type) {
 485        case TC_SETUP_BLOCK:
 486                return mlx5e_rep_indr_setup_block(netdev, sch, cb_priv, type_data,
 487                                                  mlx5e_rep_indr_setup_tc_cb,
 488                                                  data, cleanup);
 489        case TC_SETUP_FT:
 490                return mlx5e_rep_indr_setup_block(netdev, sch, cb_priv, type_data,
 491                                                  mlx5e_rep_indr_setup_ft_cb,
 492                                                  data, cleanup);
 493        default:
 494                return -EOPNOTSUPP;
 495        }
 496}
 497
 498int mlx5e_rep_tc_netdevice_event_register(struct mlx5e_rep_priv *rpriv)
 499{
 500        struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
 501
 502        /* init indirect block notifications */
 503        INIT_LIST_HEAD(&uplink_priv->tc_indr_block_priv_list);
 504
 505        return flow_indr_dev_register(mlx5e_rep_indr_setup_cb, rpriv);
 506}
 507
 508void mlx5e_rep_tc_netdevice_event_unregister(struct mlx5e_rep_priv *rpriv)
 509{
 510        flow_indr_dev_unregister(mlx5e_rep_indr_setup_cb, rpriv,
 511                                 mlx5e_rep_indr_block_unbind);
 512}
 513
 514#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
 515static bool mlx5e_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb,
 516                                 struct mlx5e_tc_update_priv *tc_priv,
 517                                 u32 tunnel_id)
 518{
 519        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 520        struct tunnel_match_enc_opts enc_opts = {};
 521        struct mlx5_rep_uplink_priv *uplink_priv;
 522        struct mlx5e_rep_priv *uplink_rpriv;
 523        struct metadata_dst *tun_dst;
 524        struct tunnel_match_key key;
 525        u32 tun_id, enc_opts_id;
 526        struct net_device *dev;
 527        int err;
 528
 529        enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK;
 530        tun_id = tunnel_id >> ENC_OPTS_BITS;
 531
 532        if (!tun_id)
 533                return true;
 534
 535        uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
 536        uplink_priv = &uplink_rpriv->uplink_priv;
 537
 538        err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key);
 539        if (err) {
 540                WARN_ON_ONCE(true);
 541                netdev_dbg(priv->netdev,
 542                           "Couldn't find tunnel for tun_id: %d, err: %d\n",
 543                           tun_id, err);
 544                return false;
 545        }
 546
 547        if (enc_opts_id) {
 548                err = mapping_find(uplink_priv->tunnel_enc_opts_mapping,
 549                                   enc_opts_id, &enc_opts);
 550                if (err) {
 551                        netdev_dbg(priv->netdev,
 552                                   "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n",
 553                                   enc_opts_id, err);
 554                        return false;
 555                }
 556        }
 557
 558        if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
 559                tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst,
 560                                           key.enc_ip.tos, key.enc_ip.ttl,
 561                                           key.enc_tp.dst, TUNNEL_KEY,
 562                                           key32_to_tunnel_id(key.enc_key_id.keyid),
 563                                           enc_opts.key.len);
 564        } else if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
 565                tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst,
 566                                             key.enc_ip.tos, key.enc_ip.ttl,
 567                                             key.enc_tp.dst, 0, TUNNEL_KEY,
 568                                             key32_to_tunnel_id(key.enc_key_id.keyid),
 569                                             enc_opts.key.len);
 570        } else {
 571                netdev_dbg(priv->netdev,
 572                           "Couldn't restore tunnel, unsupported addr_type: %d\n",
 573                           key.enc_control.addr_type);
 574                return false;
 575        }
 576
 577        if (!tun_dst) {
 578                netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n");
 579                return false;
 580        }
 581
 582        tun_dst->u.tun_info.key.tp_src = key.enc_tp.src;
 583
 584        if (enc_opts.key.len)
 585                ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
 586                                        enc_opts.key.data,
 587                                        enc_opts.key.len,
 588                                        enc_opts.key.dst_opt_type);
 589
 590        skb_dst_set(skb, (struct dst_entry *)tun_dst);
 591        dev = dev_get_by_index(&init_net, key.filter_ifindex);
 592        if (!dev) {
 593                netdev_dbg(priv->netdev,
 594                           "Couldn't find tunnel device with ifindex: %d\n",
 595                           key.filter_ifindex);
 596                return false;
 597        }
 598
 599        /* Set tun_dev so we do dev_put() after datapath */
 600        tc_priv->tun_dev = dev;
 601
 602        skb->dev = dev;
 603
 604        return true;
 605}
 606#endif /* CONFIG_NET_TC_SKB_EXT */
 607
 608bool mlx5e_rep_tc_update_skb(struct mlx5_cqe64 *cqe,
 609                             struct sk_buff *skb,
 610                             struct mlx5e_tc_update_priv *tc_priv)
 611{
 612#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
 613        u32 chain = 0, reg_c0, reg_c1, tunnel_id, zone_restore_id;
 614        struct mlx5_rep_uplink_priv *uplink_priv;
 615        struct mlx5e_rep_priv *uplink_rpriv;
 616        struct tc_skb_ext *tc_skb_ext;
 617        struct mlx5_eswitch *esw;
 618        struct mlx5e_priv *priv;
 619        int err;
 620
 621        reg_c0 = (be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK);
 622        if (reg_c0 == MLX5_FS_DEFAULT_FLOW_TAG)
 623                reg_c0 = 0;
 624        reg_c1 = be32_to_cpu(cqe->ft_metadata);
 625
 626        if (!reg_c0)
 627                return true;
 628
 629        priv = netdev_priv(skb->dev);
 630        esw = priv->mdev->priv.eswitch;
 631
 632        err = mlx5_get_chain_for_tag(esw_chains(esw), reg_c0, &chain);
 633        if (err) {
 634                netdev_dbg(priv->netdev,
 635                           "Couldn't find chain for chain tag: %d, err: %d\n",
 636                           reg_c0, err);
 637                return false;
 638        }
 639
 640        if (chain) {
 641                tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
 642                if (!tc_skb_ext) {
 643                        WARN_ON(1);
 644                        return false;
 645                }
 646
 647                tc_skb_ext->chain = chain;
 648
 649                zone_restore_id = reg_c1 & ZONE_RESTORE_MAX;
 650
 651                uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
 652                uplink_priv = &uplink_rpriv->uplink_priv;
 653                if (!mlx5e_tc_ct_restore_flow(uplink_priv->ct_priv, skb,
 654                                              zone_restore_id))
 655                        return false;
 656        }
 657
 658        tunnel_id = reg_c1 >> REG_MAPPING_SHIFT(TUNNEL_TO_REG);
 659        return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id);
 660#endif /* CONFIG_NET_TC_SKB_EXT */
 661
 662        return true;
 663}
 664
 665void mlx5_rep_tc_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv)
 666{
 667        if (tc_priv->tun_dev)
 668                dev_put(tc_priv->tun_dev);
 669}
 670