Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netpfil/ipfw/ip_fw_table_value.c
Show First 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Allocate new value index in either shared or per-table array. | * Allocate new value index in either shared or per-table array. | ||||
* Function may drop/reacquire UH lock. | * Function may drop/reacquire UH lock. | ||||
* | * | ||||
* Returns 0 on success. | * Returns 0 on success. | ||||
*/ | */ | ||||
static int | static int | ||||
alloc_table_vidx(struct ip_fw_chain *ch, struct tableop_state *ts, | alloc_table_vidx(struct ip_fw_chain *ch, struct tableop_state *ts, | ||||
struct namedobj_instance *vi, uint16_t *pvidx) | struct namedobj_instance *vi, uint16_t *pvidx, uint8_t flags) | ||||
{ | { | ||||
int error, vlimit; | int error, vlimit; | ||||
uint16_t vidx; | uint16_t vidx; | ||||
IPFW_UH_WLOCK_ASSERT(ch); | IPFW_UH_WLOCK_ASSERT(ch); | ||||
error = ipfw_objhash_alloc_idx(vi, &vidx); | error = ipfw_objhash_alloc_idx(vi, &vidx); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* | /* | ||||
* We need to resize array. This involves | * We need to resize array. This involves | ||||
* lock/unlock, so we need to check "modified" | * lock/unlock, so we need to check "modified" | ||||
* state. | * state. | ||||
*/ | */ | ||||
ts->opstate.func(ts->tc, &ts->opstate); | ts->opstate.func(ts->tc, &ts->opstate); | ||||
error = resize_shared_value_storage(ch); | error = resize_shared_value_storage(ch); | ||||
return (error); /* ts->modified should be set, we will restart */ | return (error); /* ts->modified should be set, we will restart */ | ||||
} | } | ||||
vlimit = ts->ta->vlimit; | vlimit = ts->ta->vlimit; | ||||
if (vlimit != 0 && vidx >= vlimit) { | if (vlimit != 0 && vidx >= vlimit && !(flags & IPFW_CTF_ATOMIC)) { | ||||
/* | /* | ||||
* Algorithm is not able to store given index. | * Algorithm is not able to store given index. | ||||
* We have to rollback state, start using | * We have to rollback state, start using | ||||
* per-table value array or return error | * per-table value array or return error | ||||
* if we're already using it. | * if we're already using it. | ||||
* | |||||
* TODO: do not rollback state if | |||||
* atomicity is not required. | |||||
*/ | */ | ||||
if (ts->vshared != 0) { | if (ts->vshared != 0) { | ||||
/* shared -> per-table */ | /* shared -> per-table */ | ||||
return (ENOSPC); /* TODO: proper error */ | return (ENOSPC); /* TODO: proper error */ | ||||
} | } | ||||
/* per-table. Fail for now. */ | /* per-table. Fail for now. */ | ||||
return (ENOSPC); /* TODO: proper error */ | return (ENOSPC); /* TODO: proper error */ | ||||
Show All 16 Lines | ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc, | ||||
struct table_value *pval; | struct table_value *pval; | ||||
struct namedobj_instance *vi; | struct namedobj_instance *vi; | ||||
/* | /* | ||||
* We have two slightly different ADD cases here: | * We have two slightly different ADD cases here: | ||||
* either (1) we are successful / partially successful, | * either (1) we are successful / partially successful, | ||||
* in that case we need | * in that case we need | ||||
* * to ignore ADDED entries values | * * to ignore ADDED entries values | ||||
* * rollback every other values (either UPDATED since | * * rollback every other values if atomicity is not | ||||
* old value has been stored there, or some failure like | * * required (either UPDATED since old value has been | ||||
* EXISTS or LIMIT or simply "ignored" case. | * stored there, or some failure like EXISTS or LIMIT | ||||
* or simply "ignored" case. | |||||
* | * | ||||
* (2): atomic rollback of partially successful operation | * (2): atomic rollback of partially successful operation | ||||
* in that case we simply need to unref all entries. | * in that case we simply need to unref all entries. | ||||
* | * | ||||
* DELETE case is simpler: no atomic support there, so | * DELETE case is simpler: no atomic support there, so | ||||
* we simply unref all non-zero values. | * we simply unref all non-zero values. | ||||
*/ | */ | ||||
Show All 28 Lines | |||||
/* | /* | ||||
* Main function used to link values of entries going to be added, | * Main function used to link values of entries going to be added, | ||||
* to the index. Since we may perform many UH locks drops/acquires, | * to the index. Since we may perform many UH locks drops/acquires, | ||||
* handle changes by checking tablestate "modified" field. | * handle changes by checking tablestate "modified" field. | ||||
* | * | ||||
* Success: return 0. | * Success: return 0. | ||||
*/ | */ | ||||
int | int | ||||
ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts) | ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts, | ||||
uint8_t flags) | |||||
{ | { | ||||
int error, i, found; | int error, i, found; | ||||
struct namedobj_instance *vi; | struct namedobj_instance *vi; | ||||
struct table_config *tc; | struct table_config *tc; | ||||
struct tentry_info *tei, *ptei; | struct tentry_info *tei, *ptei; | ||||
uint32_t count, vlimit; | uint32_t count, vlimit; | ||||
uint16_t vidx; | uint16_t vidx; | ||||
struct table_val_link *ptv; | struct table_val_link *ptv; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | ptv = (struct table_val_link *)ipfw_objhash_lookup_name(vi, 0, | ||||
(char *)&tval); | (char *)&tval); | ||||
if (ptv != NULL) { | if (ptv != NULL) { | ||||
ptv->pval->refcnt++; | ptv->pval->refcnt++; | ||||
ptei->value = ptv->no.kidx; | ptei->value = ptv->no.kidx; | ||||
continue; | continue; | ||||
} | } | ||||
/* May perform UH unlock/lock */ | /* May perform UH unlock/lock */ | ||||
error = alloc_table_vidx(ch, ts, vi, &vidx); | error = alloc_table_vidx(ch, ts, vi, &vidx, flags); | ||||
if (error != 0) { | if (error != 0) { | ||||
ts->opstate.func(ts->tc, &ts->opstate); | ts->opstate.func(ts->tc, &ts->opstate); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* value storage resize has happened, return */ | /* value storage resize has happened, return */ | ||||
if (ts->modified != 0) | if (ts->modified != 0) | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 220 Lines • Show Last 20 Lines |