]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
sctp: add dst_pending_confirm flag
authorJulian Anastasov <ja@ssi.bg>
Fri, 8 Sep 2017 07:00:00 +0000 (09:00 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 15 Sep 2017 13:49:14 +0000 (15:49 +0200)
BugLink: https://bugs.launchpad.net/bugs/1715812
Add new transport flag to allow sockets to confirm neighbour.
When same struct dst_entry can be used for many different
neighbours we can not use it for pending confirmations.
The flag is propagated from transport to every packet.
It is reset when cached dst is reset.

Reported-by: YueHaibing <yuehaibing@huawei.com>
Fixes: 5110effee8fd ("net: Do delayed neigh confirmation.")
Fixes: f2bb4bedf35d ("ipv4: Cache output routes in fib_info nexthops.")
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Acked-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit c86a773c78025f5b825bacd7b846f4fa60dc0317)
Signed-off-by: Daniel Axtens <daniel.axtens@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Colin King <colin.king@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
include/net/sctp/sctp.h
include/net/sctp/structs.h
net/sctp/associola.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/transport.c

index d8833a86cd7e48192f4c3b5d984ac76aee3b7516..897f6365d98dbea5bb3543040d1f1a008556fd49 100644 (file)
@@ -586,10 +586,8 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
  */
 static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
 {
-       if (t->dst && !dst_check(t->dst, t->dst_cookie)) {
-               dst_release(t->dst);
-               t->dst = NULL;
-       }
+       if (t->dst && !dst_check(t->dst, t->dst_cookie))
+               sctp_transport_dst_release(t);
 
        return t->dst;
 }
index 92daabdc007d94a544baa10d278d229e42e40eb3..e842e84816f743db64bb59bfcbf4bf8ff08e6794 100644 (file)
@@ -838,6 +838,8 @@ struct sctp_transport {
 
        __u32 burst_limited;    /* Holds old cwnd when max.burst is applied */
 
+       __u32 dst_pending_confirm;      /* need to confirm neighbour */
+
        /* Destination */
        struct dst_entry *dst;
        /* Source address. */
@@ -980,6 +982,8 @@ unsigned long sctp_transport_timeout(struct sctp_transport *);
 void sctp_transport_reset(struct sctp_transport *);
 void sctp_transport_update_pmtu(struct sock *, struct sctp_transport *, u32);
 void sctp_transport_immediate_rtx(struct sctp_transport *);
+void sctp_transport_dst_release(struct sctp_transport *t);
+void sctp_transport_dst_confirm(struct sctp_transport *t);
 
 
 /* This is the structure we use to queue packets as they come into
index d3cc30c25c41091c2bf18022506dff4145d29944..56a8c7df0f95e902cfebfaa4d2cba81f897c3348 100644 (file)
@@ -820,8 +820,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
                if (transport->state != SCTP_UNCONFIRMED)
                        transport->state = SCTP_INACTIVE;
                else {
-                       dst_release(transport->dst);
-                       transport->dst = NULL;
+                       sctp_transport_dst_release(transport);
                        ulp_notify = false;
                }
 
index f5320a87341e160d46b1160edf4c38b569e7e79b..116488a2b574e893a1d35f6029d79cbf2cd3f2ca 100644 (file)
@@ -550,6 +550,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
        struct sctp_association *asoc = tp->asoc;
        struct sctp_chunk *chunk, *tmp;
        int pkt_count, gso = 0;
+       int confirm;
        struct dst_entry *dst;
        struct sk_buff *head;
        struct sctphdr *sh;
@@ -628,7 +629,14 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                        asoc->peer.last_sent_to = tp;
        }
        head->ignore_df = packet->ipfragok;
-       tp->af_specific->sctp_xmit(head, tp);
+       confirm = tp->dst_pending_confirm;
+       if (confirm)
+               skb_set_dst_pending_confirm(head, 1);
+       /* neighbour should be confirmed on successful transmission or
+        * positive error
+        */
+       if (tp->af_specific->sctp_xmit(head, tp) >= 0 && confirm)
+               tp->dst_pending_confirm = 0;
 
 out:
        list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
index 34efaa4ef2f6acfbed9b490f948f214e91a5606c..e4a940efc4a5fa658c13a3b150863e79e1da7f20 100644 (file)
@@ -1641,7 +1641,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 
                if (forward_progress) {
                        if (transport->dst)
-                               dst_confirm(transport->dst);
+                               sctp_transport_dst_confirm(transport);
                }
        }
 
