diff options
author | rrs <rrs@FreeBSD.org> | 2008-05-20 13:47:46 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2008-05-20 13:47:46 +0000 |
commit | 8a663465644dd0d19159348afb69bb2462822ed1 (patch) | |
tree | 2eb09e824f0a51e8694f455f2aa95ba0da7b95d8 /sys/netinet/sctp_timer.c | |
parent | 2f427637e0af90ccec0c813c87cd3ae5404cedc3 (diff) | |
download | FreeBSD-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.c | 65 |
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; |