1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4 #include <linux/skbuff.h> 5 #include <net/devlink.h> 6 #include <net/pkt_cls.h> 7 8 #include "cmsg.h" 9 #include "main.h" 10 #include "../nfpcore/nfp_cpp.h" 11 #include "../nfpcore/nfp_nsp.h" 12 #include "../nfp_app.h" 13 #include "../nfp_main.h" 14 #include "../nfp_net.h" 15 #include "../nfp_port.h" 16 17 #define NFP_FLOWER_SUPPORTED_TCPFLAGS \ 18 (TCPHDR_FIN | TCPHDR_SYN | TCPHDR_RST | \ 19 TCPHDR_PSH | TCPHDR_URG) 20 21 #define NFP_FLOWER_SUPPORTED_CTLFLAGS \ 22 (FLOW_DIS_IS_FRAGMENT | \ 23 FLOW_DIS_FIRST_FRAG) 24 25 #define NFP_FLOWER_WHITELIST_DISSECTOR \ 26 (BIT(FLOW_DISSECTOR_KEY_CONTROL) | \ 27 BIT(FLOW_DISSECTOR_KEY_BASIC) | \ 28 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \ 29 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \ 30 BIT(FLOW_DISSECTOR_KEY_TCP) | \ 31 BIT(FLOW_DISSECTOR_KEY_PORTS) | \ 32 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \ 33 BIT(FLOW_DISSECTOR_KEY_VLAN) | \ 34 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ 35 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ 36 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ 37 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ 38 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ 39 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ 40 BIT(FLOW_DISSECTOR_KEY_ENC_IP) | \ 41 BIT(FLOW_DISSECTOR_KEY_MPLS) | \ 42 BIT(FLOW_DISSECTOR_KEY_IP)) 43 44 #define NFP_FLOWER_WHITELIST_TUN_DISSECTOR \ 45 (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ 46 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ 47 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ 48 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ 49 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ 50 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ 51 BIT(FLOW_DISSECTOR_KEY_ENC_IP)) 52 53 #define NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R \ 54 (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ 55 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ 56 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS)) 57 58 static int 59 nfp_flower_xmit_flow(struct nfp_app *app, struct nfp_fl_payload *nfp_flow, 60 u8 mtype) 61 { 62 u32 meta_len, key_len, mask_len, act_len, tot_len; 63 struct sk_buff *skb; 64 unsigned char *msg; 65 66 meta_len = sizeof(struct nfp_fl_rule_metadata); 67 key_len = nfp_flow->meta.key_len; 68 mask_len = nfp_flow->meta.mask_len; 69 act_len = nfp_flow->meta.act_len; 70 71 tot_len = meta_len + key_len + mask_len + act_len; 72 73 /* Convert to long words as firmware expects 74 * lengths in units of NFP_FL_LW_SIZ. 75 */ 76 nfp_flow->meta.key_len >>= NFP_FL_LW_SIZ; 77 nfp_flow->meta.mask_len >>= NFP_FL_LW_SIZ; 78 nfp_flow->meta.act_len >>= NFP_FL_LW_SIZ; 79 80 skb = nfp_flower_cmsg_alloc(app, tot_len, mtype, GFP_KERNEL); 81 if (!skb) 82 return -ENOMEM; 83 84 msg = nfp_flower_cmsg_get_data(skb); 85 memcpy(msg, &nfp_flow->meta, meta_len); 86 memcpy(&msg[meta_len], nfp_flow->unmasked_data, key_len); 87 memcpy(&msg[meta_len + key_len], nfp_flow->mask_data, mask_len); 88 memcpy(&msg[meta_len + key_len + mask_len], 89 nfp_flow->action_data, act_len); 90 91 /* Convert back to bytes as software expects 92 * lengths in units of bytes. 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 nfp_ctrl_tx(app->ctrl, skb); 99 100 return 0; 101 } 102 103 static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f) 104 { 105 struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); 106 107 return flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) || 108 flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) || 109 flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS) || 110 flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP); 111 } 112 113 static int 114 nfp_flower_calc_opt_layer(struct flow_match_enc_opts *enc_opts, 115 u32 *key_layer_two, int *key_size) 116 { 117 if (enc_opts->key->len > NFP_FL_MAX_GENEVE_OPT_KEY) 118 return -EOPNOTSUPP; 119 120 if (enc_opts->key->len > 0) { 121 *key_layer_two |= NFP_FLOWER_LAYER2_GENEVE_OP; 122 *key_size += sizeof(struct nfp_flower_geneve_options); 123 } 124 125 return 0; 126 } 127 128 static int 129 nfp_flower_calculate_key_layers(struct nfp_app *app, 130 struct net_device *netdev, 131 struct nfp_fl_key_ls *ret_key_ls, 132 struct tc_cls_flower_offload *flow, 133 enum nfp_flower_tun_type *tun_type) 134 { 135 struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); 136 struct flow_dissector *dissector = rule->match.dissector; 137 struct flow_match_basic basic = { NULL, NULL}; 138 struct nfp_flower_priv *priv = app->priv; 139 u32 key_layer_two; 140 u8 key_layer; 141 int key_size; 142 int err; 143 144 if (dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) 145 return -EOPNOTSUPP; 146 147 /* If any tun dissector is used then the required set must be used. */ 148 if (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR && 149 (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) 150 != NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) 151 return -EOPNOTSUPP; 152 153 key_layer_two = 0; 154 key_layer = NFP_FLOWER_LAYER_PORT; 155 key_size = sizeof(struct nfp_flower_meta_tci) + 156 sizeof(struct nfp_flower_in_port); 157 158 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS) || 159 flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) { 160 key_layer |= NFP_FLOWER_LAYER_MAC; 161 key_size += sizeof(struct nfp_flower_mac_mpls); 162 } 163 164 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 165 struct flow_match_vlan vlan; 166 167 flow_rule_match_vlan(rule, &vlan); 168 if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_PCP) && 169 vlan.key->vlan_priority) 170 return -EOPNOTSUPP; 171 } 172 173 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { 174 struct flow_match_enc_opts enc_op = { NULL, NULL }; 175 struct flow_match_ipv4_addrs ipv4_addrs; 176 struct flow_match_control enc_ctl; 177 struct flow_match_ports enc_ports; 178 179 flow_rule_match_enc_control(rule, &enc_ctl); 180 181 if (enc_ctl.mask->addr_type != 0xffff || 182 enc_ctl.key->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS) 183 return -EOPNOTSUPP; 184 185 /* These fields are already verified as used. */ 186 flow_rule_match_enc_ipv4_addrs(rule, &ipv4_addrs); 187 if (ipv4_addrs.mask->dst != cpu_to_be32(~0)) 188 return -EOPNOTSUPP; 189 190 flow_rule_match_enc_ports(rule, &enc_ports); 191 if (enc_ports.mask->dst != cpu_to_be16(~0)) 192 return -EOPNOTSUPP; 193 194 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS)) 195 flow_rule_match_enc_opts(rule, &enc_op); 196 197 switch (enc_ports.key->dst) { 198 case htons(NFP_FL_VXLAN_PORT): 199 *tun_type = NFP_FL_TUNNEL_VXLAN; 200 key_layer |= NFP_FLOWER_LAYER_VXLAN; 201 key_size += sizeof(struct nfp_flower_ipv4_udp_tun); 202 203 if (enc_op.key) 204 return -EOPNOTSUPP; 205 break; 206 case htons(NFP_FL_GENEVE_PORT): 207 if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE)) 208 return -EOPNOTSUPP; 209 *tun_type = NFP_FL_TUNNEL_GENEVE; 210 key_layer |= NFP_FLOWER_LAYER_EXT_META; 211 key_size += sizeof(struct nfp_flower_ext_meta); 212 key_layer_two |= NFP_FLOWER_LAYER2_GENEVE; 213 key_size += sizeof(struct nfp_flower_ipv4_udp_tun); 214 215 if (!enc_op.key) 216 break; 217 if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT)) 218 return -EOPNOTSUPP; 219 err = nfp_flower_calc_opt_layer(&enc_op, &key_layer_two, 220 &key_size); 221 if (err) 222 return err; 223 break; 224 default: 225 return -EOPNOTSUPP; 226 } 227 228 /* Ensure the ingress netdev matches the expected tun type. */ 229 if (!nfp_fl_netdev_is_tunnel_type(netdev, *tun_type)) 230 return -EOPNOTSUPP; 231 } 232 233 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) 234 flow_rule_match_basic(rule, &basic); 235 236 if (basic.mask && basic.mask->n_proto) { 237 /* Ethernet type is present in the key. */ 238 switch (basic.key->n_proto) { 239 case cpu_to_be16(ETH_P_IP): 240 key_layer |= NFP_FLOWER_LAYER_IPV4; 241 key_size += sizeof(struct nfp_flower_ipv4); 242 break; 243 244 case cpu_to_be16(ETH_P_IPV6): 245 key_layer |= NFP_FLOWER_LAYER_IPV6; 246 key_size += sizeof(struct nfp_flower_ipv6); 247 break; 248 249 /* Currently we do not offload ARP 250 * because we rely on it to get to the host. 251 */ 252 case cpu_to_be16(ETH_P_ARP): 253 return -EOPNOTSUPP; 254 255 case cpu_to_be16(ETH_P_MPLS_UC): 256 case cpu_to_be16(ETH_P_MPLS_MC): 257 if (!(key_layer & NFP_FLOWER_LAYER_MAC)) { 258 key_layer |= NFP_FLOWER_LAYER_MAC; 259 key_size += sizeof(struct nfp_flower_mac_mpls); 260 } 261 break; 262 263 /* Will be included in layer 2. */ 264 case cpu_to_be16(ETH_P_8021Q): 265 break; 266 267 default: 268 /* Other ethtype - we need check the masks for the 269 * remainder of the key to ensure we can offload. 270 */ 271 if (nfp_flower_check_higher_than_mac(flow)) 272 return -EOPNOTSUPP; 273 break; 274 } 275 } 276 277 if (basic.mask && basic.mask->ip_proto) { 278 /* Ethernet type is present in the key. */ 279 switch (basic.key->ip_proto) { 280 case IPPROTO_TCP: 281 case IPPROTO_UDP: 282 case IPPROTO_SCTP: 283 case IPPROTO_ICMP: 284 case IPPROTO_ICMPV6: 285 key_layer |= NFP_FLOWER_LAYER_TP; 286 key_size += sizeof(struct nfp_flower_tp_ports); 287 break; 288 default: 289 /* Other ip proto - we need check the masks for the 290 * remainder of the key to ensure we can offload. 291 */ 292 return -EOPNOTSUPP; 293 } 294 } 295 296 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { 297 struct flow_match_tcp tcp; 298 u32 tcp_flags; 299 300 flow_rule_match_tcp(rule, &tcp); 301 tcp_flags = be16_to_cpu(tcp.key->flags); 302 303 if (tcp_flags & ~NFP_FLOWER_SUPPORTED_TCPFLAGS) 304 return -EOPNOTSUPP; 305 306 /* We only support PSH and URG flags when either 307 * FIN, SYN or RST is present as well. 308 */ 309 if ((tcp_flags & (TCPHDR_PSH | TCPHDR_URG)) && 310 !(tcp_flags & (TCPHDR_FIN | TCPHDR_SYN | TCPHDR_RST))) 311 return -EOPNOTSUPP; 312 313 /* We need to store TCP flags in the either the IPv4 or IPv6 key 314 * space, thus we need to ensure we include a IPv4/IPv6 key 315 * layer if we have not done so already. 316 */ 317 if (!basic.key) 318 return -EOPNOTSUPP; 319 320 if (!(key_layer & NFP_FLOWER_LAYER_IPV4) && 321 !(key_layer & NFP_FLOWER_LAYER_IPV6)) { 322 switch (basic.key->n_proto) { 323 case cpu_to_be16(ETH_P_IP): 324 key_layer |= NFP_FLOWER_LAYER_IPV4; 325 key_size += sizeof(struct nfp_flower_ipv4); 326 break; 327 328 case cpu_to_be16(ETH_P_IPV6): 329 key_layer |= NFP_FLOWER_LAYER_IPV6; 330 key_size += sizeof(struct nfp_flower_ipv6); 331 break; 332 333 default: 334 return -EOPNOTSUPP; 335 } 336 } 337 } 338 339 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 340 struct flow_match_control ctl; 341 342 flow_rule_match_control(rule, &ctl); 343 if (ctl.key->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS) 344 return -EOPNOTSUPP; 345 } 346 347 ret_key_ls->key_layer = key_layer; 348 ret_key_ls->key_layer_two = key_layer_two; 349 ret_key_ls->key_size = key_size; 350 351 return 0; 352 } 353 354 static struct nfp_fl_payload * 355 nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer) 356 { 357 struct nfp_fl_payload *flow_pay; 358 359 flow_pay = kmalloc(sizeof(*flow_pay), GFP_KERNEL); 360 if (!flow_pay) 361 return NULL; 362 363 flow_pay->meta.key_len = key_layer->key_size; 364 flow_pay->unmasked_data = kmalloc(key_layer->key_size, GFP_KERNEL); 365 if (!flow_pay->unmasked_data) 366 goto err_free_flow; 367 368 flow_pay->meta.mask_len = key_layer->key_size; 369 flow_pay->mask_data = kmalloc(key_layer->key_size, GFP_KERNEL); 370 if (!flow_pay->mask_data) 371 goto err_free_unmasked; 372 373 flow_pay->action_data = kmalloc(NFP_FL_MAX_A_SIZ, GFP_KERNEL); 374 if (!flow_pay->action_data) 375 goto err_free_mask; 376 377 flow_pay->nfp_tun_ipv4_addr = 0; 378 flow_pay->meta.flags = 0; 379 380 return flow_pay; 381 382 err_free_mask: 383 kfree(flow_pay->mask_data); 384 err_free_unmasked: 385 kfree(flow_pay->unmasked_data); 386 err_free_flow: 387 kfree(flow_pay); 388 return NULL; 389 } 390 391 /** 392 * nfp_flower_add_offload() - Adds a new flow to hardware. 393 * @app: Pointer to the APP handle 394 * @netdev: netdev structure. 395 * @flow: TC flower classifier offload structure. 396 * 397 * Adds a new flow to the repeated hash structure and action payload. 398 * 399 * Return: negative value on error, 0 if configured successfully. 400 */ 401 static int 402 nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, 403 struct tc_cls_flower_offload *flow) 404 { 405 enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE; 406 struct nfp_flower_priv *priv = app->priv; 407 struct nfp_fl_payload *flow_pay; 408 struct nfp_fl_key_ls *key_layer; 409 struct nfp_port *port = NULL; 410 int err; 411 412 if (nfp_netdev_is_nfp_repr(netdev)) 413 port = nfp_port_from_netdev(netdev); 414 415 key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL); 416 if (!key_layer) 417 return -ENOMEM; 418 419 err = nfp_flower_calculate_key_layers(app, netdev, key_layer, flow, 420 &tun_type); 421 if (err) 422 goto err_free_key_ls; 423 424 flow_pay = nfp_flower_allocate_new(key_layer); 425 if (!flow_pay) { 426 err = -ENOMEM; 427 goto err_free_key_ls; 428 } 429 430 err = nfp_flower_compile_flow_match(app, flow, key_layer, netdev, 431 flow_pay, tun_type); 432 if (err) 433 goto err_destroy_flow; 434 435 err = nfp_flower_compile_action(app, flow, netdev, flow_pay); 436 if (err) 437 goto err_destroy_flow; 438 439 err = nfp_compile_flow_metadata(app, flow, flow_pay, netdev); 440 if (err) 441 goto err_destroy_flow; 442 443 flow_pay->tc_flower_cookie = flow->cookie; 444 err = rhashtable_insert_fast(&priv->flow_table, &flow_pay->fl_node, 445 nfp_flower_table_params); 446 if (err) 447 goto err_release_metadata; 448 449 err = nfp_flower_xmit_flow(app, flow_pay, 450 NFP_FLOWER_CMSG_TYPE_FLOW_ADD); 451 if (err) 452 goto err_remove_rhash; 453 454 if (port) 455 port->tc_offload_cnt++; 456 457 /* Deallocate flow payload when flower rule has been destroyed. */ 458 kfree(key_layer); 459 460 return 0; 461 462 err_remove_rhash: 463 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, 464 &flow_pay->fl_node, 465 nfp_flower_table_params)); 466 err_release_metadata: 467 nfp_modify_flow_metadata(app, flow_pay); 468 err_destroy_flow: 469 kfree(flow_pay->action_data); 470 kfree(flow_pay->mask_data); 471 kfree(flow_pay->unmasked_data); 472 kfree(flow_pay); 473 err_free_key_ls: 474 kfree(key_layer); 475 return err; 476 } 477 478 /** 479 * nfp_flower_del_offload() - Removes a flow from hardware. 480 * @app: Pointer to the APP handle 481 * @netdev: netdev structure. 482 * @flow: TC flower classifier offload structure 483 * 484 * Removes a flow from the repeated hash structure and clears the 485 * action payload. 486 * 487 * Return: negative value on error, 0 if removed successfully. 488 */ 489 static int 490 nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev, 491 struct tc_cls_flower_offload *flow) 492 { 493 struct nfp_flower_priv *priv = app->priv; 494 struct nfp_fl_payload *nfp_flow; 495 struct nfp_port *port = NULL; 496 int err; 497 498 if (nfp_netdev_is_nfp_repr(netdev)) 499 port = nfp_port_from_netdev(netdev); 500 501 nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, netdev); 502 if (!nfp_flow) 503 return -ENOENT; 504 505 err = nfp_modify_flow_metadata(app, nfp_flow); 506 if (err) 507 goto err_free_flow; 508 509 if (nfp_flow->nfp_tun_ipv4_addr) 510 nfp_tunnel_del_ipv4_off(app, nfp_flow->nfp_tun_ipv4_addr); 511 512 err = nfp_flower_xmit_flow(app, nfp_flow, 513 NFP_FLOWER_CMSG_TYPE_FLOW_DEL); 514 if (err) 515 goto err_free_flow; 516 517 err_free_flow: 518 if (port) 519 port->tc_offload_cnt--; 520 kfree(nfp_flow->action_data); 521 kfree(nfp_flow->mask_data); 522 kfree(nfp_flow->unmasked_data); 523 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, 524 &nfp_flow->fl_node, 525 nfp_flower_table_params)); 526 kfree_rcu(nfp_flow, rcu); 527 return err; 528 } 529 530 /** 531 * nfp_flower_get_stats() - Populates flow stats obtained from hardware. 532 * @app: Pointer to the APP handle 533 * @netdev: Netdev structure. 534 * @flow: TC flower classifier offload structure 535 * 536 * Populates a flow statistics structure which which corresponds to a 537 * specific flow. 538 * 539 * Return: negative value on error, 0 if stats populated successfully. 540 */ 541 static int 542 nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev, 543 struct tc_cls_flower_offload *flow) 544 { 545 struct nfp_flower_priv *priv = app->priv; 546 struct nfp_fl_payload *nfp_flow; 547 u32 ctx_id; 548 549 nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, netdev); 550 if (!nfp_flow) 551 return -EINVAL; 552 553 ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id); 554 555 spin_lock_bh(&priv->stats_lock); 556 flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes, 557 priv->stats[ctx_id].pkts, priv->stats[ctx_id].used); 558 559 priv->stats[ctx_id].pkts = 0; 560 priv->stats[ctx_id].bytes = 0; 561 spin_unlock_bh(&priv->stats_lock); 562 563 return 0; 564 } 565 566 static int 567 nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, 568 struct tc_cls_flower_offload *flower) 569 { 570 if (!eth_proto_is_802_3(flower->common.protocol)) 571 return -EOPNOTSUPP; 572 573 switch (flower->command) { 574 case TC_CLSFLOWER_REPLACE: 575 return nfp_flower_add_offload(app, netdev, flower); 576 case TC_CLSFLOWER_DESTROY: 577 return nfp_flower_del_offload(app, netdev, flower); 578 case TC_CLSFLOWER_STATS: 579 return nfp_flower_get_stats(app, netdev, flower); 580 default: 581 return -EOPNOTSUPP; 582 } 583 } 584 585 static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, 586 void *type_data, void *cb_priv) 587 { 588 struct nfp_repr *repr = cb_priv; 589 590 if (!tc_cls_can_offload_and_chain0(repr->netdev, type_data)) 591 return -EOPNOTSUPP; 592 593 switch (type) { 594 case TC_SETUP_CLSFLOWER: 595 return nfp_flower_repr_offload(repr->app, repr->netdev, 596 type_data); 597 default: 598 return -EOPNOTSUPP; 599 } 600 } 601 602 static int nfp_flower_setup_tc_block(struct net_device *netdev, 603 struct tc_block_offload *f) 604 { 605 struct nfp_repr *repr = netdev_priv(netdev); 606 607 if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) 608 return -EOPNOTSUPP; 609 610 switch (f->command) { 611 case TC_BLOCK_BIND: 612 return tcf_block_cb_register(f->block, 613 nfp_flower_setup_tc_block_cb, 614 repr, repr, f->extack); 615 case TC_BLOCK_UNBIND: 616 tcf_block_cb_unregister(f->block, 617 nfp_flower_setup_tc_block_cb, 618 repr); 619 return 0; 620 default: 621 return -EOPNOTSUPP; 622 } 623 } 624 625 int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev, 626 enum tc_setup_type type, void *type_data) 627 { 628 switch (type) { 629 case TC_SETUP_BLOCK: 630 return nfp_flower_setup_tc_block(netdev, type_data); 631 default: 632 return -EOPNOTSUPP; 633 } 634 } 635 636 struct nfp_flower_indr_block_cb_priv { 637 struct net_device *netdev; 638 struct nfp_app *app; 639 struct list_head list; 640 }; 641 642 static struct nfp_flower_indr_block_cb_priv * 643 nfp_flower_indr_block_cb_priv_lookup(struct nfp_app *app, 644 struct net_device *netdev) 645 { 646 struct nfp_flower_indr_block_cb_priv *cb_priv; 647 struct nfp_flower_priv *priv = app->priv; 648 649 /* All callback list access should be protected by RTNL. */ 650 ASSERT_RTNL(); 651 652 list_for_each_entry(cb_priv, &priv->indr_block_cb_priv, list) 653 if (cb_priv->netdev == netdev) 654 return cb_priv; 655 656 return NULL; 657 } 658 659 static int nfp_flower_setup_indr_block_cb(enum tc_setup_type type, 660 void *type_data, void *cb_priv) 661 { 662 struct nfp_flower_indr_block_cb_priv *priv = cb_priv; 663 struct tc_cls_flower_offload *flower = type_data; 664 665 if (flower->common.chain_index) 666 return -EOPNOTSUPP; 667 668 switch (type) { 669 case TC_SETUP_CLSFLOWER: 670 return nfp_flower_repr_offload(priv->app, priv->netdev, 671 type_data); 672 default: 673 return -EOPNOTSUPP; 674 } 675 } 676 677 static int 678 nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app, 679 struct tc_block_offload *f) 680 { 681 struct nfp_flower_indr_block_cb_priv *cb_priv; 682 struct nfp_flower_priv *priv = app->priv; 683 int err; 684 685 if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) 686 return -EOPNOTSUPP; 687 688 switch (f->command) { 689 case TC_BLOCK_BIND: 690 cb_priv = kmalloc(sizeof(*cb_priv), GFP_KERNEL); 691 if (!cb_priv) 692 return -ENOMEM; 693 694 cb_priv->netdev = netdev; 695 cb_priv->app = app; 696 list_add(&cb_priv->list, &priv->indr_block_cb_priv); 697 698 err = tcf_block_cb_register(f->block, 699 nfp_flower_setup_indr_block_cb, 700 cb_priv, cb_priv, f->extack); 701 if (err) { 702 list_del(&cb_priv->list); 703 kfree(cb_priv); 704 } 705 706 return err; 707 case TC_BLOCK_UNBIND: 708 cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev); 709 if (!cb_priv) 710 return -ENOENT; 711 712 tcf_block_cb_unregister(f->block, 713 nfp_flower_setup_indr_block_cb, 714 cb_priv); 715 list_del(&cb_priv->list); 716 kfree(cb_priv); 717 718 return 0; 719 default: 720 return -EOPNOTSUPP; 721 } 722 return 0; 723 } 724 725 static int 726 nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv, 727 enum tc_setup_type type, void *type_data) 728 { 729 switch (type) { 730 case TC_SETUP_BLOCK: 731 return nfp_flower_setup_indr_tc_block(netdev, cb_priv, 732 type_data); 733 default: 734 return -EOPNOTSUPP; 735 } 736 } 737 738 int nfp_flower_reg_indir_block_handler(struct nfp_app *app, 739 struct net_device *netdev, 740 unsigned long event) 741 { 742 int err; 743 744 if (!nfp_fl_is_netdev_to_offload(netdev)) 745 return NOTIFY_OK; 746 747 if (event == NETDEV_REGISTER) { 748 err = __tc_indr_block_cb_register(netdev, app, 749 nfp_flower_indr_setup_tc_cb, 750 app); 751 if (err) 752 nfp_flower_cmsg_warn(app, 753 "Indirect block reg failed - %s\n", 754 netdev->name); 755 } else if (event == NETDEV_UNREGISTER) { 756 __tc_indr_block_cb_unregister(netdev, 757 nfp_flower_indr_setup_tc_cb, app); 758 } 759 760 return NOTIFY_OK; 761 } 762