diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-02 05:21:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-05 04:03:06 -0400 |
commit | 5110effee8fde2edfacac9cd12a9960ab2dc39ea (patch) | |
tree | f74fff97af20ffdf805fedc56f0c8f88bbef2df7 /net/ipv4/tcp_input.c | |
parent | 60d354ebebd9d0f760cb6c3b9f53a7ade0f8cd0e (diff) |
net: Do delayed neigh confirmation.
When a dst_confirm() happens, mark the confirmation as pending in the
dst. Then on the next packet out, when we have the neigh in-hand, do
the update.
This removes the dependency in dst_confirm() of dst's having an
attached neigh.
While we're here, remove the explicit 'dst' NULL check, all except 2
or 3 call sites ensure it's not NULL. So just fix those cases up.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8416f8a68e65..ca0d0e7c9778 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -740,13 +740,13 @@ void tcp_update_metrics(struct sock *sk) | |||
740 | if (sysctl_tcp_nometrics_save) | 740 | if (sysctl_tcp_nometrics_save) |
741 | return; | 741 | return; |
742 | 742 | ||
743 | dst_confirm(dst); | ||
744 | |||
745 | if (dst && (dst->flags & DST_HOST)) { | 743 | if (dst && (dst->flags & DST_HOST)) { |
746 | const struct inet_connection_sock *icsk = inet_csk(sk); | 744 | const struct inet_connection_sock *icsk = inet_csk(sk); |
747 | int m; | 745 | int m; |
748 | unsigned long rtt; | 746 | unsigned long rtt; |
749 | 747 | ||
748 | dst_confirm(dst); | ||
749 | |||
750 | if (icsk->icsk_backoff || !tp->srtt) { | 750 | if (icsk->icsk_backoff || !tp->srtt) { |
751 | /* This session failed to estimate rtt. Why? | 751 | /* This session failed to estimate rtt. Why? |
752 | * Probably, no packets returned in time. | 752 | * Probably, no packets returned in time. |
@@ -3869,9 +3869,11 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3869 | tcp_cong_avoid(sk, ack, prior_in_flight); | 3869 | tcp_cong_avoid(sk, ack, prior_in_flight); |
3870 | } | 3870 | } |
3871 | 3871 | ||
3872 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) | 3872 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { |
3873 | dst_confirm(__sk_dst_get(sk)); | 3873 | struct dst_entry *dst = __sk_dst_get(sk); |
3874 | 3874 | if (dst) | |
3875 | dst_confirm(dst); | ||
3876 | } | ||
3875 | return 1; | 3877 | return 1; |
3876 | 3878 | ||
3877 | no_queue: | 3879 | no_queue: |
@@ -6140,9 +6142,14 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
6140 | 6142 | ||
6141 | case TCP_FIN_WAIT1: | 6143 | case TCP_FIN_WAIT1: |
6142 | if (tp->snd_una == tp->write_seq) { | 6144 | if (tp->snd_una == tp->write_seq) { |
6145 | struct dst_entry *dst; | ||
6146 | |||
6143 | tcp_set_state(sk, TCP_FIN_WAIT2); | 6147 | tcp_set_state(sk, TCP_FIN_WAIT2); |
6144 | sk->sk_shutdown |= SEND_SHUTDOWN; | 6148 | sk->sk_shutdown |= SEND_SHUTDOWN; |
6145 | dst_confirm(__sk_dst_get(sk)); | 6149 | |
6150 | dst = __sk_dst_get(sk); | ||
6151 | if (dst) | ||
6152 | dst_confirm(dst); | ||
6146 | 6153 | ||
6147 | if (!sock_flag(sk, SOCK_DEAD)) | 6154 | if (!sock_flag(sk, SOCK_DEAD)) |
6148 | /* Wake up lingering close() */ | 6155 | /* Wake up lingering close() */ |