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_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;
} }

View File

@ -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);