V_tcp_syncache
cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred);
sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO);
sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO);
if (sc != &scs && !V_tcp_syncache.see_other) {
new = V_tcp_syncache.rexmt_limit;
V_tcp_syncache.rexmt_limit = new;
secbit = V_tcp_syncache.secret.oddeven & 0x1;
secbits = V_tcp_syncache.secret.key[secbit];
secbits = V_tcp_syncache.secret.key[cookie.flags.odd_even];
uma_zfree(V_tcp_syncache.zone, sc);
if (V_tcp_syncache.paused)
V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE;
V_tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT;
mtx_lock(&V_tcp_syncache.pause_mtx);
if (V_tcp_syncache.paused) {
mtx_unlock(&V_tcp_syncache.pause_mtx);
V_tcp_syncache.paused = true;
V_tcp_syncache.rexmt_limit = SYNCACHE_MAXREXMTS;
delta = TCP_SYNCACHE_PAUSE_TIME << V_tcp_syncache.pause_backoff;
if (V_tcp_syncache.pause_until + delta - time_uptime > 0) {
if (V_tcp_syncache.pause_backoff < TCP_SYNCACHE_MAX_BACKOFF) {
V_tcp_syncache.hash_secret = arc4random();
V_tcp_syncache.pause_backoff++;
V_tcp_syncache.pause_backoff = 0;
V_tcp_syncache.pause_until = time_uptime + delta;
callout_reset(&V_tcp_syncache.pause_co, delta * hz, syncache_unpause,
&V_tcp_syncache);
mtx_unlock(&V_tcp_syncache.pause_mtx);
&V_tcp_syncache.hashsize);
&V_tcp_syncache.bucket_limit);
if (!powerof2(V_tcp_syncache.hashsize) ||
V_tcp_syncache.hashsize == 0) {
for (i = 0; i < V_tcp_syncache.hashsize; i++) {
sch = &V_tcp_syncache.hashbase[i];
V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE;
V_tcp_syncache.hashmask = V_tcp_syncache.hashsize - 1;
V_tcp_syncache.cache_limit =
V_tcp_syncache.hashsize * V_tcp_syncache.bucket_limit;
&V_tcp_syncache.cache_limit);
V_tcp_syncache.hashbase = malloc(V_tcp_syncache.hashsize *
V_tcp_syncache.vnet = curvnet;
for (i = 0; i < V_tcp_syncache.hashsize; i++) {
TAILQ_INIT(&V_tcp_syncache.hashbase[i].sch_bucket);
mtx_init(&V_tcp_syncache.hashbase[i].sch_mtx, "tcp_sc_head",
callout_init_mtx(&V_tcp_syncache.hashbase[i].sch_timer,
&V_tcp_syncache.hashbase[i].sch_mtx, 0);
V_tcp_syncache.hashbase[i].sch_length = 0;
V_tcp_syncache.hashbase[i].sch_sc = &V_tcp_syncache;
V_tcp_syncache.hashbase[i].sch_last_overflow =
V_tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache),
V_tcp_syncache.cache_limit = uma_zone_set_max(V_tcp_syncache.zone,
V_tcp_syncache.cache_limit);
callout_init(&V_tcp_syncache.secret.reseed, 1);
arc4rand(V_tcp_syncache.secret.key[0], SYNCOOKIE_SECRET_SIZE, 0);
arc4rand(V_tcp_syncache.secret.key[1], SYNCOOKIE_SECRET_SIZE, 0);
callout_reset(&V_tcp_syncache.secret.reseed, SYNCOOKIE_LIFETIME * hz,
syncookie_reseed, &V_tcp_syncache);
mtx_init(&V_tcp_syncache.pause_mtx, "tcp_sc_pause", NULL, MTX_DEF);
callout_init_mtx(&V_tcp_syncache.pause_co, &V_tcp_syncache.pause_mtx,
V_tcp_syncache.pause_until = time_uptime - TCP_SYNCACHE_PAUSE_TIME;
V_tcp_syncache.pause_backoff = 0;
V_tcp_syncache.paused = false;
callout_drain(&V_tcp_syncache.secret.reseed);
mtx_lock(&V_tcp_syncache.pause_mtx);
if (callout_stop(&V_tcp_syncache.pause_co) == 0) {
mtx_unlock(&V_tcp_syncache.pause_mtx);
callout_drain(&V_tcp_syncache.pause_co);
mtx_unlock(&V_tcp_syncache.pause_mtx);
for (i = 0; i < V_tcp_syncache.hashsize; i++) {
sch = &V_tcp_syncache.hashbase[i];
KASSERT(uma_zone_get_cur(V_tcp_syncache.zone) == 0,
uma_zdestroy(V_tcp_syncache.zone);
free(V_tcp_syncache.hashbase, M_SYNCACHE);
mtx_destroy(&V_tcp_syncache.pause_mtx);
if (sch->sch_length >= V_tcp_syncache.bucket_limit) {
mtx_lock(&V_tcp_syncache.pause_mtx);
paused = V_tcp_syncache.paused;
mtx_unlock(&V_tcp_syncache.pause_mtx);
if (sc->sc_rxmits > V_tcp_syncache.rexmt_limit) {
return ((V_tcp_syncookies && V_tcp_syncache.paused) ||
V_tcp_syncache.hash_secret) & V_tcp_syncache.hashmask;
return (&V_tcp_syncache.hashbase[hash]);