linux/drivers/net/ethernet/netronome/nfp/flower/offload.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Netronome Systems, Inc.
   3 *
   4 * This software is dual licensed under the GNU General License Version 2,
   5 * June 1991 as shown in the file COPYING in the top-level directory of this
   6 * source tree or the BSD 2-Clause License provided below.  You have the
   7 * option to license this software under the complete terms of either license.
   8 *
   9 * The BSD 2-Clause License:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      1. Redistributions of source code must retain the above
  16 *         copyright notice, this list of conditions and the following
  17 *         disclaimer.
  18 *
  19 *      2. Redistributions in binary form must reproduce the above
  20 *         copyright notice, this list of conditions and the following
  21 *         disclaimer in the documentation and/or other materials
  22 *         provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 */
  33
  34#include <linux/skbuff.h>
  35#include <net/devlink.h>
  36#include <net/pkt_cls.h>
  37
  38#include "cmsg.h"
  39#include "main.h"
  40#include "../nfpcore/nfp_cpp.h"
  41#include "../nfpcore/nfp_nsp.h"
  42#include "../nfp_app.h"
  43#include "../nfp_main.h"
  44#include "../nfp_net.h"
  45#include "../nfp_port.h"
  46
  47#define NFP_FLOWER_WHITELIST_DISSECTOR \
  48        (BIT(FLOW_DISSECTOR_KEY_CONTROL) | \
  49         BIT(FLOW_DISSECTOR_KEY_BASIC) | \
  50         BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \
  51         BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \
  52         BIT(FLOW_DISSECTOR_KEY_PORTS) | \
  53         BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \
  54         BIT(FLOW_DISSECTOR_KEY_VLAN) | \
  55         BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \
  56         BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \
  57         BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \
  58         BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \
  59         BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \
  60         BIT(FLOW_DISSECTOR_KEY_MPLS) | \
  61         BIT(FLOW_DISSECTOR_KEY_IP))
  62
  63#define NFP_FLOWER_WHITELIST_TUN_DISSECTOR \
  64        (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \
  65         BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \
  66         BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \
  67         BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \
  68         BIT(FLOW_DISSECTOR_KEY_ENC_PORTS))
  69
  70#define NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R \
  71        (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \
  72         BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \
  73         BIT(FLOW_DISSECTOR_KEY_ENC_PORTS))
  74
  75static int
  76nfp_flower_xmit_flow(struct net_device *netdev,
  77                     struct nfp_fl_payload *nfp_flow, u8 mtype)
  78{
  79        u32 meta_len, key_len, mask_len, act_len, tot_len;
  80        struct nfp_repr *priv = netdev_priv(netdev);
  81        struct sk_buff *skb;
  82        unsigned char *msg;
  83
  84        meta_len =  sizeof(struct nfp_fl_rule_metadata);
  85        key_len = nfp_flow->meta.key_len;
  86        mask_len = nfp_flow->meta.mask_len;
  87        act_len = nfp_flow->meta.act_len;
  88
  89        tot_len = meta_len + key_len + mask_len + act_len;
  90
  91        /* Convert to long words as firmware expects
  92         * lengths in units of NFP_FL_LW_SIZ.
  93         */
  94        nfp_flow->meta.key_len >>= NFP_FL_LW_SIZ;
  95        nfp_flow->meta.mask_len >>= NFP_FL_LW_SIZ;
  96        nfp_flow->meta.act_len >>= NFP_FL_LW_SIZ;
  97
  98        skb = nfp_flower_cmsg_alloc(priv->app, tot_len, mtype, GFP_KERNEL);
  99        if (!skb)
 100                return -ENOMEM;
 101
 102        msg = nfp_flower_cmsg_get_data(skb);
 103        memcpy(msg, &nfp_flow->meta, meta_len);
 104        memcpy(&msg[meta_len], nfp_flow->unmasked_data, key_len);
 105        memcpy(&msg[meta_len + key_len], nfp_flow->mask_data, mask_len);
 106        memcpy(&msg[meta_len + key_len + mask_len],
 107               nfp_flow->action_data, act_len);
 108
 109        /* Convert back to bytes as software expects
 110         * lengths in units of bytes.
 111         */
 112        nfp_flow->meta.key_len <<= NFP_FL_LW_SIZ;
 113        nfp_flow->meta.mask_len <<= NFP_FL_LW_SIZ;
 114        nfp_flow->meta.act_len <<= NFP_FL_LW_SIZ;
 115
 116        nfp_ctrl_tx(priv->app->ctrl, skb);
 117
 118        return 0;
 119}
 120
 121static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)
 122{
 123        return dissector_uses_key(f->dissector,
 124                                  FLOW_DISSECTOR_KEY_IPV4_ADDRS) ||
 125                dissector_uses_key(f->dissector,
 126                                   FLOW_DISSECTOR_KEY_IPV6_ADDRS) ||
 127                dissector_uses_key(f->dissector,
 128                                   FLOW_DISSECTOR_KEY_PORTS) ||
 129                dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ICMP);
 130}
 131
 132static int
 133nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
 134                                struct tc_cls_flower_offload *flow,
 135                                bool egress)
 136{
 137        struct flow_dissector_key_basic *mask_basic = NULL;
 138        struct flow_dissector_key_basic *key_basic = NULL;
 139        u32 key_layer_two;
 140        u8 key_layer;
 141        int key_size;
 142
 143        if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
 144                return -EOPNOTSUPP;
 145
 146        /* If any tun dissector is used then the required set must be used. */
 147        if (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR &&
 148            (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
 149            != NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
 150                return -EOPNOTSUPP;
 151
 152        key_layer_two = 0;
 153        key_layer = NFP_FLOWER_LAYER_PORT | NFP_FLOWER_LAYER_MAC;
 154        key_size = sizeof(struct nfp_flower_meta_one) +
 155                   sizeof(struct nfp_flower_in_port) +
 156                   sizeof(struct nfp_flower_mac_mpls);
 157
 158        if (dissector_uses_key(flow->dissector,
 159                               FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
 160                struct flow_dissector_key_ipv4_addrs *mask_ipv4 = NULL;
 161                struct flow_dissector_key_ports *mask_enc_ports = NULL;
 162                struct flow_dissector_key_ports *enc_ports = NULL;
 163                struct flow_dissector_key_control *mask_enc_ctl =
 164                        skb_flow_dissector_target(flow->dissector,
 165                                                  FLOW_DISSECTOR_KEY_ENC_CONTROL,
 166                                                  flow->mask);
 167                struct flow_dissector_key_control *enc_ctl =
 168                        skb_flow_dissector_target(flow->dissector,
 169                                                  FLOW_DISSECTOR_KEY_ENC_CONTROL,
 170                                                  flow->key);
 171                if (!egress)
 172                        return -EOPNOTSUPP;
 173
 174                if (mask_enc_ctl->addr_type != 0xffff ||
 175                    enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
 176                        return -EOPNOTSUPP;
 177
 178                /* These fields are already verified as used. */
 179                mask_ipv4 =
 180                        skb_flow_dissector_target(flow->dissector,
 181                                                  FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
 182                                                  flow->mask);
 183                if (mask_ipv4->dst != cpu_to_be32(~0))
 184                        return -EOPNOTSUPP;
 185
 186                mask_enc_ports =
 187                        skb_flow_dissector_target(flow->dissector,
 188                                                  FLOW_DISSECTOR_KEY_ENC_PORTS,
 189                                                  flow->mask);
 190                enc_ports =
 191                        skb_flow_dissector_target(flow->dissector,
 192                                                  FLOW_DISSECTOR_KEY_ENC_PORTS,
 193                                                  flow->key);
 194
 195                if (mask_enc_ports->dst != cpu_to_be16(~0) ||
 196                    enc_ports->dst != htons(NFP_FL_VXLAN_PORT))
 197                        return -EOPNOTSUPP;
 198
 199                key_layer |= NFP_FLOWER_LAYER_VXLAN;
 200                key_size += sizeof(struct nfp_flower_vxlan);
 201        } else if (egress) {
 202                /* Reject non tunnel matches offloaded to egress repr. */
 203                return -EOPNOTSUPP;
 204        }
 205
 206        if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
 207                mask_basic = skb_flow_dissector_target(flow->dissector,
 208                                                       FLOW_DISSECTOR_KEY_BASIC,
 209                                                       flow->mask);
 210
 211                key_basic = skb_flow_dissector_target(flow->dissector,
 212                                                      FLOW_DISSECTOR_KEY_BASIC,
 213                                                      flow->key);
 214        }
 215
 216        if (mask_basic && mask_basic->n_proto) {
 217                /* Ethernet type is present in the key. */
 218                switch (key_basic->n_proto) {
 219                case cpu_to_be16(ETH_P_IP):
 220                        key_layer |= NFP_FLOWER_LAYER_IPV4;
 221                        key_size += sizeof(struct nfp_flower_ipv4);
 222                        break;
 223
 224                case cpu_to_be16(ETH_P_IPV6):
 225                        key_layer |= NFP_FLOWER_LAYER_IPV6;
 226                        key_size += sizeof(struct nfp_flower_ipv6);
 227                        break;
 228
 229                /* Currently we do not offload ARP
 230                 * because we rely on it to get to the host.
 231                 */
 232                case cpu_to_be16(ETH_P_ARP):
 233                        return -EOPNOTSUPP;
 234
 235                /* Will be included in layer 2. */
 236                case cpu_to_be16(ETH_P_8021Q):
 237                        break;
 238
 239                default:
 240                        /* Other ethtype - we need check the masks for the
 241                         * remainder of the key to ensure we can offload.
 242                         */
 243                        if (nfp_flower_check_higher_than_mac(flow))
 244                                return -EOPNOTSUPP;
 245                        break;
 246                }
 247        }
 248
 249        if (mask_basic && mask_basic->ip_proto) {
 250                /* Ethernet type is present in the key. */
 251                switch (key_basic->ip_proto) {
 252                case IPPROTO_TCP:
 253                case IPPROTO_UDP:
 254                case IPPROTO_SCTP:
 255                case IPPROTO_ICMP:
 256                case IPPROTO_ICMPV6:
 257                        key_layer |= NFP_FLOWER_LAYER_TP;
 258                        key_size += sizeof(struct nfp_flower_tp_ports);
 259                        break;
 260                default:
 261                        /* Other ip proto - we need check the masks for the
 262                         * remainder of the key to ensure we can offload.
 263                         */
 264                        return -EOPNOTSUPP;
 265                }
 266        }
 267
 268        ret_key_ls->key_layer = key_layer;
 269        ret_key_ls->key_layer_two = key_layer_two;
 270        ret_key_ls->key_size = key_size;
 271
 272        return 0;
 273}
 274
 275static struct nfp_fl_payload *
 276nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
 277{
 278        struct nfp_fl_payload *flow_pay;
 279
 280        flow_pay = kmalloc(sizeof(*flow_pay), GFP_KERNEL);
 281        if (!flow_pay)
 282                return NULL;
 283
 284        flow_pay->meta.key_len = key_layer->key_size;
 285        flow_pay->unmasked_data = kmalloc(key_layer->key_size, GFP_KERNEL);
 286        if (!flow_pay->unmasked_data)
 287                goto err_free_flow;
 288
 289        flow_pay->meta.mask_len = key_layer->key_size;
 290        flow_pay->mask_data = kmalloc(key_layer->key_size, GFP_KERNEL);
 291        if (!flow_pay->mask_data)
 292                goto err_free_unmasked;
 293
 294        flow_pay->action_data = kmalloc(NFP_FL_MAX_A_SIZ, GFP_KERNEL);
 295        if (!flow_pay->action_data)
 296                goto err_free_mask;
 297
 298        flow_pay->nfp_tun_ipv4_addr = 0;
 299        flow_pay->meta.flags = 0;
 300        spin_lock_init(&flow_pay->lock);
 301
 302        return flow_pay;
 303
 304err_free_mask:
 305        kfree(flow_pay->mask_data);
 306err_free_unmasked:
 307        kfree(flow_pay->unmasked_data);
 308err_free_flow:
 309        kfree(flow_pay);
 310        return NULL;
 311}
 312
 313/**
 314 * nfp_flower_add_offload() - Adds a new flow to hardware.
 315 * @app:        Pointer to the APP handle
 316 * @netdev:     netdev structure.
 317 * @flow:       TC flower classifier offload structure.
 318 * @egress:     NFP netdev is the egress.
 319 *
 320 * Adds a new flow to the repeated hash structure and action payload.
 321 *
 322 * Return: negative value on error, 0 if configured successfully.
 323 */
 324static int
 325nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
 326                       struct tc_cls_flower_offload *flow, bool egress)
 327{
 328        struct nfp_flower_priv *priv = app->priv;
 329        struct nfp_fl_payload *flow_pay;
 330        struct nfp_fl_key_ls *key_layer;
 331        int err;
 332
 333        key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
 334        if (!key_layer)
 335                return -ENOMEM;
 336
 337        err = nfp_flower_calculate_key_layers(key_layer, flow, egress);
 338        if (err)
 339                goto err_free_key_ls;
 340
 341        flow_pay = nfp_flower_allocate_new(key_layer);
 342        if (!flow_pay) {
 343                err = -ENOMEM;
 344                goto err_free_key_ls;
 345        }
 346
 347        err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay);
 348        if (err)
 349                goto err_destroy_flow;
 350
 351        err = nfp_flower_compile_action(flow, netdev, flow_pay);
 352        if (err)
 353                goto err_destroy_flow;
 354
 355        err = nfp_compile_flow_metadata(app, flow, flow_pay);
 356        if (err)
 357                goto err_destroy_flow;
 358
 359        err = nfp_flower_xmit_flow(netdev, flow_pay,
 360                                   NFP_FLOWER_CMSG_TYPE_FLOW_ADD);
 361        if (err)
 362                goto err_destroy_flow;
 363
 364        INIT_HLIST_NODE(&flow_pay->link);
 365        flow_pay->tc_flower_cookie = flow->cookie;
 366        hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie);
 367
 368        /* Deallocate flow payload when flower rule has been destroyed. */
 369        kfree(key_layer);
 370
 371        return 0;
 372
 373err_destroy_flow:
 374        kfree(flow_pay->action_data);
 375        kfree(flow_pay->mask_data);
 376        kfree(flow_pay->unmasked_data);
 377        kfree(flow_pay);
 378err_free_key_ls:
 379        kfree(key_layer);
 380        return err;
 381}
 382
 383/**
 384 * nfp_flower_del_offload() - Removes a flow from hardware.
 385 * @app:        Pointer to the APP handle
 386 * @netdev:     netdev structure.
 387 * @flow:       TC flower classifier offload structure
 388 *
 389 * Removes a flow from the repeated hash structure and clears the
 390 * action payload.
 391 *
 392 * Return: negative value on error, 0 if removed successfully.
 393 */
 394static int
 395nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
 396                       struct tc_cls_flower_offload *flow)
 397{
 398        struct nfp_fl_payload *nfp_flow;
 399        int err;
 400
 401        nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
 402        if (!nfp_flow)
 403                return -ENOENT;
 404
 405        err = nfp_modify_flow_metadata(app, nfp_flow);
 406        if (err)
 407                goto err_free_flow;
 408
 409        if (nfp_flow->nfp_tun_ipv4_addr)
 410                nfp_tunnel_del_ipv4_off(app, nfp_flow->nfp_tun_ipv4_addr);
 411
 412        err = nfp_flower_xmit_flow(netdev, nfp_flow,
 413                                   NFP_FLOWER_CMSG_TYPE_FLOW_DEL);
 414        if (err)
 415                goto err_free_flow;
 416
 417err_free_flow:
 418        hash_del_rcu(&nfp_flow->link);
 419        kfree(nfp_flow->action_data);
 420        kfree(nfp_flow->mask_data);
 421        kfree(nfp_flow->unmasked_data);
 422        kfree_rcu(nfp_flow, rcu);
 423        return err;
 424}
 425
 426/**
 427 * nfp_flower_get_stats() - Populates flow stats obtained from hardware.
 428 * @app:        Pointer to the APP handle
 429 * @flow:       TC flower classifier offload structure
 430 *
 431 * Populates a flow statistics structure which which corresponds to a
 432 * specific flow.
 433 *
 434 * Return: negative value on error, 0 if stats populated successfully.
 435 */
 436static int
 437nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
 438{
 439        struct nfp_fl_payload *nfp_flow;
 440
 441        nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
 442        if (!nfp_flow)
 443                return -EINVAL;
 444
 445        spin_lock_bh(&nfp_flow->lock);
 446        tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
 447                              nfp_flow->stats.pkts, nfp_flow->stats.used);
 448
 449        nfp_flow->stats.pkts = 0;
 450        nfp_flow->stats.bytes = 0;
 451        spin_unlock_bh(&nfp_flow->lock);
 452
 453        return 0;
 454}
 455
 456static int
 457nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
 458                        struct tc_cls_flower_offload *flower, bool egress)
 459{
 460        if (!eth_proto_is_802_3(flower->common.protocol) ||
 461            flower->common.chain_index)
 462                return -EOPNOTSUPP;
 463
 464        switch (flower->command) {
 465        case TC_CLSFLOWER_REPLACE:
 466                return nfp_flower_add_offload(app, netdev, flower, egress);
 467        case TC_CLSFLOWER_DESTROY:
 468                return nfp_flower_del_offload(app, netdev, flower);
 469        case TC_CLSFLOWER_STATS:
 470                return nfp_flower_get_stats(app, flower);
 471        }
 472
 473        return -EOPNOTSUPP;
 474}
 475
 476int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
 477                                  void *cb_priv)
 478{
 479        struct nfp_repr *repr = cb_priv;
 480
 481        if (!tc_can_offload(repr->netdev))
 482                return -EOPNOTSUPP;
 483
 484        switch (type) {
 485        case TC_SETUP_CLSFLOWER:
 486                return nfp_flower_repr_offload(repr->app, repr->netdev,
 487                                               type_data, true);
 488        default:
 489                return -EOPNOTSUPP;
 490        }
 491}
 492
 493static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
 494                                        void *type_data, void *cb_priv)
 495{
 496        struct nfp_repr *repr = cb_priv;
 497
 498        if (!tc_can_offload(repr->netdev))
 499                return -EOPNOTSUPP;
 500
 501        switch (type) {
 502        case TC_SETUP_CLSFLOWER:
 503                return nfp_flower_repr_offload(repr->app, repr->netdev,
 504                                               type_data, false);
 505        default:
 506                return -EOPNOTSUPP;
 507        }
 508}
 509
 510static int nfp_flower_setup_tc_block(struct net_device *netdev,
 511                                     struct tc_block_offload *f)
 512{
 513        struct nfp_repr *repr = netdev_priv(netdev);
 514
 515        if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
 516                return -EOPNOTSUPP;
 517
 518        switch (f->command) {
 519        case TC_BLOCK_BIND:
 520                return tcf_block_cb_register(f->block,
 521                                             nfp_flower_setup_tc_block_cb,
 522                                             repr, repr);
 523        case TC_BLOCK_UNBIND:
 524                tcf_block_cb_unregister(f->block,
 525                                        nfp_flower_setup_tc_block_cb,
 526                                        repr);
 527                return 0;
 528        default:
 529                return -EOPNOTSUPP;
 530        }
 531}
 532
 533int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
 534                        enum tc_setup_type type, void *type_data)
 535{
 536        switch (type) {
 537        case TC_SETUP_BLOCK:
 538                return nfp_flower_setup_tc_block(netdev, type_data);
 539        default:
 540                return -EOPNOTSUPP;
 541        }
 542}
 543