svn commit: r270968 - projects/ipfw/sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Tue Sep 2 14:27:13 UTC 2014
Author: melifaro
Date: Tue Sep 2 14:27:12 2014
New Revision: 270968
URL: http://svnweb.freebsd.org/changeset/base/270968
Log:
Add more comments on newly-added functions.
Add back opstate handler function.
Modified:
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_table_value.c
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Sep 2 14:26:25 2014 (r270967)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Sep 2 14:27:12 2014 (r270968)
@@ -481,8 +481,59 @@ flush_batch_buffer(struct ip_fw_chain *c
free(ta_buf_m, M_TEMP);
}
+
+static void
+rollback_add_entry(void *object, struct op_state *_state)
+{
+ struct ip_fw_chain *ch;
+ struct tableop_state *ts;
+
+ ts = (struct tableop_state *)_state;
+
+ if (ts->tc != object && ts->ch != object)
+ return;
+
+ ch = ts->ch;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ /* Call specifid unlockers */
+ rollback_table_values(ts);
+
+ /* Indicate we've called */
+ ts->modified = 1;
+}
+
/*
* Adds/updates one or more entries in table @ti.
+ *
+ * Function may drop/reacquire UH wlock multiple times due to
+ * items alloc, algorithm callbacks (check_space), value linkage
+ * (new values, value storage realloc), etc..
+ * Other processes like other adds (which may involve storage resize),
+ * table swaps (which changes table data and may change algo type),
+ * table modify (which may change value mask) may be executed
+ * simultaneously so we need to deal with it.
+ *
+ * The following approach was implemented:
+ * we have per-chain linked list, protected with UH lock.
+ * add_table_entry prepares special on-stack structure wthich is passed
+ * to its descendants. Users add this structure to this list before unlock.
+ * After performing needed operations and acquiring UH lock back, each user
+ * checks if structure has changed. If true, it rolls local state back and
+ * returns without error to the caller.
+ * add_table_entry() on its own checks if structure has changed and restarts
+ * its operation from the beginning (goto restart).
+ *
+ * Functions which are modifying fields of interest (currently
+ * resize_shared_value_storage() and swap_tables() )
+ * traverses given list while holding UH lock immediately before
+ * performing their operations calling function provided be list entry
+ * ( currently rollback_add_entry ) which performs rollback for all necessary
+ * state and sets appropriate values in structure indicating rollback
+ * has happened.
+ *
+ * Algo interaction:
* Function references @ti first to ensure table won't
* disappear or change its type.
* After that, prepare_add callback is called for each @tei entry.
@@ -526,6 +577,7 @@ restart:
}
ta = tc->ta;
ts.ch = ch;
+ ts.opstate.func = rollback_add_entry;
ts.tc = tc;
ts.vshared = tc->vshared;
ts.vmask = tc->vmask;
@@ -624,7 +676,7 @@ restart:
IPFW_WUNLOCK(ch);
- ipfw_finalize_table_values(ch, tc, tei, count, rollback);
+ ipfw_garbage_table_values(ch, tc, tei, count, rollback);
/* Permit post-add algorithm grow/rehash. */
if (numadd != 0)
@@ -714,7 +766,7 @@ del_table_entry(struct ip_fw_chain *ch,
IPFW_WUNLOCK(ch);
/* Unlink non-used values */
- ipfw_finalize_table_values(ch, tc, tei, count, 0);
+ ipfw_garbage_table_values(ch, tc, tei, count, 0);
if (numdel != 0) {
/* Run post-del hook to permit shrinking */
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Tue Sep 2 14:26:25 2014 (r270967)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Tue Sep 2 14:27:12 2014 (r270968)
@@ -198,12 +198,13 @@ struct tableop_state;
void ipfw_table_value_init(struct ip_fw_chain *ch);
void ipfw_table_value_destroy(struct ip_fw_chain *ch);
int ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts);
-void ipfw_finalize_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+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);
void ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *iv);
void ipfw_unref_table_values(struct ip_fw_chain *ch, struct table_config *tc,
struct table_algo *ta, void *astate, struct table_info *ti);
+void rollback_table_values(struct tableop_state *ts);
int ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
struct rule_check_info *ci);
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_value.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_value.c Tue Sep 2 14:26:25 2014 (r270967)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_value.c Tue Sep 2 14:27:12 2014 (r270968)
@@ -166,6 +166,9 @@ get_value_ptrs(struct ip_fw_chain *ch, s
*pvi = vi;
}
+/*
+ * Update pointers to real vaues after @pval change.
+ */
static void
update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
{
@@ -184,9 +187,12 @@ update_tvalue(struct namedobj_instance *
/*
* Grows value storage shared among all tables.
* Drops/reacquires UH locks.
+ * Notifies other running adds on @ch shared storage resize.
+ * Note function does not guarantee that free space
+ * will be available after invocation, so one caller needs
+ * to roll cycle himself.
*
- * Returns 0 on success.
- * Note caller has to check @ts "modified" field.
+ * Returns 0 if case of no errors.
*/
static int
resize_shared_value_storage(struct ip_fw_chain *ch)
@@ -259,6 +265,10 @@ done:
return (0);
}
+/*
+ * Drops reference for table value with index @kidx, stored in @pval and
+ * @vi. Frees value if it has no references.
+ */
static void
unref_table_value(struct namedobj_instance *vi, struct table_value *pval,
uint32_t kidx)
@@ -339,21 +349,15 @@ ipfw_unref_table_values(struct ip_fw_cha
* and set "modified" field to non-zero value to indicate
* that we need to restart original operation.
*/
-static void
-rollback_table_values(void *object, struct op_state *_state)
+void
+rollback_table_values(struct tableop_state *ts)
{
struct ip_fw_chain *ch;
- struct tableop_state *ts;
struct table_value *pval;
struct tentry_info *ptei;
struct namedobj_instance *vi;
int i;
- ts = (struct tableop_state *)_state;
-
- if (ts->tc != object && ts->ch != object)
- return;
-
ch = ts->ch;
IPFW_UH_WLOCK_ASSERT(ch);
@@ -369,8 +373,6 @@ rollback_table_values(void *object, stru
unref_table_value(vi, pval, ptei->value);
}
-
- ts->modified = 1;
}
/*
@@ -378,7 +380,6 @@ rollback_table_values(void *object, stru
* Function may drop/reacquire UH lock.
*
* Returns 0 on success.
- * Note that called has to check @ts "modified" value.
*/
static int
alloc_table_vidx(struct ip_fw_chain *ch, struct tableop_state *ts,
@@ -397,7 +398,7 @@ alloc_table_vidx(struct ip_fw_chain *ch,
* lock/unlock, so we need to check "modified"
* state.
*/
- rollback_table_values(ts->tc, &ts->opstate);
+ ts->opstate.func(ts->tc, &ts->opstate);
error = resize_shared_value_storage(ch);
return (error); /* ts->modified should be set, we will restart */
}
@@ -428,11 +429,11 @@ alloc_table_vidx(struct ip_fw_chain *ch,
}
/*
- * Drops value reference for unused values (updates, partially
+ * Drops value reference for unused values (updates, deletes, partially
* successful adds or rollbacks).
*/
void
-ipfw_finalize_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc,
struct tentry_info *tei, uint32_t count, int rollback)
{
int i;
@@ -441,7 +442,7 @@ ipfw_finalize_table_values(struct ip_fw_
struct namedobj_instance *vi;
/*
- * We have two slightly different cases here:
+ * We have two slightly different ADD cases here:
* either (1) we are successful / partially successful,
* in that case we need
* * to ignore ADDED entries values
@@ -452,6 +453,8 @@ ipfw_finalize_table_values(struct ip_fw_
* (2): atomic rollback of partially successful operation
* in that case we simply need to unref all entries.
*
+ * DELETE case is simpler: no atomic support there, so
+ * we simply unref all non-zero values.
*/
/*
@@ -482,6 +485,13 @@ ipfw_finalize_table_values(struct ip_fw_
}
}
+/*
+ * Main function used to link values of entries going to be added,
+ * to the index. Since we may perform many UH locks drops/acquires,
+ * handle changes by checking tablestate "modified" field.
+ *
+ * Success: return 0.
+ */
int
ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts)
{
@@ -496,7 +506,7 @@ ipfw_link_table_values(struct ip_fw_chai
/*
* Stage 1: reference all existing values and
- * save them inside the bitmask.
+ * save their indices.
*/
IPFW_UH_WLOCK_ASSERT(ch);
get_value_ptrs(ch, ts->tc, ts->vshared, &pval, &vi);
@@ -582,9 +592,10 @@ ipfw_link_table_values(struct ip_fw_chai
/* May perform UH unlock/lock */
error = alloc_table_vidx(ch, ts, vi, &vidx);
if (error != 0) {
- rollback_table_values(tc, &ts->opstate);
+ ts->opstate.func(ts->tc, &ts->opstate);
return (error);
}
+ /* value storage resize has happened, return */
if (ts->modified != 0)
return (0);
@@ -625,6 +636,9 @@ ipfw_import_table_value_legacy(uint32_t
v->limit = value;
}
+/*
+ * Export data to legacy table dumps opcodes.
+ */
uint32_t
ipfw_export_table_value_legacy(struct table_value *v)
{
@@ -636,6 +650,10 @@ ipfw_export_table_value_legacy(struct ta
return (v->tag);
}
+/*
+ * Imports table value from current userland format.
+ * Saves value in kernel format to the same place.
+ */
void
ipfw_import_table_value_v1(ipfw_table_value *iv)
{
@@ -657,6 +675,10 @@ ipfw_import_table_value_v1(ipfw_table_va
memcpy(iv, &v, sizeof(ipfw_table_value));
}
+/*
+ * Export real table value @v to current userland format.
+ * Note that @v and @piv may point to the same memory.
+ */
void
ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *piv)
{
@@ -678,6 +700,10 @@ ipfw_export_table_value_v1(struct table_
memcpy(piv, &iv, sizeof(iv));
}
+/*
+ * Exports real value data into ipfw_table_value structure.
+ * Utilizes "spare1" field to store kernel index.
+ */
static void
dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
{
More information about the svn-src-projects
mailing list