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