From owner-svn-soc-all@FreeBSD.ORG Tue Sep 9 16:16:02 2014 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 5D4F937E for ; Tue, 9 Sep 2014 16:16:02 +0000 (UTC) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2C83E1BB for ; Tue, 9 Sep 2014 16:16:02 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.9/8.14.9) with ESMTP id s89GG27Y090656 for ; Tue, 9 Sep 2014 16:16:02 GMT (envelope-from dpl@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id s89GG1xx090647 for svn-soc-all@FreeBSD.org; Tue, 9 Sep 2014 16:16:01 GMT (envelope-from dpl@FreeBSD.org) Date: Tue, 9 Sep 2014 16:16:01 GMT Message-Id: <201409091616.s89GG1xx090647@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to dpl@FreeBSD.org using -f From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r273853 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Sep 2014 16:16:02 -0000 Author: dpl Date: Tue Sep 9 16:16:01 2014 New Revision: 273853 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=273853 Log: Added port filtering. 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 Tue Sep 9 16:15:21 2014 (r273852) +++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Tue Sep 9 16:16:01 2014 (r273853) @@ -66,6 +66,7 @@ Type *Int32Ty; Type *Int64Ty; PointerType *Int8PtrTy; + PointerType *Int16PtrTy; // Basic blocks used BasicBlock *Entry; @@ -97,15 +98,15 @@ Value *Oif; Value *Hlen; //unsigned Value *Offset; //unsigned - Value *Ip6f_mf; //unsigned + Value *Ip6fMf; //unsigned // Local copies of vars. // On optimization, unused ones will not be included. Value *Proto; //unsigned - Value *Src_port; //unsigned - Value *Dst_port; //unsigned - Value *Src_ip; - Value *Dst_ip; + Value *SrcPort; //unsigned + Value *DstPort; //unsigned + Value *SrcIp; + Value *DstIp; Value *Iplen; //unsigned Value *Pktlen; Value *Etype; //unsigned @@ -113,36 +114,36 @@ Value *Q; Value *Ulp; - Value *Is_ipv4; - Value *Is_ipv6; - Value *Icmp6_type; //unsigned - Value *Ext_hd; //unsigned + Value *IsIpv4; + Value *IsIpv6; + Value *Icmp6Type; //unsigned + Value *ExtHd; //unsigned // This sets up some vars, at star time. Function *InspectPkt; // Auxiliary functions used by our JITed code. // All this are used from our bitcode. - Function *Is_icmp_query; - Function *Flags_match; - Function *Ipopts_match; - Function *Tcpopts_match; - Function *Iface_match; - Function *Verify_path; + Function *IsIcmpQuery; + Function *FlagsMatch; + Function *IpoptsMatch; + Function *TcpoptsMatch; + Function *IfaceMatch; + Function *VerifyPath; #ifdef INET6 - Function *Icmp6type_match; - Function *Search_ip6_addr_net; - Function *Flow6id_match; - Function *Verify_path6; - Function *Is_icmp6_query; - Function *Send_reject6; + Function *Icmp6typeMatch; + Function *SearchIp6AddrNet; + Function *Flow6idMatch; + Function *VerifyPath6; + Function *IsIcmp6Query; + Function *SendReject6; #endif /* INET6 */ - Function *Send_reject; - Function *Set_match; - Function *Jump_fast; + Function *SendReject; + Function *SetMatch; + Function *JumpFast; Function *PrintfFunc; - Function *Ipfw_find_rule; + Function *IpfwFindRule; // Used structs. StructType *IfnetTy; @@ -152,6 +153,7 @@ StructType *Ip_fw_chainTy; StructType *Ip_fwTy; StructType *Ipfw_insnTy; + StructType *IpfwInsnU16Ty; StructType *Ipfw_dyn_ruleTy; StructType *Ipfw_insn_ifTy; StructType *MbufTy; @@ -165,6 +167,7 @@ PointerType *Ip_fw_chainPtrTy; PointerType *Ip_fwPtrTy; PointerType *Ipfw_insnPtrTy; + PointerType *IpfwInsnU16PtrTy; PointerType *Ipfw_dyn_rulePtrTy; PointerType *Ipfw_insn_ifPtrTy; PointerType *MbufPtrTy; @@ -219,6 +222,7 @@ Int32Ty = Type::getInt32Ty(Con); Int64Ty = Type::getInt64Ty(Con); Int8PtrTy = PointerType::getUnqual(Int8Ty); + Int16PtrTy = PointerType::getUnqual(Int16Ty); // Get StrucType from bitcode. MbufTy = mod->getTypeByName("struct.mbuf"); @@ -229,6 +233,7 @@ Ip_fw_chainTy = mod->getTypeByName("struct.ip_fw_chain"); Ip_fwTy = mod->getTypeByName("struct.ip_fw"); Ipfw_insnTy = mod->getTypeByName("struct._ipfw_insn"); + IpfwInsnU16Ty = mod->getTypeByName("struct._ipfw_insn_u16"); Ipfw_insn_ifTy = mod->getTypeByName("struct._ipfw_insn_if"); Ipfw_dyn_ruleTy = mod->getTypeByName("struct._ipfw_dyn_rule"); #ifdef __FreeBSD__ @@ -246,6 +251,7 @@ Ip_fw_chainPtrTy = PointerType::getUnqual(Ip_fw_chainTy); Ip_fwPtrTy = PointerType::getUnqual(Ip_fwTy); Ipfw_insnPtrTy = PointerType::getUnqual(Ipfw_insnTy); + IpfwInsnU16PtrTy = PointerType::getUnqual(IpfwInsnU16Ty); Ipfw_insn_ifPtrTy = PointerType::getUnqual(Ipfw_insn_ifTy); Ipfw_dyn_rulePtrTy = PointerType::getUnqual(Ipfw_dyn_ruleTy); #ifdef __FreeBSD__ @@ -254,29 +260,29 @@ // Get Function defs from bitcode. // All of them are auxiliary functions. InspectPkt = mod->getFunction("inspect_pkt"); - Is_icmp_query = mod->getFunction("is_icmp_query"); - Flags_match = mod->getFunction("flags_match"); - Ipopts_match = mod->getFunction("ipopts_match"); - Tcpopts_match = mod->getFunction("tcpopts_match"); - Iface_match = mod->getFunction("iface_match"); - Verify_path = mod->getFunction("verify_path"); + IsIcmpQuery = mod->getFunction("is_icmp_query"); + FlagsMatch = mod->getFunction("flags_match"); + IpoptsMatch = mod->getFunction("ipopts_match"); + TcpoptsMatch = mod->getFunction("tcpopts_match"); + IfaceMatch = mod->getFunction("ifaceMatch"); + VerifyPath = mod->getFunction("verify_path"); #ifdef INET6 - Icmp6type_match = mod->getFunction("icmp6type_match"); - Search_ip6_addr_net = mod->getFunction("search_ip6_addr_net"); - Flow6id_match = mod->getFunction("flow6id_match"); - Verify_path6 = mod->getFunction("verify_path6"); - Is_icmp6_query = mod->getFunction("is_icmp6_query"); - Send_reject6 = mod->getFunction("send_reject6"); + Icmp6typeMatch = mod->getFunction("icmp6type_match"); + SearchIp6AddrNet = mod->getFunction("search_ip6_addr_net"); + Flow6idMatch = mod->getFunction("flow6id_match"); + VerifyPath6 = mod->getFunction("verify_path6"); + IsIcmp6Query = mod->getFunction("is_icmp6_query"); + SendReject6 = mod->getFunction("send_reject6"); #endif /* INET6 */ - Send_reject = mod->getFunction("send_reject"); - Set_match = mod->getFunction("set_match"); - Jump_fast = mod->getFunction("jump_fast"); + SendReject = mod->getFunction("send_reject"); + SetMatch = mod->getFunction("set_match"); + JumpFast = mod->getFunction("jump_fast"); // Functions declared at bitcode. PrintfFunc = mod->getFunction("printf"); - Ipfw_find_rule = mod->getFunction("ipfw_find_rule"); + IpfwFindRule = mod->getFunction("ipfw_find_rule"); } // Allocate and initialize LLVM vars. @@ -320,8 +326,8 @@ Offset = Irb.CreateAlloca(Int16Ty, nullptr, "offset"); Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Offset); - Ip6f_mf = Irb.CreateAlloca(Int16Ty, nullptr, "ip6f_mf"); - Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Ip6f_mf); + Ip6fMf = Irb.CreateAlloca(Int16Ty, nullptr, "ip6f_mf"); + Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Ip6fMf); // proto = 0 Proto = Irb.CreateAlloca(Int8Ty, nullptr, "proto"); @@ -331,18 +337,18 @@ Value *FProto = Irb.CreateStructGEP(F_id, 5); Irb.CreateStore(ConstantInt::get(Int8Ty, 0), FProto); - Src_port = Irb.CreateAlloca(Int16Ty, nullptr, "src_port"); - Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Src_port); - Dst_port = Irb.CreateAlloca(Int16Ty, nullptr, "dst_port"); - Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Dst_port); + SrcPort = Irb.CreateAlloca(Int16Ty, nullptr, "src_port"); + Irb.CreateStore(ConstantInt::get(Int16Ty, 0), SrcPort); + DstPort = Irb.CreateAlloca(Int16Ty, nullptr, "dst_port"); + Irb.CreateStore(ConstantInt::get(Int16Ty, 0), DstPort); //src_ip.s_addr = 0; - Src_ip = Irb.CreateAlloca(In_addrTy, nullptr, "src_ip"); - Value *Src_s_addr = Irb.CreateStructGEP(Src_ip, 0); + SrcIp = Irb.CreateAlloca(In_addrTy, nullptr, "src_ip"); + Value *Src_s_addr = Irb.CreateStructGEP(SrcIp, 0); Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Src_s_addr); //dst_ip.s_addr = 0; - Dst_ip = Irb.CreateAlloca(In_addrTy, nullptr, "dst_ip"); - Value *Dst_s_addr = Irb.CreateStructGEP(Dst_ip, 0); + DstIp = Irb.CreateAlloca(In_addrTy, nullptr, "dst_ip"); + Value *Dst_s_addr = Irb.CreateStructGEP(DstIp, 0); Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Dst_s_addr); //iplen = 0; @@ -371,23 +377,23 @@ Ulp = Irb.CreateAlloca(Int8PtrTy, nullptr, "ulp"); Irb.CreateStore(ConstantPointerNull::get(Int8PtrTy), Ulp); - Is_ipv4 = Irb.CreateAlloca(Int32Ty, nullptr, "is_ipv4"); - Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Is_ipv4); - Is_ipv6 = Irb.CreateAlloca(Int32Ty, nullptr, "is_ipv6"); - Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Is_ipv6); - Icmp6_type = Irb.CreateAlloca(Int8Ty, nullptr, "icmp6_type"); - Irb.CreateStore(ConstantInt::get(Int8Ty, 0), Icmp6_type); - Ext_hd = Irb.CreateAlloca(Int16Ty, nullptr, "ext_hd"); - Irb.CreateStore(ConstantInt::get(Int16Ty, 0), Ext_hd); + IsIpv4 = Irb.CreateAlloca(Int32Ty, nullptr, "is_ipv4"); + Irb.CreateStore(ConstantInt::get(Int32Ty, 0), IsIpv4); + IsIpv6 = Irb.CreateAlloca(Int32Ty, nullptr, "is_ipv6"); + Irb.CreateStore(ConstantInt::get(Int32Ty, 0), IsIpv6); + Icmp6Type = Irb.CreateAlloca(Int8Ty, nullptr, "icmp6_type"); + Irb.CreateStore(ConstantInt::get(Int8Ty, 0), Icmp6Type); + ExtHd = Irb.CreateAlloca(Int16Ty, nullptr, "ext_hd"); + Irb.CreateStore(ConstantInt::get(Int16Ty, 0), ExtHd); // If it returns one, goto pullup_failed. // Else, goto first rule. Value *Ip = Irb.CreateLoad(IpPtr); Value *UlpL = Irb.CreateLoad(Ulp); - Value *InspectPktCall = Irb.CreateCall(InspectPkt, {Args, 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, UlpL}); + Value *InspectPktCall = Irb.CreateCall(InspectPkt, {Args, Ip, M, SrcIp, + DstIp, SrcPort, DstPort, Etype, ExtHd, Iplen, Pktlen, IsIpv4, + IsIpv6, Hlen, Proto, Icmp6Type, Ip6fMf, Offset, UlpL}); Value *Comp = Irb.CreateICmpEQ(InspectPktCall, ConstantInt::get(Int32Ty, 1)); Irb.CreateCondBr(Comp, PullupFailed, CheckTag); @@ -492,7 +498,7 @@ Value *RulenumL = Irb.CreateLoad(Rulenum); Value *RuleId = Irb.CreateStructGEP(Rule, 2); Value *RuleIdL = Irb.CreateLoad(RuleId); - Value *FindRuleCall = Irb.CreateCall3(Ipfw_find_rule, Chain, RulenumL, RuleIdL); + Value *FindRuleCall = Irb.CreateCall3(IpfwFindRule, Chain, RulenumL, RuleIdL); Irb.CreateStore(FindRuleCall, FPos); // Branch to Nottagged because it @@ -752,7 +758,6 @@ Value *Sub = Irb.CreateNSWSub(LL, CmdLenL); Irb.CreateStore(Sub, L); - // TODO - Should ensure correctness of code. // ipfw_insn *cmd; Add to pointer. // Note: Since LLVM can't add to a ptr, we can use GEP with casted Ptr. // cmd += cmdlen; @@ -995,7 +1000,7 @@ //*match = iface_match(m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd, chain, tablearg); Value *rcvif = Irb.CreateStructGEP(Irb.CreateStructGEP(Irb.CreateLoad(MPtr), 5), 0); Value *cmdc = Irb.CreateBitCast(Cmd, Ipfw_insn_ifPtrTy); - Value *IfaceMatchCall = Irb.CreateCall4(Iface_match, rcvif, cmdc, Chain, Tablearg); + Value *IfaceMatchCall = Irb.CreateCall4(IfaceMatch, rcvif, cmdc, Chain, Tablearg); Irb.CreateStore(IfaceMatchCall, Match); } @@ -1005,7 +1010,7 @@ { //*match = iface_match(oif, (ipfw_insn_if *)cmd, chain, tablearg); Value *Cmdc = Irb.CreateBitCast(Cmd, Ipfw_insn_ifPtrTy); - Value *IfaceMatchCall = Irb.CreateCall4(Iface_match, Oif, Cmdc, Chain, Tablearg); + Value *IfaceMatchCall = Irb.CreateCall4(IfaceMatch, Oif, Cmdc, Chain, Tablearg); Irb.CreateStore(IfaceMatchCall, Match); } @@ -1126,6 +1131,110 @@ void emit_ip_dstport() { + // /* + // * offset == 0 && proto != 0 is enough + // * to guarantee that we have a + // * packet with port info. + // */ + // if ((proto==IPPROTO_UDP || proto==IPPROTO_TCP) + // && offset == 0) { + // u_int16_t x = + // (cmd->opcode == O_IP_SRCPORT) ? + // src_port : dst_port ; + // u_int16_t *p = + // ((ipfw_insn_u16 *)cmd)->ports; + // int i; + + // for (i = cmdlen - 1; !match && i>0; + // i--, p += 2) + // match = (x>=p[0] && x<=p[1]); + // } + BasicBlock *Yes = BasicBlock::Create(Con, "R_Yes", Func); + BasicBlock *Out = BasicBlock::Create(Con, "R_Out", Func); + BasicBlock *Src = BasicBlock::Create(Con, "R_Src", Func); + BasicBlock *Dst = BasicBlock::Create(Con, "R_Dst", Func); + BasicBlock *Loop = BasicBlock::Create(Con, "R_Loop", Func); + BasicBlock *ContLoop = BasicBlock::Create(Con, "R_ContLoop", Func); + Value Comp; + + // Perform allocations at the beginning. + Value *X = Irb.CreateAlloca(Int16Ty, nullptr, "x"); + Value *P = Irb.CreateAlloca(Int16PtrTy, nullptr, "p"); + Value *I = Irb.CreateAlloca(Int32Ty, nullptr, "i"); + // p = ((ipfw_insn_u16 *)cmd)->ports; + // XXX TODO Ensure correctness. + CmdLBitC = Irb.CreateBitCast(Cmd, IpfwInsnU16PtrTy); + Value *Ports = Irb.CreateStructGEP(CMDLBitC, 1); + Irb.CreateStore(PortsPtr, P); + Value *PL = Irb.CreateLoad(P); + + // (proto == IPPROTO_UDP || proto == IPPROTO_TCP) + Value *Comp1 = Irb.CreateICmpEQ(Proto, ConstantInt::get(Proto->getType(), IPPROTO_TCP)); + Value *Comp2 = Irb.CreateICmpEQ(Proto, ConstantInt::get(Proto->getType(), IPPROTO_UDP)); + Value *OrComps = Irb.CreateOr(Comp1, Comp2); + + // (Offset == 0) + Value *Comp3 = Irb.CreateICmpEQ(Offset, ConstantInt::get(Offset->getType(), 0)); + // (OrComps && Comp3) + Value *Comp = Irb.CreateAnd(OrComps, Comp3); + Irb.CreateCondBr(Comp, Yes, Out); + + // yes: + Irb.SetInserPoint(Yes); + // if (cmd->opcode == O_IP_SRCPORT) + Value *CmdL = Irb.CreateLoad(Cmd); + Value *OpcodePtr = Irb.CreateStructGEP(CmdL, 0); + Value *Opcode = Irb.CreateLoad(OpcodePtr); + Comp = Irb.CreateICmpEQ(Opcode, ConstantInt::get(Opcode->getType(), O_IP_SRCPORT)); + Irb.CreateCondBr(Comp, Src, Dst); + + Irb.SetInserPoint(Src); + // u_int16_t x = src_port; + Irb.CreateStore(SrcPort, X); + Irb.CreateBr(Loop); + + Irb.SetInserPoint(Dst); + // u_int16_t x = dst_port; + Irb.CreateStore(DstPort, X); + Irb.CreateBr(Loop); + + Irb.SetInserPoint(Loop); + // Loop initialisation + // i = cmdlen - 1; + // cmdlen: signed + Value *Sub = Irb.CreateNSWSub(CmdLen, ConstantInt::get(CmdLen->getType(), 1); + Irb.CreateStore(Sub, I); + Irb.CreateBr(ContLoop); + + // Check condition + Irb.SetInserPoint(ContLoop); + // while((!match) && (i>0)) { + Value *IL = Irb.CreateLoad(I); + Value *MatchL = Irb.CreateLoad(Match); + Comp1 = Irb.CreateICmpEQ(MatchL, ConstantInt::get(Match->getType(), 0) + Comp2 = Irb.CreateICmpSGT(IL, ConstantInt::get(I->getType(), 0) + Value *BreakCond = Irb.CreateAnd(Comp1, Comp2); + Irb.CreateCondBr(BreakCond, ContLoop, Out); + + // match = ((x >= p[0]) && (x <= p[1])); + Value *PZ = Irb.CreateStructGEP(PL, 0); + Value *PO = Irb.CreateStructGEP(PL, 1); + Comp1 = Irb.CreateICmpUGE(X, PZ); + Comp2 = Irb.CreateICmpULE(X, PO); + Comp = Irb.CreateAnd(Comp1, Comp2); + Value *Comp32 = Irb.CreateSExt(Comp, Match->getType()); + Irb.CreateStore(Comp32, Match); + + // Increment, decrement. + // i--; + Value *ILD = Irb.CreateNSWSub(IL, ConstantInt::get(I->getType(), 1)); + Irb.CreateStore(ILD, I); + // p += 2; + Value PGEP = Irb.CreateInBoundsGEP(PL, ConstantInt::get(Int32Ty, 2)); + Irb.CreateStore(PGEP, P); + Irb.CreateBr(ContLoop); + + Irb.SetInsertPoint(Out); } // XXX Not tested.