Add FIB support for SCTP.

This fixes https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=200379

MFC after: 3 days
This commit is contained in:
Michael Tuexen 2015-06-17 15:20:14 +00:00
parent af10bf055f
commit d089f9b915
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284515
12 changed files with 65 additions and 46 deletions

View File

@ -1109,7 +1109,8 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
* not be changed.
*/
SCTP_RTALLOC((sctp_route_t *) & net->ro,
stcb->sctp_ep->def_vrf_id);
stcb->sctp_ep->def_vrf_id,
stcb->sctp_ep->fibnum);
if (net->ro.ro_rt == NULL)
continue;

View File

@ -186,7 +186,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"No listener");
sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
}
goto outnow;
@ -1484,7 +1484,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, "");
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, net->port);
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 2;
@ -1694,7 +1694,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, "");
sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
return (NULL);
}
@ -2572,7 +2572,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
tim = now.tv_usec - cookie->time_entered.tv_usec;
scm->time_usec = htonl(tim);
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
mflowtype, mflowid,
mflowtype, mflowid, l_inp->fibnum,
vrf_id, port);
return (NULL);
}
@ -2794,6 +2794,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
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;
inp->fibnum = (*inp_p)->fibnum;
inp->inp_starting_point_for_iterator = NULL;
/*
* copy in the authentication parameters from the
@ -4404,7 +4405,7 @@ __attribute__((noinline))
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
struct sctp_association *asoc;
@ -4568,7 +4569,7 @@ __attribute__((noinline))
msg);
/* no association, so it's out of the blue... */
sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
*offset = length;
if (locked_tcb) {
@ -4612,7 +4613,7 @@ __attribute__((noinline))
msg);
sctp_handle_ootb(m, iphlen, *offset, src, dst,
sh, inp, op_err,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
return (NULL);
}
@ -5622,7 +5623,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
uint8_t compute_crc,
#endif
uint8_t ecn_bits,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
uint32_t high_tsn;
@ -5701,7 +5702,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2(src, dst, sh,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
goto out;
}
@ -5716,7 +5717,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
"Out of the blue");
sctp_send_abort(m, iphlen, src, dst,
sh, 0, op_err,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
}
}
@ -5775,7 +5776,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
goto out;
}
@ -5786,7 +5787,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
stcb = sctp_process_control(m, iphlen, &offset, length,
src, dst, sh, ch,
inp, stcb, &net, &fwd_tsn_seen,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
if (stcb) {
/*
@ -5827,7 +5828,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
goto out;
}
@ -5899,7 +5900,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
goto out;
/* sa_ignore NOTREACHED */
@ -6023,6 +6024,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
#endif
uint32_t mflowid;
uint8_t mflowtype;
uint16_t fibnum;
iphlen = off;
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
@ -6048,6 +6050,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
mflowid = m->m_pkthdr.flowid;
mflowtype = M_HASHTYPE_GET(m);
fibnum = M_GETFIB(m);
SCTP_STAT_INCR(sctps_recvpackets);
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
@ -6107,7 +6110,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
compute_crc,
#endif
ecn_bits,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
out:
if (m) {

View File

@ -45,7 +45,7 @@ sctp_common_input_processing(struct mbuf **, int, int, int,
uint8_t,
#endif
uint8_t,
uint8_t, uint32_t,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
struct sctp_stream_reset_request *

View File

@ -413,13 +413,8 @@ typedef struct callout sctp_os_timer_t;
typedef struct route sctp_route_t;
typedef struct rtentry sctp_rtentry_t;
/*
* XXX multi-FIB support was backed out in r179783 and it seems clear that the
* VRF support as currently in FreeBSD is not ready to support multi-FIB.
* It might be best to implement multi-FIB support for both v4 and v6 indepedent
* of VRFs and leave those to a real MPLS stack.
*/
#define SCTP_RTALLOC(ro, vrf_id) rtalloc_ign((struct route *)ro, 0UL)
#define SCTP_RTALLOC(ro, vrf_id, fibnum) \
rtalloc_ign_fib((struct route *)ro, 0UL, fibnum)
/* Future zero copy wakeup/send function */
#define SCTP_ZERO_COPY_EVENT(inp, so)

View File

@ -3389,7 +3389,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
/*
* Need a route to cache.
*/
SCTP_RTALLOC(ro, vrf_id);
SCTP_RTALLOC(ro, vrf_id, inp->fibnum);
}
if (ro->ro_rt == NULL) {
return (NULL);
@ -4170,7 +4170,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sctp_free_ifa(_lsrc);
} else {
ip->ip_src = over_addr->sin.sin_addr;
SCTP_RTALLOC(ro, vrf_id);
SCTP_RTALLOC(ro, vrf_id, inp->fibnum);
}
}
if (port) {
@ -4484,7 +4484,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sctp_free_ifa(_lsrc);
} else {
lsa6->sin6_addr = over_addr->sin6.sin6_addr;
SCTP_RTALLOC(ro, vrf_id);
SCTP_RTALLOC(ro, vrf_id, inp->fibnum);
}
(void)sa6_recoverscope(sin6);
}
@ -5511,7 +5511,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Address added");
sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
return;
}
@ -5530,7 +5530,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
sctp_send_abort(init_pkt, iphlen, src, dst, sh,
init_chk->init.initiate_tag, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
return;
}
@ -10839,7 +10839,7 @@ static void
sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, uint32_t vtag,
uint8_t type, struct mbuf *cause,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
struct mbuf *o_pak;
@ -10919,6 +10919,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
SCTP_BUF_RESV_UF(mout, max_linkhdr);
SCTP_BUF_LEN(mout) = len;
SCTP_BUF_NEXT(mout) = cause;
M_SETFIB(mout, fibnum);
mout->m_pkthdr.flowid = mflowid;
M_HASHTYPE_SET(mout, mflowtype);
#ifdef INET
@ -11106,11 +11107,11 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
void
sctp_send_shutdown_complete2(struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
sctp_send_resp_msg(src, dst, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
}
@ -11929,7 +11930,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
void
sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
/* Don't respond to an ABORT with an ABORT. */
@ -11939,7 +11940,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockadd
return;
}
sctp_send_resp_msg(src, dst, sh, vtag, SCTP_ABORT_ASSOCIATION, cause,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
return;
}
@ -11947,11 +11948,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockadd
void
sctp_send_operr_to(struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
sctp_send_resp_msg(src, dst, sh, vtag, SCTP_OPERATION_ERROR, cause,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
return;
}

View File

@ -117,7 +117,7 @@ void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int);
void
sctp_send_shutdown_complete2(struct sockaddr *, struct sockaddr *,
struct sctphdr *,
uint8_t, uint32_t,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
void sctp_send_asconf(struct sctp_tcb *, struct sctp_nets *, int addr_locked);
@ -187,13 +187,13 @@ sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t,
void
sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,
struct sctphdr *, uint32_t, struct mbuf *,
uint8_t, uint32_t,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
void
sctp_send_operr_to(struct sockaddr *, struct sockaddr *,
struct sctphdr *, uint32_t, struct mbuf *,
uint8_t, uint32_t,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
#endif /* _KERNEL || __Userspace__ */

View File

@ -2485,6 +2485,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable);
inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
inp->fibnum = so->so_fibnum;
/* 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) {
@ -3949,7 +3950,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
sin6->sin6_scope_id = 0;
}
#endif
SCTP_RTALLOC((sctp_route_t *) & net->ro, stcb->asoc.vrf_id);
SCTP_RTALLOC((sctp_route_t *) & net->ro,
stcb->asoc.vrf_id,
stcb->sctp_ep->fibnum);
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) {
/* Get source address */

View File

@ -430,6 +430,7 @@ struct sctp_inpcb {
struct mtx inp_rdata_mtx;
int32_t refcount;
uint32_t def_vrf_id;
uint16_t fibnum;
uint32_t total_sends;
uint32_t total_recvs;
uint32_t last_abort_code;

View File

@ -6712,7 +6712,20 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
size_t optsize = 0;
void *p;
int error = 0;
struct sctp_inpcb *inp;
if ((sopt->sopt_level == SOL_SOCKET) &&
(sopt->sopt_name == SO_SETFIB)) {
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
return (EINVAL);
}
SCTP_INP_WLOCK(inp);
inp->fibnum = so->so_fibnum;
SCTP_INP_WUNLOCK(inp);
return (0);
}
if (sopt->sopt_level != IPPROTO_SCTP) {
/* wrong proto level... send back up to IP */
#ifdef INET6

View File

@ -3895,7 +3895,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
}
sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
mflowtype, mflowid,
mflowtype, mflowid, inp->fibnum,
vrf_id, port);
if (stcb != NULL) {
/* Ok, now lets free it */
@ -4051,7 +4051,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_inpcb *inp,
struct mbuf *cause,
uint8_t mflowtype, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
uint32_t vrf_id, uint16_t port)
{
struct sctp_chunkhdr *ch, chunk_buf;
@ -4093,7 +4093,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
return;
case SCTP_SHUTDOWN_ACK:
sctp_send_shutdown_complete2(src, dst, sh,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
return;
default:
@ -4107,7 +4107,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
(contains_init_chunk == 0))) {
sctp_send_abort(m, iphlen, src, dst, sh, 0, cause,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
}
}

View File

@ -208,7 +208,7 @@ sctp_handle_ootb(struct mbuf *, int, int,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_inpcb *,
struct mbuf *,
uint8_t, uint32_t,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
int

View File

@ -84,6 +84,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
#endif
uint32_t mflowid;
uint8_t mflowtype;
uint16_t fibnum;
iphlen = *offp;
if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
@ -109,6 +110,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
mflowid = m->m_pkthdr.flowid;
mflowtype = M_HASHTYPE_GET(m);
fibnum = M_GETFIB(m);
SCTP_STAT_INCR(sctps_recvpackets);
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
@ -169,7 +171,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
compute_crc,
#endif
ecn_bits,
mflowtype, mflowid,
mflowtype, mflowid, fibnum,
vrf_id, port);
out:
if (m) {