* Rename has_space to need_modify to be consistent with 0 as return values.

* document all callbacks supported by algorithms code.
This commit is contained in:
melifaro 2014-08-12 14:09:15 +00:00
parent 324833519e
commit 7f14a3576e
3 changed files with 246 additions and 43 deletions

View File

@ -623,7 +623,7 @@ cleanup:
* need for reallocation.
*
* Callbacks order:
* 0) has_space() (UH_WLOCK) - checks if @count items can be added w/o resize.
* 0) need_modify() (UH_WLOCK) - checks if @count items can be added w/o resize.
*
* 1) alloc_modify (no locks, M_WAITOK) - alloc new state based on @pflags.
* 2) prepare_modifyt (UH_WLOCK) - copy old data into new storage
@ -655,15 +655,15 @@ check_table_space(struct ip_fw_chain *ch, struct table_config *tc,
*/
while (true) {
pflags = 0;
if (ta->has_space(tc->astate, ti, count, &pflags) != 0) {
if (ta->need_modify(tc->astate, ti, count, &pflags) == 0) {
error = 0;
break;
}
/* We have to shrink/grow table */
IPFW_UH_WUNLOCK(ch);
memset(&ta_buf, 0, sizeof(ta_buf));
if ((error = ta->prepare_mod(ta_buf, &pflags)) != 0) {
IPFW_UH_WLOCK(ch);
break;
@ -673,7 +673,8 @@ check_table_space(struct ip_fw_chain *ch, struct table_config *tc,
/* Check if we still need to alter table */
ti = KIDX_TO_TI(ch, tc->no.kidx);
if (ta->has_space(tc->astate, ti, count, &pflags) != 0) {
if (ta->need_modify(tc->astate, ti, count, &pflags) == 0) {
IPFW_UH_WUNLOCK(ch);
/*
* Other thread has already performed resize.
@ -3230,4 +3231,3 @@ free:
return (error);
}

View File

@ -83,12 +83,12 @@ typedef int (ta_del)(void *ta_state, struct table_info *ti,
typedef void (ta_flush_entry)(struct ip_fw_chain *ch, struct tentry_info *tei,
void *ta_buf);
typedef int (ta_has_space)(void *ta_state, struct table_info *ti,
typedef int (ta_need_modify)(void *ta_state, struct table_info *ti,
uint32_t count, uint64_t *pflags);
typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
void *ta_buf, uint64_t *pflags);
typedef int (ta_modify)(void *ta_state, struct table_info *ti,
typedef void (ta_modify)(void *ta_state, struct table_info *ti,
void *ta_buf, uint64_t pflags);
typedef void (ta_flush_mod)(void *ta_buf);
@ -121,7 +121,7 @@ struct table_algo {
ta_del *del;
ta_flush_entry *flush_entry;
ta_find_tentry *find_tentry;
ta_has_space *has_space;
ta_need_modify *need_modify;
ta_prepare_mod *prepare_mod;
ta_fill_mod *fill_mod;
ta_modify *modify;

View File

@ -56,6 +56,221 @@ __FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 267384 2014-06-
#include <netpfil/ipfw/ip_fw_private.h>
#include <netpfil/ipfw/ip_fw_table.h>
/*
* IPFW table lookup algorithms.
*
* What is needed to add another table algo?
*
* Algo init:
* * struct table_algo has to be filled with:
* name: "type:algoname" format, e.g. "cidr:radix". Currently
* there are the following types: "cidr", "iface", "number" and "flow".
* type: one of IPFW_TABLE_* types
* flags: one or more TA_FLAGS_*
* ta_buf_size: size of structure used to store add/del item state.
* Needs to be less than TA_BUF_SZ.
* callbacks: see below for description.
* * ipfw_add_table_algo / ipfw_del_table_algo has to be called
*
* Callbacks description:
*
* -init: request to initialize new table instance.
* typedef int (ta_init)(struct ip_fw_chain *ch, void **ta_state,
* struct table_info *ti, char *data, uint8_t tflags);
* MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
*
* Allocate all structures needed for normal operations.
* * Caller may want to parse @data for some algo-specific
* options provided by userland.
* * Caller may want to save configuration state pointer to @ta_state
* * Caller needs to save desired runtime structure pointer(s)
* inside @ti fields. Note that it is not correct to save
* @ti pointer at this moment. Use -change_ti hook for that.
* * Caller has to fill in ti->lookup to appropriate function
* pointer.
*
*
*
* -destroy: request to destroy table instance.
* typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
* MANDATORY, may be locked (UH+WLOCK). (M_NOWAIT).
*
* Frees all table entries and all tables structures allocated by -init.
*
*
*
* -prepare_add: request to allocate state for adding new entry.
* typedef int (ta_prepare_add)(struct ip_fw_chain *ch, struct tentry_info *tei,
* void *ta_buf);
* MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
*
* Buffer ta_buf of size ta->ta_buf_sz may be used to store
* allocated state.
*
*
*
* -prepare_del: request to set state for deleting existing entry.
* typedef int (ta_prepare_del)(struct ip_fw_chain *ch, struct tentry_info *tei,
* void *ta_buf);
* MANDATORY, locked, UH. (M_NOWAIT). Returns 0 on success.
*
* Buffer ta_buf of size ta->ta_buf_sz may be used to store
* allocated state. Caller should use on-stack ta_buf allocation
* instead of doing malloc().
*
*
*
* -add: request to insert new entry into runtime/config structures.
* typedef int (ta_add)(void *ta_state, struct table_info *ti,
* struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
* MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
*
* Insert new entry using previously-allocated state in @ta_buf.
* * @tei may have the following flags:
* 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:
* 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.
* entry exists: return EEXIST
* entry not found: return ENOENT
* other error: return non-zero error code.
*
*
*
* -del: request to delete existing entry from runtime/config structures.
* typedef int (ta_del)(void *ta_state, struct table_info *ti,
* struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
* MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
*
* 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 not found: return ENOENT
* other error: return non-zero error code.
*
*
*
* -flush_entry: flush entry state created by -prepare_add / -del / others
* typedef void (ta_flush_entry)(struct ip_fw_chain *ch,
* struct tentry_info *tei, void *ta_buf);
* MANDATORY, may be locked. (M_NOWAIT).
*
* Delete state allocated by:
* -prepare_add (-add returned EEXIST|UPDATED)
* -prepare_del (if any)
* -del
* * Caller is required to handle empty @ta_buf correctly.
*
*
* -find_tentry: finds entry specified by key @tei
* typedef int ta_find_tentry(void *ta_state, struct table_info *ti,
* ipfw_obj_tentry *tent);
* OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 on success.
*
* Finds entry specified by given key.
* * Caller is requred to do the following:
* entry found: returns 0, export entry to @tent
* entry not found: returns ENOENT
*
*
* -need_modify: checks if @ti has enough space to hold another @count items.
* typedef int (ta_need_modify)(void *ta_state, struct table_info *ti,
* uint32_t count, uint64_t *pflags);
* MANDATORY, locked (UH). (M_NOWAIT). Returns 0 if has.
*
* Checks if given table has enough space to add @count items without
* resize. Caller may use @pflags to store desired modification data.
*
*
*
* -prepare_mod: allocate structures for table modification.
* typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
* MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
*
* Allocate all needed state for table modification. Caller
* should use `struct mod_item` to store new state in @ta_buf.
* Up to TA_BUF_SZ (128 bytes) can be stored in @ta_buf.
*
*
*
* -fill_mod: copy some data to new state/
* typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
* void *ta_buf, uint64_t *pflags);
* MANDATORY, locked (UH). (M_NOWAIT). Returns 0 on success.
*
* Copy as much data as we can to minimize changes under WLOCK.
* For example, array can be merged inside this callback.
*
*
*
* -modify: perform final modification.
* typedef void (ta_modify)(void *ta_state, struct table_info *ti,
* void *ta_buf, uint64_t pflags);
* MANDATORY, locked (UH+WLOCK). (M_NOWAIT).
*
* Performs all changes necessary to switch to new structures.
* * Caller should save old pointers to @ta_buf storage.
*
*
*
* -flush_mod: flush table modification state.
* typedef void (ta_flush_mod)(void *ta_buf);
* MANDATORY, unlocked. (M_WAITOK).
*
* Performs flush for the following:
* - prepare_mod (modification was not necessary)
* - modify (for the old state)
*
*
*
* -change_gi: monitor table info pointer changes
* typedef void (ta_change_ti)(void *ta_state, struct table_info *ti);
* OPTIONAL, locked (UH). (M_NOWAIT).
*
* Called on @ti pointer changed. Called immediately after -init
* to set initial state.
*
*
*
* -foreach: calls @f for each table entry
* typedef void ta_foreach(void *ta_state, struct table_info *ti,
* ta_foreach_f *f, void *arg);
* MANDATORY, locked(UH). (M_NOWAIT).
*
* Runs callback with specified argument for each table entry,
* Typically used for dumping table entries.
*
*
*
* -dump_tentry: dump table entry in current @tentry format.
* typedef int ta_dump_tentry(void *ta_state, struct table_info *ti, void *e,
* ipfw_obj_tentry *tent);
* MANDATORY, locked(UH). (M_NOWAIT). Returns 0 on success.
*
* Dumps entry @e to @tent.
*
*
* -print_config: prints custom algoritm options into buffer.
* typedef void (ta_print_config)(void *ta_state, struct table_info *ti,
* char *buf, size_t bufsize);
* OPTIONAL. locked(UH). (M_NOWAIT).
*
* Prints custom algorithm options in the format suitable to pass
* back to -init callback.
*
*
*
* -dump_tinfo: dumps algo-specific info.
* typedef void ta_dump_tinfo(void *ta_state, struct table_info *ti,
* ipfw_ta_tinfo *tinfo);
* OPTIONAL. locked(UH). (M_NOWAIT).
*
* Dumps options like items size/hash size, etc.
*/
static MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
/*
@ -587,7 +802,7 @@ ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
}
static int
ta_has_space_radix(void *ta_state, struct table_info *ti, uint32_t count,
ta_need_modify_radix(void *ta_state, struct table_info *ti, uint32_t count,
uint64_t *pflags)
{
@ -597,7 +812,7 @@ ta_has_space_radix(void *ta_state, struct table_info *ti, uint32_t count,
* but we don't have any API to call (and we don't known which
* sizes do we need).
*/
return (1);
return (0);
}
struct table_algo cidr_radix = {
@ -616,7 +831,7 @@ struct table_algo cidr_radix = {
.dump_tentry = ta_dump_radix_tentry,
.find_tentry = ta_find_radix_tentry,
.dump_tinfo = ta_dump_radix_tinfo,
.has_space = ta_has_space_radix,
.need_modify = ta_need_modify_radix,
};
@ -1357,7 +1572,7 @@ ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
*/
static int
ta_has_space_chash(void *ta_state, struct table_info *ti, uint32_t count,
ta_need_modify_chash(void *ta_state, struct table_info *ti, uint32_t count,
uint64_t *pflags)
{
struct chash_cfg *cfg;
@ -1379,10 +1594,10 @@ ta_has_space_chash(void *ta_state, struct table_info *ti, uint32_t count,
if (data != 0) {
*pflags = data;
return (0);
return (1);
}
return (1);
return (0);
}
/*
@ -1434,7 +1649,7 @@ ta_fill_mod_chash(void *ta_state, struct table_info *ti, void *ta_buf,
/*
* Switch old & new arrays.
*/
static int
static void
ta_modify_chash(void *ta_state, struct table_info *ti, void *ta_buf,
uint64_t pflags)
{
@ -1495,8 +1710,6 @@ ta_modify_chash(void *ta_state, struct table_info *ti, void *ta_buf,
/* Update lower 32 bits with new values */
ti->data &= 0xFFFFFFFF00000000;
ti->data |= log2(cfg->size4) << 8 | log2(cfg->size6);
return (0);
}
/*
@ -1530,7 +1743,7 @@ struct table_algo cidr_hash = {
.find_tentry = ta_find_chash_tentry,
.print_config = ta_print_chash_config,
.dump_tinfo = ta_dump_chash_tinfo,
.has_space = ta_has_space_chash,
.need_modify = ta_need_modify_chash,
.prepare_mod = ta_prepare_mod_chash,
.fill_mod = ta_fill_mod_chash,
.modify = ta_modify_chash,
@ -2033,7 +2246,7 @@ if_notifier(struct ip_fw_chain *ch, void *cbdata, uint16_t ifindex)
*/
static int
ta_has_space_ifidx(void *ta_state, struct table_info *ti, uint32_t count,
ta_need_modify_ifidx(void *ta_state, struct table_info *ti, uint32_t count,
uint64_t *pflags)
{
struct iftable_cfg *cfg;
@ -2047,10 +2260,10 @@ ta_has_space_ifidx(void *ta_state, struct table_info *ti, uint32_t count,
if (size != cfg->size) {
*pflags = size;
return (0);
return (1);
}
return (1);
return (0);
}
/*
@ -2098,7 +2311,7 @@ ta_fill_mod_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
/*
* Switch old & new arrays.
*/
static int
static void
ta_modify_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
uint64_t pflags)
{
@ -2115,8 +2328,6 @@ ta_modify_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
ti->state = icfg->main_ptr;
mi->main_ptr = old_ptr;
return (0);
}
/*
@ -2220,7 +2431,7 @@ struct table_algo iface_idx = {
.dump_tentry = ta_dump_ifidx_tentry,
.find_tentry = ta_find_ifidx_tentry,
.dump_tinfo = ta_dump_ifidx_tinfo,
.has_space = ta_has_space_ifidx,
.need_modify = ta_need_modify_ifidx,
.prepare_mod = ta_prepare_mod_ifidx,
.fill_mod = ta_fill_mod_ifidx,
.modify = ta_modify_ifidx,
@ -2460,7 +2671,7 @@ ta_flush_numarray_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
*/
static int
ta_has_space_numarray(void *ta_state, struct table_info *ti, uint32_t count,
ta_need_modify_numarray(void *ta_state, struct table_info *ti, uint32_t count,
uint64_t *pflags)
{
struct numarray_cfg *cfg;
@ -2474,10 +2685,10 @@ ta_has_space_numarray(void *ta_state, struct table_info *ti, uint32_t count,
if (size != cfg->size) {
*pflags = size;
return (0);
return (1);
}
return (1);
return (0);
}
/*
@ -2525,7 +2736,7 @@ ta_fill_mod_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
/*
* Switch old & new arrays.
*/
static int
static void
ta_modify_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
uint64_t pflags)
{
@ -2542,8 +2753,6 @@ ta_modify_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
ti->state = cfg->main_ptr;
mi->main_ptr = old_ptr;
return (0);
}
/*
@ -2622,7 +2831,7 @@ struct table_algo number_array = {
.dump_tentry = ta_dump_numarray_tentry,
.find_tentry = ta_find_numarray_tentry,
.dump_tinfo = ta_dump_numarray_tinfo,
.has_space = ta_has_space_numarray,
.need_modify = ta_need_modify_numarray,
.prepare_mod = ta_prepare_mod_numarray,
.fill_mod = ta_fill_mod_numarray,
.modify = ta_modify_numarray,
@ -3186,7 +3395,7 @@ ta_flush_fhash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
*/
static int
ta_has_space_fhash(void *ta_state, struct table_info *ti, uint32_t count,
ta_need_modify_fhash(void *ta_state, struct table_info *ti, uint32_t count,
uint64_t *pflags)
{
struct fhash_cfg *cfg;
@ -3195,10 +3404,10 @@ ta_has_space_fhash(void *ta_state, struct table_info *ti, uint32_t count,
if (cfg->items > cfg->size && cfg->size < 65536) {
*pflags = cfg->size * 2;
return (0);
return (1);
}
return (1);
return (0);
}
/*
@ -3240,7 +3449,7 @@ ta_fill_mod_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
/*
* Switch old & new arrays.
*/
static int
static void
ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
uint64_t pflags)
{
@ -3255,13 +3464,9 @@ ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
mi = (struct mod_item *)ta_buf;
cfg = (struct fhash_cfg *)ta_state;
/* Check which hash we need to grow and do we still need that */
old_size = cfg->size;
old_head = ti->state;
if (old_size >= mi->size)
return (0);
new_head = (struct fhashbhead *)mi->main_ptr;
for (i = 0; i < old_size; i++) {
SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
@ -3276,8 +3481,6 @@ ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
cfg->size = mi->size;
mi->main_ptr = old_head;
return (0);
}
/*
@ -3309,7 +3512,7 @@ struct table_algo flow_hash = {
.dump_tentry = ta_dump_fhash_tentry,
.find_tentry = ta_find_fhash_tentry,
.dump_tinfo = ta_dump_fhash_tinfo,
.has_space = ta_has_space_fhash,
.need_modify = ta_need_modify_fhash,
.prepare_mod = ta_prepare_mod_fhash,
.fill_mod = ta_fill_mod_fhash,
.modify = ta_modify_fhash,