Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/ipfw/ip_fw_dynamic.c
Show First 20 Lines • Show All 2,576 Lines • ▼ Show 20 Lines | dyn_send_keepalive_ipv6(struct ip_fw_chain *chain) | ||||
} | } | ||||
IPFW_UH_RUNLOCK(chain); | IPFW_UH_RUNLOCK(chain); | ||||
while ((m = mbufq_dequeue(&q)) != NULL) | while ((m = mbufq_dequeue(&q)) != NULL) | ||||
ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); | ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
static void | static void | ||||
dyn_grow_hashtable(struct ip_fw_chain *chain, uint32_t new) | dyn_grow_hashtable(struct ip_fw_chain *chain, uint32_t new, int flags) | ||||
{ | { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct dyn_ipv6ck_slist *ipv6, *ipv6_parent; | struct dyn_ipv6ck_slist *ipv6, *ipv6_parent; | ||||
uint32_t *ipv6_add, *ipv6_del, *ipv6_parent_add, *ipv6_parent_del; | uint32_t *ipv6_add, *ipv6_del, *ipv6_parent_add, *ipv6_parent_del; | ||||
struct dyn_ipv6_state *s6; | struct dyn_ipv6_state *s6; | ||||
#endif | #endif | ||||
struct dyn_ipv4ck_slist *ipv4, *ipv4_parent; | struct dyn_ipv4ck_slist *ipv4, *ipv4_parent; | ||||
uint32_t *ipv4_add, *ipv4_del, *ipv4_parent_add, *ipv4_parent_del; | uint32_t *ipv4_add, *ipv4_del, *ipv4_parent_add, *ipv4_parent_del; | ||||
struct dyn_ipv4_state *s4; | struct dyn_ipv4_state *s4; | ||||
struct mtx *bucket_lock; | struct mtx *bucket_lock; | ||||
void *tmp; | void *tmp; | ||||
uint32_t bucket; | uint32_t bucket; | ||||
MPASS(powerof2(new)); | MPASS(powerof2(new)); | ||||
DYN_DEBUG("grow hash size %u -> %u", V_curr_dyn_buckets, new); | DYN_DEBUG("grow hash size %u -> %u", V_curr_dyn_buckets, new); | ||||
/* | /* | ||||
* Allocate and initialize new lists. | * Allocate and initialize new lists. | ||||
* XXXAE: on memory pressure this can disable callout timer. | |||||
*/ | */ | ||||
bucket_lock = malloc(new * sizeof(struct mtx), M_IPFW, | bucket_lock = malloc(new * sizeof(struct mtx), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (bucket_lock == NULL) | |||||
return; | |||||
ipv4 = ipv4_parent = NULL; | |||||
ipv4_add = ipv4_del = ipv4_parent_add = ipv4_parent_del = NULL; | |||||
#ifdef INET6 | |||||
ipv6 = ipv6_parent = NULL; | |||||
ipv6_add = ipv6_del = ipv6_parent_add = ipv6_parent_del = NULL; | |||||
#endif | |||||
ipv4 = malloc(new * sizeof(struct dyn_ipv4ck_slist), M_IPFW, | ipv4 = malloc(new * sizeof(struct dyn_ipv4ck_slist), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv4 == NULL) | |||||
goto bad; | |||||
ipv4_parent = malloc(new * sizeof(struct dyn_ipv4ck_slist), M_IPFW, | ipv4_parent = malloc(new * sizeof(struct dyn_ipv4ck_slist), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
ipv4_add = malloc(new * sizeof(uint32_t), M_IPFW, M_WAITOK | M_ZERO); | if (ipv4_parent == NULL) | ||||
ipv4_del = malloc(new * sizeof(uint32_t), M_IPFW, M_WAITOK | M_ZERO); | goto bad; | ||||
ipv4_add = malloc(new * sizeof(uint32_t), M_IPFW, flags | M_ZERO); | |||||
if (ipv4_add == NULL) | |||||
goto bad; | |||||
ipv4_del = malloc(new * sizeof(uint32_t), M_IPFW, flags | M_ZERO); | |||||
if (ipv4_del == NULL) | |||||
goto bad; | |||||
ipv4_parent_add = malloc(new * sizeof(uint32_t), M_IPFW, | ipv4_parent_add = malloc(new * sizeof(uint32_t), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv4_parent_add == NULL) | |||||
goto bad; | |||||
ipv4_parent_del = malloc(new * sizeof(uint32_t), M_IPFW, | ipv4_parent_del = malloc(new * sizeof(uint32_t), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv4_parent_del == NULL) | |||||
goto bad; | |||||
#ifdef INET6 | #ifdef INET6 | ||||
ipv6 = malloc(new * sizeof(struct dyn_ipv6ck_slist), M_IPFW, | ipv6 = malloc(new * sizeof(struct dyn_ipv6ck_slist), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv6 == NULL) | |||||
goto bad; | |||||
ipv6_parent = malloc(new * sizeof(struct dyn_ipv6ck_slist), M_IPFW, | ipv6_parent = malloc(new * sizeof(struct dyn_ipv6ck_slist), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
ipv6_add = malloc(new * sizeof(uint32_t), M_IPFW, M_WAITOK | M_ZERO); | if (ipv6_parent == NULL) | ||||
ipv6_del = malloc(new * sizeof(uint32_t), M_IPFW, M_WAITOK | M_ZERO); | goto bad; | ||||
ipv6_add = malloc(new * sizeof(uint32_t), M_IPFW, flags | M_ZERO); | |||||
if (ipv6_add == NULL) | |||||
goto bad; | |||||
ipv6_del = malloc(new * sizeof(uint32_t), M_IPFW, flags | M_ZERO); | |||||
if (ipv6_add == NULL) | |||||
goto bad; | |||||
ipv6_parent_add = malloc(new * sizeof(uint32_t), M_IPFW, | ipv6_parent_add = malloc(new * sizeof(uint32_t), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv6_parent_add == NULL) | |||||
goto bad; | |||||
ipv6_parent_del = malloc(new * sizeof(uint32_t), M_IPFW, | ipv6_parent_del = malloc(new * sizeof(uint32_t), M_IPFW, | ||||
M_WAITOK | M_ZERO); | flags | M_ZERO); | ||||
if (ipv6_parent_del == NULL) | |||||
goto bad; | |||||
#endif | #endif | ||||
for (bucket = 0; bucket < new; bucket++) { | for (bucket = 0; bucket < new; bucket++) { | ||||
DYN_BUCKET_LOCK_INIT(bucket_lock, bucket); | DYN_BUCKET_LOCK_INIT(bucket_lock, bucket); | ||||
CK_SLIST_INIT(&ipv4[bucket]); | CK_SLIST_INIT(&ipv4[bucket]); | ||||
CK_SLIST_INIT(&ipv4_parent[bucket]); | CK_SLIST_INIT(&ipv4_parent[bucket]); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
CK_SLIST_INIT(&ipv6[bucket]); | CK_SLIST_INIT(&ipv6[bucket]); | ||||
CK_SLIST_INIT(&ipv6_parent[bucket]); | CK_SLIST_INIT(&ipv6_parent[bucket]); | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | #endif | ||||
V_curr_dyn_buckets = new; | V_curr_dyn_buckets = new; | ||||
IPFW_WUNLOCK(chain); | IPFW_WUNLOCK(chain); | ||||
IPFW_UH_WUNLOCK(chain); | IPFW_UH_WUNLOCK(chain); | ||||
/* Release old resources */ | /* Release old resources */ | ||||
while (bucket-- != 0) | while (bucket-- != 0) | ||||
DYN_BUCKET_LOCK_DESTROY(bucket_lock, bucket); | DYN_BUCKET_LOCK_DESTROY(bucket_lock, bucket); | ||||
bad: | |||||
free(bucket_lock, M_IPFW); | free(bucket_lock, M_IPFW); | ||||
free(ipv4, M_IPFW); | free(ipv4, M_IPFW); | ||||
free(ipv4_parent, M_IPFW); | free(ipv4_parent, M_IPFW); | ||||
free(ipv4_add, M_IPFW); | free(ipv4_add, M_IPFW); | ||||
free(ipv4_parent_add, M_IPFW); | free(ipv4_parent_add, M_IPFW); | ||||
free(ipv4_del, M_IPFW); | free(ipv4_del, M_IPFW); | ||||
free(ipv4_parent_del, M_IPFW); | free(ipv4_parent_del, M_IPFW); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | #endif | ||||
* than current states count. | * than current states count. | ||||
*/ | */ | ||||
if (V_curr_dyn_buckets < V_dyn_buckets_max && | if (V_curr_dyn_buckets < V_dyn_buckets_max && | ||||
(V_curr_dyn_buckets < V_dyn_count / 2 || ( | (V_curr_dyn_buckets < V_dyn_count / 2 || ( | ||||
V_curr_dyn_buckets < V_dyn_count && V_curr_max_length > 8))) { | V_curr_dyn_buckets < V_dyn_count && V_curr_max_length > 8))) { | ||||
buckets = 1 << fls(V_dyn_count); | buckets = 1 << fls(V_dyn_count); | ||||
if (buckets > V_dyn_buckets_max) | if (buckets > V_dyn_buckets_max) | ||||
buckets = V_dyn_buckets_max; | buckets = V_dyn_buckets_max; | ||||
dyn_grow_hashtable(&V_layer3_chain, buckets); | dyn_grow_hashtable(&V_layer3_chain, buckets, M_NOWAIT); | ||||
} | } | ||||
callout_reset_on(&V_dyn_timeout, hz, dyn_tick, vnetx, 0); | callout_reset_on(&V_dyn_timeout, hz, dyn_tick, vnetx, 0); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | void | ||||
ipfw_expire_dyn_states(struct ip_fw_chain *chain, ipfw_range_tlv *rt) | ipfw_expire_dyn_states(struct ip_fw_chain *chain, ipfw_range_tlv *rt) | ||||
▲ Show 20 Lines • Show All 408 Lines • ▼ Show 20 Lines | #ifdef INET6 | ||||
V_dyn_ipv6_zone = uma_zcreate("IPFW IPv6 dynamic states", | V_dyn_ipv6_zone = uma_zcreate("IPFW IPv6 dynamic states", | ||||
sizeof(struct dyn_ipv6_state), NULL, NULL, NULL, NULL, | sizeof(struct dyn_ipv6_state), NULL, NULL, NULL, NULL, | ||||
UMA_ALIGN_PTR, 0); | UMA_ALIGN_PTR, 0); | ||||
#endif | #endif | ||||
/* Initialize buckets. */ | /* Initialize buckets. */ | ||||
V_curr_dyn_buckets = 0; | V_curr_dyn_buckets = 0; | ||||
V_dyn_bucket_lock = NULL; | V_dyn_bucket_lock = NULL; | ||||
dyn_grow_hashtable(chain, 256); | dyn_grow_hashtable(chain, 256, M_WAITOK); | ||||
freebsd_igalic.co: why is it okay to wait here | |||||
Done Inline ActionsIt is initialization code, it is called from userland when you are doing kldload, user can wait. ae: It is initialization code, it is called from userland when you are doing kldload, user can wait. | |||||
if (IS_DEFAULT_VNET(curvnet)) | if (IS_DEFAULT_VNET(curvnet)) | ||||
dyn_hp_cache = malloc(mp_ncpus * sizeof(void *), M_IPFW, | dyn_hp_cache = malloc(mp_ncpus * sizeof(void *), M_IPFW, | ||||
M_WAITOK | M_ZERO); | M_WAITOK | M_ZERO); | ||||
DYN_EXPIRED_LOCK_INIT(); | DYN_EXPIRED_LOCK_INIT(); | ||||
callout_init(&V_dyn_timeout, 1); | callout_init(&V_dyn_timeout, 1); | ||||
callout_reset(&V_dyn_timeout, hz, dyn_tick, curvnet); | callout_reset(&V_dyn_timeout, hz, dyn_tick, curvnet); | ||||
▲ Show 20 Lines • Show All 69 Lines • Show Last 20 Lines |
why is it okay to wait here