Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105114605
D31484.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D31484.diff
View Options
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -144,14 +144,14 @@
/* Use 128 tables by default */
static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
+static int jump_lookup_pos(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+ int tablearg, int jump_backwards);
#ifndef LINEAR_SKIPTO
-static int jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+static int jump_cached(struct ip_fw_chain *chain, struct ip_fw *f, int num,
int tablearg, int jump_backwards);
-#define JUMP(ch, f, num, targ, back) jump_fast(ch, f, num, targ, back)
+#define JUMP(ch, f, num, targ, back) jump_cached(ch, f, num, targ, back)
#else
-static int jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
- int tablearg, int jump_backwards);
-#define JUMP(ch, f, num, targ, back) jump_linear(ch, f, num, targ, back)
+#define JUMP(ch, f, num, targ, back) jump_lookup_pos(ch, f, num, targ, back)
#endif
/*
@@ -1227,60 +1227,83 @@
args->flags |= IPFW_ARGS_REF;
}
-#ifndef LINEAR_SKIPTO
-/*
- * Helper function to enable cached rule lookups using
- * cached_id and cached_pos fields in ipfw rule.
- */
static int
-jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+jump_lookup_pos(struct ip_fw_chain *chain, struct ip_fw *f, int num,
int tablearg, int jump_backwards)
{
- int f_pos;
+ int f_pos, i;
- /* If possible use cached f_pos (in f->cached_pos),
- * whose version is written in f->cached_id
- * (horrible hacks to avoid changing the ABI).
- */
- if (num != IP_FW_TARG && f->cached_id == chain->id)
- f_pos = f->cached_pos;
- else {
- int i = IP_FW_ARG_TABLEARG(chain, num, skipto);
- /* make sure we do not jump backward */
- if (jump_backwards == 0 && i <= f->rulenum)
- i = f->rulenum + 1;
- if (chain->idxmap != NULL)
- f_pos = chain->idxmap[i];
- else
- f_pos = ipfw_find_rule(chain, i, 0);
- /* update the cache */
- if (num != IP_FW_TARG) {
- f->cached_id = chain->id;
- f->cached_pos = f_pos;
- }
- }
+ i = IP_FW_ARG_TABLEARG(chain, num, skipto);
+ /* make sure we do not jump backward */
+ if (jump_backwards == 0 && i <= f->rulenum)
+ i = f->rulenum + 1;
+
+#ifndef LINEAR_SKIPTO
+ if (chain->idxmap != NULL)
+ f_pos = chain->idxmap[i];
+ else
+ f_pos = ipfw_find_rule(chain, i, 0);
+#else
+ f_pos = chain->idxmap[i];
+#endif /* LINEAR_SKIPTO */
return (f_pos);
}
-#else
+
+
+#ifndef LINEAR_SKIPTO
/*
- * Helper function to enable real fast rule lookups.
+ * Helper function to enable cached rule lookups using
+ * cache.id and cache.pos fields in ipfw rule.
*/
static int
-jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+jump_cached(struct ip_fw_chain *chain, struct ip_fw *f, int num,
int tablearg, int jump_backwards)
{
int f_pos;
- num = IP_FW_ARG_TABLEARG(chain, num, skipto);
- /* make sure we do not jump backward */
- if (jump_backwards == 0 && num <= f->rulenum)
- num = f->rulenum + 1;
- f_pos = chain->idxmap[num];
+ /* Can't use cache with IP_FW_TARG */
+ if (num == IP_FW_TARG)
+ return jump_lookup_pos(chain, f, num, tablearg, jump_backwards);
+
+ /*
+ * If possible use cached f_pos (in f->cache.pos),
+ * whose version is written in f->cache.id (horrible hacks
+ * to avoid changing the ABI).
+ *
+ * Multiple threads can execute the same rule simultaneously,
+ * we need to ensure that cache.pos is updated before cache.id.
+ */
+#ifdef __LP64__
+ struct ip_fw_jump_cache cache;
+
+ cache.raw_value = f->cache.raw_value;
+ if (cache.id == chain->id)
+ return (cache.pos);
+
+ f_pos = jump_lookup_pos(chain, f, num, tablearg, jump_backwards);
+
+ cache.pos = f_pos;
+ cache.id = chain->id;
+ f->cache.raw_value = cache.raw_value;
+#else
+ if (f->cache.id == chain->id) {
+ /* Load pos after id */
+ atomic_thread_fence_acq();
+ return (f->cache.pos);
+ }
+
+ f_pos = jump_lookup_pos(chain, f, num, tablearg, jump_backwards);
+
+ f->cache.pos = f_pos;
+ /* Store id after pos */
+ atomic_thread_fence_rel();
+ f->cache.id = chain->id;
+#endif /* !__LP64__ */
return (f_pos);
}
-#endif
+#endif /* !LINEAR_SKIPTO */
#define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f)
/*
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
--- a/sys/netpfil/ipfw/ip_fw_private.h
+++ b/sys/netpfil/ipfw/ip_fw_private.h
@@ -265,6 +265,15 @@
* ACTION_PTR(r) is the start of the first action (things to do
* once a rule matched).
*/
+struct ip_fw_jump_cache {
+ union {
+ struct {
+ uint32_t id;
+ uint32_t pos;
+ };
+ uint64_t raw_value;
+ };
+};
struct ip_fw {
uint16_t act_ofs; /* offset of action in 32-bit units */
@@ -273,10 +282,9 @@
uint8_t set; /* rule set (0..31) */
uint8_t flags; /* currently unused */
counter_u64_t cntr; /* Pointer to rule counters */
+ struct ip_fw_jump_cache cache; /* used by jump_fast */
uint32_t timestamp; /* tv_sec of last match */
uint32_t id; /* rule id */
- uint32_t cached_id; /* used by jump_fast */
- uint32_t cached_pos; /* used by jump_fast */
uint32_t refcnt; /* number of references */
struct ip_fw *next; /* linked list of deleted rules */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Dec 13, 12:59 PM (15 m, 3 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15360175
Default Alt Text
D31484.diff (5 KB)
Attached To
Mode
D31484: Fix data race in jump cache read/update
Attached
Detach File
Event Timeline
Log In to Comment