Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

1) Revert CHECKSUM_UNNECESSARY for UDP packet from conntrack.

2) Reject unsupported families when creating tables, from Phil Sutter.

3) GRE support for the flowtable, from Toshiaki Makita.

4) Add GRE offload support for act_ct, also from Toshiaki.

5) Update mlx5 driver to support for GRE flowtable offload,
from Toshiaki Makita.

6) Oneliner to clean up incorrect indentation in nf_conntrack_bridge,
from Jiapeng Chong.

* git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
netfilter: bridge: clean up some inconsistent indenting
net/mlx5: Support GRE conntrack offload
act_ct: Support GRE offload
netfilter: flowtable: Support GRE
netfilter: nf_tables: Reject tables of unsupported family
Revert "netfilter: conntrack: mark UDP zero checksum as CHECKSUM_UNNECESSARY"
====================

Link: https://lore.kernel.org/r/20220315091513.66544-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+223 -53
+15 -6
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
··· 260 260 return -EOPNOTSUPP; 261 261 } 262 262 } else { 263 - return -EOPNOTSUPP; 263 + if (tuple->ip_proto != IPPROTO_GRE) 264 + return -EOPNOTSUPP; 264 265 } 265 266 266 267 return 0; ··· 810 809 attr->dest_chain = 0; 811 810 attr->dest_ft = mlx5e_tc_post_act_get_ft(ct_priv->post_act); 812 811 attr->ft = nat ? ct_priv->ct_nat : ct_priv->ct; 813 - attr->outer_match_level = MLX5_MATCH_L4; 812 + if (entry->tuple.ip_proto == IPPROTO_TCP || 813 + entry->tuple.ip_proto == IPPROTO_UDP) 814 + attr->outer_match_level = MLX5_MATCH_L4; 815 + else 816 + attr->outer_match_level = MLX5_MATCH_L3; 814 817 attr->counter = entry->counter->counter; 815 818 attr->flags |= MLX5_ATTR_FLAG_NO_IN_PORT; 816 819 if (ct_priv->ns_type == MLX5_FLOW_NAMESPACE_FDB) ··· 1231 1226 struct flow_keys flow_keys; 1232 1227 1233 1228 skb_reset_network_header(skb); 1234 - skb_flow_dissect_flow_keys(skb, &flow_keys, 0); 1229 + skb_flow_dissect_flow_keys(skb, &flow_keys, FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP); 1235 1230 1236 1231 tuple->zone = zone; 1237 1232 1238 1233 if (flow_keys.basic.ip_proto != IPPROTO_TCP && 1239 - flow_keys.basic.ip_proto != IPPROTO_UDP) 1234 + flow_keys.basic.ip_proto != IPPROTO_UDP && 1235 + flow_keys.basic.ip_proto != IPPROTO_GRE) 1240 1236 return false; 1241 1237 1242 - tuple->port.src = flow_keys.ports.src; 1243 - tuple->port.dst = flow_keys.ports.dst; 1238 + if (flow_keys.basic.ip_proto == IPPROTO_TCP || 1239 + flow_keys.basic.ip_proto == IPPROTO_UDP) { 1240 + tuple->port.src = flow_keys.ports.src; 1241 + tuple->port.dst = flow_keys.ports.dst; 1242 + } 1244 1243 tuple->n_proto = flow_keys.basic.n_proto; 1245 1244 tuple->ip_proto = flow_keys.basic.ip_proto; 1246 1245
+1 -1
net/bridge/netfilter/nf_conntrack_bridge.c
··· 381 381 protoff = skb_network_offset(skb) + ip_hdrlen(skb); 382 382 break; 383 383 case htons(ETH_P_IPV6): { 384 - unsigned char pnum = ipv6_hdr(skb)->nexthdr; 384 + unsigned char pnum = ipv6_hdr(skb)->nexthdr; 385 385 __be16 frag_off; 386 386 387 387 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum,
+1 -3
net/netfilter/nf_conntrack_proto_udp.c
··· 63 63 } 64 64 65 65 /* Packet with no checksum */ 66 - if (!hdr->check) { 67 - skb->ip_summed = CHECKSUM_UNNECESSARY; 66 + if (!hdr->check) 68 67 return false; 69 - } 70 68 71 69 /* Checksum invalid? Ignore. 72 70 * We skip checking packets on the outgoing path
+8 -2
net/netfilter/nf_flow_table_core.c
··· 39 39 40 40 ft->l3proto = ctt->src.l3num; 41 41 ft->l4proto = ctt->dst.protonum; 42 - ft->src_port = ctt->src.u.tcp.port; 43 - ft->dst_port = ctt->dst.u.tcp.port; 42 + 43 + switch (ctt->dst.protonum) { 44 + case IPPROTO_TCP: 45 + case IPPROTO_UDP: 46 + ft->src_port = ctt->src.u.tcp.port; 47 + ft->dst_port = ctt->dst.u.tcp.port; 48 + break; 49 + } 44 50 } 45 51 46 52 struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
+52 -10
net/netfilter/nf_flow_table_ip.c
··· 172 172 struct flow_ports *ports; 173 173 unsigned int thoff; 174 174 struct iphdr *iph; 175 + u8 ipproto; 175 176 176 177 if (!pskb_may_pull(skb, sizeof(*iph) + offset)) 177 178 return -1; ··· 186 185 187 186 thoff += offset; 188 187 189 - switch (iph->protocol) { 188 + ipproto = iph->protocol; 189 + switch (ipproto) { 190 190 case IPPROTO_TCP: 191 191 *hdrsize = sizeof(struct tcphdr); 192 192 break; 193 193 case IPPROTO_UDP: 194 194 *hdrsize = sizeof(struct udphdr); 195 195 break; 196 + #ifdef CONFIG_NF_CT_PROTO_GRE 197 + case IPPROTO_GRE: 198 + *hdrsize = sizeof(struct gre_base_hdr); 199 + break; 200 + #endif 196 201 default: 197 202 return -1; 198 203 } ··· 209 202 if (!pskb_may_pull(skb, thoff + *hdrsize)) 210 203 return -1; 211 204 205 + switch (ipproto) { 206 + case IPPROTO_TCP: 207 + case IPPROTO_UDP: 208 + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 209 + tuple->src_port = ports->source; 210 + tuple->dst_port = ports->dest; 211 + break; 212 + case IPPROTO_GRE: { 213 + struct gre_base_hdr *greh; 214 + 215 + greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 216 + if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 217 + return -1; 218 + break; 219 + } 220 + } 221 + 212 222 iph = (struct iphdr *)(skb_network_header(skb) + offset); 213 - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 214 223 215 224 tuple->src_v4.s_addr = iph->saddr; 216 225 tuple->dst_v4.s_addr = iph->daddr; 217 - tuple->src_port = ports->source; 218 - tuple->dst_port = ports->dest; 219 226 tuple->l3proto = AF_INET; 220 - tuple->l4proto = iph->protocol; 227 + tuple->l4proto = ipproto; 221 228 tuple->iifidx = dev->ifindex; 222 229 nf_flow_tuple_encap(skb, tuple); 223 230 ··· 542 521 struct flow_ports *ports; 543 522 struct ipv6hdr *ip6h; 544 523 unsigned int thoff; 524 + u8 nexthdr; 545 525 546 526 thoff = sizeof(*ip6h) + offset; 547 527 if (!pskb_may_pull(skb, thoff)) ··· 550 528 551 529 ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); 552 530 553 - switch (ip6h->nexthdr) { 531 + nexthdr = ip6h->nexthdr; 532 + switch (nexthdr) { 554 533 case IPPROTO_TCP: 555 534 *hdrsize = sizeof(struct tcphdr); 556 535 break; 557 536 case IPPROTO_UDP: 558 537 *hdrsize = sizeof(struct udphdr); 559 538 break; 539 + #ifdef CONFIG_NF_CT_PROTO_GRE 540 + case IPPROTO_GRE: 541 + *hdrsize = sizeof(struct gre_base_hdr); 542 + break; 543 + #endif 560 544 default: 561 545 return -1; 562 546 } ··· 573 545 if (!pskb_may_pull(skb, thoff + *hdrsize)) 574 546 return -1; 575 547 548 + switch (nexthdr) { 549 + case IPPROTO_TCP: 550 + case IPPROTO_UDP: 551 + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 552 + tuple->src_port = ports->source; 553 + tuple->dst_port = ports->dest; 554 + break; 555 + case IPPROTO_GRE: { 556 + struct gre_base_hdr *greh; 557 + 558 + greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 559 + if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 560 + return -1; 561 + break; 562 + } 563 + } 564 + 576 565 ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); 577 - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 578 566 579 567 tuple->src_v6 = ip6h->saddr; 580 568 tuple->dst_v6 = ip6h->daddr; 581 - tuple->src_port = ports->source; 582 - tuple->dst_port = ports->dest; 583 569 tuple->l3proto = AF_INET6; 584 - tuple->l4proto = ip6h->nexthdr; 570 + tuple->l4proto = nexthdr; 585 571 tuple->iifidx = dev->ifindex; 586 572 nf_flow_tuple_encap(skb, tuple); 587 573
+15 -7
net/netfilter/nf_flow_table_offload.c
··· 174 174 match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP); 175 175 break; 176 176 case IPPROTO_UDP: 177 + case IPPROTO_GRE: 177 178 break; 178 179 default: 179 180 return -EOPNOTSUPP; ··· 183 182 key->basic.ip_proto = tuple->l4proto; 184 183 mask->basic.ip_proto = 0xff; 185 184 186 - key->tp.src = tuple->src_port; 187 - mask->tp.src = 0xffff; 188 - key->tp.dst = tuple->dst_port; 189 - mask->tp.dst = 0xffff; 190 - 191 185 match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_META) | 192 186 BIT(FLOW_DISSECTOR_KEY_CONTROL) | 193 - BIT(FLOW_DISSECTOR_KEY_BASIC) | 194 - BIT(FLOW_DISSECTOR_KEY_PORTS); 187 + BIT(FLOW_DISSECTOR_KEY_BASIC); 188 + 189 + switch (tuple->l4proto) { 190 + case IPPROTO_TCP: 191 + case IPPROTO_UDP: 192 + key->tp.src = tuple->src_port; 193 + mask->tp.src = 0xffff; 194 + key->tp.dst = tuple->dst_port; 195 + mask->tp.dst = 0xffff; 196 + 197 + match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS); 198 + break; 199 + } 200 + 195 201 return 0; 196 202 } 197 203
+27
net/netfilter/nf_tables_api.c
··· 1072 1072 return strcmp(obj->key.name, k->name); 1073 1073 } 1074 1074 1075 + static bool nft_supported_family(u8 family) 1076 + { 1077 + return false 1078 + #ifdef CONFIG_NF_TABLES_INET 1079 + || family == NFPROTO_INET 1080 + #endif 1081 + #ifdef CONFIG_NF_TABLES_IPV4 1082 + || family == NFPROTO_IPV4 1083 + #endif 1084 + #ifdef CONFIG_NF_TABLES_ARP 1085 + || family == NFPROTO_ARP 1086 + #endif 1087 + #ifdef CONFIG_NF_TABLES_NETDEV 1088 + || family == NFPROTO_NETDEV 1089 + #endif 1090 + #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) 1091 + || family == NFPROTO_BRIDGE 1092 + #endif 1093 + #ifdef CONFIG_NF_TABLES_IPV6 1094 + || family == NFPROTO_IPV6 1095 + #endif 1096 + ; 1097 + } 1098 + 1075 1099 static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info, 1076 1100 const struct nlattr * const nla[]) 1077 1101 { ··· 1109 1085 struct nft_ctx ctx; 1110 1086 u32 flags = 0; 1111 1087 int err; 1088 + 1089 + if (!nft_supported_family(family)) 1090 + return -EOPNOTSUPP; 1112 1091 1113 1092 lockdep_assert_held(&nft_net->commit_mutex); 1114 1093 attr = nla[NFTA_TABLE_NAME];
+13
net/netfilter/nft_flow_offload.c
··· 298 298 break; 299 299 case IPPROTO_UDP: 300 300 break; 301 + #ifdef CONFIG_NF_CT_PROTO_GRE 302 + case IPPROTO_GRE: { 303 + struct nf_conntrack_tuple *tuple; 304 + 305 + if (ct->status & IPS_NAT_MASK) 306 + goto out; 307 + tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 308 + /* No support for GRE v1 */ 309 + if (tuple->src.u.gre.key || tuple->dst.u.gre.key) 310 + goto out; 311 + break; 312 + } 313 + #endif 301 314 default: 302 315 goto out; 303 316 }
+91 -24
net/sched/act_ct.c
··· 420 420 break; 421 421 case IPPROTO_UDP: 422 422 break; 423 + #ifdef CONFIG_NF_CT_PROTO_GRE 424 + case IPPROTO_GRE: { 425 + struct nf_conntrack_tuple *tuple; 426 + 427 + if (ct->status & IPS_NAT_MASK) 428 + return; 429 + tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 430 + /* No support for GRE v1 */ 431 + if (tuple->src.u.gre.key || tuple->dst.u.gre.key) 432 + return; 433 + break; 434 + } 435 + #endif 423 436 default: 424 437 return; 425 438 } ··· 452 439 struct flow_ports *ports; 453 440 unsigned int thoff; 454 441 struct iphdr *iph; 442 + size_t hdrsize; 443 + u8 ipproto; 455 444 456 445 if (!pskb_network_may_pull(skb, sizeof(*iph))) 457 446 return false; ··· 465 450 unlikely(thoff != sizeof(struct iphdr))) 466 451 return false; 467 452 468 - if (iph->protocol != IPPROTO_TCP && 469 - iph->protocol != IPPROTO_UDP) 453 + ipproto = iph->protocol; 454 + switch (ipproto) { 455 + case IPPROTO_TCP: 456 + hdrsize = sizeof(struct tcphdr); 457 + break; 458 + case IPPROTO_UDP: 459 + hdrsize = sizeof(*ports); 460 + break; 461 + #ifdef CONFIG_NF_CT_PROTO_GRE 462 + case IPPROTO_GRE: 463 + hdrsize = sizeof(struct gre_base_hdr); 464 + break; 465 + #endif 466 + default: 470 467 return false; 468 + } 471 469 472 470 if (iph->ttl <= 1) 473 471 return false; 474 472 475 - if (!pskb_network_may_pull(skb, iph->protocol == IPPROTO_TCP ? 476 - thoff + sizeof(struct tcphdr) : 477 - thoff + sizeof(*ports))) 473 + if (!pskb_network_may_pull(skb, thoff + hdrsize)) 478 474 return false; 479 475 480 - iph = ip_hdr(skb); 481 - if (iph->protocol == IPPROTO_TCP) 476 + switch (ipproto) { 477 + case IPPROTO_TCP: 482 478 *tcph = (void *)(skb_network_header(skb) + thoff); 479 + fallthrough; 480 + case IPPROTO_UDP: 481 + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 482 + tuple->src_port = ports->source; 483 + tuple->dst_port = ports->dest; 484 + break; 485 + case IPPROTO_GRE: { 486 + struct gre_base_hdr *greh; 483 487 484 - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 488 + greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 489 + if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 490 + return false; 491 + break; 492 + } 493 + } 494 + 495 + iph = ip_hdr(skb); 496 + 485 497 tuple->src_v4.s_addr = iph->saddr; 486 498 tuple->dst_v4.s_addr = iph->daddr; 487 - tuple->src_port = ports->source; 488 - tuple->dst_port = ports->dest; 489 499 tuple->l3proto = AF_INET; 490 - tuple->l4proto = iph->protocol; 500 + tuple->l4proto = ipproto; 491 501 492 502 return true; 493 503 } ··· 525 485 struct flow_ports *ports; 526 486 struct ipv6hdr *ip6h; 527 487 unsigned int thoff; 488 + size_t hdrsize; 489 + u8 nexthdr; 528 490 529 491 if (!pskb_network_may_pull(skb, sizeof(*ip6h))) 530 492 return false; 531 493 532 494 ip6h = ipv6_hdr(skb); 495 + thoff = sizeof(*ip6h); 533 496 534 - if (ip6h->nexthdr != IPPROTO_TCP && 535 - ip6h->nexthdr != IPPROTO_UDP) 536 - return false; 497 + nexthdr = ip6h->nexthdr; 498 + switch (nexthdr) { 499 + case IPPROTO_TCP: 500 + hdrsize = sizeof(struct tcphdr); 501 + break; 502 + case IPPROTO_UDP: 503 + hdrsize = sizeof(*ports); 504 + break; 505 + #ifdef CONFIG_NF_CT_PROTO_GRE 506 + case IPPROTO_GRE: 507 + hdrsize = sizeof(struct gre_base_hdr); 508 + break; 509 + #endif 510 + default: 511 + return -1; 512 + } 537 513 538 514 if (ip6h->hop_limit <= 1) 539 515 return false; 540 516 541 - thoff = sizeof(*ip6h); 542 - if (!pskb_network_may_pull(skb, ip6h->nexthdr == IPPROTO_TCP ? 543 - thoff + sizeof(struct tcphdr) : 544 - thoff + sizeof(*ports))) 517 + if (!pskb_network_may_pull(skb, thoff + hdrsize)) 545 518 return false; 546 519 547 - ip6h = ipv6_hdr(skb); 548 - if (ip6h->nexthdr == IPPROTO_TCP) 520 + switch (nexthdr) { 521 + case IPPROTO_TCP: 549 522 *tcph = (void *)(skb_network_header(skb) + thoff); 523 + fallthrough; 524 + case IPPROTO_UDP: 525 + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 526 + tuple->src_port = ports->source; 527 + tuple->dst_port = ports->dest; 528 + break; 529 + case IPPROTO_GRE: { 530 + struct gre_base_hdr *greh; 550 531 551 - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 532 + greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 533 + if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 534 + return false; 535 + break; 536 + } 537 + } 538 + 539 + ip6h = ipv6_hdr(skb); 540 + 552 541 tuple->src_v6 = ip6h->saddr; 553 542 tuple->dst_v6 = ip6h->daddr; 554 - tuple->src_port = ports->source; 555 - tuple->dst_port = ports->dest; 556 543 tuple->l3proto = AF_INET6; 557 - tuple->l4proto = ip6h->nexthdr; 544 + tuple->l4proto = nexthdr; 558 545 559 546 return true; 560 547 }