| 244 | } |
| 245 | |
| 246 | void |
| 247 | syncache_init(void) |
| 248 | { |
| 249 | int i; |
| 250 | |
| 251 | V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; |
| 252 | V_tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT; |
| 253 | V_tcp_syncache.rexmt_limit = SYNCACHE_MAXREXMTS; |
| 254 | V_tcp_syncache.hash_secret = arc4random(); |
| 255 | |
| 256 | TUNABLE_INT_FETCH("net.inet.tcp.syncache.hashsize", |
| 257 | &V_tcp_syncache.hashsize); |
| 258 | TUNABLE_INT_FETCH("net.inet.tcp.syncache.bucketlimit", |
| 259 | &V_tcp_syncache.bucket_limit); |
| 260 | if (!powerof2(V_tcp_syncache.hashsize) || |
| 261 | V_tcp_syncache.hashsize == 0) { |
| 262 | printf("WARNING: syncache hash size is not a power of 2.\n"); |
| 263 | V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; |
| 264 | } |
| 265 | V_tcp_syncache.hashmask = V_tcp_syncache.hashsize - 1; |
| 266 | |
| 267 | /* Set limits. */ |
| 268 | V_tcp_syncache.cache_limit = |
| 269 | V_tcp_syncache.hashsize * V_tcp_syncache.bucket_limit; |
| 270 | TUNABLE_INT_FETCH("net.inet.tcp.syncache.cachelimit", |
| 271 | &V_tcp_syncache.cache_limit); |
| 272 | |
| 273 | /* Allocate the hash table. */ |
| 274 | V_tcp_syncache.hashbase = malloc(V_tcp_syncache.hashsize * |
| 275 | sizeof(struct syncache_head), M_SYNCACHE, M_WAITOK | M_ZERO); |
| 276 | |
| 277 | #ifdef VIMAGE |
| 278 | V_tcp_syncache.vnet = curvnet; |
| 279 | #endif |
| 280 | |
| 281 | /* Initialize the hash buckets. */ |
| 282 | for (i = 0; i < V_tcp_syncache.hashsize; i++) { |
| 283 | TAILQ_INIT(&V_tcp_syncache.hashbase[i].sch_bucket); |
| 284 | mtx_init(&V_tcp_syncache.hashbase[i].sch_mtx, "tcp_sc_head", |
| 285 | NULL, MTX_DEF); |
| 286 | callout_init_mtx(&V_tcp_syncache.hashbase[i].sch_timer, |
| 287 | &V_tcp_syncache.hashbase[i].sch_mtx, 0); |
| 288 | V_tcp_syncache.hashbase[i].sch_length = 0; |
| 289 | V_tcp_syncache.hashbase[i].sch_sc = &V_tcp_syncache; |
| 290 | V_tcp_syncache.hashbase[i].sch_last_overflow = |
| 291 | -(SYNCOOKIE_LIFETIME + 1); |
| 292 | } |
| 293 | |
| 294 | /* Create the syncache entry zone. */ |
| 295 | V_tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache), |
| 296 | NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); |
| 297 | V_tcp_syncache.cache_limit = uma_zone_set_max(V_tcp_syncache.zone, |
| 298 | V_tcp_syncache.cache_limit); |
| 299 | |
| 300 | /* Start the SYN cookie reseeder callout. */ |
| 301 | callout_init(&V_tcp_syncache.secret.reseed, 1); |
| 302 | arc4rand(V_tcp_syncache.secret.key[0], SYNCOOKIE_SECRET_SIZE, 0); |
| 303 | arc4rand(V_tcp_syncache.secret.key[1], SYNCOOKIE_SECRET_SIZE, 0); |
no test coverage detected