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

ip6_tunnel: add optional fwmark inherit

Add IP6_TNL_F_USE_ORIG_FWMARK to ip6_tunnel, so that ip6_tnl_xmit2()
makes a route lookup taking into account skb->fwmark and doesnt cache
lookup result.

This permits more flexibility in policies and firewall setups.

To setup such a tunnel, "fwmark inherit" option should be added to "ip
-f inet6 tunnel" command.

Reported-by: Anders Franzen <Anders.Franzen@ericsson.com>
CC: Hans Schillström <hans.schillstrom@ericsson.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
d24f22f3 46151ae8

+18 -7
+2
include/linux/ip6_tunnel.h
··· 16 16 #define IP6_TNL_F_MIP6_DEV 0x8 17 17 /* copy DSCP from the outer packet */ 18 18 #define IP6_TNL_F_RCV_DSCP_COPY 0x10 19 + /* copy fwmark from inner packet */ 20 + #define IP6_TNL_F_USE_ORIG_FWMARK 0x20 19 21 20 22 struct ip6_tnl_parm { 21 23 char name[IFNAMSIZ]; /* name of tunnel device */
+16 -7
net/ipv6/ip6_tunnel.c
··· 889 889 struct net_device_stats *stats = &t->dev->stats; 890 890 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 891 891 struct ipv6_tel_txoption opt; 892 - struct dst_entry *dst, *ndst = NULL; 892 + struct dst_entry *dst = NULL, *ndst = NULL; 893 893 struct net_device *tdev; 894 894 int mtu; 895 895 unsigned int max_headroom = sizeof(struct ipv6hdr); ··· 897 897 int err = -1; 898 898 int pkt_len; 899 899 900 - dst = ip6_tnl_dst_check(t); 900 + if (!fl6->flowi6_mark) 901 + dst = ip6_tnl_dst_check(t); 901 902 if (!dst) { 902 903 ndst = ip6_route_output(net, NULL, fl6); 903 904 ··· 956 955 skb = new_skb; 957 956 } 958 957 skb_dst_drop(skb); 959 - skb_dst_set_noref(skb, dst); 960 - 958 + if (fl6->flowi6_mark) { 959 + skb_dst_set(skb, dst); 960 + ndst = NULL; 961 + } else { 962 + skb_dst_set_noref(skb, dst); 963 + } 961 964 skb->transport_header = skb->network_header; 962 965 963 966 proto = fl6->flowi6_proto; ··· 1026 1021 1027 1022 dsfield = ipv4_get_dsfield(iph); 1028 1023 1029 - if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) 1024 + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 1030 1025 fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) 1031 1026 & IPV6_TCLASS_MASK; 1027 + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 1028 + fl6.flowi6_mark = skb->mark; 1032 1029 1033 1030 err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); 1034 1031 if (err != 0) { ··· 1077 1070 fl6.flowi6_proto = IPPROTO_IPV6; 1078 1071 1079 1072 dsfield = ipv6_get_dsfield(ipv6h); 1080 - if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) 1073 + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 1081 1074 fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); 1082 - if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) 1075 + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) 1083 1076 fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); 1077 + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 1078 + fl6.flowi6_mark = skb->mark; 1084 1079 1085 1080 err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); 1086 1081 if (err != 0) {