diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 1f05b942564e872c6dd421fc19423ef143d732a8..caba989f4e76197a7d87eb9cc4f11eded3d9aab3 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -584,6 +584,33 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
 	    asoc->addip_last_asconf->transport == peer)
 		asoc->addip_last_asconf->transport = NULL;
 
+	/* If we have something on the transmitted list, we have to
+	 * save it off.  The best place is the active path.
+	 */
+	if (!list_empty(&peer->transmitted)) {
+		struct sctp_transport *active = asoc->peer.active_path;
+		struct sctp_chunk *ch;
+
+		/* Reset the transport of each chunk on this list */
+		list_for_each_entry(ch, &peer->transmitted,
+					transmitted_list) {
+			ch->transport = NULL;
+			ch->rtt_in_progress = 0;
+		}
+
+		list_splice_tail_init(&peer->transmitted,
+					&active->transmitted);
+
+		/* Start a T3 timer here in case it wasn't running so
+		 * that these migrated packets have a chance to get
+		 * retrnasmitted.
+		 */
+		if (!timer_pending(&active->T3_rtx_timer))
+			if (!mod_timer(&active->T3_rtx_timer,
+					jiffies + active->rto))
+				sctp_transport_hold(active);
+	}
+
 	asoc->peer.transport_count--;
 
 	sctp_transport_free(peer);
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d765fc53e74dd63447d5d47a96664ecedbde45a8..c9f20e28521b069b17583e7120ea44ac0dd9eec5 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -406,8 +406,9 @@ void sctp_retransmit_mark(struct sctp_outq *q,
 			 * not be retransmitted
 			 */
 			if (!chunk->tsn_gap_acked) {
-				chunk->transport->flight_size -=
-						sctp_data_size(chunk);
+				if (chunk->transport)
+					chunk->transport->flight_size -=
+							sctp_data_size(chunk);
 				q->outstanding_bytes -= sctp_data_size(chunk);
 				q->asoc->peer.rwnd += (sctp_data_size(chunk) +
 							sizeof(struct sk_buff));
@@ -443,7 +444,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
 			q->asoc->peer.rwnd += (sctp_data_size(chunk) +
 						sizeof(struct sk_buff));
 			q->outstanding_bytes -= sctp_data_size(chunk);
-			transport->flight_size -= sctp_data_size(chunk);
+			if (chunk->transport)
+				transport->flight_size -= sctp_data_size(chunk);
 
 			/* sctpimpguide-05 Section 2.8.2
 			 * M5) If a T3-rtx timer expires, the
@@ -1310,6 +1312,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 	__u32 rtt;
 	__u8 restart_timer = 0;
 	int bytes_acked = 0;
+	int migrate_bytes = 0;
 
 	/* These state variables are for coherent debug output. --xguo */
 
@@ -1343,8 +1346,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 			 * considering it as 'outstanding'.
 			 */
 			if (!tchunk->tsn_gap_acked) {
-				tchunk->transport->flight_size -=
-						sctp_data_size(tchunk);
+				if (tchunk->transport)
+					tchunk->transport->flight_size -=
+							sctp_data_size(tchunk);
 				q->outstanding_bytes -= sctp_data_size(tchunk);
 			}
 			continue;
@@ -1378,6 +1382,20 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 								  rtt);
 				}
 			}
+
+			/* If the chunk hasn't been marked as ACKED,
+			 * mark it and account bytes_acked if the
+			 * chunk had a valid transport (it will not
+			 * have a transport if ASCONF had deleted it
+			 * while DATA was outstanding).
+			 */
+			if (!tchunk->tsn_gap_acked) {
+				tchunk->tsn_gap_acked = 1;
+				bytes_acked += sctp_data_size(tchunk);
+				if (!tchunk->transport)
+					migrate_bytes += sctp_data_size(tchunk);
+			}
+
 			if (TSN_lte(tsn, sack_ctsn)) {
 				/* RFC 2960  6.3.2 Retransmission Timer Rules
 				 *
@@ -1391,8 +1409,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 				restart_timer = 1;
 
 				if (!tchunk->tsn_gap_acked) {
-					tchunk->tsn_gap_acked = 1;
-					bytes_acked += sctp_data_size(tchunk);
 					/*
 					 * SFR-CACC algorithm:
 					 * 2) If the SACK contains gap acks
@@ -1432,10 +1448,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 				 * older than that newly acknowledged DATA
 				 * chunk, are qualified as 'Stray DATA chunks'.
 				 */
-				if (!tchunk->tsn_gap_acked) {
-					tchunk->tsn_gap_acked = 1;
-					bytes_acked += sctp_data_size(tchunk);
-				}
 				list_add_tail(lchunk, &tlist);
 			}
 
@@ -1491,7 +1503,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 						  tsn);
 				tchunk->tsn_gap_acked = 0;
 
-				bytes_acked -= sctp_data_size(tchunk);
+				if (tchunk->transport)
+					bytes_acked -= sctp_data_size(tchunk);
 
 				/* RFC 2960 6.3.2 Retransmission Timer Rules
 				 *
@@ -1561,6 +1574,14 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 #endif /* SCTP_DEBUG */
 	if (transport) {
 		if (bytes_acked) {
+			/* We may have counted DATA that was migrated
+			 * to this transport due to DEL-IP operation.
+			 * Subtract those bytes, since the were never
+			 * send on this transport and shouldn't be
+			 * credited to this transport.
+			 */
+			bytes_acked -= migrate_bytes;
+
 			/* 8.2. When an outstanding TSN is acknowledged,
 			 * the endpoint shall clear the error counter of
 			 * the destination transport address to which the
@@ -1589,7 +1610,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 			transport->flight_size -= bytes_acked;
 			if (transport->flight_size == 0)
 				transport->partial_bytes_acked = 0;
-			q->outstanding_bytes -= bytes_acked;
+			q->outstanding_bytes -= bytes_acked + migrate_bytes;
 		} else {
 			/* RFC 2960 6.1, sctpimpguide-06 2.15.2
 			 * When a sender is doing zero window probing, it
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 45b8bcafd8272ca1322d7569e4e6ba9fadfd5faa..a7f18a3523641cc462187c8546802ec8d2a443d7 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3543,6 +3543,12 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
 		asconf_ack = sctp_assoc_lookup_asconf_ack(asoc, hdr->serial);
 		if (!asconf_ack)
 			return SCTP_DISPOSITION_DISCARD;
+
+		/* Reset the transport so that we select the correct one
+		 * this time around.  This is to make sure that we don't
+		 * accidentally use a stale transport that's been removed.
+		 */
+		asconf_ack->transport = NULL;
 	} else {
 		/* ADDIP 5.2 E5) Otherwise, the ASCONF Chunk is discarded since
 		 * it must be either a stale packet or from an attacker.