svn commit: r200851 - user/luigi/ipfw3-head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Tue Dec 22 17:02:57 UTC 2009


Author: luigi
Date: Tue Dec 22 17:02:57 2009
New Revision: 200851
URL: http://svn.freebsd.org/changeset/base/200851

Log:
  restore the skipto cache, so we have O(1) cost for direct skipto.

Modified:
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_sockopt.c

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c	Tue Dec 22 16:06:38 2009	(r200850)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c	Tue Dec 22 17:02:57 2009	(r200851)
@@ -1189,7 +1189,7 @@ do {								\
 	 * need to break out of one or both loops, or re-enter one of
 	 * the loops with updated variables. Loop variables are:
 	 *
-	 *	f (outer loop) points to the current rule.
+	 *	f_pos (outer loop) points to the current rule.
 	 *		On output it points to the matching rule.
 	 *	done (outer loop) is used as a flag to break the loop.
 	 *	l (inner loop)	residual length of current rule.
@@ -1198,7 +1198,7 @@ do {								\
 	 * We break the inner loop by setting l=0 and possibly
 	 * cmdlen=0 if we don't want to advance cmd.
 	 * We break the outer loop by setting done=1
-	 * We can restart the inner loop by setting l>0 and f, cmd
+	 * We can restart the inner loop by setting l>0 and f_pos, f, cmd
 	 * as needed.
 	 */
 	for (; f_pos < chain->n_rules; f_pos++) {
@@ -1827,8 +1827,8 @@ do {								\
 			 * Exceptions:
 			 * O_COUNT and O_SKIPTO actions:
 			 *   instead of terminating, we jump to the next rule
-			 *   (setting l=0), or to the SKIPTO target (by
-			 *   setting f, cmd and l as needed), respectively.
+			 *   (setting l=0), or to the SKIPTO target (setting
+			 *   f/f_len, cmd and l as needed), respectively.
 			 *
 			 * O_TAG, O_LOG and O_ALTQ action parameters:
 			 *   perform some action and set match = 1;
@@ -1892,7 +1892,7 @@ do {								\
 					/* XXX we would like to have f_pos
 					 * readily accessible in the dynamic
 				         * rule, instead of having to
-					 * looku q->rule.
+					 * lookup q->rule.
 					 */
 					f = q->rule;
 					f_pos = ipfw_find_rule(chain,
@@ -1959,39 +1959,57 @@ do {								\
 				break;
 
 			case O_COUNT:
-			case O_SKIPTO:
-			    {
-				int i;
-
 				f->pcnt++;	/* update stats */
 				f->bcnt += pktlen;
 				f->timestamp = time_uptime;
-				if (cmd->opcode == O_COUNT) {
-					l = 0;		/* exit inner loop */
-					break;
-				}
-				/* skipto: */
-				i = (cmd->arg1 == IP_FW_TABLEARG) ?
+				l = 0;		/* exit inner loop */
+				break;
+
+			case O_SKIPTO:
+			    f->pcnt++;	/* update stats */
+			    f->bcnt += pktlen;
+			    f->timestamp = time_uptime;
+			    /* If possible use cached f_pos (in f->next_rule),
+			     * whose version is written in f->next_rule
+			     * (horrible hacks to avoid changing the ABI).
+			     */
+			    if (cmd->arg1 != IP_FW_TABLEARG &&
+				    (uint32_t)f->x_next == chain->id) {
+				f_pos = (uint32_t)f->next_rule;
+			    } else {
+				int i = (cmd->arg1 == IP_FW_TABLEARG) ?
 					tablearg : cmd->arg1;
 				/* make sure we do not jump backward */
 				if (i <= f->rulenum)
-					i = f->rulenum + 1;
+				    i = f->rulenum + 1;
 				f_pos = ipfw_find_rule(chain, i, 0);
+				/* update the cache */
+				if (cmd->arg1 != IP_FW_TABLEARG) {
+				    f->next_rule =
+					(void *)(uintptr_t)f_pos;
+				    f->x_next =
+					(void *)(uintptr_t)chain->id;
+				}
 			    }
-				/*
-				 * Skip disabled rules, and
-				 * re-enter the inner loop
-				 * with the correct f, l and cmd.
-				 * Also clear cmdlen and skip_or
-				 */
-				for (; f_pos < chain->n_rules - 1 && (V_set_disable & (1 << chain->map[f_pos]->set)); f_pos++)
-					;
-				l = f->cmd_len;
-				cmd = f->cmd;
-				match = 1;
-				cmdlen = 0;
-				skip_or = 0;
-				break;
+			    /*
+			     * Skip disabled rules, and re-enter
+			     * the inner loop with the correct
+			     * f_pos, f, l and cmd.
+			     * Also clear cmdlen and skip_or
+			     */
+			    for (; f_pos < chain->n_rules - 1 &&
+				    (V_set_disable &
+				     (1 << chain->map[f_pos]->set));
+				    f_pos++)
+				;
+			    /* prepare to enter the inner loop */
+			    f = chain->map[f_pos];
+			    l = f->cmd_len;
+			    cmd = f->cmd;
+			    match = 1;
+			    cmdlen = 0;
+			    skip_or = 0;
+			    break;
 
 			case O_REJECT:
 				/*

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_sockopt.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_sockopt.c	Tue Dec 22 16:06:38 2009	(r200850)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_sockopt.c	Tue Dec 22 17:02:57 2009	(r200851)
@@ -180,9 +180,9 @@ ipfw_add_rule(struct ip_fw_chain *chain,
 	}
 
 	bcopy(input_rule, rule, l);
+	/* clear fields not settable from userland */
 	rule->x_next = NULL;
-	//rule->next_rule = NULL;
-
+	rule->next_rule = NULL;
 	rule->pcnt = 0;
 	rule->bcnt = 0;
 	rule->timestamp = 0;


More information about the svn-src-user mailing list