socsvn commit: r272599 - in soc2014/dpl/netmap-ipfwjit: . sys/netpfil/ipfw
dpl at FreeBSD.org
dpl at FreeBSD.org
Mon Aug 18 10:23:43 UTC 2014
Author: dpl
Date: Mon Aug 18 10:23:41 2014
New Revision: 272599
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272599
Log:
Added all the flow control necessary to JIT compile the rules.
Modified:
soc2014/dpl/netmap-ipfwjit/Makefile.kipfw
soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc
Modified: soc2014/dpl/netmap-ipfwjit/Makefile.kipfw
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/Makefile.kipfw Mon Aug 18 09:40:19 2014 (r272598)
+++ soc2014/dpl/netmap-ipfwjit/Makefile.kipfw Mon Aug 18 10:23:41 2014 (r272599)
@@ -141,7 +141,7 @@
EFILES = $(foreach i,$(EDIRS),$(subst $(empty) , $(i)/, $(EFILES_$(i): = )))
BCFLAGS=-emit-llvm -c
-CXXFLAGS=`llvm-config-devel --cxxflags`
+CXXFLAGS= -g `llvm-config-devel --cxxflags`
include_e:
- at echo "Building $(OBJPATH)/include_e ..."
@@ -169,7 +169,7 @@
$(HIDE)clang++ -o $@ $^ $(LIBS)
jit.o: jit.cc ../ip_fw_rules.bc
- clang++ $(J_CFLAGS) $(CXXFLAGS) ../sys/netpfil/ipfw/jit.cc -o ./jit.o
+ clang++ -v $(J_CFLAGS) $(CXXFLAGS) $(LIBS) ../sys/netpfil/ipfw/jit.cc -o ./jit.o
clean:
-rm -f *.o $(DN) $(MOD)
Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Mon Aug 18 09:40:19 2014 (r272598)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Mon Aug 18 10:23:41 2014 (r272599)
@@ -8,9 +8,14 @@
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CodeGen/MachineCodeInfo.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/IR/BasicBlock.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Value.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/ErrorOr.h>
#define _KERNEL
@@ -50,13 +55,18 @@
Type *int8Ty;
Type *int16Ty;
Type *int32Ty;
+ Type *int64Ty;
PointerType *int8PtrTy;
// Basic blocks used
- BasicBlock *entry;
+ BasicBlock *entry, *end;
BasicBlock *pullup_failed;
BasicBlock *startrules;
- BasicBlock *end;
+ BasicBlock *outer_for_prologue;
+ BasicBlock *inner_for_prologue;
+ BasicBlock *outer_for_epilogue;
+ BasicBlock *inner_for_epilogue;
+
// This BB is the next emitted rule, always.
BasicBlock *next;
@@ -70,11 +80,16 @@
Value *done;
Value *f_pos;
Value *retval;
+ Value *cmd;
+ Value *cmdlen;
+ Value *tablearg;
+ Value *skip_or;
+ Value *f;
// Packet matching variables.
Value *m;
Value *ip;
- Value *ucred;
+ Value *ucred_cache;
Value *ucred_lookup;
Value *oif;
Value *hlen; //unsigned
@@ -127,6 +142,7 @@
// Not pkg-filtering related funcs.
Function *printfFunc;
Function *ipfw_find_rule;
+ Function *crfree;
// Used structs.
StructType *ifnetTy;
@@ -135,7 +151,7 @@
StructType *ip_fw_argsTy;
StructType *ip_fw_chainTy;
StructType *ip_fwTy;
- StructType *ip_fw_insnTy;
+ StructType *ipfw_insnTy;
StructType *ipfw_dyn_ruleTy;
StructType *ipfw_insn_ifTy;
StructType *mbufTy;
@@ -148,7 +164,7 @@
PointerType *ip_fw_argsPtrTy;
PointerType *ip_fw_chainPtrTy;
PointerType *ip_fwPtrTy;
- PointerType *ip_fw_insnPtrTy;
+ PointerType *ipfw_insnPtrTy;
PointerType *ipfw_dyn_rulePtrTy;
PointerType *ipfw_insn_ifPtrTy;
PointerType *mbufPtrTy;
@@ -193,6 +209,7 @@
int8Ty = Type::getInt8Ty(con);
int16Ty = Type::getInt16Ty(con);
int32Ty = Type::getInt32Ty(con);
+ int64Ty = Type::getInt64Ty(con);
int8PtrTy = PointerType::getUnqual(int8Ty);
// Get StrucType from bitcode.
@@ -203,7 +220,7 @@
ip_fw_argsTy = mod->getTypeByName("ip_fw_args");
ip_fw_chainTy = mod->getTypeByName("ip_fw_chain");
ip_fwTy = mod->getTypeByName("ip_fw");
- ip_fw_insnTy = mod->getTypeByName("_ip_fw_insn");
+ ipfw_insnTy = mod->getTypeByName("_ipfw_insn");
ipfw_insn_ifTy = mod->getTypeByName("_ipfw_insn_if");
mbufTy = mod->getTypeByName("mbuf");
#ifdef __FreeBSD__
@@ -220,7 +237,7 @@
ip_fw_argsPtrTy = PointerType::get(ip_fw_argsTy, 0);
ip_fw_chainPtrTy = PointerType::get(ip_fw_chainTy, 0);
ip_fwPtrTy = PointerType::get(ip_fwTy, 0);
- ip_fw_insnPtrTy = PointerType::get(ip_fw_insnTy, 0);
+ ipfw_insnPtrTy = PointerType::get(ipfw_insnTy, 0);
ipfw_insn_ifPtrTy = PointerType::get(ipfw_insn_ifTy, 0);
mbufPtrTy = PointerType::get(mbufTy, 0);
#ifdef __FreeBSD__
@@ -253,12 +270,15 @@
// Functions declared at bitcode.
printfFunc = mod->getFunction("printf");
ipfw_find_rule = mod->getFunction("ipfw_find_rule");
+ crfree = mod->getFunction("crfree");
}
- // Allocate and initialize vars.
+ // Allocate and initialize LLVM vars.
void
allocaAndInit(struct ip_fw_args *args, struct ip_fw_chain *chain)
{
+ irb.SetInsertPoint(entry);
+ // Control flow variables.
match = irb.CreateAlloca(int32Ty);
l = irb.CreateAlloca(int32Ty);
done = irb.CreateAlloca(int32Ty);
@@ -267,6 +287,11 @@
irb.CreateStore(ConstantInt::get(int32Ty, 0), f_pos);
retval = irb.CreateAlloca(int32Ty);
irb.CreateStore(ConstantInt::get(int32Ty, 0), retval);
+ cmd = irb.CreateAlloca(ipfw_insnPtrTy);
+ tablearg = irb.CreateAlloca(int32Ty);
+ cmdlen = irb.CreateAlloca(int32Ty);
+ skip_or = irb.CreateAlloca(int32Ty);
+ f = irb.CreateAlloca(ip_fwPtrTy);
// m = args->m (idx: 0)
m = irb.CreateAlloca(mbufPtrTy);
@@ -277,10 +302,10 @@
irb.CreateStore(irb.CreateBitCast(irb.CreateInBoundsGEP(argsptr, ConstantInt::get(int32Ty, 2)), ipPtrTy), ip);
#ifdef __FreeBSD__
- ucred = irb.CreateAlloca(ucredPtrTy); // Init: NULL if type ucred.
- irb.CreateStore(ConstantPointerNull::get(ucredPtrTy), ucred);
+ ucred_cache = irb.CreateAlloca(ucredPtrTy); // Init: NULL if type ucred.
+ irb.CreateStore(ConstantPointerNull::get(ucredPtrTy), ucred_cache);
#else
- ucred = irb.CreateAlloca(ucredTy);
+ ucred_cache = irb.CreateAlloca(ucredTy);
#endif
ucred_lookup = irb.CreateAlloca(int32Ty);
@@ -352,7 +377,9 @@
emit_pullup_failed()
{
Value *is_verbose, *str;
- BasicBlock *print, *ret;
+
+ BasicBlock *print = BasicBlock::Create(con, "print", func);
+ BasicBlock *ret = BasicBlock::Create(con, "ret", func);
// VNET_DECLARE(int, fw_verbose);
// #define V_fw_verbose VNET(fw_verbose)
@@ -366,6 +393,8 @@
is_verbose = mod->getGlobalVariable("fw_verbose");
str = irb.CreateGlobalString("ipfw: pullup failed\n");
+ irb.SetInsertPoint(pullup_failed);
+
// if (V_fw_verbose)
irb.CreateCondBr(irb.CreateICmpEQ(is_verbose, ConstantInt::get(int32Ty, 0)), ret, print);
// printf("ipfw: pullup failed\n");
@@ -381,8 +410,10 @@
void
emit_check_tag()
{
- BasicBlock *tagged, *nottagged;
- BasicBlock *yes, *no;
+ BasicBlock *tagged = BasicBlock::Create(con, "tagged", func);
+ BasicBlock *nottagged = BasicBlock::Create(con, "nottagged", func);
+ BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+ BasicBlock *jf = BasicBlock::Create(con, "jf", func);
// if (args->rule.slot) {
// /*
@@ -404,15 +435,15 @@
irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4),ConstantInt::get(int32Ty, 0)}), ConstantInt::get(int32Ty, 0)), nottagged, tagged);
// if (args->rule.chain_id == chain->id)
irb.SetInsertPoint(tagged);
- irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 3)}), irb.CreateInBoundsGEP(chainptr, ConstantInt::get(int32Ty, 12))), yes, no);
+ irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 3)}), irb.CreateInBoundsGEP(chainptr, ConstantInt::get(int32Ty, 12))), jt, jf);
// f_pos = args->rule.slot;
- irb.SetInsertPoint(yes);
+ irb.SetInsertPoint(jt);
irb.CreateStore(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4),ConstantInt::get(int32Ty, 0)}), f_pos);
irb.CreateBr(nottagged);
// else fpos = ipfw_find_rule(chain, args->rule.rulenum, args->rule.rule_id)
- irb.SetInsertPoint(no);
+ irb.SetInsertPoint(jf);
irb.CreateStore(irb.CreateCall3(ipfw_find_rule, chainptr, irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 1)}), irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 2)})), f_pos);
// Branch to nottagged because it
@@ -425,6 +456,249 @@
irb.CreateBr(startrules);
}
+ void
+ emit_outer_for_prologue()
+ {
+ BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+ BasicBlock *jf = BasicBlock::Create(con, "jf", func);
+ Value *set_disable = mod->getGlobalVariable("set_disable");
+
+ // All this variables are already allocated.
+ // 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;
+
+ irb.SetInsertPoint(outer_for_prologue);
+ // uint32_t tablearg = 0;
+ irb.CreateStore(ConstantInt::get(int32Ty, 0), tablearg);
+
+ // f = chain->map[f_pos];
+ irb.CreateStore(irb.CreateInBoundsGEP(chainptr, {ConstantInt::get(int32Ty, 5), f_pos}), f);
+
+ // if (V_set_disable & (1 << f->set) )
+ irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(set_disable, irb.CreateShl(ConstantInt::get(int32Ty, 1), irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 5)))), ConstantInt::get(int32Ty, 0)), jt, jf);
+
+ irb.SetInsertPoint(jt);
+ // continue;
+ irb.CreateBr(next);
+
+ // skip_or = 0;
+ irb.SetInsertPoint(jf);
+ irb.CreateStore(ConstantInt::get(int32Ty, 0), skip_or);
+
+ irb.CreateBr(inner_for_prologue);
+ }
+
+ void
+ emit_inner_for_prologue()
+ {
+ BasicBlock *firstt = BasicBlock::Create(con, "firstt", func);
+ BasicBlock *firstf = BasicBlock::Create(con, "firstf", func);
+ BasicBlock *secondt = BasicBlock::Create(con, "secondt", func);
+ BasicBlock *secondf = BasicBlock::Create(con, "secondf", func);
+
+ // The first to are the intializers of the for loop.
+ // l = f->cmd_len;
+ // cmd = f->cmd;
+ //
+ // int match;
+ // cmdlen = F_LEN(cmd);
+ // 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 */
+ irb.SetInsertPoint(inner_for_prologue);
+
+ // l = f->cmd_len;
+ // XXX - ask David about types. int l; uint16_t cmd_len;
+ irb.CreateStore(irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 3)), l);
+ // cmd = f->cmd;
+ irb.CreateStore(irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 11)), cmd);
+ // int match;
+ // match is already allocated.
+
+ // cmdlen = ((cmd)->len & F_LEN_MASK);
+ irb.CreateStore(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_LEN_MASK)), cmdlen);
+
+ // if (skip_or)
+ irb.CreateCondBr(irb.CreateICmpNE(skip_or, ConstantInt::get(int32Ty, 0)), firstt, firstf);
+
+ irb.SetInsertPoint(firstt);
+ // if ((cmd->len & F_OR) == 0)
+ irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int8Ty, 0)), secondt, secondf);
+
+ irb.SetInsertPoint(secondt);
+ // skip_or = 0;
+ irb.CreateStore(ConstantInt::get(int32Ty, 0), skip_or);
+ irb.CreateBr(secondf);
+
+ irb.SetInsertPoint(secondf);
+ // continue;
+ irb.CreateBr(next);
+
+ irb.SetInsertPoint(firstf);
+ // match = 0;
+ irb.CreateStore(ConstantInt::get(int32Ty, 0), match);
+
+ irb.CreateBr(inner_for_epilogue);
+ }
+
+ // We get here ar the end of switch() on opcodes.
+ void
+ emit_inner_for_epilogue()
+ {
+ BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+ BasicBlock *jf = BasicBlock::Create(con, "jf", func);
+ BasicBlock *sec_cond = BasicBlock::Create(con, "sec_cond", func);
+ BasicBlock *matchzero = BasicBlock::Create(con, "matchzero", func);
+ BasicBlock *matchnotzero = BasicBlock::Create(con, "matchnotzero", func);
+ BasicBlock *is_or = BasicBlock::Create(con, "is_or", func);
+ BasicBlock *is_not_or = BasicBlock::Create(con, "is_not_or", func);
+
+ // This are the increments of the for loop.
+ // l -= cmdlen, cmd += cmdlen;
+ irb.CreateStore(irb.CreateNSWSub(l, cmdlen), l);
+ irb.CreateStore(irb.CreateAdd(cmd, cmdlen), cmd);
+
+ // 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 */
+ // }
+
+ irb.SetInsertPoint(inner_for_epilogue);
+
+ // if (cmd->len & F_NOT)
+ irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_NOT)), ConstantInt::get(int32Ty, 0)), jt, sec_cond);
+
+ irb.SetInsertPoint(jt);
+ // match = !match;
+ irb.CreateStore(irb.CreateNot(match), match);
+ irb.CreateBr(sec_cond);
+
+ irb.SetInsertPoint(sec_cond);
+ // if (match)
+ irb.CreateCondBr(irb.CreateICmpNE(match, ConstantInt::get(int32Ty, 0)), matchnotzero, matchzero);
+
+ irb.SetInsertPoint(matchnotzero);
+ // if (cmd->len & F_OR)
+ irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int32Ty, 0)), is_or, outer_for_epilogue);
+
+ irb.SetInsertPoint(is_or);
+ // skip_or = 1;
+ irb.CreateStore(ConstantInt::get(int32Ty, 1), skip_or);
+ irb.CreateBr(outer_for_epilogue);
+
+ irb.SetInsertPoint(matchzero);
+ // if (!(cmd->len & F_OR)) /* not an OR block, */
+ // break;
+ irb.CreateCondBr(irb.CreateICmpNE(irb.CreateNot(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR))), ConstantInt::get(int32Ty, 0)), next /* break */, outer_for_epilogue);
+ }
+
+ // This code gets executed at the end of inner loop.
+ // In this context, break means goto end, else continue loop.
+ void
+ emit_outer_for_epilogue()
+ {
+ // f_pos++, increment of the for loop.
+ irb.CreateStore(irb.CreateAdd(f_pos, ConstantInt::get(int32Ty, 1)), f_pos);
+
+ // if (done)
+ // break;
+ irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), end, next);
+
+ }
+
+ void
+ emit_end()
+ {
+ Value *rule, *timestamp, *str;
+
+ BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+ BasicBlock *jf = BasicBlock::Create(con, "jf", func);
+ BasicBlock *ret = BasicBlock::Create(con, "ret", func);
+
+ // if (done) {
+ // struct ip_fw *rule = chain->map[f_pos];
+ // /* Update statistics */
+ // (rule)->pcnt++;
+ // (rule)->bcnt += pktlen;
+ // (rule)->timestamp = time_uptime;
+ // } else {
+ // retval = IP_FW_DENY;
+ // printf("ipfw: ouch!, skip past end of rules, denying packet\n");
+ // }
+ //
+ // #ifdef __FreeBSD__
+ // if (ucred_cache != NULL)
+ // crfree(ucred_cache);
+ // #endif
+ //
+ // return (retval);
+
+ irb.SetInsertPoint(end);
+ // We need to get the timestamp variable.
+ timestamp = mod->getGlobalVariable("timestamp");
+ str = irb.CreateGlobalString("ipfw: ouch!, skip past end of rules, denying packet\n");
+
+ // if (done)
+ irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), jt, jf);
+
+ irb.SetInsertPoint(jt);
+ // struct ip_fw *rule = chain->map[f_pos];
+ rule = irb.CreateAlloca(ip_fwPtrTy);
+ irb.CreateStore(irb.CreateInBoundsGEP(chainptr, {ConstantInt::get(int32Ty, 5), f_pos}), rule);
+
+ // uint64_t pcnt;
+ // (rule)->pcnt++;
+ irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty,8)), irb.CreateAdd(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 8)), ConstantInt::get(int64Ty, 1)));
+ // uint64_t bnct;
+ // (rule)->bcnt += pktlen;
+ irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 9)), irb.CreateAdd(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 9)), pktlen));
+
+ // (rule)->timestamp = time_uptime;
+ // uint32_t timestamp;
+ irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 10)), timestamp);
+
+ irb.SetInsertPoint(jf);
+ // retval = IP_FW_DENY;
+ // printf("ipfw: ouch!, skip past end of rules, denying packet\n");
+ irb.CreateStore(ConstantInt::get(int32Ty, IP_FW_DENY), retval);
+ irb.CreateCall(printfFunc, str);
+#ifndef __FreeBSD__
+ irb.CreateBr(ret);
+#endif
+
+#ifdef __FreeBSD__
+ {
+ irb.SetInsertPoint(end);
+ BasicBlock *cache_nnull;
+ // if (ucred_cache != NULL)
+ irb.CreateCondBr(irb.CreateICmpNE(ucred_cache, ConstantPointerNull::get(ucredPtrTy)), cache_nnull, ret);
+
+ irb.SetInsertPoint(cache_nnull);
+ // crfree(ucred_cache);
+ irb.CreateCall(crfree, ucred_cache);
+ irb.CreateBr(ret);
+ }
+#endif
+
+ irb.SetInsertPoint(ret);
+ irb.CreateRet(retval);
+ }
+
public:
ipfwJIT(struct ip_fw_args *args, struct ip_fw_chain *chain): irb(con)
{
@@ -446,15 +720,26 @@
// This will be executed at the end of ipfw_chk_jit().
end = BasicBlock::Create(con, "end", func);
+ //Snippets of code to be executed when iterating through the rules.
+ outer_for_prologue = BasicBlock::Create(con, "outer_for_prologue", func);
+ inner_for_prologue = BasicBlock::Create(con, "inner_for_prologue", func);
+ inner_for_epilogue = BasicBlock::Create(con, "inner_for_epilogue", func);
+ outer_for_epilogue = BasicBlock::Create(con, "outer_for_epilogue", func);
+
// Get struct types, and store vars
- irb.SetInsertPoint(entry);
setEnv();
allocaAndInit(args, chain);
emit_check_tag();
-
- irb.SetInsertPoint(pullup_failed);
emit_pullup_failed();
+
+ // Snippets of code to be used for each iteration.
+ emit_outer_for_prologue();
+ emit_inner_for_prologue();
+ emit_inner_for_epilogue();
+ emit_outer_for_epilogue();
+ emit_end();
+
}
~ipfwJIT()
{
@@ -477,60 +762,41 @@
// Call the function that fills in some vars.
void
- emit_lookpkt()
+ emit_lookpkt_call()
{
// If it returns one, goto pullup_failed.
// Else, goto starrules.
irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateCall(inspect_pkt, {argsptr, ip, m, src_ip, dst_ip, src_port, dst_port, etype, ext_hd, iplen, pktlen, is_ipv4, is_ipv6, hlen, proto, icmp6_type, ip6f_mf, offset, ulp}), ConstantInt::get(int32Ty, 1)), pullup_failed, startrules);
- return;
}
- // We get here ar the end of switch() on opcodes.
- // XXX
void
- emit_end_switch()
+ emit_outer_for_prologue_call()
{
- // /* if we get here with l=0, then match is irrelevant. */
- // if (cmd->len & F_NOT)
- // match = !match;
+ irb.CreateBr(outer_for_prologue);
+ }
- // if (match) {
- // if (cmd->len & F_OR)
- // skip_or = 1;
- // } else {
- // if (!(cmd->len & F_OR)) /* not an OR block, */
- // break; /* try next rule */
- // }
+ void
+ emit_inner_for_prologue_call()
+ {
+ irb.CreateBr(inner_for_prologue);
}
- // This code gets executed at the end of inner loop.
- // In this context, break means goto end, else continue loop.
void
- emit_end_opcodes()
+ emit_inner_for_epilogue_call()
{
- // if (done)
- // break;
- irb.CreateCondBr(irb.CreateCmpNE(done, ConstantInt::get(int32Ty, 0)), end, next);
+ irb.CreateBr(inner_for_epilogue);
}
- // This will emit some code executed at the end.
- // And set up basic blocks, if necessary.
- // XXX
void
- emit_end()
+ emit_outer_for_epilogue_call()
{
- // if (done) {
- // struct ip_fw *rule = chain->map[f_pos];
- // /* Update statistics */
- // (rule)->pcnt++;
- // (rule)->bcnt += pktlen;
- // (rule)->timestamp = time_uptime;
- // } else {
- // retval = IP_FW_DENY;
- // printf("ipfw: ouch!, skip past end of rules, denying packet\n");
- // }
+ irb.CreateBr(outer_for_epilogue);
+ }
- irb.SetInsertPoint(end);
+ void
+ emit_end_call()
+ {
+ irb.CreateBr(end);
}
// Rules
@@ -567,13 +833,13 @@
extern "C" funcptr
compile_code(struct ip_fw_args *args, struct ip_fw_chain *chain)
{
- ipfwJIT comp(args, chain);
+ ipfwJIT compiler(args, chain);
int res;
int f_pos = 0;
- // Fill up needed variables type.
- comp.emit_lookpkt();
+ // Fill up needed local variables.
+ compiler.emit_lookpkt_call();
// Iterate through the rules.
int pktlen = args->m->m_pkthdr.len;
@@ -587,208 +853,211 @@
f = chain->map[f_pos];
+ compiler.emit_outer_for_prologue_call();
+
// For each different command.
for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
l -= cmdlen, cmd += cmdlen) {
/* check_body: */
cmdlen = F_LEN(cmd);
+ compiler.emit_inner_for_prologue_call();
switch (cmd->opcode) {
case O_NOP:
- comp.emit_nop();
+ compiler.emit_nop();
break;
case O_FORWARD_MAC:
- comp.emit_forward_mac(cmd->opcode);
+ compiler.emit_forward_mac(cmd->opcode);
break;
case O_GID:
case O_UID:
case O_JAIL:
- comp.emit_jail();
+ compiler.emit_jail();
break;
case O_RECV:
- comp.emit_recv();
+ compiler.emit_recv();
break;
/* XXX
case O_XMIT:
- comp.emit_xmit();
+ compiler.emit_xmit();
break;
case O_VIA:
- comp.emit_via();
+ compiler.emit_via();
break;
case O_MACADDR2:
- comp.emit_macaddr2();
+ compiler.emit_macaddr2();
break;
case O_MAC_TYPE:
- comp.emit_mac_type();
+ compiler.emit_mac_type();
break;
case O_FRAG:
- comp.emit_frag();
+ compiler.emit_frag();
break;
case O_IN:
- comp.emit_in();
+ compiler.emit_in();
break;
case O_LAYER2:
- comp.emit_layer2();
+ compiler.emit_layer2();
break;
case O_DIVERTED:
- comp.emit_diverted();
+ compiler.emit_diverted();
break;
case O_PROTO:
- comp.emit_proto();
+ compiler.emit_proto();
break;
case O_IP_SRC:
- comp.emit_ip_src();
+ compiler.emit_ip_src();
break;
case O_IP_SRC_LOOKUP:
case O_IP_DST_LOOKUP:
- comp.emit_ip_dst_lookup();
+ compiler.emit_ip_dst_lookup();
break;
case O_IP_SRC_MASK:
case O_IP_DST_MASK:
- comp.emit_ip_dst_mask();
+ compiler.emit_ip_dst_mask();
break;
case O_IP_SRC_ME:
- comp.emit_ip_src_me();
+ compiler.emit_ip_src_me();
#ifdef INET6
/* FALLTHROUGH */
/* XXX
case O_IP6_SRC_ME:
- comp.emit_ip6_src_me();
+ compiler.emit_ip6_src_me();
#endif
break;
case O_IP_DST_SET:
case O_IP_SRC_SET:
- comp.emit_ip_src_set();
+ compiler.emit_ip_src_set();
break;
case O_IP_DST:
- comp.emit_ip_dst();
+ compiler.emit_ip_dst();
break;
case O_IP_DST_ME:
- comp.emit_ip_dst_me();
+ compiler.emit_ip_dst_me();
#ifdef INET6
/* FALLTHROUGH */
/* XXX
case O_IP6_DST_ME:
- comp.emit_ip6_dst_me();
+ compiler.emit_ip6_dst_me();
#endif
break;
case O_IP_SRCPORT:
case O_IP_DSTPORT:
- comp.emit_ip_dstport();
+ compiler.emit_ip_dstport();
break;
case O_ICMPTYPE:
- comp.emit_icmptype();
+ compiler.emit_icmptype();
break;
#ifdef INET6
case O_ICMP6TYPE:
- comp.emit_icmp6type();
+ compiler.emit_icmp6type();
break;
#endif /* INET6 */
/*
case O_IPOPT:
- comp.emit_ipopt();
+ compiler.emit_ipopt();
break;
case O_IPVER:
- comp.emit_ipver();
+ compiler.emit_ipver();
break;
case O_IPID:
case O_IPLEN:
case O_IPTTL:
- comp.emit_ipttl();
+ compiler.emit_ipttl();
break;
case O_IPPRECEDENCE:
- comp.emit_ipprecedence();
+ compiler.emit_ipprecedence();
break;
case O_IPTOS:
- comp.emit_iptos();
+ compiler.emit_iptos();
break;
case O_DSCP:
- comp.emit_dscp();
+ compiler.emit_dscp();
break;
case O_TCPDATALEN:
- comp.emit_tcpdatalen();
+ compiler.emit_tcpdatalen();
break;
case O_TCPFLAGS:
- comp.emit_tcpflags();
+ compiler.emit_tcpflags();
break;
case O_TCPOPTS:
- comp.emit_tcpopts();
+ compiler.emit_tcpopts();
break;
case O_TCPSEQ:
- comp.emit_tcpseq();
+ compiler.emit_tcpseq();
break;
case O_TCPACK:
- comp.emit_tcpack();
+ compiler.emit_tcpack();
break;
case O_TCPWIN:
- comp.emit_tcpwin();
+ compiler.emit_tcpwin();
break;
case O_ESTAB:
- comp.emit_estab();
+ compiler.emit_estab();
break;
case O_ALTQ:
- comp.emit_altq();
+ compiler.emit_altq();
break;
case O_LOG:
- comp.emit_log();
+ compiler.emit_log();
break;
case O_PROB:
- comp.emit_prob();
+ compiler.emit_prob();
break;
case O_VERREVPATH:
- comp.emit_verrevpath();
+ compiler.emit_verrevpath();
break;
case O_VERSRCREACH:
- comp.emit_versrcreach();
+ compiler.emit_versrcreach();
break;
case O_ANTISPOOF:
- comp.emit_antispoof();
+ compiler.emit_antispoof();
break;
case O_IPSEC:
#ifdef IPSEC
- comp.emit_ipsec();
+ compiler.emit_ipsec();
#endif
/* otherwise no match */
/* XXX
@@ -796,50 +1065,50 @@
#ifdef INET6
case O_IP6_SRC:
- comp.emit_ip6_src();
+ compiler.emit_ip6_src();
break;
case O_IP6_DST:
- comp.emit_ip6_dst();
+ compiler.emit_ip6_dst();
break;
case O_IP6_SRC_MASK:
case O_IP6_DST_MASK:
- comp.emit_ip6_dst_mask();
+ compiler.emit_ip6_dst_mask();
break;
case O_FLOW6ID:
- comp.emit_flow6id();
+ compiler.emit_flow6id();
break;
case O_EXT_HDR:
- comp.emit_ext_hdr();
+ compiler.emit_ext_hdr();
break;
case O_IP6:
- comp.emit_ip6();
+ compiler.emit_ip6();
break;
#endif
case O_IP4:
- comp.emit_ip4();
+ compiler.emit_ip4();
break;
case O_TAG:
- comp.emit_tag();
+ compiler.emit_tag();
break;
case O_FIB: /* try match the specified fib */
/* XXX
- comp.emit_fib();
+ compiler.emit_fib();
break;
case O_SOCKARG:
- comp.emit_sockarg();
+ compiler.emit_sockarg();
break;
case O_TAGGED:
- comp.emit_tagged();
+ compiler.emit_tagged();
break;
/*
@@ -886,101 +1155,101 @@
/* XXX
case O_LIMIT:
case O_KEEP_STATE:
- comp.emit_keep_state();
+ compiler.emit_keep_state();
break;
case O_PROBE_STATE:
case O_CHECK_STATE:
- comp.emit_check_state();
+ compiler.emit_check_state();
break;
case O_ACCEPT:
- comp.emit_accept();
+ compiler.emit_accept();
break;
case O_PIPE:
case O_QUEUE:
- comp.emit_queue();
+ compiler.emit_queue();
break;
case O_DIVERT:
case O_TEE:
- comp.emit_tee();
+ compiler.emit_tee();
break;
case O_COUNT:
- comp.emit_count();
+ compiler.emit_count();
break;
case O_SKIPTO:
- comp.emit_skipto();
+ compiler.emit_skipto();
continue;
break; /* NOTREACHED */
/* XXX
case O_CALLRETURN:
- comp.emit_callreturn();
+ compiler.emit_callreturn();
continue;
break; /* NOTREACHED */
/* XXX
case O_REJECT:
- comp.emit_reject();
+ compiler.emit_reject();
/* FALLTHROUGH */
/* XXX
#ifdef INET6
case O_UNREACH6:
- comp.emit_unreach6();
+ compiler.emit_unreach6();
/* FALLTHROUGH */
/* XXX
#endif
case O_DENY:
- comp.emit_deny();
+ compiler.emit_deny();
break;
case O_FORWARD_IP:
- comp.emit_forward_ip();
+ compiler.emit_forward_ip();
break;
#ifdef INET6
case O_FORWARD_IP6:
- comp.emit_forward_ip6();
+ compiler.emit_forward_ip6();
break;
#endif
case O_NETGRAPH:
case O_NGTEE:
- comp.emit_ngtee();
+ compiler.emit_ngtee();
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-soc-all
mailing list