socsvn commit: r272045 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw

dpl at FreeBSD.org dpl at FreeBSD.org
Thu Aug 7 18:34:12 UTC 2014


Author: dpl
Date: Thu Aug  7 18:34:11 2014
New Revision: 272045
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272045

Log:
  Generally working on the JITter.

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	Thu Aug  7 18:33:18 2014	(r272044)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Thu Aug  7 18:34:11 2014	(r272045)
@@ -1,11 +1,13 @@
-/* JIT compilation code */
 #undef _KERNEL
 #include <iostream>
 #include <string>
 #include <vector>
 
 #include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/ArrayRef.h>
 #include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/CodeGen/MachineCodeInfo.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/IR/IRBuilder.h>
 #include <llvm/IR/LLVMContext.h>
 #include <llvm/IR/Module.h>
@@ -18,6 +20,7 @@
 #include <missing.h>
 
 #include <sys/mbuf.h>
+#include <sys/types.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ip_dummynet.h>
 #include <netinet/in_pcb.h>
@@ -27,7 +30,6 @@
 #include <netpfil/ipfw/ip_fw_private.h>
 }
 
-
 typedef int (*funcptr)();
 
 using namespace llvm;
@@ -39,11 +41,26 @@
 	LLVMContext con;
 	OwningPtr<MemoryBuffer> buffer;
 	IRBuilder<> irb;
-	std::vector<BasicBlock> BBs;
+	std::vector<BasicBlock*> blocks;
+
+	// Vars Types
+	Type *int8Ty;
+	Type *int16Ty;
+	Type *int32Ty;
+
+	// JIT Compiled Vars
+	Value *match;
+	Value *l;
+	Value *done;
+	Value *f_pos;
+	Value *retval;
+
+	// Functions used by our JITed code.
+	Function *iface_match;
 