index 9e9690b7afe118636eb64751f9c58637be56c5e8..6fb15bf5387d812517f122a4d8bad707c34aa207 100644 (file)
@@ -3317,8 +3317,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
                local_bh_enable();
                list_for_each_entry(transport, &asoc->peer.transport_addr_list,
                                transports) {
-                       dst_release(transport->dst);
-                       transport->dst = NULL;
+                       sctp_transport_dst_release(transport);
                }
                break;
        case SCTP_PARAM_DEL_IP:
@@ -3332,8 +3331,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
                local_bh_enable();
                list_for_each_entry(transport, &asoc->peer.transport_addr_list,
                                transports) {
-                       dst_release(transport->dst);
-                       transport->dst = NULL;
+                       sctp_transport_dst_release(transport);
                }
                break;
        default:
index c345bf153bed2393479b3e5e471d8c987e908960..9255b291ebfd976c9dfb7d881a2f6a42e52c79da 100644 (file)
@@ -723,7 +723,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
         * forward progress.
         */
        if (t->dst)
-               dst_confirm(t->dst);
+               sctp_transport_dst_confirm(t);
 
        /* The receiver of the HEARTBEAT ACK should also perform an
         * RTT measurement for that destination transport address
index 6932cf34fea86344bdee9b8dd0f88a4372e26f9c..02de002ed7c5ab562b987a3817a350cace6a2d38 100644 (file)
@@ -592,7 +592,7 @@ static int sctp_send_asconf_add_ip(struct sock              *sk,
                        list_for_each_entry(trans,
                            &asoc->peer.transport_addr_list, transports) {
                                /* Clear the source and route cache */
-                               dst_release(trans->dst);
+                               sctp_transport_dst_release(trans);
                                trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
                                    2*asoc->pathmtu, 4380));
                                trans->ssthresh = asoc->peer.i.a_rwnd;
@@ -843,7 +843,7 @@ skip_mkasconf:
                 */
                list_for_each_entry(transport, &asoc->peer.transport_addr_list,
                                        transports) {
-                       dst_release(transport->dst);
+                       sctp_transport_dst_release(transport);
                        sctp_transport_route(transport, NULL,
                                             sctp_sk(asoc->base.sk));
                }
index a1652ab63918940be605eaf002b5506f5e4e6673..cd52f161ebd1a9ef5d11355e571038cf9eb8eb48 100644 (file)
@@ -227,7 +227,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
 {
        /* If we don't have a fresh route, look one up */
        if (!transport->dst || transport->dst->obsolete) {
-               dst_release(transport->dst);
+               sctp_transport_dst_release(transport);
                transport->af_specific->get_dst(transport, &transport->saddr,
                                                &transport->fl, sk);
        }
@@ -659,3 +659,17 @@ void sctp_transport_immediate_rtx(struct sctp_transport *t)
                        sctp_transport_hold(t);
        }
 }
+
+/* Drop dst */
+void sctp_transport_dst_release(struct sctp_transport *t)
+{
+       dst_release(t->dst);
+       t->dst = NULL;
+       t->dst_pending_confirm = 0;
+}
+
+/* Schedule neighbour confirm */
+void sctp_transport_dst_confirm(struct sctp_transport *t)
+{
+       t->dst_pending_confirm = 1;
+}