summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2014-08-22 20:08:50 +0000
committertuexen <tuexen@FreeBSD.org>2014-08-22 20:08:50 +0000
commit5a4252e3c473170a493004da8e482390b54ddedd (patch)
tree300a64dfd6390b1eb5172ba04ae10a5d561e40cf /sys/netinet
parent94e8309da0a98cd328fb5723308f6b1faaf4af51 (diff)
downloadFreeBSD-src-5a4252e3c473170a493004da8e482390b54ddedd.zip
FreeBSD-src-5a4252e3c473170a493004da8e482390b54ddedd.tar.gz
MFC r269481:
Add support for the SCTP_PKTDROP_SUPPORTED socket option and the corresponding sysctl variable. The default is off, since the specification is not an RFC yet.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp.h1
-rw-r--r--sys/netinet/sctp_input.c1
-rw-r--r--sys/netinet/sctp_output.c11
-rw-r--r--sys/netinet/sctp_pcb.c7
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_peeloff.c1
-rw-r--r--sys/netinet/sctp_structs.h6
-rw-r--r--sys/netinet/sctp_sysctl.c6
-rw-r--r--sys/netinet/sctp_sysctl.h6
-rw-r--r--sys/netinet/sctp_usrreq.c56
-rw-r--r--sys/netinet/sctputil.c2
11 files changed, 87 insertions, 11 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index c74c5f4..da13cab 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -124,6 +124,7 @@ struct sctp_paramhdr {
#define SCTP_ECN_SUPPORTED 0x00000025
#define SCTP_PR_SUPPORTED 0x00000026
#define SCTP_NRSACK_SUPPORTED 0x00000027
+#define SCTP_PKTDROP_SUPPORTED 0x00000028
/*
* read-only options
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index a15e352..b7f533a 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2788,6 +2788,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
inp->ecn_supported = (*inp_p)->ecn_supported;
inp->prsctp_supported = (*inp_p)->prsctp_supported;
inp->nrsack_supported = (*inp_p)->nrsack_supported;
+ inp->pktdrop_supported = (*inp_p)->pktdrop_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;
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 4e5e8f1..6edabc1 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -4817,7 +4817,9 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
if (stcb->asoc.prsctp_supported == 1) {
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
}
- pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+ if (stcb->asoc.pktdrop_supported == 1) {
+ pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+ }
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
@@ -5920,7 +5922,10 @@ do_a_abort:
((asoc == NULL) && (inp->prsctp_supported == 1))) {
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
}
- pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+ if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
+ ((asoc == NULL) && (inp->pktdrop_supported == 1))) {
+ pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+ }
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
@@ -11399,7 +11404,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
}
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
- if (asoc->peer_supports_pktdrop == 0) {
+ if (asoc->pktdrop_supported == 0) {
/*-
* peer must declare support before I send one.
*/
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 4051dae..11f0793 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2486,6 +2486,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable);
inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
+ inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_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) {
@@ -6086,6 +6087,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
uint8_t ecn_supported;
uint8_t prsctp_supported;
uint8_t nrsack_supported;
+ uint8_t pktdrop_supported;
#ifdef INET
struct sockaddr_in sin;
@@ -6118,6 +6120,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
ecn_supported = 0;
prsctp_supported = 0;
nrsack_supported = 0;
+ pktdrop_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;
@@ -6455,7 +6458,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-25);
}
stcb->asoc.peer_supports_asconf = 0;
- stcb->asoc.peer_supports_pktdrop = 0;
stcb->asoc.peer_supports_strreset = 0;
stcb->asoc.peer_supports_auth = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
@@ -6470,7 +6472,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
prsctp_supported = 1;
break;
case SCTP_PACKET_DROPPED:
- stcb->asoc.peer_supports_pktdrop = 1;
+ pktdrop_supported = 1;
break;
case SCTP_NR_SELECTIVE_ACK:
nrsack_supported = 1;
@@ -6619,6 +6621,7 @@ next_param:
stcb->asoc.ecn_supported &= ecn_supported;
stcb->asoc.prsctp_supported &= prsctp_supported;
stcb->asoc.nrsack_supported &= nrsack_supported;
+ stcb->asoc.pktdrop_supported &= pktdrop_supported;
/* validate authentication required parameters */
if (got_random && got_hmacs) {
stcb->asoc.peer_supports_auth = 1;
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index deaca24..30e35f8 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -409,6 +409,7 @@ struct sctp_inpcb {
uint8_t ecn_supported;
uint8_t prsctp_supported;
uint8_t nrsack_supported;
+ uint8_t pktdrop_supported;
struct sctp_nonpad_sndrcvinfo def_send;
/*-
* These three are here for the sosend_dgram
diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c
index b1ea310..2aa691d 100644
--- a/sys/netinet/sctp_peeloff.c
+++ b/sys/netinet/sctp_peeloff.c
@@ -121,6 +121,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
n_inp->ecn_supported = inp->ecn_supported;
n_inp->prsctp_supported = inp->prsctp_supported;
n_inp->nrsack_supported = inp->nrsack_supported;
+ n_inp->pktdrop_supported = inp->pktdrop_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;
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index d3200df..29a9d89 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -1154,6 +1154,7 @@ struct sctp_association {
uint8_t ecn_supported;
uint8_t prsctp_supported;
uint8_t nrsack_supported;
+ uint8_t pktdrop_supported;
/* Did the peer make the stream config (add out) request */
uint8_t peer_req_out;
@@ -1167,11 +1168,6 @@ struct sctp_association {
uint8_t local_strreset_support;
uint8_t peer_supports_nat;
- /*
- * packet drop's are supported by the peer, we don't really care
- * about this but we bookkeep it anyway.
- */
- uint8_t peer_supports_pktdrop;
struct sctp_scoping scope;
/* flags to handle send alternate net tracking */
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index dd3074f..908cd4c 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -57,6 +57,7 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
@@ -604,6 +605,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pr_enable), SCTPCTL_PR_ENABLE_MIN, SCTPCTL_PR_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nrsack_enable), SCTPCTL_NRSACK_ENABLE_MIN, SCTPCTL_NRSACK_ENABLE_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_pktdrop_enable), SCTPCTL_PKTDROP_ENABLE_MIN, SCTPCTL_PKTDROP_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
@@ -871,6 +873,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_UINT | CTLFLA
&SCTP_BASE_SYSCTL(sctp_nrsack_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_NRSACK_ENABLE_DESC);
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pktdrop_enable, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_pktdrop_enable), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_PKTDROP_ENABLE_DESC);
+
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_SACKS_DESC);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 3f16279..741d031 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -47,6 +47,7 @@ struct sctp_sysctl {
uint32_t sctp_ecn_enable;
uint32_t sctp_pr_enable;
uint32_t sctp_nrsack_enable;
+ uint32_t sctp_pktdrop_enable;
uint32_t sctp_fr_max_burst_default;
uint32_t sctp_strict_sacks;
uint32_t sctp_peer_chunk_oh;
@@ -166,6 +167,11 @@ struct sctp_sysctl {
#define SCTPCTL_NRSACK_ENABLE_MAX 1
#define SCTPCTL_NRSACK_ENABLE_DEFAULT 0
+/* pktdrop_enable: Enable SCTP Packet Drop Reports */
+#define SCTPCTL_PKTDROP_ENABLE_DESC "Enable SCTP PKTDROP"
+#define SCTPCTL_PKTDROP_ENABLE_MIN 0
+#define SCTPCTL_PKTDROP_ENABLE_MAX 1
+#define SCTPCTL_PKTDROP_ENABLE_DEFAULT 0
/* strict_sacks: Enable SCTP Strict SACK checking */
#define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking"
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 806094b..7f2e6ee 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -3375,6 +3375,33 @@ flags_out:
}
break;
}
+ case SCTP_PKTDROP_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.pktdrop_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->pktdrop_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;
@@ -6025,6 +6052,35 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
}
+ case SCTP_PKTDROP_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->pktdrop_supported = 0;
+ } else {
+ inp->pktdrop_supported = 1;
+ }
+ 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;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 14cd62b..1c83177 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -907,6 +907,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->ecn_supported = inp->ecn_supported;
asoc->prsctp_supported = inp->prsctp_supported;
asoc->nrsack_supported = inp->nrsack_supported;
+ asoc->pktdrop_supported = inp->pktdrop_supported;
asoc->sctp_cmt_pf = (uint8_t) 0;
asoc->sctp_frag_point = inp->sctp_frag_point;
asoc->sctp_features = inp->sctp_features;
@@ -952,7 +953,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_select_initial_TSN(&inp->sctp_ep);
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
/* we are optimisitic here */
- asoc->peer_supports_pktdrop = 1;
asoc->peer_supports_nat = 0;
asoc->sent_queue_retran_cnt = 0;
OpenPOWER on IntegriCloud