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

ipv6: tcp_ipv6 policy route issue

The issue raises when adding policy route, specify a particular
NIC as oif, the policy route did not take effect. The reason is
that fl6.oif is not set and route map failed. From the
tcp_v6_send_response function, if the binding address is linklocal,
fl6.oif is set, but not for global address.

Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Wang Yufen and committed by
David S. Miller
9c76a114 60ea37f7

+11 -7
+11 -7
net/ipv6/tcp_ipv6.c
··· 726 726 #endif 727 727 728 728 static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, 729 - u32 tsval, u32 tsecr, 729 + u32 tsval, u32 tsecr, int oif, 730 730 struct tcp_md5sig_key *key, int rst, u8 tclass, 731 731 u32 label) 732 732 { ··· 798 798 __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); 799 799 800 800 fl6.flowi6_proto = IPPROTO_TCP; 801 - if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) 801 + if (rt6_need_strict(&fl6.daddr) || !oif) 802 802 fl6.flowi6_oif = inet6_iif(skb); 803 + else 804 + fl6.flowi6_oif = oif; 803 805 fl6.fl6_dport = t1->dest; 804 806 fl6.fl6_sport = t1->source; 805 807 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); ··· 835 833 int genhash; 836 834 struct sock *sk1 = NULL; 837 835 #endif 836 + int oif; 838 837 839 838 if (th->rst) 840 839 return; ··· 879 876 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - 880 877 (th->doff << 2); 881 878 882 - tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0, 0); 879 + oif = sk ? sk->sk_bound_dev_if : 0; 880 + tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); 883 881 884 882 #ifdef CONFIG_TCP_MD5SIG 885 883 release_sk1: ··· 892 888 } 893 889 894 890 static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, 895 - u32 win, u32 tsval, u32 tsecr, 891 + u32 win, u32 tsval, u32 tsecr, int oif, 896 892 struct tcp_md5sig_key *key, u8 tclass, 897 893 u32 label) 898 894 { 899 - tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass, 895 + tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, oif, key, 0, tclass, 900 896 label); 901 897 } 902 898 ··· 908 904 tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, 909 905 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, 910 906 tcp_time_stamp + tcptw->tw_ts_offset, 911 - tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), 907 + tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), 912 908 tw->tw_tclass, (tw->tw_flowlabel << 12)); 913 909 914 910 inet_twsk_put(tw); ··· 918 914 struct request_sock *req) 919 915 { 920 916 tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, 921 - req->rcv_wnd, tcp_time_stamp, req->ts_recent, 917 + req->rcv_wnd, tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, 922 918 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 923 919 0, 0); 924 920 }