1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4 #include <linux/bitfield.h> 5 #include <net/pkt_cls.h> 6 #include <net/switchdev.h> 7 #include <net/tc_act/tc_csum.h> 8 #include <net/tc_act/tc_gact.h> 9 #include <net/tc_act/tc_mirred.h> 10 #include <net/tc_act/tc_pedit.h> 11 #include <net/tc_act/tc_vlan.h> 12 #include <net/tc_act/tc_tunnel_key.h> 13 14 #include "cmsg.h" 15 #include "main.h" 16 #include "../nfp_net_repr.h" 17 18 /* The kernel versions of TUNNEL_* are not ABI and therefore vulnerable 19 * to change. Such changes will break our FW ABI. 20 */ 21 #define NFP_FL_TUNNEL_CSUM cpu_to_be16(0x01) 22 #define NFP_FL_TUNNEL_KEY cpu_to_be16(0x04) 23 #define NFP_FL_TUNNEL_GENEVE_OPT cpu_to_be16(0x0800) 24 #define NFP_FL_SUPPORTED_TUNNEL_INFO_FLAGS IP_TUNNEL_INFO_TX 25 #define NFP_FL_SUPPORTED_IPV4_UDP_TUN_FLAGS (NFP_FL_TUNNEL_CSUM | \ 26 NFP_FL_TUNNEL_KEY | \ 27 NFP_FL_TUNNEL_GENEVE_OPT) 28 29 static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan) 30 { 31 size_t act_size = sizeof(struct nfp_fl_pop_vlan); 32 33 pop_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_POP_VLAN; 34 pop_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ; 35 pop_vlan->reserved = 0; 36 } 37 38 static void 39 nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan, 40 const struct tc_action *action) 41 { 42 size_t act_size = sizeof(struct nfp_fl_push_vlan); 43 u16 tmp_push_vlan_tci; 44 45 push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN; 46 push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ; 47 push_vlan->reserved = 0; 48 push_vlan->vlan_tpid = tcf_vlan_push_proto(action); 49 50 tmp_push_vlan_tci = 51 FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, tcf_vlan_push_prio(action)) | 52 FIELD_PREP(NFP_FL_PUSH_VLAN_VID, tcf_vlan_push_vid(action)) | 53 NFP_FL_PUSH_VLAN_CFI; 54 push_vlan->vlan_tci = cpu_to_be16(tmp_push_vlan_tci); 55 } 56 57 static int 58 nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action, 59 struct nfp_fl_payload *nfp_flow, int act_len) 60 { 61 size_t act_size = sizeof(struct nfp_fl_pre_lag); 62 struct nfp_fl_pre_lag *pre_lag; 63 struct net_device *out_dev; 64 int err; 65 66 out_dev = tcf_mirred_dev(action); 67 if (!out_dev || !netif_is_lag_master(out_dev)) 68 return 0; 69 70 if (act_len + act_size > NFP_FL_MAX_A_SIZ) 71 return -EOPNOTSUPP; 72 73 /* Pre_lag action must be first on action list. 74 * If other actions already exist they need pushed forward. 75 */ 76 if (act_len) 77 memmove(nfp_flow->action_data + act_size, 78 nfp_flow->action_data, act_len); 79 80 pre_lag = (struct nfp_fl_pre_lag *)nfp_flow->action_data; 81 err = nfp_flower_lag_populate_pre_action(app, out_dev, pre_lag); 82 if (err) 83 return err; 84 85 pre_lag->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_LAG; 86 pre_lag->head.len_lw = act_size >> NFP_FL_LW_SIZ; 87 88 nfp_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); 89 90 return act_size; 91 } 92 93 static int 94 nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, 95 const struct tc_action *action, struct nfp_fl_payload *nfp_flow, 96 bool last, struct net_device *in_dev, 97 enum nfp_flower_tun_type tun_type, int *tun_out_cnt) 98 { 99 size_t act_size = sizeof(struct nfp_fl_output); 100 struct nfp_flower_priv *priv = app->priv; 101 struct net_device *out_dev; 102 u16 tmp_flags; 103 104 output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT; 105 output->head.len_lw = act_size >> NFP_FL_LW_SIZ; 106 107 out_dev = tcf_mirred_dev(action); 108 if (!out_dev) 109 return -EOPNOTSUPP; 110 111 tmp_flags = last ? NFP_FL_OUT_FLAGS_LAST : 0; 112 113 if (tun_type) { 114 /* Verify the egress netdev matches the tunnel type. */ 115 if (!nfp_fl_netdev_is_tunnel_type(out_dev, tun_type)) 116 return -EOPNOTSUPP; 117 118 if (*tun_out_cnt) 119 return -EOPNOTSUPP; 120 (*tun_out_cnt)++; 121 122 output->flags = cpu_to_be16(tmp_flags | 123 NFP_FL_OUT_FLAGS_USE_TUN); 124 output->port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type); 125 } else if (netif_is_lag_master(out_dev) && 126 priv->flower_ext_feats & NFP_FL_FEATS_LAG) { 127 int gid; 128 129 output->flags = cpu_to_be16(tmp_flags); 130 gid = nfp_flower_lag_get_output_id(app, out_dev); 131 if (gid < 0) 132 return gid; 133 output->port = cpu_to_be32(NFP_FL_LAG_OUT | gid); 134 } else { 135 /* Set action output parameters. */ 136 output->flags = cpu_to_be16(tmp_flags); 137 138 if (nfp_netdev_is_nfp_repr(in_dev)) { 139 /* Confirm ingress and egress are on same device. */ 140 if (!switchdev_port_same_parent_id(in_dev, out_dev)) 141 return -EOPNOTSUPP; 142 } 143 144 if (!nfp_netdev_is_nfp_repr(out_dev)) 145 return -EOPNOTSUPP; 146 147 output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev)); 148 if (!output->port) 149 return -EOPNOTSUPP; 150 } 151 nfp_flow->meta.shortcut = output->port; 152 153 return 0; 154 } 155 156 static enum nfp_flower_tun_type 157 nfp_fl_get_tun_from_act_l4_port(struct nfp_app *app, 158 const struct tc_action *action) 159 { 160 struct ip_tunnel_info *tun = tcf_tunnel_info(action); 161 struct nfp_flower_priv *priv = app->priv; 162 163 switch (tun->key.tp_dst) { 164 case htons(NFP_FL_VXLAN_PORT): 165 return NFP_FL_TUNNEL_VXLAN; 166 case htons(NFP_FL_GENEVE_PORT): 167 if (priv->flower_ext_feats & NFP_FL_FEATS_GENEVE) 168 return NFP_FL_TUNNEL_GENEVE; 169 /* FALLTHROUGH */ 170 default: 171 return NFP_FL_TUNNEL_NONE; 172 } 173 } 174 175 static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len) 176 { 177 size_t act_size = sizeof(struct nfp_fl_pre_tunnel); 178 struct nfp_fl_pre_tunnel *pre_tun_act; 179 180 /* Pre_tunnel action must be first on action list. 181 * If other actions already exist they need to be pushed forward. 182 */ 183 if (act_len) 184 memmove(act_data + act_size, act_data, act_len); 185 186 pre_tun_act = (struct nfp_fl_pre_tunnel *)act_data; 187 188 memset(pre_tun_act, 0, act_size); 189 190 pre_tun_act->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL; 191 pre_tun_act->head.len_lw = act_size >> NFP_FL_LW_SIZ; 192 193 return pre_tun_act; 194 } 195 196 static int 197 nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len, 198 const struct tc_action *action) 199 { 200 struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action); 201 int opt_len, opt_cnt, act_start, tot_push_len; 202 u8 *src = ip_tunnel_info_opts(ip_tun); 203 204 /* We need to populate the options in reverse order for HW. 205 * Therefore we go through the options, calculating the 206 * number of options and the total size, then we populate 207 * them in reverse order in the action list. 208 */ 209 opt_cnt = 0; 210 tot_push_len = 0; 211 opt_len = ip_tun->options_len; 212 while (opt_len > 0) { 213 struct geneve_opt *opt = (struct geneve_opt *)src; 214 215 opt_cnt++; 216 if (opt_cnt > NFP_FL_MAX_GENEVE_OPT_CNT) 217 return -EOPNOTSUPP; 218 219 tot_push_len += sizeof(struct nfp_fl_push_geneve) + 220 opt->length * 4; 221 if (tot_push_len > NFP_FL_MAX_GENEVE_OPT_ACT) 222 return -EOPNOTSUPP; 223 224 opt_len -= sizeof(struct geneve_opt) + opt->length * 4; 225 src += sizeof(struct geneve_opt) + opt->length * 4; 226 } 227 228 if (*list_len + tot_push_len > NFP_FL_MAX_A_SIZ) 229 return -EOPNOTSUPP; 230 231 act_start = *list_len; 232 *list_len += tot_push_len; 233 src = ip_tunnel_info_opts(ip_tun); 234 while (opt_cnt) { 235 struct geneve_opt *opt = (struct geneve_opt *)src; 236 struct nfp_fl_push_geneve *push; 237 size_t act_size, len; 238 239 opt_cnt--; 240 act_size = sizeof(struct nfp_fl_push_geneve) + opt->length * 4; 241 tot_push_len -= act_size; 242 len = act_start + tot_push_len; 243 244 push = (struct nfp_fl_push_geneve *)&nfp_fl->action_data[len]; 245 push->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_GENEVE; 246 push->head.len_lw = act_size >> NFP_FL_LW_SIZ; 247 push->reserved = 0; 248 push->class = opt->opt_class; 249 push->type = opt->type; 250 push->length = opt->length; 251 memcpy(&push->opt_data, opt->opt_data, opt->length * 4); 252 253 src += sizeof(struct geneve_opt) + opt->length * 4; 254 } 255 256 return 0; 257 } 258 259 static int 260 nfp_fl_set_ipv4_udp_tun(struct nfp_app *app, 261 struct nfp_fl_set_ipv4_udp_tun *set_tun, 262 const struct tc_action *action, 263 struct nfp_fl_pre_tunnel *pre_tun, 264 enum nfp_flower_tun_type tun_type, 265 struct net_device *netdev) 266 { 267 size_t act_size = sizeof(struct nfp_fl_set_ipv4_udp_tun); 268 struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action); 269 struct nfp_flower_priv *priv = app->priv; 270 u32 tmp_set_ip_tun_type_index = 0; 271 /* Currently support one pre-tunnel so index is always 0. */ 272 int pretun_idx = 0; 273 274 BUILD_BUG_ON(NFP_FL_TUNNEL_CSUM != TUNNEL_CSUM || 275 NFP_FL_TUNNEL_KEY != TUNNEL_KEY || 276 NFP_FL_TUNNEL_GENEVE_OPT != TUNNEL_GENEVE_OPT); 277 if (ip_tun->options_len && 278 (tun_type != NFP_FL_TUNNEL_GENEVE || 279 !(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT))) 280 return -EOPNOTSUPP; 281 282 set_tun->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL; 283 set_tun->head.len_lw = act_size >> NFP_FL_LW_SIZ; 284 285 /* Set tunnel type and pre-tunnel index. */ 286 tmp_set_ip_tun_type_index |= 287 FIELD_PREP(NFP_FL_IPV4_TUNNEL_TYPE, tun_type) | 288 FIELD_PREP(NFP_FL_IPV4_PRE_TUN_INDEX, pretun_idx); 289 290 set_tun->tun_type_index = cpu_to_be32(tmp_set_ip_tun_type_index); 291 set_tun->tun_id = ip_tun->key.tun_id; 292 293 if (ip_tun->key.ttl) { 294 set_tun->ttl = ip_tun->key.ttl; 295 } else { 296 struct net *net = dev_net(netdev); 297 struct flowi4 flow = {}; 298 struct rtable *rt; 299 int err; 300 301 /* Do a route lookup to determine ttl - if fails then use 302 * default. Note that CONFIG_INET is a requirement of 303 * CONFIG_NET_SWITCHDEV so must be defined here. 304 */ 305 flow.daddr = ip_tun->key.u.ipv4.dst; 306 flow.flowi4_proto = IPPROTO_UDP; 307 rt = ip_route_output_key(net, &flow); 308 err = PTR_ERR_OR_ZERO(rt); 309 if (!err) { 310 set_tun->ttl = ip4_dst_hoplimit(&rt->dst); 311 ip_rt_put(rt); 312 } else { 313 set_tun->ttl = net->ipv4.sysctl_ip_default_ttl; 314 } 315 } 316 317 set_tun->tos = ip_tun->key.tos; 318 319 if (!(ip_tun->key.tun_flags & NFP_FL_TUNNEL_KEY) || 320 ip_tun->key.tun_flags & ~NFP_FL_SUPPORTED_IPV4_UDP_TUN_FLAGS) 321 return -EOPNOTSUPP; 322 set_tun->tun_flags = ip_tun->key.tun_flags; 323 324 if (tun_type == NFP_FL_TUNNEL_GENEVE) { 325 set_tun->tun_proto = htons(ETH_P_TEB); 326 set_tun->tun_len = ip_tun->options_len / 4; 327 } 328 329 /* Complete pre_tunnel action. */ 330 pre_tun->ipv4_dst = ip_tun->key.u.ipv4.dst; 331 332 return 0; 333 } 334 335 static void nfp_fl_set_helper32(u32 value, u32 mask, u8 *p_exact, u8 *p_mask) 336 { 337 u32 oldvalue = get_unaligned((u32 *)p_exact); 338 u32 oldmask = get_unaligned((u32 *)p_mask); 339 340 value &= mask; 341 value |= oldvalue & ~mask; 342 343 put_unaligned(oldmask | mask, (u32 *)p_mask); 344 put_unaligned(value, (u32 *)p_exact); 345 } 346 347 static int 348 nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off, 349 struct nfp_fl_set_eth *set_eth) 350 { 351 u32 exact, mask; 352 353 if (off + 4 > ETH_ALEN * 2) 354 return -EOPNOTSUPP; 355 356 mask = ~tcf_pedit_mask(action, idx); 357 exact = tcf_pedit_val(action, idx); 358 359 if (exact & ~mask) 360 return -EOPNOTSUPP; 361 362 nfp_fl_set_helper32(exact, mask, &set_eth->eth_addr_val[off], 363 &set_eth->eth_addr_mask[off]); 364 365 set_eth->reserved = cpu_to_be16(0); 366 set_eth->head.jump_id = NFP_FL_ACTION_OPCODE_SET_ETHERNET; 367 set_eth->head.len_lw = sizeof(*set_eth) >> NFP_FL_LW_SIZ; 368 369 return 0; 370 } 371 372 struct ipv4_ttl_word { 373 __u8 ttl; 374 __u8 protocol; 375 __sum16 check; 376 }; 377 378 static int 379 nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off, 380 struct nfp_fl_set_ip4_addrs *set_ip_addr, 381 struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos) 382 { 383 struct ipv4_ttl_word *ttl_word_mask; 384 struct ipv4_ttl_word *ttl_word; 385 struct iphdr *tos_word_mask; 386 struct iphdr *tos_word; 387 __be32 exact, mask; 388 389 /* We are expecting tcf_pedit to return a big endian value */ 390 mask = (__force __be32)~tcf_pedit_mask(action, idx); 391 exact = (__force __be32)tcf_pedit_val(action, idx); 392 393 if (exact & ~mask) 394 return -EOPNOTSUPP; 395 396 switch (off) { 397 case offsetof(struct iphdr, daddr): 398 set_ip_addr->ipv4_dst_mask |= mask; 399 set_ip_addr->ipv4_dst &= ~mask; 400 set_ip_addr->ipv4_dst |= exact & mask; 401 set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS; 402 set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >> 403 NFP_FL_LW_SIZ; 404 break; 405 case offsetof(struct iphdr, saddr): 406 set_ip_addr->ipv4_src_mask |= mask; 407 set_ip_addr->ipv4_src &= ~mask; 408 set_ip_addr->ipv4_src |= exact & mask; 409 set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS; 410 set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >> 411 NFP_FL_LW_SIZ; 412 break; 413 case offsetof(struct iphdr, ttl): 414 ttl_word_mask = (struct ipv4_ttl_word *)&mask; 415 ttl_word = (struct ipv4_ttl_word *)&exact; 416 417 if (ttl_word_mask->protocol || ttl_word_mask->check) 418 return -EOPNOTSUPP; 419 420 set_ip_ttl_tos->ipv4_ttl_mask |= ttl_word_mask->ttl; 421 set_ip_ttl_tos->ipv4_ttl &= ~ttl_word_mask->ttl; 422 set_ip_ttl_tos->ipv4_ttl |= ttl_word->ttl & ttl_word_mask->ttl; 423 set_ip_ttl_tos->head.jump_id = 424 NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS; 425 set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >> 426 NFP_FL_LW_SIZ; 427 break; 428 case round_down(offsetof(struct iphdr, tos), 4): 429 tos_word_mask = (struct iphdr *)&mask; 430 tos_word = (struct iphdr *)&exact; 431 432 if (tos_word_mask->version || tos_word_mask->ihl || 433 tos_word_mask->tot_len) 434 return -EOPNOTSUPP; 435 436 set_ip_ttl_tos->ipv4_tos_mask |= tos_word_mask->tos; 437 set_ip_ttl_tos->ipv4_tos &= ~tos_word_mask->tos; 438 set_ip_ttl_tos->ipv4_tos |= tos_word->tos & tos_word_mask->tos; 439 set_ip_ttl_tos->head.jump_id = 440 NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS; 441 set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >> 442 NFP_FL_LW_SIZ; 443 break; 444 default: 445 return -EOPNOTSUPP; 446 } 447 448 return 0; 449 } 450 451 static void 452 nfp_fl_set_ip6_helper(int opcode_tag, u8 word, __be32 exact, __be32 mask, 453 struct nfp_fl_set_ipv6_addr *ip6) 454 { 455 ip6->ipv6[word].mask |= mask; 456 ip6->ipv6[word].exact &= ~mask; 457 ip6->ipv6[word].exact |= exact & mask; 458 459 ip6->reserved = cpu_to_be16(0); 460 ip6->head.jump_id = opcode_tag; 461 ip6->head.len_lw = sizeof(*ip6) >> NFP_FL_LW_SIZ; 462 } 463 464 struct ipv6_hop_limit_word { 465 __be16 payload_len; 466 u8 nexthdr; 467 u8 hop_limit; 468 }; 469 470 static int 471 nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask, 472 struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl) 473 { 474 struct ipv6_hop_limit_word *fl_hl_mask; 475 struct ipv6_hop_limit_word *fl_hl; 476 477 switch (off) { 478 case offsetof(struct ipv6hdr, payload_len): 479 fl_hl_mask = (struct ipv6_hop_limit_word *)&mask; 480 fl_hl = (struct ipv6_hop_limit_word *)&exact; 481 482 if (fl_hl_mask->nexthdr || fl_hl_mask->payload_len) 483 return -EOPNOTSUPP; 484 485 ip_hl_fl->ipv6_hop_limit_mask |= fl_hl_mask->hop_limit; 486 ip_hl_fl->ipv6_hop_limit &= ~fl_hl_mask->hop_limit; 487 ip_hl_fl->ipv6_hop_limit |= fl_hl->hop_limit & 488 fl_hl_mask->hop_limit; 489 break; 490 case round_down(offsetof(struct ipv6hdr, flow_lbl), 4): 491 if (mask & ~IPV6_FLOW_LABEL_MASK || 492 exact & ~IPV6_FLOW_LABEL_MASK) 493 return -EOPNOTSUPP; 494 495 ip_hl_fl->ipv6_label_mask |= mask; 496 ip_hl_fl->ipv6_label &= ~mask; 497 ip_hl_fl->ipv6_label |= exact & mask; 498 break; 499 } 500 501 ip_hl_fl->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL; 502 ip_hl_fl->head.len_lw = sizeof(*ip_hl_fl) >> NFP_FL_LW_SIZ; 503 504 return 0; 505 } 506 507 static int 508 nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off, 509 struct nfp_fl_set_ipv6_addr *ip_dst, 510 struct nfp_fl_set_ipv6_addr *ip_src, 511 struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl) 512 { 513 __be32 exact, mask; 514 int err = 0; 515 u8 word; 516 517 /* We are expecting tcf_pedit to return a big endian value */ 518 mask = (__force __be32)~tcf_pedit_mask(action, idx); 519 exact = (__force __be32)tcf_pedit_val(action, idx); 520 521 if (exact & ~mask) 522 return -EOPNOTSUPP; 523 524 if (off < offsetof(struct ipv6hdr, saddr)) { 525 err = nfp_fl_set_ip6_hop_limit_flow_label(off, exact, mask, 526 ip_hl_fl); 527 } else if (off < offsetof(struct ipv6hdr, daddr)) { 528 word = (off - offsetof(struct ipv6hdr, saddr)) / sizeof(exact); 529 nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_SRC, word, 530 exact, mask, ip_src); 531 } else if (off < offsetof(struct ipv6hdr, daddr) + 532 sizeof(struct in6_addr)) { 533 word = (off - offsetof(struct ipv6hdr, daddr)) / sizeof(exact); 534 nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_DST, word, 535 exact, mask, ip_dst); 536 } else { 537 return -EOPNOTSUPP; 538 } 539 540 return err; 541 } 542 543 static int 544 nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off, 545 struct nfp_fl_set_tport *set_tport, int opcode) 546 { 547 u32 exact, mask; 548 549 if (off) 550 return -EOPNOTSUPP; 551 552 mask = ~tcf_pedit_mask(action, idx); 553 exact = tcf_pedit_val(action, idx); 554 555 if (exact & ~mask) 556 return -EOPNOTSUPP; 557 558 nfp_fl_set_helper32(exact, mask, set_tport->tp_port_val, 559 set_tport->tp_port_mask); 560 561 set_tport->reserved = cpu_to_be16(0); 562 set_tport->head.jump_id = opcode; 563 set_tport->head.len_lw = sizeof(*set_tport) >> NFP_FL_LW_SIZ; 564 565 return 0; 566 } 567 568 static u32 nfp_fl_csum_l4_to_flag(u8 ip_proto) 569 { 570 switch (ip_proto) { 571 case 0: 572 /* Filter doesn't force proto match, 573 * both TCP and UDP will be updated if encountered 574 */ 575 return TCA_CSUM_UPDATE_FLAG_TCP | TCA_CSUM_UPDATE_FLAG_UDP; 576 case IPPROTO_TCP: 577 return TCA_CSUM_UPDATE_FLAG_TCP; 578 case IPPROTO_UDP: 579 return TCA_CSUM_UPDATE_FLAG_UDP; 580 default: 581 /* All other protocols will be ignored by FW */ 582 return 0; 583 } 584 } 585 586 static int 587 nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, 588 char *nfp_action, int *a_len, u32 *csum_updated) 589 { 590 struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src; 591 struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl; 592 struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos; 593 struct nfp_fl_set_ip4_addrs set_ip_addr; 594 struct nfp_fl_set_tport set_tport; 595 struct nfp_fl_set_eth set_eth; 596 enum pedit_header_type htype; 597 int idx, nkeys, err; 598 size_t act_size = 0; 599 u32 offset, cmd; 600 u8 ip_proto = 0; 601 602 memset(&set_ip6_tc_hl_fl, 0, sizeof(set_ip6_tc_hl_fl)); 603 memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos)); 604 memset(&set_ip6_dst, 0, sizeof(set_ip6_dst)); 605 memset(&set_ip6_src, 0, sizeof(set_ip6_src)); 606 memset(&set_ip_addr, 0, sizeof(set_ip_addr)); 607 memset(&set_tport, 0, sizeof(set_tport)); 608 memset(&set_eth, 0, sizeof(set_eth)); 609 nkeys = tcf_pedit_nkeys(action); 610 611 for (idx = 0; idx < nkeys; idx++) { 612 cmd = tcf_pedit_cmd(action, idx); 613 htype = tcf_pedit_htype(action, idx); 614 offset = tcf_pedit_offset(action, idx); 615 616 if (cmd != TCA_PEDIT_KEY_EX_CMD_SET) 617 return -EOPNOTSUPP; 618 619 switch (htype) { 620 case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: 621 err = nfp_fl_set_eth(action, idx, offset, &set_eth); 622 break; 623 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: 624 err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr, 625 &set_ip_ttl_tos); 626 break; 627 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: 628 err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst, 629 &set_ip6_src, &set_ip6_tc_hl_fl); 630 break; 631 case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: 632 err = nfp_fl_set_tport(action, idx, offset, &set_tport, 633 NFP_FL_ACTION_OPCODE_SET_TCP); 634 break; 635 case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: 636 err = nfp_fl_set_tport(action, idx, offset, &set_tport, 637 NFP_FL_ACTION_OPCODE_SET_UDP); 638 break; 639 default: 640 return -EOPNOTSUPP; 641 } 642 if (err) 643 return err; 644 } 645 646 if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) { 647 struct flow_dissector_key_basic *basic; 648 649 basic = skb_flow_dissector_target(flow->dissector, 650 FLOW_DISSECTOR_KEY_BASIC, 651 flow->key); 652 ip_proto = basic->ip_proto; 653 } 654 655 if (set_eth.head.len_lw) { 656 act_size = sizeof(set_eth); 657 memcpy(nfp_action, &set_eth, act_size); 658 *a_len += act_size; 659 } 660 if (set_ip_ttl_tos.head.len_lw) { 661 nfp_action += act_size; 662 act_size = sizeof(set_ip_ttl_tos); 663 memcpy(nfp_action, &set_ip_ttl_tos, act_size); 664 *a_len += act_size; 665 666 /* Hardware will automatically fix IPv4 and TCP/UDP checksum. */ 667 *csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR | 668 nfp_fl_csum_l4_to_flag(ip_proto); 669 } 670 if (set_ip_addr.head.len_lw) { 671 nfp_action += act_size; 672 act_size = sizeof(set_ip_addr); 673 memcpy(nfp_action, &set_ip_addr, act_size); 674 *a_len += act_size; 675 676 /* Hardware will automatically fix IPv4 and TCP/UDP checksum. */ 677 *csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR | 678 nfp_fl_csum_l4_to_flag(ip_proto); 679 } 680 if (set_ip6_tc_hl_fl.head.len_lw) { 681 nfp_action += act_size; 682 act_size = sizeof(set_ip6_tc_hl_fl); 683 memcpy(nfp_action, &set_ip6_tc_hl_fl, act_size); 684 *a_len += act_size; 685 686 /* Hardware will automatically fix TCP/UDP checksum. */ 687 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto); 688 } 689 if (set_ip6_dst.head.len_lw && set_ip6_src.head.len_lw) { 690 /* TC compiles set src and dst IPv6 address as a single action, 691 * the hardware requires this to be 2 separate actions. 692 */ 693 nfp_action += act_size; 694 act_size = sizeof(set_ip6_src); 695 memcpy(nfp_action, &set_ip6_src, act_size); 696 *a_len += act_size; 697 698 act_size = sizeof(set_ip6_dst); 699 memcpy(&nfp_action[sizeof(set_ip6_src)], &set_ip6_dst, 700 act_size); 701 *a_len += act_size; 702 703 /* Hardware will automatically fix TCP/UDP checksum. */ 704 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto); 705 } else if (set_ip6_dst.head.len_lw) { 706 nfp_action += act_size; 707 act_size = sizeof(set_ip6_dst); 708 memcpy(nfp_action, &set_ip6_dst, act_size); 709 *a_len += act_size; 710 711 /* Hardware will automatically fix TCP/UDP checksum. */ 712 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto); 713 } else if (set_ip6_src.head.len_lw) { 714 nfp_action += act_size; 715 act_size = sizeof(set_ip6_src); 716 memcpy(nfp_action, &set_ip6_src, act_size); 717 *a_len += act_size; 718 719 /* Hardware will automatically fix TCP/UDP checksum. */ 720 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto); 721 } 722 if (set_tport.head.len_lw) { 723 nfp_action += act_size; 724 act_size = sizeof(set_tport); 725 memcpy(nfp_action, &set_tport, act_size); 726 *a_len += act_size; 727 728 /* Hardware will automatically fix TCP/UDP checksum. */ 729 *csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto); 730 } 731 732 return 0; 733 } 734 735 static int 736 nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a, 737 struct nfp_fl_payload *nfp_fl, int *a_len, 738 struct net_device *netdev, bool last, 739 enum nfp_flower_tun_type *tun_type, int *tun_out_cnt, 740 int *out_cnt, u32 *csum_updated) 741 { 742 struct nfp_flower_priv *priv = app->priv; 743 struct nfp_fl_output *output; 744 int err, prelag_size; 745 746 /* If csum_updated has not been reset by now, it means HW will 747 * incorrectly update csums when they are not requested. 748 */ 749 if (*csum_updated) 750 return -EOPNOTSUPP; 751 752 if (*a_len + sizeof(struct nfp_fl_output) > NFP_FL_MAX_A_SIZ) 753 return -EOPNOTSUPP; 754 755 output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len]; 756 err = nfp_fl_output(app, output, a, nfp_fl, last, netdev, *tun_type, 757 tun_out_cnt); 758 if (err) 759 return err; 760 761 *a_len += sizeof(struct nfp_fl_output); 762 763 if (priv->flower_ext_feats & NFP_FL_FEATS_LAG) { 764 /* nfp_fl_pre_lag returns -err or size of prelag action added. 765 * This will be 0 if it is not egressing to a lag dev. 766 */ 767 prelag_size = nfp_fl_pre_lag(app, a, nfp_fl, *a_len); 768 if (prelag_size < 0) 769 return prelag_size; 770 else if (prelag_size > 0 && (!last || *out_cnt)) 771 return -EOPNOTSUPP; 772 773 *a_len += prelag_size; 774 } 775 (*out_cnt)++; 776 777 return 0; 778 } 779 780 static int 781 nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a, 782 struct tc_cls_flower_offload *flow, 783 struct nfp_fl_payload *nfp_fl, int *a_len, 784 struct net_device *netdev, 785 enum nfp_flower_tun_type *tun_type, int *tun_out_cnt, 786 int *out_cnt, u32 *csum_updated) 787 { 788 struct nfp_fl_set_ipv4_udp_tun *set_tun; 789 struct nfp_fl_pre_tunnel *pre_tun; 790 struct nfp_fl_push_vlan *psh_v; 791 struct nfp_fl_pop_vlan *pop_v; 792 int err; 793 794 if (is_tcf_gact_shot(a)) { 795 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_DROP); 796 } else if (is_tcf_mirred_egress_redirect(a)) { 797 err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev, 798 true, tun_type, tun_out_cnt, 799 out_cnt, csum_updated); 800 if (err) 801 return err; 802 803 } else if (is_tcf_mirred_egress_mirror(a)) { 804 err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev, 805 false, tun_type, tun_out_cnt, 806 out_cnt, csum_updated); 807 if (err) 808 return err; 809 810 } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_POP) { 811 if (*a_len + sizeof(struct nfp_fl_pop_vlan) > NFP_FL_MAX_A_SIZ) 812 return -EOPNOTSUPP; 813 814 pop_v = (struct nfp_fl_pop_vlan *)&nfp_fl->action_data[*a_len]; 815 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_POPV); 816 817 nfp_fl_pop_vlan(pop_v); 818 *a_len += sizeof(struct nfp_fl_pop_vlan); 819 } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) { 820 if (*a_len + sizeof(struct nfp_fl_push_vlan) > NFP_FL_MAX_A_SIZ) 821 return -EOPNOTSUPP; 822 823 psh_v = (struct nfp_fl_push_vlan *)&nfp_fl->action_data[*a_len]; 824 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); 825 826 nfp_fl_push_vlan(psh_v, a); 827 *a_len += sizeof(struct nfp_fl_push_vlan); 828 } else if (is_tcf_tunnel_set(a)) { 829 struct ip_tunnel_info *ip_tun = tcf_tunnel_info(a); 830 831 *tun_type = nfp_fl_get_tun_from_act_l4_port(app, a); 832 if (*tun_type == NFP_FL_TUNNEL_NONE) 833 return -EOPNOTSUPP; 834 835 if (ip_tun->mode & ~NFP_FL_SUPPORTED_TUNNEL_INFO_FLAGS) 836 return -EOPNOTSUPP; 837 838 /* Pre-tunnel action is required for tunnel encap. 839 * This checks for next hop entries on NFP. 840 * If none, the packet falls back before applying other actions. 841 */ 842 if (*a_len + sizeof(struct nfp_fl_pre_tunnel) + 843 sizeof(struct nfp_fl_set_ipv4_udp_tun) > NFP_FL_MAX_A_SIZ) 844 return -EOPNOTSUPP; 845 846 pre_tun = nfp_fl_pre_tunnel(nfp_fl->action_data, *a_len); 847 nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); 848 *a_len += sizeof(struct nfp_fl_pre_tunnel); 849 850 err = nfp_fl_push_geneve_options(nfp_fl, a_len, a); 851 if (err) 852 return err; 853 854 set_tun = (void *)&nfp_fl->action_data[*a_len]; 855 err = nfp_fl_set_ipv4_udp_tun(app, set_tun, a, pre_tun, 856 *tun_type, netdev); 857 if (err) 858 return err; 859 *a_len += sizeof(struct nfp_fl_set_ipv4_udp_tun); 860 } else if (is_tcf_tunnel_release(a)) { 861 /* Tunnel decap is handled by default so accept action. */ 862 return 0; 863 } else if (is_tcf_pedit(a)) { 864 if (nfp_fl_pedit(a, flow, &nfp_fl->action_data[*a_len], 865 a_len, csum_updated)) 866 return -EOPNOTSUPP; 867 } else if (is_tcf_csum(a)) { 868 /* csum action requests recalc of something we have not fixed */ 869 if (tcf_csum_update_flags(a) & ~*csum_updated) 870 return -EOPNOTSUPP; 871 /* If we will correctly fix the csum we can remove it from the 872 * csum update list. Which will later be used to check support. 873 */ 874 *csum_updated &= ~tcf_csum_update_flags(a); 875 } else { 876 /* Currently we do not handle any other actions. */ 877 return -EOPNOTSUPP; 878 } 879 880 return 0; 881 } 882 883 int nfp_flower_compile_action(struct nfp_app *app, 884 struct tc_cls_flower_offload *flow, 885 struct net_device *netdev, 886 struct nfp_fl_payload *nfp_flow) 887 { 888 int act_len, act_cnt, err, tun_out_cnt, out_cnt, i; 889 enum nfp_flower_tun_type tun_type; 890 const struct tc_action *a; 891 u32 csum_updated = 0; 892 893 memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ); 894 nfp_flow->meta.act_len = 0; 895 tun_type = NFP_FL_TUNNEL_NONE; 896 act_len = 0; 897 act_cnt = 0; 898 tun_out_cnt = 0; 899 out_cnt = 0; 900 901 tcf_exts_for_each_action(i, a, flow->exts) { 902 err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len, 903 netdev, &tun_type, &tun_out_cnt, 904 &out_cnt, &csum_updated); 905 if (err) 906 return err; 907 act_cnt++; 908 } 909 910 /* We optimise when the action list is small, this can unfortunately 911 * not happen once we have more than one action in the action list. 912 */ 913 if (act_cnt > 1) 914 nfp_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); 915 916 nfp_flow->meta.act_len = act_len; 917 918 return 0; 919 } 920