diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 517f1d1935b..36bace92572 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4072,6 +4072,13 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, net->prev_cwnd = net->cwnd; net->net_ack = 0; net->net_ack2 = 0; + + /* + * CMT: Reset CUC and Fast recovery algo variables before + * SACK processing + */ + net->new_pseudo_cumack = 0; + net->will_exit_fast_recovery = 0; } if (sctp_strict_sacks) { uint32_t send_s; @@ -4173,6 +4180,22 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, tp1->do_rtt = 0; } } + /* + * CMT: CUCv2 algorithm. From the + * cumack'd TSNs, for each TSN being + * acked for the first time, set the + * following variables for the + * corresp destination. + * new_pseudo_cumack will trigger a + * cwnd update. + * find_(rtx_)pseudo_cumack will + * trigger search for the next + * expected (rtx-)pseudo-cumack. + */ + tp1->whoTo->new_pseudo_cumack = 1; + tp1->whoTo->find_pseudo_cumack = 1; + tp1->whoTo->find_rtx_pseudo_cumack = 1; + #ifdef SCTP_CWND_LOGGING sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); #endif diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 945161b1dc1..87c17f148be 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -249,6 +249,13 @@ typedef struct callout sctp_os_timer_t; #define SCTP_CLEAR_SO_NBIO(so) ((so)->so_state &= ~SS_NBIO) /* get the socket type */ #define SCTP_SO_TYPE(so) ((so)->so_type) +/* reserve sb space for a socket */ +#define SCTP_SORESERVE(so, send, recv) soreserve(so, send, recv) +/* clear the socket buffer state */ +#define SCTP_SB_CLEAR(sb) \ + (sb).sb_cc = 0; \ + (sb).sb_mb = NULL; \ + (sb).sb_mbcnt = 0; /* * SCTP AUTH diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 883f272287f..4c20802ceef 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -2187,20 +2187,42 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa, if ((dest_is_priv == 0) && (dest_is_loop == 0)) { dest_is_global = 1; } +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { + printf("Is destination prefered:"); + sctp_print_address(&ifa->address.sa); + } +#endif + /* Ok the address may be ok */ if (fam == AF_INET6) { /* ok to use deprecated addresses? */ if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:1\n"); + } +#endif return (NULL); } if (ifa->src_is_priv) { if (dest_is_loop) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:2\n"); + } +#endif return (NULL); } } if (ifa->src_is_glob) { if (dest_is_loop) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:3\n"); + } +#endif return (NULL); } } @@ -2210,18 +2232,54 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa, * theory be done slicker (it used to be), but this is * straightforward and easier to validate :-) */ +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("src_loop:%d src_priv:%d src_glob:%d\n", + ifa->src_is_loop, ifa->src_is_priv, + ifa->src_is_glob); + printf("dest_loop:%d dest_priv:%d dest_glob:%d\n", + dest_is_loop, dest_is_priv, + dest_is_global); + } +#endif + if ((ifa->src_is_loop) && (dest_is_priv)) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:4\n"); + } +#endif return (NULL); } if ((ifa->src_is_glob) && (dest_is_priv)) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:5\n"); + } +#endif return (NULL); } if ((ifa->src_is_loop) && (dest_is_global)) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:6\n"); + } +#endif return (NULL); } if ((ifa->src_is_priv) && (dest_is_global)) { +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("NO:7\n"); + } +#endif return (NULL); } +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT3) { + printf("YES\n"); + } +#endif /* its a prefered address */ return (ifa); } @@ -2708,7 +2766,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp, dest_is_loop, dest_is_priv, fam); #ifdef SCTP_DEBUG - if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { printf("Found %d prefered source addresses\n", num_prefered); } #endif @@ -2732,7 +2790,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp, * nth) and 0 is the first one, 1 is the second one etc... */ #ifdef SCTP_DEBUG - if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { printf("cur_addr_num:%d\n", cur_addr_num); } #endif @@ -2753,6 +2811,11 @@ sctp_choose_boundall(struct sctp_inpcb *inp, * prefered fall through to plan_c. */ bound_all_plan_b: +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { + printf("Plan B?\n"); + } +#endif LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { /* wrong base scope */ @@ -2764,7 +2827,7 @@ bound_all_plan_b: num_prefered = sctp_count_num_prefered_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); #ifdef SCTP_DEBUG - if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { printf("Found ifn:%p %d prefered source addresses\n", ifn, num_prefered); } #endif @@ -2818,10 +2881,7 @@ bound_all_plan_b: */ #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - if (net) { - printf("Plan C no prefered for Dest:"); - sctp_print_address(&net->ro._l_addr.sa); - } + printf("Plan C no prefered for Dest, acceptable for?\n"); } #endif @@ -2850,6 +2910,11 @@ bound_all_plan_b: * out and see if we can find an acceptable address somewhere * amongst all interfaces. */ +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { + printf("Plan C fails plan D?\n"); + } +#endif LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { /* wrong base scope */ @@ -2999,6 +3064,12 @@ sctp_source_address_selection(struct sctp_inpcb *inp, dest_is_priv = 1; } } +#ifdef SCTP_DEBUG + if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { + printf("Select source for:"); + sctp_print_address((struct sockaddr *)to); + } +#endif if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { /* * When bound to all if the address list is set it is a @@ -10329,7 +10400,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb, struct sctp_nets *net, int max_send_len, int user_marks_eor, - int *errno, + int *error, int non_blocking) { /* @@ -10342,14 +10413,12 @@ sctp_copy_it_in(struct sctp_tcb *stcb, struct sctp_stream_queue_pending *sp = NULL; int resv_in_first; - *errno = 0; - /* - * Unless E_EOR mode is on, we must make a send FIT in one call. - */ + *error = 0; + /* Unless E_EOR mode is on, we must make a send FIT in one call. */ if (((user_marks_eor == 0) && non_blocking) && (uio->uio_resid > stcb->sctp_socket->so_snd.sb_hiwat)) { /* It will NEVER fit */ - *errno = EMSGSIZE; + *error = EMSGSIZE; goto out_now; } /* Now can we send this? */ @@ -10358,12 +10427,12 @@ sctp_copy_it_in(struct sctp_tcb *stcb, (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) || (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { /* got data while shutting down */ - *errno = ECONNRESET; + *error = ECONNRESET; goto out_now; } sp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending); if (sp == NULL) { - *errno = ENOMEM; + *error = ENOMEM; goto out_now; } SCTP_INCR_STRMOQ_COUNT(); @@ -10389,8 +10458,8 @@ sctp_copy_it_in(struct sctp_tcb *stcb, sp->some_taken = 0; resv_in_first = sizeof(struct sctp_data_chunk); sp->data = sp->tail_mbuf = NULL; - *errno = sctp_copy_one(sp, uio, resv_in_first); - if (*errno) { + *error = sctp_copy_one(sp, uio, resv_in_first); + if (*error) { sctp_free_a_strmoq(stcb, sp); sp->data = NULL; sp->net = NULL; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 82e6e24023e..820bd98b3ba 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -292,7 +292,7 @@ sctp_add_addr_to_vrf(uint32_t vrfid, void *ifn, uint32_t ifn_index, #endif return (NULL); } - memset(sctp_ifap, 0, sizeof(sctp_ifap)); + memset(sctp_ifap, 0, sizeof(struct sctp_ifa)); sctp_ifap->ifn_p = sctp_ifnp; atomic_add_int(&sctp_ifnp->refcount, 1); diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 8c0be0c32c0..0f90503a030 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -568,6 +568,5 @@ sctp_initiate_iterator(inp_func inpf, struct sctp_inpcb *, uint8_t co_off); - #endif /* _KERNEL */ #endif /* !__sctp_pcb_h__ */ diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 550a8b3115e..82c952ecd30 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#if defined(INET6) +#include +#endif #include #include #include @@ -96,27 +99,9 @@ sctp_pcbinfo_cleanup(void) SCTP_HASH_FREE(sctppcbinfo.sctp_restarthash, sctppcbinfo.hashrestartmark); } -#ifdef INET6 -void -ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip) -{ - bzero(ip6, sizeof(*ip6)); - - ip6->ip6_vfc = IPV6_VERSION; - ip6->ip6_plen = ip->ip_len; - ip6->ip6_nxt = ip->ip_p; - ip6->ip6_hlim = ip->ip_ttl; - ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] = - IPV6_ADDR_INT32_SMP; - ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr; - ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr; -} - -#endif /* INET6 */ - static void -sctp_pathmtu_adustment(struct sctp_inpcb *inp, +sctp_pathmtu_adjustment(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net, uint16_t nxtsz) @@ -219,7 +204,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, } /* now what about the ep? */ if (stcb->asoc.smallest_mtu > nxtsz) { - sctp_pathmtu_adustment(inp, stcb, net, nxtsz); + sctp_pathmtu_adjustment(inp, stcb, net, nxtsz); } if (tmr_stopped) sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); @@ -230,7 +215,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, void sctp_notify(struct sctp_inpcb *inp, - int errno, + int error, struct sctphdr *sh, struct sockaddr *to, struct sctp_tcb *stcb, @@ -247,11 +232,11 @@ sctp_notify(struct sctp_inpcb *inp, } /* FIX ME FIX ME PROTOPT i.e. no SCTP should ALWAYS be an ABORT */ - if ((errno == EHOSTUNREACH) || /* Host is not reachable */ - (errno == EHOSTDOWN) || /* Host is down */ - (errno == ECONNREFUSED) || /* Host refused the connection, (not + if ((error == EHOSTUNREACH) || /* Host is not reachable */ + (error == EHOSTDOWN) || /* Host is down */ + (error == ECONNREFUSED) || /* Host refused the connection, (not * an abort?) */ - (errno == ENOPROTOOPT) /* SCTP is not present on host */ + (error == ENOPROTOOPT) /* SCTP is not present on host */ ) { /* * Hmm reachablity problems we must examine closely. If its @@ -259,7 +244,7 @@ sctp_notify(struct sctp_inpcb *inp, * NO protocol at the other end named SCTP. well we consider * it a OOTB abort. */ - if ((errno == EHOSTUNREACH) || (errno == EHOSTDOWN)) { + if ((error == EHOSTUNREACH) || (error == EHOSTDOWN)) { if (net->dest_state & SCTP_ADDR_REACHABLE) { /* Ok that destination is NOT reachable */ printf("ICMP (thresh %d/%d) takes interface %p down\n", @@ -300,7 +285,7 @@ sctp_notify(struct sctp_inpcb *inp, sctp_log_lock(inp, stcb, SCTP_LOG_LOCK_SOCK); #endif SOCK_LOCK(inp->sctp_socket); - inp->sctp_socket->so_error = errno; + inp->sctp_socket->so_error = error; sctp_sowwakeup(inp, inp->sctp_socket); SOCK_UNLOCK(inp->sctp_socket); } @@ -465,23 +450,16 @@ sctp_must_try_again: #endif sctp_inpcb_free(inp, 1, 0); SOCK_LOCK(so); - so->so_snd.sb_cc = 0; - so->so_snd.sb_mb = NULL; - so->so_snd.sb_mbcnt = 0; - + SCTP_SB_CLEAR(so->so_snd); /* * same for the rcv ones, they are only here for the * accounting/select. */ - so->so_rcv.sb_cc = 0; - so->so_rcv.sb_mb = NULL; - so->so_rcv.sb_mbcnt = 0; - /* - * Now null out the reference, we are completely detached. - */ + SCTP_SB_CLEAR(so->so_rcv); + + /* Now null out the reference, we are completely detached. */ so->so_pcb = NULL; SOCK_UNLOCK(so); - } else { flags = inp->sctp_flags; if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { @@ -506,7 +484,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p) if (inp != 0) { return EINVAL; } - error = soreserve(so, sctp_sendspace, sctp_recvspace); + error = SCTP_SORESERVE(so, sctp_sendspace, sctp_recvspace); if (error) { return error; } @@ -600,20 +578,14 @@ sctp_must_try_again: * the SCTP association. */ SOCK_LOCK(so); - so->so_snd.sb_cc = 0; - so->so_snd.sb_mb = NULL; - so->so_snd.sb_mbcnt = 0; - + SCTP_SB_CLEAR(so->so_snd); /* * same for the rcv ones, they are only here for the * accounting/select. */ - so->so_rcv.sb_cc = 0; - so->so_rcv.sb_mb = NULL; - so->so_rcv.sb_mbcnt = 0; - /* - * Now null out the reference, we are completely detached. - */ + SCTP_SB_CLEAR(so->so_rcv); + + /* Now null out the reference, we are completely detached. */ so->so_pcb = NULL; SOCK_UNLOCK(so); } else { @@ -1349,7 +1321,9 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, SCTP_INP_WUNLOCK(inp); } - vrf_id = SCTP_DEFAULT_VRFID; + /* FIX ME: do we want to pass in a vrf on the connect call? */ + vrf_id = inp->def_vrf_id; + /* We are GOOD to go */ stcb = sctp_aloc_assoc(inp, sa, 1, &error, 0, vrf_id); if (stcb == NULL) { @@ -3066,7 +3040,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) { net->mtu = paddrp->spp_pathmtu; if (net->mtu < stcb->asoc.smallest_mtu) - sctp_pathmtu_adustment(inp, stcb, net, net->mtu); + sctp_pathmtu_adjustment(inp, stcb, net, net->mtu); } } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { @@ -3338,6 +3312,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } /* Is the VRF one we have */ addr_touse = addrs->addr; +#if defined(INET6) if (addrs->addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; @@ -3347,6 +3322,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, addr_touse = (struct sockaddr *)&sin; } } +#endif if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { if (p == NULL) { /* Can't get proc for Net/Open BSD */ @@ -3410,6 +3386,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, break; } addr_touse = addrs->addr; +#if defined(INET6) if (addrs->addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; @@ -3419,6 +3396,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, addr_touse = (struct sockaddr *)&sin; } } +#endif /* * No lock required mgmt_ep_sa does its own locking. * If the FIX: below is ever changed we may need to @@ -3760,6 +3738,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr) struct sockaddr_in *sin; uint32_t vrf_id; struct sctp_inpcb *inp; + struct sctp_ifa *sctp_ifa; /* * Do the malloc first in case it blocks. @@ -3773,8 +3752,6 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr) return ECONNRESET; } SCTP_INP_RLOCK(inp); - struct sctp_ifa *sctp_ifa; - sin->sin_port = inp->sctp_lport; if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 4149ad9981b..0fd0ae758e9 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -252,11 +252,6 @@ __P((struct sctp_inpcb *, int, struct sctphdr *, struct sockaddr *, struct sctp_tcb *, struct sctp_nets *)); -#if defined(INET6) - void ip_2_ip6_hdr __P((struct ip6_hdr *, struct ip *)); - -#endif - int sctp_bindx(struct socket *, int, struct sockaddr_storage *, int, int, struct proc *); diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index cb1c006969b..7fba8883088 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -517,20 +517,13 @@ sctp_must_try_again: #endif sctp_inpcb_free(inp, 1, 0); SOCK_LOCK(so); - so->so_snd.sb_cc = 0; - so->so_snd.sb_mb = NULL; - so->so_snd.sb_mbcnt = 0; - + SCTP_SB_CLEAR(so->so_snd); /* * same for the rcv ones, they are only here for the * accounting/select. */ - so->so_rcv.sb_cc = 0; - so->so_rcv.sb_mb = NULL; - so->so_rcv.sb_mbcnt = 0; - /* - * Now null out the reference, we are completely detached. - */ + SCTP_SB_CLEAR(so->so_rcv); + /* Now null out the reference, we are completely detached. */ so->so_pcb = NULL; SOCK_UNLOCK(so); } else { @@ -554,7 +547,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p) return EINVAL; if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { - error = soreserve(so, sctp_sendspace, sctp_recvspace); + error = SCTP_SORESERVE(so, sctp_sendspace, sctp_recvspace); if (error) return error; } @@ -677,20 +670,13 @@ sctp_must_try_again: * the SCTP association. */ SOCK_LOCK(so); - so->so_snd.sb_cc = 0; - so->so_snd.sb_mb = NULL; - so->so_snd.sb_mbcnt = 0; - + SCTP_SB_CLEAR(so->so_snd); /* * same for the rcv ones, they are only here for the * accounting/select. */ - so->so_rcv.sb_cc = 0; - so->so_rcv.sb_mb = NULL; - so->so_rcv.sb_mbcnt = 0; - /* - * Now null out the reference, we are completely detached. - */ + SCTP_SB_CLEAR(so->so_rcv); + /* Now null out the reference, we are completely detached. */ so->so_pcb = NULL; SOCK_UNLOCK(so); } else { diff --git a/sys/netinet6/sctp6_var.h b/sys/netinet6/sctp6_var.h index 05990703d35..178d987024e 100644 --- a/sys/netinet6/sctp6_var.h +++ b/sys/netinet6/sctp6_var.h @@ -41,11 +41,11 @@ int sctp6_ctloutput __P((struct socket *, struct sockopt *)); int sctp6_input __P((struct mbuf **, int *, int)); - int sctp6_output __P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); void sctp6_ctlinput __P((int, struct sockaddr *, void *)); + #endif /* _KERNEL */ #endif