*/
#include <linux/types.h>
+#include <linux/random.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
* parameter 'RTO.Initial'.
*/
peer->rtt = 0;
- peer->rto = sctp_rto_initial;
+ peer->rto = msecs_to_jiffies(sctp_rto_initial);
peer->rttvar = 0;
peer->srtt = 0;
peer->rto_pending = 0;
peer->init_sent_count = 0;
- peer->state = SCTP_ACTIVE;
peer->param_flags = SPP_HB_DISABLE |
SPP_PMTUD_ENABLE |
SPP_SACKDELAY_ENABLE;
peer->hb_timer.function = sctp_generate_heartbeat_event;
peer->hb_timer.data = (unsigned long)peer;
+ /* Initialize the 64-bit random nonce sent with heartbeat. */
+ get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
+
atomic_set(&peer->refcnt, 1);
peer->dead = 0;
struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
gfp_t gfp)
{
- struct sctp_transport *transport;
+ struct sctp_transport *transport;
- transport = t_new(struct sctp_transport, gfp);
+ transport = t_new(struct sctp_transport, gfp);
if (!transport)
goto fail;
if (transport->asoc)
sctp_association_put(transport->asoc);
- sctp_packet_free(&transport->packet);
+ sctp_packet_free(&transport->packet);
dst_release(transport->dst);
kfree(transport);
/* Initialize sk->sk_rcv_saddr, if the transport is the
* association's active path for getsockname().
- */
+ */
if (asoc && (transport == asoc->peer.active_path))
opt->pf->af->to_sk_saddr(&transport->saddr,
asoc->base.sk);
* destination address(es) to which the missing DATA chunks
* were last sent, according to the formula described in
* Section 7.2.3.
- *
- * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
+ *
+ * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
* losses from SACK (see Section 7.2.4), An endpoint
* should do the following:
* ssthresh = max(cwnd/2, 4*MTU)
if ((jiffies - transport->last_time_ecne_reduced) >
transport->rtt) {
transport->ssthresh = max(transport->cwnd/2,
- 4*transport->asoc->pathmtu);
+ 4*transport->asoc->pathmtu);
transport->cwnd = transport->ssthresh;
transport->last_time_ecne_reduced = jiffies;
}
unsigned long sctp_transport_timeout(struct sctp_transport *t)
{
unsigned long timeout;
- timeout = t->hbinterval + t->rto + sctp_jitter(t->rto);
+ timeout = t->rto + sctp_jitter(t->rto);
+ if (t->state != SCTP_UNCONFIRMED)
+ timeout += t->hbinterval;
timeout += jiffies;
return timeout;
}
+
+/* Reset transport variables to their initial values */
+void sctp_transport_reset(struct sctp_transport *t)
+{
+ struct sctp_association *asoc = t->asoc;
+
+ /* RFC 2960 (bis), Section 5.2.4
+ * All the congestion control parameters (e.g., cwnd, ssthresh)
+ * related to this peer MUST be reset to their initial values
+ * (see Section 6.2.1)
+ */
+ t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
+ t->ssthresh = asoc->peer.i.a_rwnd;
+ t->rto = asoc->rto_initial;
+ t->rtt = 0;
+ t->srtt = 0;
+ t->rttvar = 0;
+
+ /* Reset these additional varibles so that we have a clean
+ * slate.
+ */
+ t->partial_bytes_acked = 0;
+ t->flight_size = 0;
+ t->error_count = 0;
+ t->rto_pending = 0;
+
+ /* Initialize the state information for SFR-CACC */
+ t->cacc.changeover_active = 0;
+ t->cacc.cycling_changeover = 0;
+ t->cacc.next_tsn_at_change = 0;
+ t->cacc.cacc_saw_newack = 0;
+}