Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Jul 2014 16:06:47 GMT
From:      dpl@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r271610 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw
Message-ID:  <201407301606.s6UG6lig053320@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dpl
Date: Wed Jul 30 16:06:47 2014
New Revision: 271610
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=271610

Log:
  Added the loop, to be refined, to iterate through the ruleset in order to get the rules to be compiled.

Modified:
  soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc

Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Wed Jul 30 15:43:17 2014	(r271609)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Wed Jul 30 16:06:47 2014	(r271610)
@@ -17,6 +17,11 @@
 
 typedef int (*funcptr)();
 
+extern "C" {
+VNET_DECLARE(struct ip_fw_chain, layer3_chain);
+#define	V_layer3_chain		VNET(layer3_chain)
+}
+
 using namespace llvm;
 
 class jitCompiler { 
@@ -68,6 +73,463 @@
 	// XXX Now I have to load the stubs of the loaded rules.
 	// For that, I need a table: RULE, "functname", #args
 	// Iterate through the rules.
+	if (args->rule.slot) {
+		/*
+		 * Packet has already been tagged as a result of a previous
+		 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
+		 * REASS, NETGRAPH, DIVERT/TEE...)
+		 * Validate the slot and continue from the next one
+		 * if still present, otherwise do a lookup.
+		 */
+		f_pos = (args->rule.chain_id == chain->id) ?
+		    args->rule.slot :
+		    ipfw_find_rule(chain, args->rule.rulenum,
+			args->rule.rule_id);
+	} else {
+		f_pos = 0;
+	}
+
+	// Iterate through the rules.
+	for (; f_pos < chain->n_rules; f_pos++) {
+		ipfw_insn *cmd;
+		uint32_t tablearg = 0;
+		int l, cmdlen, skip_or; /* skip rest of OR block */
+		struct ip_fw *f;
+
+		f = chain->map[f_pos];
+		if (V_set_disable & (1 << f->set) )
+			continue;
+
+		skip_or = 0;
+		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
+		    l -= cmdlen, cmd += cmdlen) {
+			int match;
+			/*
+			 * check_body is a jump target used when we find a
+			 * CHECK_STATE, and need to jump to the body of
+			 * the target rule.
+			 */
+
+/* check_body: */
+			cmdlen = F_LEN(cmd);
+			/*
+			 * An OR block (insn_1 || .. || insn_n) has the
+			 * F_OR bit set in all but the last instruction.
+			 * The first match will set "skip_or", and cause
+			 * the following instructions to be skipped until
+			 * past the one with the F_OR bit clear.
+			 */
+			if (skip_or) {		/* skip this instruction */
+				if ((cmd->len & F_OR) == 0)
+					skip_or = 0;	/* next one is good */
+				continue;
+			}
+			match = 0; /* set to 1 if we succeed */
+
+			switch (cmd->opcode) {
+			case O_NOP:
+				rule_nop(&match);
+				break;
+
+			case O_FORWARD_MAC:
+				rule_forward_mac(cmd->opcode);
+				break;
+
+			case O_GID:
+			case O_UID:
+			case O_JAIL:
+				rule_jail(&match, offset, proto, cmd, args, ucred_lookup, ucred_cache);
+				break;
+
+			case O_RECV:
+				rule_recv(&match, cmd, m, chain, &tablearg);
+				break;
+
+			case O_XMIT:
+				rule_xmit(&match, oif, cmd, chain, &tablearg);
+				break;
+
+			case O_VIA:
+				rule_via(&match, oif, m, cmd, chain, &tablearg);
+				break;
+
+			case O_MACADDR2:
+				rule_macaddr2(&match, args, cmd);
+				break;
+
+			case O_MAC_TYPE:
+				rule_mac_type(&match, args, cmd, cmdlen, etype);
+				break;
+
+			case O_FRAG:
+				rule_frag(&match, offset);
+				break;
+
+			case O_IN:
+				rule_in(&match, oif);
+				break;
+
+			case O_LAYER2:
+				rule_layer2(&match, args);
+				break;
+
+			case O_DIVERTED:
+				rule_diverted(&match, args, cmd);
+				break;
+
+			case O_PROTO:
+				rule_proto(&match, proto, cmd);
+				break;
+
+			case O_IP_SRC:
+				rule_ip_src(&match, is_ipv4, cmd, &src_ip);
+				break;
+
+			case O_IP_SRC_LOOKUP:
+			case O_IP_DST_LOOKUP:
+				rule_ip_dst_lookup(&match, cmd, cmdlen, args, &tablearg, is_ipv4, is_ipv6, ip, &dst_ip, &src_ip, dst_port, src_port, offset, proto, ucred_lookup, ucred_cache, chain);
+				break;
+
+			case O_IP_SRC_MASK:
+			case O_IP_DST_MASK:
+				rule_ip_dst_mask(&match, is_ipv4, cmd, cmdlen, &dst_ip, &src_ip);
+				break;
+
+			case O_IP_SRC_ME:
+				rule_ip_src_me(&match, is_ipv4, is_ipv6, &src_ip, args);
+#ifdef INET6
+				/* FALLTHROUGH */
+			case O_IP6_SRC_ME:
+				rule_ip6_src_me(&match, is_ipv6, args);
+#endif
+				break;
+
+			case O_IP_DST_SET:
+			case O_IP_SRC_SET:
+				rule_ip_src_set(&match, is_ipv4, cmd, args);
+				break;
+
+			case O_IP_DST:
+				rule_ip_dst(&match, is_ipv4, cmd, &dst_ip);
+				break;
+
+			case O_IP_DST_ME:
+				rule_ip_dst_me(&match, args, is_ipv4, is_ipv6, &dst_ip);
+				
+#ifdef INET6
+				/* FALLTHROUGH */
+			case O_IP6_DST_ME:
+				rule_ip6_dst_me(&match, args, is_ipv6);
+#endif
+				break;
+
+
+			case O_IP_SRCPORT:
+			case O_IP_DSTPORT:
+				rule_ip_dstport(&match, proto, offset, cmd, cmdlen, dst_port, src_port);
+				break;
+
+			case O_ICMPTYPE:
+				rule_icmptype(&match, offset, proto, ulp, cmd);
+				break;
+
+#ifdef INET6
+			case O_ICMP6TYPE:
+				rule_icmp6type(&match, offset, is_ipv6, proto, ulp, cmd);
+				break;
+#endif /* INET6 */
+
+			case O_IPOPT:
+				rule_ipopt(&match, is_ipv4, ip, cmd);
+				break;
+
+			case O_IPVER:
+				rule_ipver(&match, is_ipv4, cmd, ip);
+				break;
+
+			case O_IPID:
+			case O_IPLEN:
+			case O_IPTTL:
+				rule_ipttl(&match, is_ipv4, cmd, cmdlen, ip, iplen);
+				break;
+
+			case O_IPPRECEDENCE:
+				rule_ipprecedence(&match, is_ipv4, cmd, ip);
+				break;
+
+			case O_IPTOS:
+				rule_iptos(&match, is_ipv4, cmd, ip);
+				break;
+
+			case O_DSCP:
+				rule_dscp(&match, is_ipv4, is_ipv6, cmd, ip);
+				break;
+
+			case O_TCPDATALEN:
+				rule_tcpdatalen(&match, proto, offset, ulp, iplen, cmdlen, cmd, ip);
+				break;
+
+			case O_TCPFLAGS:
+				rule_tcpflags(&match, proto, offset, cmd, ulp);
+				break;
+
+			case O_TCPOPTS:
+				if (rule_tcpopts(&match, hlen, ulp, proto, offset, cmd, m, args))
+					goto pullup_failed;
+				break;
+
+			case O_TCPSEQ:
+				rule_tcpseq(&match, proto, offset, cmd, ulp);
+				break;
+
+			case O_TCPACK:
+				rule_tcpack(&match, proto, offset, cmd, ulp);
+				break;
+
+			case O_TCPWIN:
+				rule_tcpwin(&match, proto, offset, cmd, cmdlen, ulp);
+				break;
+
+			case O_ESTAB:
+				rule_estab(&match, proto, offset, ulp);
+				break;
+
+			case O_ALTQ:
+				rule_altq(&match, cmd, m, ip);
+				break;
+
+			case O_LOG:
+				rule_log(&match, f, hlen, args, m, oif, offset, ip6f_mf, tablearg, ip);
+				break;
+
+			case O_PROB:
+				rule_prob(&match, cmd);
+				break;
+
+			case O_VERREVPATH:
+				rule_verrevpath(&match, oif, m, is_ipv6, args, &src_ip);
+				break;
+
+			case O_VERSRCREACH:
+				rule_versrcreach(&match, hlen, oif, is_ipv6, args, &src_ip);
+				break;
+
+			case O_ANTISPOOF:
+				rule_antispoof(&match, oif, hlen, is_ipv4, is_ipv6, &src_ip, args, m);
+				break;
+
+			case O_IPSEC:
+#ifdef IPSEC
+				rule_ipsec(&match, m);
+#endif
+				/* otherwise no match */
+				break;
+
+#ifdef INET6
+			case O_IP6_SRC:
+				rule_ip6_src(&match, is_ipv6, args, cmd);
+				break;
+
+			case O_IP6_DST:
+				rule_ip6_dst(&match, is_ipv6, args, cmd);
+				break;
+
+			case O_IP6_SRC_MASK:
+			case O_IP6_DST_MASK:
+				rule_ip6_dst_mask(&match, args, cmd, cmdlen, is_ipv6);
+				break;
+
+			case O_FLOW6ID:
+				rule_flow6id(&match, is_ipv6, args, cmd);
+				break;
+
+			case O_EXT_HDR:
+				rule_ext_hdr(&match, is_ipv6, ext_hd, cmd);
+				break;
+
+			case O_IP6:
+				rule_ip6(&match, is_ipv6);
+				break;
+#endif
+
+			case O_IP4:
+				rule_ip4(&match, is_ipv4);
+				break;
+
+			case O_TAG: 
+				rule_tag(&match, cmd, m, tablearg);
+				break;
+
+			case O_FIB: /* try match the specified fib */
+				rule_fib(&match, args, cmd);
+				break;
+
+			case O_SOCKARG:
+				rule_sockarg(&match, is_ipv6, proto, &dst_ip, &src_ip, dst_port, src_port, args, &tablearg);
+				break;
+
+			case O_TAGGED:
+				rule_tagged(&match, cmd, cmdlen, m, tablearg);
+				break;
+				
+			/*
+			 * The second set of opcodes represents 'actions',
+			 * i.e. the terminal part of a rule once the packet
+			 * matches all previous patterns.
+			 * Typically there is only one action for each rule,
+			 * and the opcode is stored at the end of the rule
+			 * (but there are exceptions -- see below).
+			 *
+			 * In general, here we set retval and terminate the
+			 * outer loop (would be a 'break 3' in some language,
+			 * but we need to set l=0, done=1)
+			 *
+			 * Exceptions:
+			 * O_COUNT and O_SKIPTO actions:
+			 *   instead of terminating, we jump to the next rule
+			 *   (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;
+			 *
+			 * O_LIMIT and O_KEEP_STATE: these opcodes are
+			 *   not real 'actions', and are stored right
+			 *   before the 'action' part of the rule.
+			 *   These opcodes try to install an entry in the
+			 *   state tables; if successful, we continue with
+			 *   the next opcode (match=1; break;), otherwise
+			 *   the packet must be dropped (set retval,
+			 *   break loops with l=0, done=1)
+			 *
+			 * O_PROBE_STATE and O_CHECK_STATE: these opcodes
+			 *   cause a lookup of the state table, and a jump
+			 *   to the 'action' part of the parent rule
+			 *   if an entry is found, or
+			 *   (CHECK_STATE only) a jump to the next rule if
+			 *   the entry is not found.
+			 *   The result of the lookup is cached so that
+			 *   further instances of these opcodes become NOPs.
+			 *   The jump to the next rule is done by setting
+			 *   l=0, cmdlen=0.
+			 */
+			case O_LIMIT:
+			case O_KEEP_STATE:
+				rule_keep_state(&match, f, cmd, args, tablearg, &retval, &l, &done);
+				break;
+
+			case O_PROBE_STATE:
+			case O_CHECK_STATE:
+				rule_check_state(&match, &dyn_dir, q, args, proto, ulp, pktlen, f, &f_pos, chain, cmd, &cmdlen, &l);
+				break;
+
+			case O_ACCEPT:
+				rule_accept(&retval, &l, &done);
+				break;
+
+			case O_PIPE:
+			case O_QUEUE:
+				rule_queue(args, f_pos, chain, cmd, tablearg, &retval, &l, &done);
+				break;
+
+			case O_DIVERT:
+			case O_TEE:
+				rule_tee(&l, &done, &retval, cmd, args, f_pos, tablearg, chain);
+				break;
+
+			case O_COUNT:
+				rule_count(&l, f, pktlen);
+				break;
+
+			case O_SKIPTO:
+				rule_skipto(&match, &l, cmd, &cmdlen, &skip_or, &f_pos, f, pktlen, chain, tablearg);
+			    continue;
+			    break;	/* NOTREACHED */
+
+			case O_CALLRETURN:
+				rule_callreturn(cmd, m, f, chain, tablearg, pktlen, &skip_or, &cmdlen, &f_pos, &l);
+				continue;
+				break;	/* NOTREACHED */
+
+			case O_REJECT:
+				rule_reject(hlen, is_ipv4, offset, proto, ulp, m, &dst_ip, args, cmd, iplen, ip);
+				/* FALLTHROUGH */
+#ifdef INET6
+			case O_UNREACH6:
+				rule_unreach6(hlen, is_ipv6, offset, proto, icmp6_type, m, args, cmd, ip);
+				/* FALLTHROUGH */
+#endif
+			case O_DENY:
+				rule_deny(&l, &done, &retval);
+				break;
+
+			case O_FORWARD_IP:
+				rule_forward_ip(args, q, f, dyn_dir, cmd, tablearg, &retval, &l, &done);
+				break;
+
+#ifdef INET6
+			case O_FORWARD_IP6:
+				rule_forward_ip6(args, q, f, dyn_dir, cmd, &retval, &l, &done);
+				break;
+#endif
+
+			case O_NETGRAPH:
+			case O_NGTEE:
+				rule_ngtee(args, f_pos, chain, cmd, tablearg, &retval, &l, &done);
+				break;
+
+			case O_SETFIB:
+				rule_setfib(f, pktlen, tablearg, cmd, m, args, &l);
+				break;
+
+			case O_SETDSCP:
+				rule_setdscp(cmd, ip, is_ipv4, is_ipv6, tablearg, f, pktlen, &l);
+				break;
+
+			case O_NAT:
+				rule_nat(args, f_pos, chain, cmd, m, tablearg, &retval, &done, &l);
+				break;
+
+			case O_REASS:
+				rule_reass(f, f_pos, chain, pktlen, ip, args, m, &retval, &done, &l);
+				break;
+
+			default:
+				panic("-- unknown opcode %d\n", cmd->opcode);
+			} /* end of switch() on opcodes */
+			/*
+			 * if we get here with l=0, then match is irrelevant.
+			 */
+
+			if (cmd->len & F_NOT)
+				match = !match;
+
+			if (match) {
+				if (cmd->len & F_OR)
+					skip_or = 1;
+			} else {
+				if (!(cmd->len & F_OR)) /* not an OR block, */
+					break;		/* try next rule    */
+			}
+
+		}	/* end of inner loop, scan opcodes */
+#undef PULLUP_LEN
+
+		if (done)
+			break;
+
+/* next_rule:; */	/* try next rule		*/
+
+	}		/* end of outer for, scan rules */
+
+	if (done) {
+		struct ip_fw *rule = chain->map[f_pos];
+		/* Update statistics */
+		IPFW_INC_RULE_COUNTER(rule, pktlen);
+	} else {
+		retval = IP_FW_DENY;
+		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
+	}
 
 	/*
 	// Get the stub (prototype) for the cell function



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407301606.s6UG6lig053320>