📄 transport.c
字号:
/* SCTP kernel implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2003 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll * * This file is part of the SCTP kernel implementation * * This module provides the abstraction for an SCTP tranport representing * a remote transport address. For local transport addresses, we just use * union sctp_addr. * * This SCTP implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This SCTP implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * * Written or modified by: * La Monte H.P. Yarroll <piggy@acm.org> * Karl Knutson <karl@athena.chicago.il.us> * Jon Grimm <jgrimm@us.ibm.com> * Xingang Guo <xingang.guo@intel.com> * Hui Huang <hui.huang@nokia.com> * Sridhar Samudrala <sri@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */#include <linux/types.h>#include <linux/random.h>#include <net/sctp/sctp.h>#include <net/sctp/sm.h>/* 1st Level Abstractions. *//* Initialize a new transport from provided memory. */static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, const union sctp_addr *addr, gfp_t gfp){ /* Copy in the address. */ peer->ipaddr = *addr; peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; peer->dst = NULL; memset(&peer->saddr, 0, sizeof(union sctp_addr)); /* From 6.3.1 RTO Calculation: * * C1) Until an RTT measurement has been made for a packet sent to the * given destination transport address, set RTO to the protocol * parameter 'RTO.Initial'. */ peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial); peer->rtt = 0; peer->rttvar = 0; peer->srtt = 0; peer->rto_pending = 0; peer->last_time_heard = jiffies; peer->last_time_used = jiffies; peer->last_time_ecne_reduced = jiffies; peer->init_sent_count = 0; peer->param_flags = SPP_HB_DISABLE | SPP_PMTUD_ENABLE | SPP_SACKDELAY_ENABLE; peer->hbinterval = 0; /* Initialize the default path max_retrans. */ peer->pathmaxrxt = sctp_max_retrans_path; peer->error_count = 0; INIT_LIST_HEAD(&peer->transmitted); INIT_LIST_HEAD(&peer->send_ready); INIT_LIST_HEAD(&peer->transports); setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, (unsigned long)peer); setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, (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; peer->malloced = 0; /* Initialize the state information for SFR-CACC */ peer->cacc.changeover_active = 0; peer->cacc.cycling_changeover = 0; peer->cacc.next_tsn_at_change = 0; peer->cacc.cacc_saw_newack = 0; return peer;}/* Allocate and initialize a new transport. */struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, gfp_t gfp){ struct sctp_transport *transport; transport = t_new(struct sctp_transport, gfp); if (!transport) goto fail; if (!sctp_transport_init(transport, addr, gfp)) goto fail_init; transport->malloced = 1; SCTP_DBG_OBJCNT_INC(transport); return transport;fail_init: kfree(transport);fail: return NULL;}/* This transport is no longer needed. Free up if possible, or * delay until it last reference count. */void sctp_transport_free(struct sctp_transport *transport){ transport->dead = 1; /* Try to delete the heartbeat timer. */ if (del_timer(&transport->hb_timer)) sctp_transport_put(transport); /* Delete the T3_rtx timer if it's active. * There is no point in not doing this now and letting * structure hang around in memory since we know * the tranport is going away. */ if (timer_pending(&transport->T3_rtx_timer) && del_timer(&transport->T3_rtx_timer)) sctp_transport_put(transport); sctp_transport_put(transport);}/* Destroy the transport data structure. * Assumes there are no more users of this structure. */static void sctp_transport_destroy(struct sctp_transport *transport){ SCTP_ASSERT(transport->dead, "Transport is not dead", return); if (transport->asoc) sctp_association_put(transport->asoc); sctp_packet_free(&transport->packet); dst_release(transport->dst); kfree(transport); SCTP_DBG_OBJCNT_DEC(transport);}/* Start T3_rtx timer if it is not already running and update the heartbeat * timer. This routine is called every time a DATA chunk is sent. */void sctp_transport_reset_timers(struct sctp_transport *transport){ /* RFC 2960 6.3.2 Retransmission Timer Rules * * R1) Every time a DATA chunk is sent to any address(including a * retransmission), if the T3-rtx timer of that address is not running * start it running so that it will expire after the RTO of that * address. */ if (!timer_pending(&transport->T3_rtx_timer)) if (!mod_timer(&transport->T3_rtx_timer, jiffies + transport->rto)) sctp_transport_hold(transport); /* When a data chunk is sent, reset the heartbeat interval. */ if (!mod_timer(&transport->hb_timer, sctp_transport_timeout(transport))) sctp_transport_hold(transport);}/* This transport has been assigned to an association. * Initialize fields from the association or from the sock itself. * Register the reference count in the association. */void sctp_transport_set_owner(struct sctp_transport *transport, struct sctp_association *asoc){ transport->asoc = asoc; sctp_association_hold(asoc);}/* Initialize the pmtu of a transport. */void sctp_transport_pmtu(struct sctp_transport *transport){ struct dst_entry *dst; dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); if (dst) { transport->pathmtu = dst_mtu(dst); dst_release(dst); } else transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;}/* this is a complete rip-off from __sk_dst_check * the cookie is always 0 since this is how it's used in the * pmtu code */static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t){ struct dst_entry *dst = t->dst; if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) { dst_release(t->dst); t->dst = NULL; return NULL; } return dst;}void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu){ struct dst_entry *dst; if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { printk(KERN_WARNING "%s: Reported pmtu %d too low, " "using default minimum of %d\n", __FUNCTION__, pmtu, SCTP_DEFAULT_MINSEGMENT); /* Use default minimum segment size and disable * pmtu discovery on this transport. */ t->pathmtu = SCTP_DEFAULT_MINSEGMENT; } else { t->pathmtu = pmtu; } dst = sctp_transport_dst_check(t); if (dst) dst->ops->update_pmtu(dst, pmtu);}/* Caches the dst entry and source address for a transport's destination * address. */void sctp_transport_route(struct sctp_transport *transport, union sctp_addr *saddr, struct sctp_sock *opt){ struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; union sctp_addr *daddr = &transport->ipaddr; struct dst_entry *dst; dst = af->get_dst(asoc, daddr, saddr); if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); else af->get_saddr(asoc, dst, daddr, &transport->saddr); transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -