PERFORCE change 165359 for review
Tatsiana Elavaya
tsel at FreeBSD.org
Sun Jun 28 21:50:40 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=165359
Change 165359 by tsel at tsel_mz on 2009/06/28 21:50:04
Finish per rule optimization instruction rewrite. Add negative match optimization
Affected files ...
.. //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.c#8 edit
.. //depot/projects/soc2009/tsel_ipfw/sys/netinet/ip_fw2.c#5 edit
Differences ...
==== //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.c#8 (text+ko) ====
@@ -1619,8 +1619,14 @@
break;
case O_OPTIMIZE:
- if (co.verbose)
- printf(" [optimize %d %u]", cmd->arg1, ((ipfw_insn_u32*)cmd)->d[0]);
+ if (co.verbose) {
+ int i, cnt = (F_LEN(cmd) - 1) * 2;
+ printf(" [optimize");
+ for (i = 0; i < cnt; i++)
+ if (((ipfw_insn_u16*)cmd)->ports[i])
+ printf(" %d", ((ipfw_insn_u16*)cmd)->ports[i]);
+ printf("]");
+ }
break;
default:
@@ -2067,9 +2073,9 @@
int
insn_eq(ipfw_insn *a, ipfw_insn *b)
{
- if ((a->len | b->len) & (F_NOT | F_OR))
+ if ((a->len | b->len) & F_OR)
return 0;
- if (F_LEN(a) != F_LEN(b) || a->arg1 != b->arg1 || a->opcode != b->opcode)
+ if (a->len != b->len || a->arg1 != b->arg1 || a->opcode != b->opcode)
return 0;
switch (a->opcode) {
case O_IP_SRC:
@@ -2228,7 +2234,7 @@
&labels_max, &group_count, NULL, 0) == -1) {
errx(EX_DATAERR, "optimization not supported");
}
- labels_max *= 8;
+ labels_max *= 8 / 2; /* one label is 2 bits long */
group_count = 0;
LIST_FOREACH_SAFE(g, head, group_entries, g_tmp) {
@@ -2239,7 +2245,7 @@
LIST_REMOVE(g, group_entries);
continue;
}
- g->label = group_count++;
+ g->label = (group_count++) + 1;
printf("sorted: %d; opcode %d; match_count %d; rank %d\n",
g->label, LIST_FIRST(&g->match_head)->cmd->opcode,
g->match_count, g->rank);
@@ -2251,7 +2257,7 @@
optimization_setup(int enable, int labels)
{
if (enable) {
- labels = (labels + 7)/8;
+ labels = (labels + 3)/4;
if (sysctlbyname("net.inet.ip.fw.optimization_buf",
NULL, 0, &labels, sizeof(labels)) == -1) {
errx(EX_DATAERR, "optimization not supported");
@@ -2333,24 +2339,13 @@
for (i = 0; rules[i]; i++) {
ipfw_insn *cmd, *rcmd;
struct insn_match *m;
- ipfw_insn_u32 *optimize_cmd;
+ ipfw_insn_u16 *optimize_cmd;
+ int optimize_cnt = 0;
int l;
if (LIST_EMPTY(&match_rules[i].rule_head))
continue;
- printf("rule %d; before sort: ", rules[i]->rulenum);
- LIST_FOREACH(m, &match_rules[i].rule_head, rule_entries) {
- printf("optimize %d:%d; ", m->cmd->opcode, m->group->rank);
- }
- printf("\n");
- insn_match_rule_cmd_sort(&match_rules[i].rule_head, insn_match_rule_cmd_cmp);
- printf("rule %d; after sort: ", rules[i]->rulenum);
- LIST_FOREACH(m, &match_rules[i].rule_head, rule_entries) {
- printf("optimize %d:%d; ", m->cmd->opcode, m->group->rank);
- }
- printf("\n");
-
memcpy(orule, rules[i], sizeof(struct ip_fw) - 4);
cmd = orule->cmd;
rcmd = rules[i]->cmd;
@@ -2362,12 +2357,29 @@
l -= F_LEN(rcmd);
}
- // FIXME
- optimize_cmd = (ipfw_insn_u32 *) cmd;
- optimize_cmd->o.len = F_INSN_SIZE(ipfw_insn_u32);
+ optimize_cmd = (ipfw_insn_u16 *) cmd;
optimize_cmd->o.opcode = O_OPTIMIZE;
optimize_cmd->o.arg1 = 0;
- optimize_cmd->d[0] = 0;
+
+ /*
+ printf("rule %d; before sort: ", rules[i]->rulenum);
+ LIST_FOREACH(m, &match_rules[i].rule_head, rule_entries) {
+ printf("optimize %d:%d; ", m->cmd->opcode, m->group->rank);
+ }
+ printf("\n");
+ */
+ insn_match_rule_cmd_sort(&match_rules[i].rule_head, insn_match_rule_cmd_cmp);
+ //printf("rule %d; after sort: ", rules[i]->rulenum);
+ LIST_FOREACH(m, &match_rules[i].rule_head, rule_entries) {
+ //printf("optimize %d:%d; ", m->cmd->opcode, m->group->rank);
+ optimize_cmd->ports[optimize_cnt] = m->group->label;
+ if (optimize_cnt % 2 == 0)
+ optimize_cmd->ports[optimize_cnt + 1] = 0;
+ optimize_cnt++;
+ }
+ //printf("\n");
+
+ optimize_cmd->o.len = F_INSN_SIZE(ipfw_insn) + (optimize_cnt + 1) / 2;
cmd += optimize_cmd->o.len;
orule->cmd_len += optimize_cmd->o.len;
orule->act_ofs += optimize_cmd->o.len;
@@ -2394,35 +2406,10 @@
}
rcmd += F_LEN(rcmd);
}
- printf(" insn original: ");
+
+ printf("before optimization: ");
show_ipfw(rules[i], 0, 0);
- printf("insn reordered: ");
- show_ipfw(orule, 0, 0);
-
- /*
- LIST_FOREACH_SAFE(m, &match_rules[i].rule_head, rule_entries, m_tmp) {
- ipfw_insn_u32 optimize_cmd;
- int cmd_offset = ((int32_t*) m->cmd) - ((int32_t*) rules[i]->cmd);
-
- optimize_cmd.o.len = F_INSN_SIZE(ipfw_insn_u32);
- optimize_cmd.o.opcode = O_OPTIMIZE;
- optimize_cmd.o.arg1 = m->cmd->opcode;
- optimize_cmd.d[0] = m->group->label;
- if (cmd_offset >= orule->act_ofs)
- errx(EX_DATAERR, "optimizing action: rule %d\n", orule->rulenum);
- if (orule->cmd_len + F_LEN(&optimize_cmd.o) > 255)
- errx(EX_DATAERR, "option list is too long: rule %d", orule->rulenum);
- memcpy(orule->cmd + cmd_offset + F_LEN(&optimize_cmd.o),
- orule->cmd + cmd_offset,
- (orule->cmd_len - cmd_offset) * 4);
- memcpy(orule->cmd + cmd_offset, &optimize_cmd, F_LEN(&optimize_cmd.o) * 4);
- orule->cmd_len += F_LEN(&optimize_cmd.o);
- orule->act_ofs += F_LEN(&optimize_cmd.o);
- // printf("rule %d; cmd %d; offset %d\n", orule->rulenum, m->cmd->opcode, cmd_offset);
- }
- */
-
l = orule->rulenum & 0xffff;
if (do_cmd(IP_FW_DEL, &l, sizeof(l)))
errx(EX_DATAERR, "rule %u: setsockopt(IP_FW_DEL)", orule->rulenum);
@@ -2434,7 +2421,8 @@
show_ipfw(orule, 0, 0);
}
- optimization_setup(1, group_count);
+ if (group_count)
+ optimization_setup(1, group_count);
}
static int
==== //depot/projects/soc2009/tsel_ipfw/sys/netinet/ip_fw2.c#5 (text+ko) ====
@@ -362,7 +362,7 @@
if (sz > OPTIMIZATION_BUF_MAX)
sz = OPTIMIZATION_BUF_MAX;
- /* do not shrink buffers. ruleset may contain old o_optimize insn's */
+ /* do not shrink buffers. ruleset may contain old o_optimize instructions */
if (sz <= *(int *)arg1)
return 0;
@@ -2378,8 +2378,10 @@
/* end of ipv6 variables */
int is_ipv4 = 0;
-#define GET_OPTIMIZ_LABEL(a) (optimiz_buf ? optimiz_buf[(a) / 32] & (1 << ((a) % 32)) : 0)
-#define SET_OPTIMIZ_LABEL(a) (optimiz_buf ? optimiz_buf[(a) / 32] |= (1 << ((a) % 32)) : 0)
+#define GET_OPTIMIZ_LABEL(a) (optimiz_buf ? optimiz_buf[((a) - 1) / 32] & (1 << (((a) - 1) % 32)) : 0)
+#define SET_OPTIMIZ_LABEL(a) (optimiz_buf ? optimiz_buf[((a) - 1) / 32] |= (1 << (((a) - 1) % 32)) : 0)
+#define GET_NEG_OPTIMIZ_LABEL(a) GET_OPTIMIZ_LABEL((a) + V_optimization_buf_sz*4)
+#define SET_NEG_OPTIMIZ_LABEL(a) SET_OPTIMIZ_LABEL((a) + V_optimization_buf_sz*4)
uint32_t *optimiz_buf = NULL;
uint32_t optimiz_buf_ind = 0;
@@ -2693,9 +2695,10 @@
ipfw_insn *cmd;
uint32_t tablearg = 0;
int l, cmdlen, skip_or; /* skip rest of OR block */
- int optimiz_match = 0;
+ ipfw_insn_u16 *optimiz_cmd = NULL;
+ int optimiz_ind = 0, optimiz_match = 0;
#ifdef IPFW_OPTIMIZE_DEBUG
- ipfw_insn_u32 *optimiz_cmd = NULL;
+ int optimiz_match_neg = 0;
#endif
again:
@@ -2729,23 +2732,39 @@
}
match = 0; /* set to 1 if we succeed */
- if (V_optimization_enable && optimiz_match > 0 && cmd->opcode != O_OPTIMIZE) {
-#ifdef IPFW_OPTIMIZE_DEBUG
- if (optimiz_cmd->o.arg1 != cmd->opcode ||
- optimiz_cmd->d[0] + 1 != optimiz_match) {
- printf("ipfw: optimization error %d %d; expected %d %d\n",
- cmd->opcode, optimiz_match - 1,
- optimiz_cmd->o.arg1, optimiz_cmd->d[0] + 1);
- }
+ if (V_optimization_enable && optimiz_cmd != NULL && cmd->opcode != O_OPTIMIZE) {
+ int label = optimiz_cmd->ports[optimiz_ind];
+
+ if (optimiz_ind >= (F_LEN(&optimiz_cmd->o) - 1) * 2 || label == 0) {
+ optimiz_cmd = NULL;
+ optimiz_ind = 0;
+ optimiz_match = 0;
+ } else {
+ optimiz_ind++;
+ if (GET_OPTIMIZ_LABEL(label)) {
+ optimiz_match = label;
+ printf("ipfw: rule %d: optimized %d %d\n", f->rulenum, cmd->opcode, optimiz_match);
+#ifndef IPFW_OPTIMIZE_DEBUG
+ continue;
#else
- printf("ipfw: optimized %d %d\n", cmd->opcode, optimiz_match - 1);
- optimiz_match = 0;
- match = !(cmd->len & F_NOT);
+ optimiz_match_neg = 0;
#endif
- }
+ } if (GET_NEG_OPTIMIZ_LABEL(label)) {
+ optimiz_match = label;
+ printf("ipfw: rule %d: negative optimized %d %d\n", f->rulenum, cmd->opcode, optimiz_match);
#ifndef IPFW_OPTIMIZE_DEBUG
- else
+ goto next_rule;
+#else
+ optimiz_match_neg = 1;
#endif
+
+ } else {
+ optimiz_match = -label;
+ }
+ }
+
+ }
+
switch (cmd->opcode) {
/*
* The first set of opcodes compares the packet's
@@ -3291,23 +3310,25 @@
break;
}
case O_OPTIMIZE: {
- int label = ((ipfw_insn_u32 *) cmd)->d[0];
+ optimiz_cmd = (ipfw_insn_u16 *) cmd;
+ optimiz_ind = 0;
- if (!V_optimization_enable || !optimiz_buf ||
- label > V_optimization_buf_sz * 8)
+ if (!V_optimization_enable || !optimiz_buf) {
+ optimiz_cmd = NULL;
continue;
+ }
+
+ for (int i = 0; i < (F_LEN(cmd) - 1) * 2; i++)
+ if (optimiz_cmd->ports[i] > V_optimization_buf_sz * 8 / 2) {
+ printf("ipfw: invalid O_OPTIMIZE instruction. ignoring");
+ optimiz_cmd = NULL;
+ continue;
+ }
if (optimiz_match) {
printf("ipfw: unexpected O_OPTIMIZE instruction. ignoring");
continue;
}
-#ifdef IPFW_OPTIMIZE_DEBUG
- optimiz_cmd = (ipfw_insn_u32 *) cmd;
-#endif
- if (GET_OPTIMIZ_LABEL(label))
- optimiz_match = label + 1;
- else
- optimiz_match = -(label + 1);
continue;
}
@@ -3613,26 +3634,25 @@
panic("-- unknown opcode %d\n", cmd->opcode);
} /* end of switch() on opcodes */
+ if (cmd->len & F_NOT)
+ match = !match;
+
#ifdef IPFW_OPTIMIZE_DEBUG
- if (optimiz_match > 0 && !match)
- printf("ipfw: optimization error: cmd mismatch %d (optimiz_cmd=%d) %d\n", cmd->opcode, optimiz_cmd->o.arg1, optimiz_match);
+ if (optimiz_match > 0 && (match != !optimiz_match_neg || cmd->len & F_OR))
+ printf("ipfw: rule %d: optimization error: cmd mismatch %d (optimiz_ind=%d, neg=%d) %d\n", f->rulenum, cmd->opcode, optimiz_ind, optimiz_match_neg, optimiz_match);
#endif
if (V_optimization_enable) {
- if (match) {
- if (optimiz_match < 0) {
- optimiz_match = -optimiz_match - 1;
+ if (optimiz_match < 0) {
+ optimiz_match = -optimiz_match;
+ if (match)
SET_OPTIMIZ_LABEL(optimiz_match);
- printf("ipfw: set optimize match %d %d\n", cmd->opcode, optimiz_match);
- optimiz_match = 0;
- }
- } else {
- optimiz_match = 0;
+ else
+ SET_NEG_OPTIMIZ_LABEL(optimiz_match);
+ printf("ipfw: rule %d: set %soptimize match %d %d\n", f->rulenum, match ? "" : "negative ", cmd->opcode, optimiz_match);
}
+ optimiz_match = 0;
}
- if (cmd->len & F_NOT)
- match = !match;
-
if (match) {
if (cmd->len & F_OR)
skip_or = 1;
@@ -4230,7 +4250,7 @@
break;
case O_OPTIMIZE:
- if (cmdlen < F_INSN_SIZE(ipfw_insn_u32))
+ if (cmdlen < F_INSN_SIZE(ipfw_insn_u16))
goto bad_size;
break;
More information about the p4-projects
mailing list