summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_timer.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2008-05-20 13:47:46 +0000
committerrrs <rrs@FreeBSD.org>2008-05-20 13:47:46 +0000
commit8a663465644dd0d19159348afb69bb2462822ed1 (patch)
tree2eb09e824f0a51e8694f455f2aa95ba0da7b95d8 /sys/netinet/sctp_timer.c
parent2f427637e0af90ccec0c813c87cd3ae5404cedc3 (diff)
downloadFreeBSD-src-8a663465644dd0d19159348afb69bb2462822ed1.zip
FreeBSD-src-8a663465644dd0d19159348afb69bb2462822ed1.tar.gz
- Adds support for the multi-asconf (From Kozuka-san)
- Adds some prepwork (Not all yet) for vimage in particular support the delete the sctppcbinfo.xx structs. There is still a leak in here if it were to be called plus we stil need the regrouping (From Me and Michael Tuexen) - Adds support for UDP tunneling. For BSD there is no socket yet setup so its disabled, but major argument changes are in here to emcompass the passing of the port number (zero when you don't have a udp tunnel, the default for BSD). Will add some hooks in UDP here shortly (discussed with Robert) that will allow easy tunneling. (Mainly from Peter Lei and Michael Tuexen with some BSD work from me :-D) - Some ease for windows, evidently leave is reserved by their compile move label leave: -> out: MFC after: 1 week
Diffstat (limited to 'sys/netinet/sctp_timer.c')
-rw-r--r--sys/netinet/sctp_timer.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 6f6d188..b6dd318 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -173,6 +173,11 @@ sctp_audit_retranmission_queue(struct sctp_association *asoc)
sctp_ucount_incr(asoc->sent_queue_retran_cnt);
}
}
+ TAILQ_FOREACH(chk, &asoc->asconf_send_queue, sctp_next) {
+ if (chk->sent == SCTP_DATAGRAM_RESEND) {
+ sctp_ucount_incr(asoc->sent_queue_retran_cnt);
+ }
+ }
SCTPDBG(SCTP_DEBUG_TIMER4, "Audit completes retran:%d onqueue:%d\n",
asoc->sent_queue_retran_cnt,
asoc->sent_queue_cnt);
@@ -1314,10 +1319,10 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
struct sctp_nets *alt;
- struct sctp_tmit_chunk *asconf, *chk;
+ struct sctp_tmit_chunk *asconf, *chk, *nchk;
/* is this a first send, or a retransmission? */
- if (stcb->asoc.asconf_sent == 0) {
+ if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) {
/* compose a new ASCONF chunk and send it */
sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
} else {
@@ -1326,12 +1331,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*/
/* find the existing ASCONF */
- TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
- sctp_next) {
- if (asconf->rec.chunk_id.id == SCTP_ASCONF) {
- break;
- }
- }
+ asconf = TAILQ_FIRST(&stcb->asoc.asconf_send_queue);
if (asconf == NULL) {
return (0);
}
@@ -1359,10 +1359,11 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*/
sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0);
alt = sctp_find_alternate_net(stcb, asconf->whoTo, 0);
- sctp_free_remote_addr(asconf->whoTo);
- asconf->whoTo = alt;
- atomic_add_int(&alt->ref_count, 1);
-
+ if (asconf->whoTo != alt) {
+ sctp_free_remote_addr(asconf->whoTo);
+ asconf->whoTo = alt;
+ atomic_add_int(&alt->ref_count, 1);
+ }
/* See if an ECN Echo is also stranded */
TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
if ((chk->whoTo == net) &&
@@ -1376,17 +1377,32 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_add_int(&alt->ref_count, 1);
}
}
+ for (chk = asconf; chk; chk = nchk) {
+ nchk = TAILQ_NEXT(chk, sctp_next);
+ if (chk->whoTo != alt) {
+ sctp_free_remote_addr(chk->whoTo);
+ chk->whoTo = alt;
+ atomic_add_int(&alt->ref_count, 1);
+ }
+ if (asconf->sent != SCTP_DATAGRAM_RESEND && chk->sent != SCTP_DATAGRAM_UNSENT)
+ sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
+ chk->sent = SCTP_DATAGRAM_RESEND;
+ }
if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
/*
* If the address went un-reachable, we need to move
* to the alternate for ALL chunks in queue
*/
sctp_move_all_chunks_to_alt(stcb, net, alt);
+ net = alt;
}
/* mark the retran info */
if (asconf->sent != SCTP_DATAGRAM_RESEND)
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
asconf->sent = SCTP_DATAGRAM_RESEND;
+
+ /* send another ASCONF if any and we can do */
+ sctp_send_asconf(stcb, alt, SCTP_ADDR_NOT_LOCKED);
}
return (0);
}
@@ -1677,16 +1693,11 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
- uint32_t next_mtu;
+ uint32_t next_mtu, mtu;
- /* restart the timer in any case */
next_mtu = sctp_getnext_mtu(inp, net->mtu);
- if (next_mtu <= net->mtu) {
- /* nothing to do */
- return;
- } {
- uint32_t mtu;
+ if ((next_mtu > net->mtu) && (net->port == 0)) {
if ((net->src_addr_selected == 0) ||
(net->ro._s_addr == NULL) ||
(net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) {
@@ -1695,10 +1706,26 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
} else if (net->ro._s_addr == NULL) {
+#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE)
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
+
+ /* KAME hack: embed scopeid */
+ (void)sa6_embedscope(sin6, ip6_use_defzone);
+ }
+#endif
+
net->ro._s_addr = sctp_source_address_selection(inp,
stcb,
(sctp_route_t *) & net->ro,
net, 0, stcb->asoc.vrf_id);
+#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE)
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
+
+ (void)sa6_recoverscope(sin6);
+ }
+#endif /* INET6 */
}
if (net->ro._s_addr)
net->src_addr_selected = 1;
OpenPOWER on IntegriCloud