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 7 #include "cmsg.h" 8 #include "main.h" 9 10 static void 11 nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext, 12 struct nfp_flower_meta_tci *msk, 13 struct flow_rule *rule, u8 key_type) 14 { 15 u16 tmp_tci; 16 17 memset(ext, 0, sizeof(struct nfp_flower_meta_tci)); 18 memset(msk, 0, sizeof(struct nfp_flower_meta_tci)); 19 20 /* Populate the metadata frame. */ 21 ext->nfp_flow_key_layer = key_type; 22 ext->mask_id = ~0; 23 24 msk->nfp_flow_key_layer = key_type; 25 msk->mask_id = ~0; 26 27 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 28 struct flow_match_vlan match; 29 30 flow_rule_match_vlan(rule, &match); 31 /* Populate the tci field. */ 32 tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT; 33 tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO, 34 match.key->vlan_priority) | 35 FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID, 36 match.key->vlan_id); 37 ext->tci = cpu_to_be16(tmp_tci); 38 39 tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT; 40 tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO, 41 match.mask->vlan_priority) | 42 FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID, 43 match.mask->vlan_id); 44 msk->tci = cpu_to_be16(tmp_tci); 45 } 46 } 47 48 static void 49 nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta *frame, u32 key_ext) 50 { 51 frame->nfp_flow_key_layer2 = cpu_to_be32(key_ext); 52 } 53 54 static int 55 nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port, 56 bool mask_version, enum nfp_flower_tun_type tun_type, 57 struct netlink_ext_ack *extack) 58 { 59 if (mask_version) { 60 frame->in_port = cpu_to_be32(~0); 61 return 0; 62 } 63 64 if (tun_type) { 65 frame->in_port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type); 66 } else { 67 if (!cmsg_port) { 68 NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid ingress interface for match offload"); 69 return -EOPNOTSUPP; 70 } 71 frame->in_port = cpu_to_be32(cmsg_port); 72 } 73 74 return 0; 75 } 76 77 static void 78 nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext, 79 struct nfp_flower_mac_mpls *msk, struct flow_rule *rule) 80 { 81 memset(ext, 0, sizeof(struct nfp_flower_mac_mpls)); 82 memset(msk, 0, sizeof(struct nfp_flower_mac_mpls)); 83 84 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 85 struct flow_match_eth_addrs match; 86 87 flow_rule_match_eth_addrs(rule, &match); 88 /* Populate mac frame. */ 89 ether_addr_copy(ext->mac_dst, &match.key->dst[0]); 90 ether_addr_copy(ext->mac_src, &match.key->src[0]); 91 ether_addr_copy(msk->mac_dst, &match.mask->dst[0]); 92 ether_addr_copy(msk->mac_src, &match.mask->src[0]); 93 } 94 95 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) { 96 struct flow_match_mpls match; 97 u32 t_mpls; 98 99 flow_rule_match_mpls(rule, &match); 100 t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.key->mpls_label) | 101 FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.key->mpls_tc) | 102 FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.key->mpls_bos) | 103 NFP_FLOWER_MASK_MPLS_Q; 104 ext->mpls_lse = cpu_to_be32(t_mpls); 105 t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.mask->mpls_label) | 106 FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.mask->mpls_tc) | 107 FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.mask->mpls_bos) | 108 NFP_FLOWER_MASK_MPLS_Q; 109 msk->mpls_lse = cpu_to_be32(t_mpls); 110 } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 111 /* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q 112 * bit, which indicates an mpls ether type but without any 113 * mpls fields. 114 */ 115 struct flow_match_basic match; 116 117 flow_rule_match_basic(rule, &match); 118 if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) || 119 match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) { 120 ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q); 121 msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q); 122 } 123 } 124 } 125 126 static void 127 nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext, 128 struct nfp_flower_tp_ports *msk, 129 struct flow_rule *rule) 130 { 131 memset(ext, 0, sizeof(struct nfp_flower_tp_ports)); 132 memset(msk, 0, sizeof(struct nfp_flower_tp_ports)); 133 134 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 135 struct flow_match_ports match; 136 137 flow_rule_match_ports(rule, &match); 138 ext->port_src = match.key->src; 139 ext->port_dst = match.key->dst; 140 msk->port_src = match.mask->src; 141 msk->port_dst = match.mask->dst; 142 } 143 } 144 145 static void 146 nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext, 147 struct nfp_flower_ip_ext *msk, struct flow_rule *rule) 148 { 149 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 150 struct flow_match_basic match; 151 152 flow_rule_match_basic(rule, &match); 153 ext->proto = match.key->ip_proto; 154 msk->proto = match.mask->ip_proto; 155 } 156 157 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { 158 struct flow_match_ip match; 159 160 flow_rule_match_ip(rule, &match); 161 ext->tos = match.key->tos; 162 ext->ttl = match.key->ttl; 163 msk->tos = match.mask->tos; 164 msk->ttl = match.mask->ttl; 165 } 166 167 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { 168 u16 tcp_flags, tcp_flags_mask; 169 struct flow_match_tcp match; 170 171 flow_rule_match_tcp(rule, &match); 172 tcp_flags = be16_to_cpu(match.key->flags); 173 tcp_flags_mask = be16_to_cpu(match.mask->flags); 174 175 if (tcp_flags & TCPHDR_FIN) 176 ext->flags |= NFP_FL_TCP_FLAG_FIN; 177 if (tcp_flags_mask & TCPHDR_FIN) 178 msk->flags |= NFP_FL_TCP_FLAG_FIN; 179 180 if (tcp_flags & TCPHDR_SYN) 181 ext->flags |= NFP_FL_TCP_FLAG_SYN; 182 if (tcp_flags_mask & TCPHDR_SYN) 183 msk->flags |= NFP_FL_TCP_FLAG_SYN; 184 185 if (tcp_flags & TCPHDR_RST) 186 ext->flags |= NFP_FL_TCP_FLAG_RST; 187 if (tcp_flags_mask & TCPHDR_RST) 188 msk->flags |= NFP_FL_TCP_FLAG_RST; 189 190 if (tcp_flags & TCPHDR_PSH) 191 ext->flags |= NFP_FL_TCP_FLAG_PSH; 192 if (tcp_flags_mask & TCPHDR_PSH) 193 msk->flags |= NFP_FL_TCP_FLAG_PSH; 194 195 if (tcp_flags & TCPHDR_URG) 196 ext->flags |= NFP_FL_TCP_FLAG_URG; 197 if (tcp_flags_mask & TCPHDR_URG) 198 msk->flags |= NFP_FL_TCP_FLAG_URG; 199 } 200 201 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 202 struct flow_match_control match; 203 204 flow_rule_match_control(rule, &match); 205 if (match.key->flags & FLOW_DIS_IS_FRAGMENT) 206 ext->flags |= NFP_FL_IP_FRAGMENTED; 207 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) 208 msk->flags |= NFP_FL_IP_FRAGMENTED; 209 if (match.key->flags & FLOW_DIS_FIRST_FRAG) 210 ext->flags |= NFP_FL_IP_FRAG_FIRST; 211 if (match.mask->flags & FLOW_DIS_FIRST_FRAG) 212 msk->flags |= NFP_FL_IP_FRAG_FIRST; 213 } 214 } 215 216 static void 217 nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext, 218 struct nfp_flower_ipv4 *msk, struct flow_rule *rule) 219 { 220 struct flow_match_ipv4_addrs match; 221 222 memset(ext, 0, sizeof(struct nfp_flower_ipv4)); 223 memset(msk, 0, sizeof(struct nfp_flower_ipv4)); 224 225 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { 226 flow_rule_match_ipv4_addrs(rule, &match); 227 ext->ipv4_src = match.key->src; 228 ext->ipv4_dst = match.key->dst; 229 msk->ipv4_src = match.mask->src; 230 msk->ipv4_dst = match.mask->dst; 231 } 232 233 nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 234 } 235 236 static void 237 nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext, 238 struct nfp_flower_ipv6 *msk, struct flow_rule *rule) 239 { 240 memset(ext, 0, sizeof(struct nfp_flower_ipv6)); 241 memset(msk, 0, sizeof(struct nfp_flower_ipv6)); 242 243 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { 244 struct flow_match_ipv6_addrs match; 245 246 flow_rule_match_ipv6_addrs(rule, &match); 247 ext->ipv6_src = match.key->src; 248 ext->ipv6_dst = match.key->dst; 249 msk->ipv6_src = match.mask->src; 250 msk->ipv6_dst = match.mask->dst; 251 } 252 253 nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 254 } 255 256 static int 257 nfp_flower_compile_geneve_opt(void *ext, void *msk, struct flow_rule *rule) 258 { 259 struct flow_match_enc_opts match; 260 261 flow_rule_match_enc_opts(rule, &match); 262 memcpy(ext, match.key->data, match.key->len); 263 memcpy(msk, match.mask->data, match.mask->len); 264 265 return 0; 266 } 267 268 static void 269 nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 *ext, 270 struct nfp_flower_tun_ipv4 *msk, 271 struct flow_rule *rule) 272 { 273 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { 274 struct flow_match_ipv4_addrs match; 275 276 flow_rule_match_enc_ipv4_addrs(rule, &match); 277 ext->src = match.key->src; 278 ext->dst = match.key->dst; 279 msk->src = match.mask->src; 280 msk->dst = match.mask->dst; 281 } 282 } 283 284 static void 285 nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 *ext, 286 struct nfp_flower_tun_ipv6 *msk, 287 struct flow_rule *rule) 288 { 289 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) { 290 struct flow_match_ipv6_addrs match; 291 292 flow_rule_match_enc_ipv6_addrs(rule, &match); 293 ext->src = match.key->src; 294 ext->dst = match.key->dst; 295 msk->src = match.mask->src; 296 msk->dst = match.mask->dst; 297 } 298 } 299 300 static void 301 nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext *ext, 302 struct nfp_flower_tun_ip_ext *msk, 303 struct flow_rule *rule) 304 { 305 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { 306 struct flow_match_ip match; 307 308 flow_rule_match_enc_ip(rule, &match); 309 ext->tos = match.key->tos; 310 ext->ttl = match.key->ttl; 311 msk->tos = match.mask->tos; 312 msk->ttl = match.mask->ttl; 313 } 314 } 315 316 static void 317 nfp_flower_compile_tun_udp_key(__be32 *key, __be32 *key_msk, 318 struct flow_rule *rule) 319 { 320 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { 321 struct flow_match_enc_keyid match; 322 u32 vni; 323 324 flow_rule_match_enc_keyid(rule, &match); 325 vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET; 326 *key = cpu_to_be32(vni); 327 vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET; 328 *key_msk = cpu_to_be32(vni); 329 } 330 } 331 332 static void 333 nfp_flower_compile_tun_gre_key(__be32 *key, __be32 *key_msk, __be16 *flags, 334 __be16 *flags_msk, struct flow_rule *rule) 335 { 336 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { 337 struct flow_match_enc_keyid match; 338 339 flow_rule_match_enc_keyid(rule, &match); 340 *key = match.key->keyid; 341 *key_msk = match.mask->keyid; 342 343 *flags = cpu_to_be16(NFP_FL_GRE_FLAG_KEY); 344 *flags_msk = cpu_to_be16(NFP_FL_GRE_FLAG_KEY); 345 } 346 } 347 348 static void 349 nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun *ext, 350 struct nfp_flower_ipv4_gre_tun *msk, 351 struct flow_rule *rule) 352 { 353 memset(ext, 0, sizeof(struct nfp_flower_ipv4_gre_tun)); 354 memset(msk, 0, sizeof(struct nfp_flower_ipv4_gre_tun)); 355 356 /* NVGRE is the only supported GRE tunnel type */ 357 ext->ethertype = cpu_to_be16(ETH_P_TEB); 358 msk->ethertype = cpu_to_be16(~0); 359 360 nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule); 361 nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 362 nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key, 363 &ext->tun_flags, &msk->tun_flags, rule); 364 } 365 366 static void 367 nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext, 368 struct nfp_flower_ipv4_udp_tun *msk, 369 struct flow_rule *rule) 370 { 371 memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun)); 372 memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun)); 373 374 nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule); 375 nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 376 nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule); 377 } 378 379 static void 380 nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun *ext, 381 struct nfp_flower_ipv6_udp_tun *msk, 382 struct flow_rule *rule) 383 { 384 memset(ext, 0, sizeof(struct nfp_flower_ipv6_udp_tun)); 385 memset(msk, 0, sizeof(struct nfp_flower_ipv6_udp_tun)); 386 387 nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule); 388 nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 389 nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule); 390 } 391 392 static void 393 nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun *ext, 394 struct nfp_flower_ipv6_gre_tun *msk, 395 struct flow_rule *rule) 396 { 397 memset(ext, 0, sizeof(struct nfp_flower_ipv6_gre_tun)); 398 memset(msk, 0, sizeof(struct nfp_flower_ipv6_gre_tun)); 399 400 /* NVGRE is the only supported GRE tunnel type */ 401 ext->ethertype = cpu_to_be16(ETH_P_TEB); 402 msk->ethertype = cpu_to_be16(~0); 403 404 nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule); 405 nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule); 406 nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key, 407 &ext->tun_flags, &msk->tun_flags, rule); 408 } 409 410 int nfp_flower_compile_flow_match(struct nfp_app *app, 411 struct flow_cls_offload *flow, 412 struct nfp_fl_key_ls *key_ls, 413 struct net_device *netdev, 414 struct nfp_fl_payload *nfp_flow, 415 enum nfp_flower_tun_type tun_type, 416 struct netlink_ext_ack *extack) 417 { 418 struct flow_rule *rule = flow_cls_offload_flow_rule(flow); 419 u32 port_id; 420 int err; 421 u8 *ext; 422 u8 *msk; 423 424 port_id = nfp_flower_get_port_id_from_netdev(app, netdev); 425 426 memset(nfp_flow->unmasked_data, 0, key_ls->key_size); 427 memset(nfp_flow->mask_data, 0, key_ls->key_size); 428 429 ext = nfp_flow->unmasked_data; 430 msk = nfp_flow->mask_data; 431 432 nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext, 433 (struct nfp_flower_meta_tci *)msk, 434 rule, key_ls->key_layer); 435 ext += sizeof(struct nfp_flower_meta_tci); 436 msk += sizeof(struct nfp_flower_meta_tci); 437 438 /* Populate Extended Metadata if Required. */ 439 if (NFP_FLOWER_LAYER_EXT_META & key_ls->key_layer) { 440 nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)ext, 441 key_ls->key_layer_two); 442 nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)msk, 443 key_ls->key_layer_two); 444 ext += sizeof(struct nfp_flower_ext_meta); 445 msk += sizeof(struct nfp_flower_ext_meta); 446 } 447 448 /* Populate Exact Port data. */ 449 err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext, 450 port_id, false, tun_type, extack); 451 if (err) 452 return err; 453 454 /* Populate Mask Port Data. */ 455 err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk, 456 port_id, true, tun_type, extack); 457 if (err) 458 return err; 459 460 ext += sizeof(struct nfp_flower_in_port); 461 msk += sizeof(struct nfp_flower_in_port); 462 463 if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) { 464 nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext, 465 (struct nfp_flower_mac_mpls *)msk, 466 rule); 467 ext += sizeof(struct nfp_flower_mac_mpls); 468 msk += sizeof(struct nfp_flower_mac_mpls); 469 } 470 471 if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) { 472 nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext, 473 (struct nfp_flower_tp_ports *)msk, 474 rule); 475 ext += sizeof(struct nfp_flower_tp_ports); 476 msk += sizeof(struct nfp_flower_tp_ports); 477 } 478 479 if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) { 480 nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext, 481 (struct nfp_flower_ipv4 *)msk, 482 rule); 483 ext += sizeof(struct nfp_flower_ipv4); 484 msk += sizeof(struct nfp_flower_ipv4); 485 } 486 487 if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) { 488 nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext, 489 (struct nfp_flower_ipv6 *)msk, 490 rule); 491 ext += sizeof(struct nfp_flower_ipv6); 492 msk += sizeof(struct nfp_flower_ipv6); 493 } 494 495 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GRE) { 496 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) { 497 struct nfp_flower_ipv6_gre_tun *gre_match; 498 struct nfp_ipv6_addr_entry *entry; 499 struct in6_addr *dst; 500 501 nfp_flower_compile_ipv6_gre_tun((void *)ext, 502 (void *)msk, rule); 503 gre_match = (struct nfp_flower_ipv6_gre_tun *)ext; 504 dst = &gre_match->ipv6.dst; 505 ext += sizeof(struct nfp_flower_ipv6_gre_tun); 506 msk += sizeof(struct nfp_flower_ipv6_gre_tun); 507 508 entry = nfp_tunnel_add_ipv6_off(app, dst); 509 if (!entry) 510 return -EOPNOTSUPP; 511 512 nfp_flow->nfp_tun_ipv6 = entry; 513 } else { 514 __be32 dst; 515 516 nfp_flower_compile_ipv4_gre_tun((void *)ext, 517 (void *)msk, rule); 518 dst = ((struct nfp_flower_ipv4_gre_tun *)ext)->ipv4.dst; 519 ext += sizeof(struct nfp_flower_ipv4_gre_tun); 520 msk += sizeof(struct nfp_flower_ipv4_gre_tun); 521 522 /* Store the tunnel destination in the rule data. 523 * This must be present and be an exact match. 524 */ 525 nfp_flow->nfp_tun_ipv4_addr = dst; 526 nfp_tunnel_add_ipv4_off(app, dst); 527 } 528 } 529 530 if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN || 531 key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) { 532 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) { 533 struct nfp_flower_ipv6_udp_tun *udp_match; 534 struct nfp_ipv6_addr_entry *entry; 535 struct in6_addr *dst; 536 537 nfp_flower_compile_ipv6_udp_tun((void *)ext, 538 (void *)msk, rule); 539 udp_match = (struct nfp_flower_ipv6_udp_tun *)ext; 540 dst = &udp_match->ipv6.dst; 541 ext += sizeof(struct nfp_flower_ipv6_udp_tun); 542 msk += sizeof(struct nfp_flower_ipv6_udp_tun); 543 544 entry = nfp_tunnel_add_ipv6_off(app, dst); 545 if (!entry) 546 return -EOPNOTSUPP; 547 548 nfp_flow->nfp_tun_ipv6 = entry; 549 } else { 550 __be32 dst; 551 552 nfp_flower_compile_ipv4_udp_tun((void *)ext, 553 (void *)msk, rule); 554 dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ipv4.dst; 555 ext += sizeof(struct nfp_flower_ipv4_udp_tun); 556 msk += sizeof(struct nfp_flower_ipv4_udp_tun); 557 558 /* Store the tunnel destination in the rule data. 559 * This must be present and be an exact match. 560 */ 561 nfp_flow->nfp_tun_ipv4_addr = dst; 562 nfp_tunnel_add_ipv4_off(app, dst); 563 } 564 565 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) { 566 err = nfp_flower_compile_geneve_opt(ext, msk, rule); 567 if (err) 568 return err; 569 } 570 } 571 572 return 0; 573 } 574