Cleanup the ECN configuration handling and provide an SCTP socket
option for controlling ECN on future associations and get the status on current associations. A simialar pattern will be used for controlling SCTP extensions in upcoming commits.
This commit is contained in:
parent
04cadbc959
commit
f342355a0e
@ -350,6 +350,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size)
|
||||
case SCTP_REMOTE_UDP_ENCAPS_PORT:
|
||||
((struct sctp_udpencaps *)arg)->sue_assoc_id = id;
|
||||
break;
|
||||
case SCTP_ECN_SUPPORTED:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
case SCTP_MAX_BURST:
|
||||
((struct sctp_assoc_value *)arg)->assoc_id = id;
|
||||
break;
|
||||
|
@ -121,6 +121,7 @@ struct sctp_paramhdr {
|
||||
#define SCTP_DEFAULT_PRINFO 0x00000022
|
||||
#define SCTP_PEER_ADDR_THLDS 0x00000023
|
||||
#define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024
|
||||
#define SCTP_ECN_SUPPORTED 0x00000025
|
||||
|
||||
/*
|
||||
* read-only options
|
||||
|
@ -2785,7 +2785,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
inp->sctp_socket = so;
|
||||
inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
|
||||
inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
|
||||
inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable;
|
||||
inp->ecn_supported = (*inp_p)->ecn_supported;
|
||||
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
|
||||
inp->sctp_context = (*inp_p)->sctp_context;
|
||||
inp->local_strreset_support = (*inp_p)->local_strreset_support;
|
||||
@ -5898,7 +5898,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
}
|
||||
/* take care of ecn */
|
||||
if ((data_processed == 1) &&
|
||||
(stcb->asoc.ecn_allowed == 1) &&
|
||||
(stcb->asoc.ecn_supported == 1) &&
|
||||
((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
|
||||
/* Yep, we need to add a ECNE */
|
||||
sctp_send_ecn_echo(stcb, net, high_tsn);
|
||||
|
@ -3914,7 +3914,7 @@ sctp_add_cookie(struct mbuf *init, int init_offset,
|
||||
static uint8_t
|
||||
sctp_get_ect(struct sctp_tcb *stcb)
|
||||
{
|
||||
if ((stcb != NULL) && (stcb->asoc.ecn_allowed == 1)) {
|
||||
if ((stcb != NULL) && (stcb->asoc.ecn_supported == 1)) {
|
||||
return (SCTP_ECT0_BIT);
|
||||
} else {
|
||||
return (0);
|
||||
@ -4785,7 +4785,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* ECN parameter */
|
||||
if (stcb->asoc.ecn_allowed == 1) {
|
||||
if (stcb->asoc.ecn_supported == 1) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_ECN_CAPABLE);
|
||||
@ -5882,8 +5882,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* ECN parameter */
|
||||
if (((asoc != NULL) && (asoc->ecn_allowed == 1)) ||
|
||||
((asoc == NULL) && (inp->sctp_ecn_enable == 1))) {
|
||||
if (((asoc != NULL) && (asoc->ecn_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->ecn_supported == 1))) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_ECN_CAPABLE);
|
||||
|
@ -2483,7 +2483,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
|
||||
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
|
||||
inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
|
||||
inp->sctp_ecn_enable = SCTP_BASE_SYSCTL(sctp_ecn_enable);
|
||||
inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
|
||||
/* init the small hash table we use to track asocid <-> tcb */
|
||||
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
|
||||
if (inp->sctp_asocidhash == NULL) {
|
||||
@ -6081,7 +6081,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sctp_key_t *new_key;
|
||||
uint32_t keylen;
|
||||
int got_random = 0, got_hmacs = 0, got_chklist = 0;
|
||||
uint8_t ecn_allowed;
|
||||
uint8_t ecn_supported;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
@ -6111,7 +6111,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
sa = src;
|
||||
}
|
||||
/* Turn off ECN until we get through all params */
|
||||
ecn_allowed = 0;
|
||||
ecn_supported = 0;
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
/* mark all addresses that we have currently on the list */
|
||||
net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
|
||||
@ -6360,7 +6360,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
} else
|
||||
#endif
|
||||
if (ptype == SCTP_ECN_CAPABLE) {
|
||||
ecn_allowed = 1;
|
||||
ecn_supported = 1;
|
||||
} else if (ptype == SCTP_ULP_ADAPTATION) {
|
||||
if (stcb->asoc.state != SCTP_STATE_OPEN) {
|
||||
struct sctp_adaptation_layer_indication ai,
|
||||
@ -6612,9 +6612,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ecn_allowed == 0) {
|
||||
stcb->asoc.ecn_allowed = 0;
|
||||
}
|
||||
stcb->asoc.ecn_supported &= ecn_supported;
|
||||
/* validate authentication required parameters */
|
||||
if (got_random && got_hmacs) {
|
||||
stcb->asoc.peer_supports_auth = 1;
|
||||
|
@ -406,7 +406,7 @@ struct sctp_inpcb {
|
||||
uint32_t sctp_context;
|
||||
uint8_t local_strreset_support;
|
||||
uint32_t sctp_cmt_on_off;
|
||||
uint32_t sctp_ecn_enable;
|
||||
uint8_t ecn_supported;
|
||||
struct sctp_nonpad_sndrcvinfo def_send;
|
||||
/*-
|
||||
* These three are here for the sosend_dgram
|
||||
|
@ -118,7 +118,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
|
||||
n_inp->sctp_mobility_features = inp->sctp_mobility_features;
|
||||
n_inp->sctp_frag_point = inp->sctp_frag_point;
|
||||
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
|
||||
n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
|
||||
n_inp->ecn_supported = inp->ecn_supported;
|
||||
n_inp->partial_delivery_point = inp->partial_delivery_point;
|
||||
n_inp->sctp_context = inp->sctp_context;
|
||||
n_inp->local_strreset_support = inp->local_strreset_support;
|
||||
|
@ -1151,7 +1151,7 @@ struct sctp_association {
|
||||
*/
|
||||
|
||||
/* Flag to tell if ECN is allowed */
|
||||
uint8_t ecn_allowed;
|
||||
uint8_t ecn_supported;
|
||||
|
||||
/* Did the peer make the stream config (add out) request */
|
||||
uint8_t peer_req_out;
|
||||
|
@ -3294,6 +3294,33 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_ECN_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
|
||||
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
av->assoc_value = stcb->asoc.ecn_supported;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(av->assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_RLOCK(inp);
|
||||
av->assoc_value = inp->ecn_supported;
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
*optsize = sizeof(struct sctp_assoc_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_ENABLE_STREAM_RESET:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
@ -5857,6 +5884,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_ECN_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
|
||||
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(av->assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
if (av->assoc_value == 0) {
|
||||
inp->ecn_supported = 0;
|
||||
} else {
|
||||
inp->ecn_supported = 0;
|
||||
}
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
|
||||
error = ENOPROTOOPT;
|
||||
|
@ -904,7 +904,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
|
||||
asoc->cookie_life = inp->sctp_ep.def_cookie_life;
|
||||
asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
|
||||
asoc->ecn_allowed = inp->sctp_ecn_enable;
|
||||
asoc->ecn_supported = inp->ecn_supported;
|
||||
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
|
||||
asoc->sctp_cmt_pf = (uint8_t) 0;
|
||||
asoc->sctp_frag_point = inp->sctp_frag_point;
|
||||
|
Loading…
Reference in New Issue
Block a user