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>