372-netfilter-nft_flow_offload-fix-interaction-with-vrf-.patch 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. From: wenxu <wenxu@ucloud.cn>
  2. Date: Thu, 10 Jan 2019 14:51:35 +0800
  3. Subject: [PATCH] netfilter: nft_flow_offload: fix interaction with vrf slave
  4. device
  5. In the forward chain, the iif is changed from slave device to master vrf
  6. device. Thus, flow offload does not find a match on the lower slave
  7. device.
  8. This patch uses the cached route, ie. dst->dev, to update the iif and
  9. oif fields in the flow entry.
  10. After this patch, the following example works fine:
  11. # ip addr add dev eth0 1.1.1.1/24
  12. # ip addr add dev eth1 10.0.0.1/24
  13. # ip link add user1 type vrf table 1
  14. # ip l set user1 up
  15. # ip l set dev eth0 master user1
  16. # ip l set dev eth1 master user1
  17. # nft add table firewall
  18. # nft add flowtable f fb1 { hook ingress priority 0 \; devices = { eth0, eth1 } \; }
  19. # nft add chain f ftb-all {type filter hook forward priority 0 \; policy accept \; }
  20. # nft add rule f ftb-all ct zone 1 ip protocol tcp flow offload @fb1
  21. # nft add rule f ftb-all ct zone 1 ip protocol udp flow offload @fb1
  22. Signed-off-by: wenxu <wenxu@ucloud.cn>
  23. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  24. ---
  25. --- a/include/net/netfilter/nf_flow_table.h
  26. +++ b/include/net/netfilter/nf_flow_table.h
  27. @@ -84,7 +84,6 @@ struct flow_offload {
  28. struct nf_flow_route {
  29. struct {
  30. struct dst_entry *dst;
  31. - int ifindex;
  32. } tuple[FLOW_OFFLOAD_DIR_MAX];
  33. };
  34. --- a/net/netfilter/nf_flow_table_core.c
  35. +++ b/net/netfilter/nf_flow_table_core.c
  36. @@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offloa
  37. {
  38. struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
  39. struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
  40. + struct dst_entry *other_dst = route->tuple[!dir].dst;
  41. struct dst_entry *dst = route->tuple[dir].dst;
  42. ft->dir = dir;
  43. @@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offloa
  44. ft->src_port = ctt->src.u.tcp.port;
  45. ft->dst_port = ctt->dst.u.tcp.port;
  46. - ft->iifidx = route->tuple[dir].ifindex;
  47. - ft->oifidx = route->tuple[!dir].ifindex;
  48. + ft->iifidx = other_dst->dev->ifindex;
  49. + ft->oifidx = dst->dev->ifindex;
  50. ft->dst_cache = dst;
  51. }
  52. --- a/net/netfilter/nft_flow_offload.c
  53. +++ b/net/netfilter/nft_flow_offload.c
  54. @@ -30,9 +30,11 @@ static int nft_flow_route(const struct n
  55. switch (nft_pf(pkt)) {
  56. case NFPROTO_IPV4:
  57. fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
  58. + fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex;
  59. break;
  60. case NFPROTO_IPV6:
  61. fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
  62. + fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex;
  63. break;
  64. }
  65. @@ -41,9 +43,7 @@ static int nft_flow_route(const struct n
  66. return -ENOENT;
  67. route->tuple[dir].dst = this_dst;
  68. - route->tuple[dir].ifindex = nft_in(pkt)->ifindex;
  69. route->tuple[!dir].dst = other_dst;
  70. - route->tuple[!dir].ifindex = nft_out(pkt)->ifindex;
  71. return 0;
  72. }