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:
kmacy 2007-12-12 20:35:59 +00:00
parent 59ef90c02d
commit dcdbd55c9a
2 changed files with 50 additions and 15 deletions

View File

@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_syncache.h>
#include <netinet/tcp_ofld.h>
#ifdef INET6
#include <netinet6/tcp6_var.h>
#endif
@ -136,7 +137,8 @@ struct syncache {
#define SCF_SIGNATURE 0x20 /* send MD5 digests */
#define SCF_SACK 0x80 /* send SACK option */
#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
#ifdef MAC
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);
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);
tcp_syncache.cache_count--;
}
@ -406,7 +412,6 @@ syncache_timer(void *xsch)
sch->sch_nextc = sc->sc_rxttime;
continue;
}
if (sc->sc_rxmits > tcp_syncache.rexmt_limit) {
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
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:
* 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)))
log(LOG_DEBUG, "%s; %s: ACK %u != ISS+1 %u, segment "
"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
* 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)))
log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, segment "
"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
* 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)))
log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, "
"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
* the data, we avoid this DoS scenario.
*/
void
syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct inpcb *inp, struct socket **lsop, struct mbuf *m)
static void
_syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct inpcb *inp, struct socket **lsop, struct mbuf *m,
struct toe_usrreqs *tu, void *toepcb)
{
struct tcpcb *tp;
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 */
SCH_LOCK_ASSERT(sch);
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++;
if (ipopts) {
/*
@ -1055,7 +1067,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
s, __func__);
free(s, M_TCPLOG);
}
if (syncache_respond(sc) == 0) {
if ((sc->sc_toepcb == NULL) && syncache_respond(sc) == 0) {
sc->sc_rxmits = 0;
syncache_timeout(sc, sch, 1);
tcpstat.tcps_sndacks++;
@ -1088,7 +1100,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
}
/*
* 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_ttl = ip_ttl;
}
#ifndef DISABLE_TCP_OFFLOAD
sc->sc_tu = tu;
sc->sc_toepcb = toepcb;
#endif
sc->sc_irs = th->th_seq;
sc->sc_iss = arc4random();
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.
*/
if (syncache_respond(sc) == 0) {
if (sc->sc_toepcb || syncache_respond(sc) == 0) {
if (tcp_syncookies && tcp_syncookiesonly && sc != &scs)
syncache_free(sc);
else if (sc != &scs)
@ -1214,8 +1229,11 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (sc == &scs)
mac_syncache_destroy(&maclabel);
#endif
*lsop = NULL;
m_freem(m);
if (m) {
*lsop = NULL;
m_freem(m);
}
return;
}
@ -1374,6 +1392,21 @@ syncache_respond(struct syncache *sc)
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
* 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;
return error;
}

View File

@ -40,6 +40,9 @@ int syncache_expand(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct socket **, struct mbuf *);
void syncache_add(struct in_conninfo *, struct tcpopt *,
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_badack(struct in_conninfo *);
int syncache_pcbcount(void);