aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_connection_sock.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-16 06:28:06 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-16 06:28:06 -0400
commit80d0a69fc57715dc9080c0567df1ed911b78abea (patch)
treefeb310b5075d3a4f118fcdde7bc44970b1c3f07e /net/ipv4/inet_connection_sock.c
parent141e369de698f2e17bf716b83fcc647ddcb2220c (diff)
ipv4: Add helper inet_csk_update_pmtu().
This abstracts away the call to dst_ops->update_pmtu() so that we can transparently handle the fact that, in the future, the dst itself can be invalidated by the PMTU update (when we have non-host routes cached in sockets). So we try to rebuild the socket cached route after the method invocation if necessary. This isn't used by SCTP because it needs to cache dsts per-transport, and thus will need it's own local version of this helper. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inet_connection_sock.c')
-rw-r--r--net/ipv4/inet_connection_sock.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 76825be3b643..200d21809379 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -803,3 +803,49 @@ int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
803} 803}
804EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); 804EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt);
805#endif 805#endif
806
807static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl)
808{
809 struct inet_sock *inet = inet_sk(sk);
810 struct ip_options_rcu *inet_opt;
811 __be32 daddr = inet->inet_daddr;
812 struct flowi4 *fl4;
813 struct rtable *rt;
814
815 rcu_read_lock();
816 inet_opt = rcu_dereference(inet->inet_opt);
817 if (inet_opt && inet_opt->opt.srr)
818 daddr = inet_opt->opt.faddr;
819 fl4 = &fl->u.ip4;
820 rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr,
821 inet->inet_saddr, inet->inet_dport,
822 inet->inet_sport, sk->sk_protocol,
823 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
824 if (IS_ERR(rt))
825 rt = NULL;
826 if (rt)
827 sk_setup_caps(sk, &rt->dst);
828 rcu_read_unlock();
829
830 return &rt->dst;
831}
832
833struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu)
834{
835 struct dst_entry *dst = __sk_dst_check(sk, 0);
836 struct inet_sock *inet = inet_sk(sk);
837
838 if (!dst) {
839 dst = inet_csk_rebuild_route(sk, &inet->cork.fl);
840 if (!dst)
841 goto out;
842 }
843 dst->ops->update_pmtu(dst, mtu);
844
845 dst = __sk_dst_check(sk, 0);
846 if (!dst)
847 dst = inet_csk_rebuild_route(sk, &inet->cork.fl);
848out:
849 return dst;
850}
851EXPORT_SYMBOL_GPL(inet_csk_update_pmtu);