+	// Load the bc for JIT compilation.
 	Module *loadbc(std::string name)
 	{
-		/* We load the bc for JIT compilation */
 		error_code ec = MemoryBuffer::getFile(name, buffer);
 		if (ec) {
 			std::cerr << "Failed to open bitcode: " << ec.message() << "\n";
@@ -60,32 +77,49 @@
 		return (mod);
 	}
 
-	/* Set the needed variables to perform pkt filtering. */
+	// Create the needed variables to perform pkt filtering.
 	int
-	setVars()
+	setEnv()
 	{
-		//We need the match var.
-		Value *match;
-		Value *f_pos;
+		// Get Type objects
+		int8Ty = Type::getInt8Ty(con);
+		int16Ty = Type::getInt16Ty(con);
+		int32Ty = Type::getInt32Ty(con);
+
+		// Get StrucType from bitcode.
+
+		// Store vars.
+		match = irb.CreateAlloca(int32Ty);
+		l = irb.CreateAlloca(int32Ty);
+		done = irb.CreateAlloca(int32Ty);
+		f_pos = irb.CreateAlloca(int32Ty);
+		retval = irb.CreateAlloca(int32Ty);
+
+		// Create needed GlobalVariables.
+
+		// Get Function defs from bitcode.
+		iface_match = mod->getFunction("iface_match");
+
 		return (0);
 	}
 
-	public: 
+	public:
 	ipfwJIT(): irb(con)
 	{
-		//Create the module and load the code.
+		// Create the module and load the code.
 		mod = loadbc("ip_fw_rules.bc");
-		setVars();
-		//Create Function, and start its first BasicBlock.
-		//int ipfw_chk_jitted(ip_fw_args *);
-		// XXX Do we have to define ip_fw_args using this?
-		StructType ipfwargsTy = StructType::get(/*TYPE1, TYPE2, TYPE3...*/);
-		Type *argsTy[] = { PointerType::getUnqual(ipfwargsTy) };
-		FunctionType *ipfwchkTy = FunctionType::get(Int32Ty, argsTy, false);
-		func = Function::Create(ipfwchkTy, GlobalValue::PrivateLinkage, "ipfw_chk", mod);
-
-		// XXX Create basic block, and add it to BBs
 
+		func = mod->getFunction("ipfw_chk_jit");
+		func->setLinkage(GlobalValue::ExternalLinkage);
+		// Create the entry point of the function
+		BasicBlock *entry = BasicBlock::Create(con, "entry", func);
+		// Add the entry block to ArrayRef
+		blocks.push_back(entry);
+		// Set the IRBuilder to insert instructions after the basic block.
+		irb.SetInsertPoint(entry);
+		// Get struct types, and store vars
+		setEnv();
+		// From on on, it's just a matter of emitting the code for each rule/action.
 	}
 	~ipfwJIT()
 	{
@@ -93,63 +127,86 @@
 			delete mod;
 	}
 
+	funcptr
+	functionPtr()
+	{
+		MachineCodeInfo machinf;
+
+		ExecutionEngine::runJITOnFunction(func, &machinf);
+		return ((funcptr)machinf.address());
+	}
+
 	int
-	emit_nop(int *match)
+	emit_nop(int *matchptr)
 	{
-		/*
-			static IPFW_RULES_INLINE void
-			rule_nop(int *match)
-			{
-				*match = 1;
-			}
-		// Get the stub (prototype) for the cell function
-		F = Mod->getFunction("cell");
-		// Set it to have private linkage, so that it can be removed after being
-		// inlined.
-		F->setLinkage(GlobalValue::PrivateLinkage);
-
-		// Add an entry basic block to this function and set it
-		BasicBlock *entry = BasicBlock::Create(C, "entry", F);
-		B.SetInsertPoint(entry);
-		// Cache the type of registers
-		regTy = Type::getInt16Ty(C);
-
-		// Collect the function parameters
-		auto args = F->arg_begin();
-		oldGrid = args++;
-		newGrid = args++;
-		width = args++;
-		height = args++;
-		x = args++;
-		y = args++;
+		// static IPFW_RULES_INLINE void
+		// rule_nop(int *match)
+		// {
+		// 	*match = 1;
+		// }
 
-		// Create space on the stack for the local registers
-		for (int i=0 ; i<10 ; i++)
-		{
-			a[i] = B.CreateAlloca(regTy);
-		}
+		*matchptr = 1;
 
-		// Create a space on the stack for the current value.  This can be
-		// assigned to, and will be returned at the end.  Store the value passed
-		// as a parameter in this.
-		v = B.CreateAlloca(regTy);
-		B.CreateStore(args++, v);
-		// Create a load of pointers to the global registers.
-		Value *gArg = args;
-		for (int i=0 ; i<10 ; i++)
-		{
-			B.CreateStore(ConstantInt::get(regTy, 0), a[i]);
-			g[i] = B.CreateConstGEP1_32(gArg, i);
-		}
-		*/
+		irb.CreateStore(ConstantInt::get(int32Ty, 1), match);
 		return (0);
 	}
 
 	int
-	emit_forward_mac()
+	emit_forward_mac(u_int8_t opcode)
 	{
+		// printf("ipfw: opcode %d unimplemented\n",
+		// 	opcode);
+
+		Function *printf;
+		
+		printf = mod->getFunction("printf");
+		irb.CreateCall(printf, "ipfw: opcode %d unimplemented\n", opcode);
 		return (0);
 	}
+
+	int
+	emit_jail()
+	{
+		// static IPFW_RULES_INLINE void
+		// rule_jail(int * match, u_short offset, uint8_t proto, ipfw_insn *cmd, struct ip_fw_args *args, int ucred_lookup, void *ucred_cache)
+		// {
+		// 	/*
+		// 	 * We only check offset == 0 && proto != 0,
+		// 	 * as this ensures that we have a
+		// 	 * packet with the ports info.
+		// 	 */
+		// 	if (offset != 0)
+		// 		return;
+		// 	if (proto == IPPROTO_TCP ||
+		// 		proto == IPPROTO_UDP)
+		// 		*match = check_uidgid(
+		// 				(ipfw_insn_u32 *)cmd,
+		// 				args, &ucred_lookup,
+		// #ifdef __FreeBSD__
+		// 				//(struct bsd_ucred **)&ucred_cache);
+		// 				(struct ucred **)&ucred_cache);
+		// #else
+		// 				(void *)&ucred_cache);
+		// #endif
+		// }
+
+		return (0);
+	}
+
+	int
+	emit_recv()
+	{
+		// static IPFW_RULES_INLINE void
+		// rule_recv(int *match, ipfw_insn *cmd, struct mbuf *m, struct ip_fw_chain *chain, uint32_t *tablearg)
+		// {
+		// 	*match = iface_match(m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd, chain, tablearg);
+		// }
+
+		irb.CreateStore(irb.CreateCall4(/*STUFF GOING HERE*/ match);
+
+		return (0);
+	}
+
 };
 
 extern "C" funcptr
@@ -157,33 +214,16 @@
 {
 	int res;
 	ipfwJIT comp;
-	Module *mod;
 
 	int f_pos = 0;
 	int retval = 0;
 
-	// Now I have to load the stubs of the loaded rules.
 	// 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;
-	}
 
 	int done = 0;		/* flag to exit the outer loop */
 	int pktlen = args->m->m_pkthdr.len;
 
-	// Iterate through the rules.
+	// For all the number of rules.
 	for (; f_pos < chain->n_rules; f_pos++) {
 		ipfw_insn *cmd;
 		int l, cmdlen, skip_or; /* skip rest of OR block */
@@ -194,6 +234,7 @@
 			continue;
 
 		skip_or = 0;
+		// For each different command.
 		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
 		    l -= cmdlen, cmd += cmdlen) {
 			int match;
@@ -225,15 +266,16 @@
 				break;
 
 			case O_FORWARD_MAC:
-				comp.emit_forward_mac();
+				comp.emit_forward_mac(cmd->opcode);
 				break;
-/* XXX
+
 			case O_GID:
 			case O_UID:
 			case O_JAIL:
 				comp.emit_jail();
 				break;
 
+/* XXX
 			case O_RECV:
 				comp.emit_recv();
 				break;
@@ -635,6 +677,8 @@
 		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
 	}
 
+	// Once we're done iterating through the rules, return the pointer.
+
 	return (0);
 }
 }


More information about the svn-soc-all mailing list