Add interface for tcp offload to syncache:
- make neccessary changes to release offload resources when a syncache entry is removed before connection establishment - disable checks for offloaded connection where insufficient information is available Reviewed by: silby
This commit is contained in:
parent
59ef90c02d
commit
dcdbd55c9a
@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <netinet/tcp_timer.h>
|
#include <netinet/tcp_timer.h>
|
||||||
#include <netinet/tcp_var.h>
|
#include <netinet/tcp_var.h>
|
||||||
#include <netinet/tcp_syncache.h>
|
#include <netinet/tcp_syncache.h>
|
||||||
|
#include <netinet/tcp_ofld.h>
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
#include <netinet6/tcp6_var.h>
|
#include <netinet6/tcp6_var.h>
|
||||||
#endif
|
#endif
|
||||||
@ -136,7 +137,8 @@ struct syncache {
|
|||||||
#define SCF_SIGNATURE 0x20 /* send MD5 digests */
|
#define SCF_SIGNATURE 0x20 /* send MD5 digests */
|
||||||
#define SCF_SACK 0x80 /* send SACK option */
|
#define SCF_SACK 0x80 /* send SACK option */
|
||||||
#ifndef DISABLE_TCP_OFFLOAD
|
#ifndef DISABLE_TCP_OFFLOAD
|
||||||
void *sc_pspare[2]; /* toepcb / toe_usrreqs */
|
struct toe_usrreqs *sc_tu; /* TOE operations */
|
||||||
|
void *sc_toepcb; /* TOE protocol block */
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
struct label *sc_label; /* MAC label reference */
|
struct label *sc_label; /* MAC label reference */
|
||||||
@ -356,6 +358,10 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
|
|||||||
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
|
||||||
sch->sch_length--;
|
sch->sch_length--;
|
||||||
|
|
||||||
|
#ifndef DISABLE_TCP_OFFLOAD
|
||||||
|
if (sc->sc_tu)
|
||||||
|
sc->sc_tu->tu_syncache_event(SC_DROP, sc->sc_toepcb);
|
||||||
|
#endif
|
||||||
syncache_free(sc);
|
syncache_free(sc);
|
||||||
tcp_syncache.cache_count--;
|
tcp_syncache.cache_count--;
|
||||||
}
|
}
|
||||||
@ -406,7 +412,6 @@ syncache_timer(void *xsch)
|
|||||||
sch->sch_nextc = sc->sc_rxttime;
|
sch->sch_nextc = sc->sc_rxttime;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->sc_rxmits > tcp_syncache.rexmt_limit) {
|
if (sc->sc_rxmits > tcp_syncache.rexmt_limit) {
|
||||||
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
|
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
|
||||||
log(LOG_DEBUG, "%s; %s: Retransmits exhausted, "
|
log(LOG_DEBUG, "%s; %s: Retransmits exhausted, "
|
||||||
@ -873,7 +878,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
* Segment validation:
|
* Segment validation:
|
||||||
* ACK must match our initial sequence number + 1 (the SYN|ACK).
|
* ACK must match our initial sequence number + 1 (the SYN|ACK).
|
||||||
*/
|
*/
|
||||||
if (th->th_ack != sc->sc_iss + 1) {
|
if (th->th_ack != sc->sc_iss + 1 && sc->sc_toepcb == NULL) {
|
||||||
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
||||||
log(LOG_DEBUG, "%s; %s: ACK %u != ISS+1 %u, segment "
|
log(LOG_DEBUG, "%s; %s: ACK %u != ISS+1 %u, segment "
|
||||||
"rejected\n", s, __func__, th->th_ack, sc->sc_iss);
|
"rejected\n", s, __func__, th->th_ack, sc->sc_iss);
|
||||||
@ -884,7 +889,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
* number + 1 (the SYN) because we didn't ACK any data that
|
* number + 1 (the SYN) because we didn't ACK any data that
|
||||||
* may have come with the SYN.
|
* may have come with the SYN.
|
||||||
*/
|
*/
|
||||||
if (th->th_seq != sc->sc_irs + 1) {
|
if (th->th_seq != sc->sc_irs + 1 && sc->sc_toepcb == NULL) {
|
||||||
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
||||||
log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, segment "
|
log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, segment "
|
||||||
"rejected\n", s, __func__, th->th_seq, sc->sc_irs);
|
"rejected\n", s, __func__, th->th_seq, sc->sc_irs);
|
||||||
@ -901,7 +906,8 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
* If timestamps were negotiated the reflected timestamp
|
* If timestamps were negotiated the reflected timestamp
|
||||||
* must be equal to what we actually sent in the SYN|ACK.
|
* must be equal to what we actually sent in the SYN|ACK.
|
||||||
*/
|
*/
|
||||||
if ((to->to_flags & TOF_TS) && to->to_tsecr != sc->sc_ts) {
|
if ((to->to_flags & TOF_TS) && to->to_tsecr != sc->sc_ts &&
|
||||||
|
sc->sc_toepcb == NULL) {
|
||||||
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
|
||||||
log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, "
|
log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, "
|
||||||
"segment rejected\n",
|
"segment rejected\n",
|
||||||
@ -941,9 +947,10 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
* consume all available buffer space if it were ACKed. By not ACKing
|
* consume all available buffer space if it were ACKed. By not ACKing
|
||||||
* the data, we avoid this DoS scenario.
|
* the data, we avoid this DoS scenario.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
_syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
||||||
struct inpcb *inp, struct socket **lsop, struct mbuf *m)
|
struct inpcb *inp, struct socket **lsop, struct mbuf *m,
|
||||||
|
struct toe_usrreqs *tu, void *toepcb)
|
||||||
{
|
{
|
||||||
struct tcpcb *tp;
|
struct tcpcb *tp;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
@ -1021,6 +1028,11 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
sc = syncache_lookup(inc, &sch); /* returns locked entry */
|
sc = syncache_lookup(inc, &sch); /* returns locked entry */
|
||||||
SCH_LOCK_ASSERT(sch);
|
SCH_LOCK_ASSERT(sch);
|
||||||
if (sc != NULL) {
|
if (sc != NULL) {
|
||||||
|
#ifndef DISABLE_TCP_OFFLOAD
|
||||||
|
if (sc->sc_tu)
|
||||||
|
sc->sc_tu->tu_syncache_event(SC_ENTRY_PRESENT,
|
||||||
|
sc->sc_toepcb);
|
||||||
|
#endif
|
||||||
tcpstat.tcps_sc_dupsyn++;
|
tcpstat.tcps_sc_dupsyn++;
|
||||||
if (ipopts) {
|
if (ipopts) {
|
||||||
/*
|
/*
|
||||||
@ -1055,7 +1067,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
s, __func__);
|
s, __func__);
|
||||||
free(s, M_TCPLOG);
|
free(s, M_TCPLOG);
|
||||||
}
|
}
|
||||||
if (syncache_respond(sc) == 0) {
|
if ((sc->sc_toepcb == NULL) && syncache_respond(sc) == 0) {
|
||||||
sc->sc_rxmits = 0;
|
sc->sc_rxmits = 0;
|
||||||
syncache_timeout(sc, sch, 1);
|
syncache_timeout(sc, sch, 1);
|
||||||
tcpstat.tcps_sndacks++;
|
tcpstat.tcps_sndacks++;
|
||||||
@ -1088,7 +1100,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in the syncache values.
|
* Fill in the syncache values.
|
||||||
*/
|
*/
|
||||||
@ -1104,7 +1116,10 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
sc->sc_ip_tos = ip_tos;
|
sc->sc_ip_tos = ip_tos;
|
||||||
sc->sc_ip_ttl = ip_ttl;
|
sc->sc_ip_ttl = ip_ttl;
|
||||||
}
|
}
|
||||||
|
#ifndef DISABLE_TCP_OFFLOAD
|
||||||
|
sc->sc_tu = tu;
|
||||||
|
sc->sc_toepcb = toepcb;
|
||||||
|
#endif
|
||||||
sc->sc_irs = th->th_seq;
|
sc->sc_irs = th->th_seq;
|
||||||
sc->sc_iss = arc4random();
|
sc->sc_iss = arc4random();
|
||||||
sc->sc_flags = 0;
|
sc->sc_flags = 0;
|
||||||
@ -1196,7 +1211,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
/*
|
/*
|
||||||
* Do a standard 3-way handshake.
|
* Do a standard 3-way handshake.
|
||||||
*/
|
*/
|
||||||
if (syncache_respond(sc) == 0) {
|
if (sc->sc_toepcb || syncache_respond(sc) == 0) {
|
||||||
if (tcp_syncookies && tcp_syncookiesonly && sc != &scs)
|
if (tcp_syncookies && tcp_syncookiesonly && sc != &scs)
|
||||||
syncache_free(sc);
|
syncache_free(sc);
|
||||||
else if (sc != &scs)
|
else if (sc != &scs)
|
||||||
@ -1214,8 +1229,11 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
|||||||
if (sc == &scs)
|
if (sc == &scs)
|
||||||
mac_syncache_destroy(&maclabel);
|
mac_syncache_destroy(&maclabel);
|
||||||
#endif
|
#endif
|
||||||
*lsop = NULL;
|
if (m) {
|
||||||
m_freem(m);
|
|
||||||
|
*lsop = NULL;
|
||||||
|
m_freem(m);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1374,6 +1392,21 @@ syncache_respond(struct syncache *sc)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
||||||
|
struct inpcb *inp, struct socket **lsop, struct mbuf *m)
|
||||||
|
{
|
||||||
|
_syncache_add(inc, to, th, inp, lsop, m, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syncache_offload_add(struct in_conninfo *inc, struct tcpopt *to,
|
||||||
|
struct tcphdr *th, struct inpcb *inp, struct socket **lsop,
|
||||||
|
struct toe_usrreqs *tu, void *toepcb)
|
||||||
|
{
|
||||||
|
_syncache_add(inc, to, th, inp, lsop, NULL, tu, toepcb);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The purpose of SYN cookies is to avoid keeping track of all SYN's we
|
* The purpose of SYN cookies is to avoid keeping track of all SYN's we
|
||||||
* receive and to be able to handle SYN floods from bogus source addresses
|
* receive and to be able to handle SYN floods from bogus source addresses
|
||||||
@ -1699,4 +1732,3 @@ syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported)
|
|||||||
*pcbs_exported = count;
|
*pcbs_exported = count;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,9 @@ int syncache_expand(struct in_conninfo *, struct tcpopt *,
|
|||||||
struct tcphdr *, struct socket **, struct mbuf *);
|
struct tcphdr *, struct socket **, struct mbuf *);
|
||||||
void syncache_add(struct in_conninfo *, struct tcpopt *,
|
void syncache_add(struct in_conninfo *, struct tcpopt *,
|
||||||
struct tcphdr *, struct inpcb *, struct socket **, struct mbuf *);
|
struct tcphdr *, struct inpcb *, struct socket **, struct mbuf *);
|
||||||
|
void syncache_offload_add(struct in_conninfo *, struct tcpopt *,
|
||||||
|
struct tcphdr *, struct inpcb *, struct socket **,
|
||||||
|
struct toe_usrreqs *tu, void *toepcb);
|
||||||
void syncache_chkrst(struct in_conninfo *, struct tcphdr *);
|
void syncache_chkrst(struct in_conninfo *, struct tcphdr *);
|
||||||
void syncache_badack(struct in_conninfo *);
|
void syncache_badack(struct in_conninfo *);
|
||||||
int syncache_pcbcount(void);
|
int syncache_pcbcount(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user