ipv6: datagram: Refactor dst lookup and update codes to a new function
This patch moves the route lookup and update codes for connected datagram sk to a newly created function ip6_datagram_dst_update() It will be reused during the pmtu update in the later patch. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Wei Wang <weiwan@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
80fbdb208f
commit
7e2040db15
@ -64,16 +64,65 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
|
||||
}
|
||||
|
||||
static int ip6_datagram_dst_update(struct sock *sk)
|
||||
{
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct in6_addr *final_p, final;
|
||||
struct ipv6_txoptions *opt;
|
||||
struct dst_entry *dst;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct flowi6 fl6;
|
||||
int err = 0;
|
||||
|
||||
if (np->sndflow && (np->flow_label & IPV6_FLOWLABEL_MASK)) {
|
||||
flowlabel = fl6_sock_lookup(sk, np->flow_label);
|
||||
if (!flowlabel)
|
||||
return -EINVAL;
|
||||
}
|
||||
ip6_datagram_flow_key_init(&fl6, sk);
|
||||
|
||||
rcu_read_lock();
|
||||
opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt);
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
|
||||
if (IS_ERR(dst)) {
|
||||
err = PTR_ERR(dst);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ipv6_addr_any(&np->saddr))
|
||||
np->saddr = fl6.saddr;
|
||||
|
||||
if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
|
||||
sk->sk_v6_rcv_saddr = fl6.saddr;
|
||||
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
ip6_dst_store(sk, dst,
|
||||
ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
|
||||
&sk->sk_v6_daddr : NULL,
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
|
||||
&np->saddr :
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
out:
|
||||
fl6_sock_release(flowlabel);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
struct dst_entry *dst;
|
||||
struct flowi6 fl6;
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct ipv6_txoptions *opt;
|
||||
struct in6_addr *daddr;
|
||||
int addr_type;
|
||||
int err;
|
||||
__be32 fl6_flowlabel = 0;
|
||||
@ -91,14 +140,8 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a
|
||||
if (usin->sin6_family != AF_INET6)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (np->sndflow) {
|
||||
if (np->sndflow)
|
||||
fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
|
||||
if (fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
|
||||
flowlabel = fl6_sock_lookup(sk, fl6_flowlabel);
|
||||
if (!flowlabel)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
addr_type = ipv6_addr_type(&usin->sin6_addr);
|
||||
|
||||
@ -178,45 +221,13 @@ ipv4_connected:
|
||||
* destination cache for it.
|
||||
*/
|
||||
|
||||
ip6_datagram_flow_key_init(&fl6, sk);
|
||||
|
||||
rcu_read_lock();
|
||||
opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt);
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
|
||||
err = 0;
|
||||
if (IS_ERR(dst)) {
|
||||
err = PTR_ERR(dst);
|
||||
err = ip6_datagram_dst_update(sk);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* source address lookup done in ip6_dst_lookup */
|
||||
|
||||
if (ipv6_addr_any(&np->saddr))
|
||||
np->saddr = fl6.saddr;
|
||||
|
||||
if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
|
||||
sk->sk_v6_rcv_saddr = fl6.saddr;
|
||||
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
ip6_dst_store(sk, dst,
|
||||
ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
|
||||
&sk->sk_v6_daddr : NULL,
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
|
||||
&np->saddr :
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
sk_set_txhash(sk);
|
||||
out:
|
||||
fl6_sock_release(flowlabel);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user