* Make objhash api a bit more abstract by providing ability to specify
own hash/compare functions. * Add requirement for table algorithms to copy "valie" field in @add callback instead of "prepare_add". * Document existing requirement for table algorithms to store value of deleted record to @tei.
This commit is contained in:
parent
832fd78087
commit
1326363253
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/ipfw/; revision=270846
@ -267,7 +267,7 @@ struct ip_fw_chain {
|
||||
uint32_t id; /* ruleset id */
|
||||
int n_rules; /* number of static rules */
|
||||
LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */
|
||||
void *tablestate; /* runtime table info */
|
||||
void *tablestate; /* runtime table info */
|
||||
int *idxmap; /* skipto array of rules */
|
||||
#if defined( __linux__ ) || defined( _WIN32 )
|
||||
spinlock_t rwmtx;
|
||||
@ -519,6 +519,9 @@ caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed);
|
||||
|
||||
typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *,
|
||||
void *arg);
|
||||
typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, void *key,
|
||||
uint32_t kopt);
|
||||
typedef int (objhash_cmp_f)(struct named_object *no, void *key, uint32_t kopt);
|
||||
struct namedobj_instance *ipfw_objhash_create(uint32_t items);
|
||||
void ipfw_objhash_destroy(struct namedobj_instance *);
|
||||
void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks);
|
||||
@ -527,6 +530,7 @@ void ipfw_objhash_bitmap_merge(struct namedobj_instance *ni,
|
||||
void ipfw_objhash_bitmap_swap(struct namedobj_instance *ni,
|
||||
void **idx, int *blocks);
|
||||
void ipfw_objhash_bitmap_free(void *idx, int blocks);
|
||||
void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f);
|
||||
struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni,
|
||||
uint32_t set, char *name);
|
||||
struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni,
|
||||
@ -540,6 +544,8 @@ void ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f,
|
||||
void *arg);
|
||||
int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx);
|
||||
int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx);
|
||||
void ipfw_objhash_set_funcs(struct namedobj_instance *ni,
|
||||
objhash_hash_f *hash_f, objhash_cmp_f *cmp_f);
|
||||
|
||||
/* In ip_fw_table.c */
|
||||
struct table_info;
|
||||
|
@ -88,12 +88,15 @@ struct namedobj_instance {
|
||||
uint32_t max_blocks; /* number of "long" blocks in bitmask */
|
||||
uint32_t count; /* number of items */
|
||||
uint16_t free_off[IPFW_MAX_SETS]; /* first possible free offset */
|
||||
objhash_hash_f *hash_f;
|
||||
objhash_cmp_f *cmp_f;
|
||||
};
|
||||
#define BLOCK_ITEMS (8 * sizeof(u_long)) /* Number of items for ffsl() */
|
||||
|
||||
static uint32_t objhash_hash_name(struct namedobj_instance *ni, uint32_t set,
|
||||
char *name);
|
||||
static uint32_t objhash_hash_val(struct namedobj_instance *ni, uint32_t val);
|
||||
static uint32_t objhash_hash_name(struct namedobj_instance *ni, void *key,
|
||||
uint32_t kopt);
|
||||
static uint32_t objhash_hash_idx(struct namedobj_instance *ni, uint32_t val);
|
||||
static int objhash_cmp_name(struct named_object *no, void *name, uint32_t set);
|
||||
|
||||
static int ipfw_flush_sopt_data(struct sockopt_data *sd);
|
||||
|
||||
@ -3078,6 +3081,10 @@ ipfw_objhash_create(uint32_t items)
|
||||
for (i = 0; i < ni->nv_size; i++)
|
||||
TAILQ_INIT(&ni->values[i]);
|
||||
|
||||
/* Set default hashing/comparison functions */
|
||||
ni->hash_f = objhash_hash_name;
|
||||
ni->cmp_f = objhash_cmp_name;
|
||||
|
||||
/* Allocate bitmask separately due to possible resize */
|
||||
ipfw_objhash_bitmap_alloc(items, (void*)&ni->idx_mask, &ni->max_blocks);
|
||||
|
||||
@ -3092,18 +3099,37 @@ ipfw_objhash_destroy(struct namedobj_instance *ni)
|
||||
free(ni, M_IPFW);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f,
|
||||
objhash_cmp_f *cmp_f)
|
||||
{
|
||||
|
||||
ni->hash_f = hash_f;
|
||||
ni->cmp_f = cmp_f;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
objhash_hash_name(struct namedobj_instance *ni, uint32_t set, char *name)
|
||||
objhash_hash_name(struct namedobj_instance *ni, void *name, uint32_t set)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = fnv_32_str(name, FNV1_32_INIT);
|
||||
v = fnv_32_str((char *)name, FNV1_32_INIT);
|
||||
|
||||
return (v % ni->nn_size);
|
||||
}
|
||||
|
||||
static int
|
||||
objhash_cmp_name(struct named_object *no, void *name, uint32_t set)
|
||||
{
|
||||
|
||||
if ((strcmp(no->name, (char *)name) == 0) && (no->set == set))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
objhash_hash_val(struct namedobj_instance *ni, uint32_t val)
|
||||
objhash_hash_idx(struct namedobj_instance *ni, uint32_t val)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
@ -3118,10 +3144,10 @@ ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name)
|
||||
struct named_object *no;
|
||||
uint32_t hash;
|
||||
|
||||
hash = objhash_hash_name(ni, set, name);
|
||||
hash = ni->hash_f(ni, name, set);
|
||||
|
||||
TAILQ_FOREACH(no, &ni->names[hash], nn_next) {
|
||||
if ((strcmp(no->name, name) == 0) && (no->set == set))
|
||||
if (ni->cmp_f(no, name, set) == 0)
|
||||
return (no);
|
||||
}
|
||||
|
||||
@ -3134,7 +3160,7 @@ ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, uint16_t kidx)
|
||||
struct named_object *no;
|
||||
uint32_t hash;
|
||||
|
||||
hash = objhash_hash_val(ni, kidx);
|
||||
hash = objhash_hash_idx(ni, kidx);
|
||||
|
||||
TAILQ_FOREACH(no, &ni->values[hash], nv_next) {
|
||||
if (no->kidx == kidx)
|
||||
@ -3160,10 +3186,10 @@ ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = objhash_hash_name(ni, no->set, no->name);
|
||||
hash = ni->hash_f(ni, no->name, no->set);
|
||||
TAILQ_INSERT_HEAD(&ni->names[hash], no, nn_next);
|
||||
|
||||
hash = objhash_hash_val(ni, no->kidx);
|
||||
hash = objhash_hash_idx(ni, no->kidx);
|
||||
TAILQ_INSERT_HEAD(&ni->values[hash], no, nv_next);
|
||||
|
||||
ni->count++;
|
||||
@ -3174,10 +3200,10 @@ ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = objhash_hash_name(ni, no->set, no->name);
|
||||
hash = ni->hash_f(ni, no->name, no->set);
|
||||
TAILQ_REMOVE(&ni->names[hash], no, nn_next);
|
||||
|
||||
hash = objhash_hash_val(ni, no->kidx);
|
||||
hash = objhash_hash_idx(ni, no->kidx);
|
||||
TAILQ_REMOVE(&ni->values[hash], no, nv_next);
|
||||
|
||||
ni->count--;
|
||||
@ -3238,7 +3264,7 @@ ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx)
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate new index in given set and stores in in @pidx.
|
||||
* Allocate new index in given instance and stores in in @pidx.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int
|
||||
|
@ -106,6 +106,9 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06-
|
||||
* void *ta_buf);
|
||||
* MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
|
||||
*
|
||||
* Allocates state and fills it in with all necessary data (EXCEPT value)
|
||||
* from @tei to minimize operations needed to be done under WLOCK.
|
||||
* "value" field has to be copied to new entry in @add callback.
|
||||
* Buffer ta_buf of size ta->ta_buf_sz may be used to store
|
||||
* allocated state.
|
||||
*
|
||||
@ -132,6 +135,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06-
|
||||
* TEI_FLAGS_UPDATE: request to add or update entry.
|
||||
* TEI_FLAGS_DONTADD: request to update (but not add) entry.
|
||||
* * Caller is required to do the following:
|
||||
* copy real entry value from @tei
|
||||
* entry added: return 0, set 1 to @pnum
|
||||
* entry updated: return 0, store 0 to @pnum, store old value in @tei,
|
||||
* add TEI_FLAGS_UPDATED flag to @tei.
|
||||
@ -148,7 +152,7 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06-
|
||||
*
|
||||
* Delete entry using previously set up in @ta_buf.
|
||||
* * Caller is required to do the following:
|
||||
* entry deleted: return 0, set 1 to @pnum
|
||||
* entry deleted: return 0, set 1 to @pnum, store old value in @tei.
|
||||
* entry not found: return ENOENT
|
||||
* other error: return non-zero error code.
|
||||
*
|
||||
@ -620,7 +624,6 @@ ta_prepare_add_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||
if (mlen > 32)
|
||||
return (EINVAL);
|
||||
ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
|
||||
ent->value = tei->value;
|
||||
ent->masklen = mlen;
|
||||
|
||||
addr = (struct sockaddr *)&ent->addr;
|
||||
@ -633,7 +636,6 @@ ta_prepare_add_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||
if (mlen > 128)
|
||||
return (EINVAL);
|
||||
xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
|
||||
xent->value = tei->value;
|
||||
xent->masklen = mlen;
|
||||
|
||||
addr = (struct sockaddr *)&xent->addr6;
|
||||
@ -667,10 +669,14 @@ ta_add_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
cfg = (struct radix_cfg *)ta_state;
|
||||
tb = (struct ta_buf_radix *)ta_buf;
|
||||
|
||||
if (tei->subtype == AF_INET)
|
||||
/* Save current entry value from @tei */
|
||||
if (tei->subtype == AF_INET) {
|
||||
rnh = ti->state;
|
||||
else
|
||||
((struct radix_addr_entry *)tb->ent_ptr)->value = tei->value;
|
||||
} else {
|
||||
rnh = ti->xstate;
|
||||
((struct radix_addr_xentry *)tb->ent_ptr)->value = tei->value;
|
||||
}
|
||||
|
||||
/* Search for an entry first */
|
||||
rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, rnh);
|
||||
@ -1320,7 +1326,6 @@ tei_to_chash_ent(struct tentry_info *tei, struct chashentry *ent)
|
||||
/* Unknown CIDR type */
|
||||
return (EINVAL);
|
||||
}
|
||||
ent->value = tei->value;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -1439,6 +1444,10 @@ ta_add_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
hash = 0;
|
||||
exists = 0;
|
||||
|
||||
/* Read current value from @tei */
|
||||
ent->value = tei->value;
|
||||
|
||||
/* Read cuurrent value */
|
||||
if (tei->subtype == AF_INET) {
|
||||
if (tei->masklen != cfg->mask4)
|
||||
return (EINVAL);
|
||||
@ -2030,7 +2039,6 @@ ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||
return (EINVAL);
|
||||
|
||||
ife = malloc(sizeof(struct ifentry), M_IPFW_TBL, M_WAITOK | M_ZERO);
|
||||
ife->value = tei->value;
|
||||
ife->ic.cb = if_notifier;
|
||||
ife->ic.cbdata = ife;
|
||||
|
||||
@ -2063,6 +2071,7 @@ ta_add_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
ife = tb->ife;
|
||||
|
||||
ife->icfg = icfg;
|
||||
ife->value = tei->value;
|
||||
|
||||
tmp = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
|
||||
|
||||
@ -2577,7 +2586,6 @@ ta_prepare_add_numarray(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||
tb = (struct ta_buf_numarray *)ta_buf;
|
||||
|
||||
tb->na.number = *((uint32_t *)tei->paddr);
|
||||
tb->na.value = tei->value;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -2595,6 +2603,9 @@ ta_add_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
tb = (struct ta_buf_numarray *)ta_buf;
|
||||
cfg = (struct numarray_cfg *)ta_state;
|
||||
|
||||
/* Read current value from @tei */
|
||||
tb->na.value = tei->value;
|
||||
|
||||
ri = numarray_find(ti, &tb->na.number);
|
||||
|
||||
if (ri != NULL) {
|
||||
@ -3155,7 +3166,6 @@ tei_to_fhash_ent(struct tentry_info *tei, struct fhashentry *ent)
|
||||
|
||||
ent->af = tei->subtype;
|
||||
ent->proto = tfe->proto;
|
||||
ent->value = tei->value;
|
||||
ent->dport = ntohs(tfe->dport);
|
||||
ent->sport = ntohs(tfe->sport);
|
||||
|
||||
@ -3287,6 +3297,9 @@ ta_add_fhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
ent = (struct fhashentry *)tb->ent_ptr;
|
||||
exists = 0;
|
||||
|
||||
/* Read current value from @tei */
|
||||
ent->value = tei->value;
|
||||
|
||||
head = cfg->head;
|
||||
hash = hash_flow_ent(ent, cfg->size);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user