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