[SCTP] Flag a pmtu change request
authorVlad Yasevich <vladislav.yasevich@hp.com>
Thu, 7 Jun 2007 18:21:05 +0000 (14:21 -0400)
committerVladislav Yasevich <vxy@hera.kernel.org>
Wed, 13 Jun 2007 20:44:42 +0000 (20:44 +0000)
Currently, if the socket is owned by the user, we drop the ICMP
message.  As a result SCTP forgets that path MTU changed and
never adjusting it's estimate.  This causes all subsequent
packets to be fragmented.  With this patch, we'll flag the association
that it needs to udpate it's estimate based on the already updated
routing information.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Acked-by: Sridhar Samudrala <sri@us.ibm.com>
include/net/sctp/sctp.h
include/net/sctp/structs.h
net/sctp/associola.c
net/sctp/input.c
net/sctp/socket.c

index dda72bf5b9b4cab8775b478b0b24c7454c8c3487..16baef4dab7ed813729d9879be38399b85682f6a 100644 (file)
@@ -503,6 +503,13 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
        return frag;
 }
 
+static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
+{
+
+       sctp_assoc_sync_pmtu(asoc);
+       asoc->pmtu_pending = 0;
+}
+
 /* Walk through a list of TLV parameters.  Don't trust the
  * individual parameter lengths and instead depend on
  * the chunk length to indicate when to stop.  Make sure
index dc0e70cb0f8b587a1a79ce59a305ba75f368c12b..ee4559b1130201e845548d07e12bd425cbb1349c 100644 (file)
@@ -912,6 +912,9 @@ struct sctp_transport {
         */
        __u16 pathmaxrxt;
 
+       /* is the Path MTU update pending on this tranport */
+       __u8 pmtu_pending;
+
        /* PMTU       : The current known path MTU.  */
        __u32 pathmtu;
 
@@ -1566,6 +1569,9 @@ struct sctp_association {
         */
        __u16 pathmaxrxt;
 
+       /* Flag that path mtu update is pending */
+       __u8   pmtu_pending;
+
        /* Association : The smallest PMTU discovered for all of the
         * PMTU        : peer's transport addresses.
         */
index df94e3cdfba3ede94fd9ee5a9fb4de4478913b92..498edb0cd4e5f7156cb98506304db1f48bcc8cef 100644 (file)
@@ -1231,6 +1231,10 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
        /* Get the lowest pmtu of all the transports. */
        list_for_each(pos, &asoc->peer.transport_addr_list) {
                t = list_entry(pos, struct sctp_transport, transports);
+               if (t->pmtu_pending && t->dst) {
+                       sctp_transport_update_pmtu(t, dst_mtu(t->dst));
+                       t->pmtu_pending = 0;
+               }
                if (!pmtu || (t->pathmtu < pmtu))
                        pmtu = t->pathmtu;
        }
index 45d6a644cf06a75b3ff560f8acbbf33fd7a6edf1..d57ff7f3c5764510e32c8b1812c2c89492df9da8 100644 (file)
@@ -367,9 +367,15 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
                           struct sctp_transport *t, __u32 pmtu)
 {
-       if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu))
+       if (!t || (t->pathmtu == pmtu))
                return;
 
+       if (sock_owned_by_user(sk)) {
+               asoc->pmtu_pending = 1;
+               t->pmtu_pending = 1;
+               return;
+       }
+
        if (t->param_flags & SPP_PMTUD_ENABLE) {
                /* Update transports view of the MTU */
                sctp_transport_update_pmtu(t, pmtu);
index 45510c46c2232663ecb0cc3af5058490462bb78c..6edaaa009d627ed17ef559f75a950d75a9aa3dec 100644 (file)
@@ -1662,6 +1662,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                goto out_free;
        }
 
+       if (asoc->pmtu_pending)
+               sctp_assoc_pending_pmtu(asoc);
+
        /* If fragmentation is disabled and the message length exceeds the
         * association fragmentation point, return EMSGSIZE.  The I-D
         * does not specify what this error is, but this looks like