Index: sys/netpfil/ipfw/ip_fw_table.h =================================================================== --- sys/netpfil/ipfw/ip_fw_table.h +++ sys/netpfil/ipfw/ip_fw_table.h @@ -168,7 +168,8 @@ struct tableop_state; void ipfw_table_value_init(struct ip_fw_chain *ch, int first); void ipfw_table_value_destroy(struct ip_fw_chain *ch, int last); -int ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts); +int ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts, + uint8_t flags); void ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc, struct tentry_info *tei, uint32_t count, int rollback); void ipfw_import_table_value_v1(ipfw_table_value *iv); Index: sys/netpfil/ipfw/ip_fw_table.c =================================================================== --- sys/netpfil/ipfw/ip_fw_table.c +++ sys/netpfil/ipfw/ip_fw_table.c @@ -623,7 +623,7 @@ * * May release/reacquire UH_WLOCK. */ - error = ipfw_link_table_values(ch, &ts); + error = ipfw_link_table_values(ch, &ts, flags); if (error != 0) goto cleanup; if (ts.modified != 0) Index: sys/netpfil/ipfw/ip_fw_table_value.c =================================================================== --- sys/netpfil/ipfw/ip_fw_table_value.c +++ sys/netpfil/ipfw/ip_fw_table_value.c @@ -363,7 +363,7 @@ */ static int 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; uint16_t vidx; @@ -384,16 +384,13 @@ } 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. * We have to rollback state, start using * per-table value array or return error * if we're already using it. - * - * TODO: do not rollback state if - * atomicity is not required. */ if (ts->vshared != 0) { /* shared -> per-table */ @@ -473,7 +470,8 @@ * Success: return 0. */ 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; struct namedobj_instance *vi; @@ -577,7 +575,7 @@ } /* 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) { ts->opstate.func(ts->tc, &ts->opstate); return (error);