📄 transport.c
字号:
/* SCTP kernel reference 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 reference 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. * * The SCTP reference 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. * * The SCTP reference 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 <net/sctp/sctp.h>#include <net/sctp/sm.h>/* 1st Level Abstractions. *//* Allocate and initialize a new transport. */struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int 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;}/* Initialize a new transport from provided memory. */struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, const union sctp_addr *addr, int 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->rtt = 0; peer->rto = sctp_rto_initial; 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->active = SCTP_ACTIVE; peer->hb_allowed = 0; /* Initialize the default path max_retrans. */ peer->max_retrans = sctp_max_retrans_path; peer->error_threshold = 0; peer->error_count = 0; INIT_LIST_HEAD(&peer->transmitted); INIT_LIST_HEAD(&peer->send_ready); INIT_LIST_HEAD(&peer->transports); /* Set up the retransmission timer. */ init_timer(&peer->T3_rtx_timer); peer->T3_rtx_timer.function = sctp_generate_t3_rtx_event; peer->T3_rtx_timer.data = (unsigned long)peer; /* Set up the heartbeat timer. */ init_timer(&peer->hb_timer); peer->hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; peer->hb_timer.function = sctp_generate_heartbeat_event; peer->hb_timer.data = (unsigned long)peer; 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;}/* 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); sctp_transport_put(transport);}/* Destroy the transport data structure. * Assumes there are no more users of this structure. */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->pmtu = dst_pmtu(dst); dst_release(dst); } else transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;}/* 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_opt *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 (dst) { transport->pmtu = dst_pmtu(dst); /* Initialize sk->sk_rcv_saddr, if the transport is the * association's active path for getsockname(). */ if (asoc && (transport == asoc->peer.active_path)) af->to_sk_saddr(&transport->saddr, asoc->base.sk);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -