This commit is contained in:
mzz2017
2023-01-29 13:38:15 +08:00
parent 1ef1b048a1
commit 3c55d086e9
10 changed files with 67 additions and 141 deletions

View File

@ -19,10 +19,10 @@ make
Run: Run:
```shell ```shell
./dae run -c example.conf ./dae run -c example.dae
``` ```
See [example.conf](https://github.com/v2rayA/dae/blob/main/example.conf). See [example.dae](https://github.com/v2rayA/dae/blob/main/example.dae).
## TODO ## TODO

View File

@ -29,7 +29,7 @@ var (
) )
func init() { func init() {
runCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "dae.conf", "config file") runCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "config.dae", "config file")
} }
func Run() (err error) { func Run() (err error) {

View File

@ -29,7 +29,7 @@ const (
DisableL4ChecksumPolicy_SetZero DisableL4ChecksumPolicy_SetZero
) )
type RoutingType uint32 type RoutingType uint8
const ( const (
RoutingType_DomainSet RoutingType = iota RoutingType_DomainSet RoutingType = iota

View File

@ -11,6 +11,7 @@ import (
"fmt" "fmt"
"github.com/cilium/ebpf" "github.com/cilium/ebpf"
"github.com/cilium/ebpf/rlimit" "github.com/cilium/ebpf/rlimit"
"github.com/mzz2017/softwind/pool"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common" "github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
@ -19,7 +20,6 @@ import (
"github.com/v2rayA/dae/component/routing" "github.com/v2rayA/dae/component/routing"
"github.com/v2rayA/dae/config" "github.com/v2rayA/dae/config"
"github.com/v2rayA/dae/pkg/config_parser" "github.com/v2rayA/dae/pkg/config_parser"
"github.com/v2rayA/dae/pkg/pool"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"

View File

@ -33,10 +33,10 @@
#define MAX_PARAM_LEN 16 #define MAX_PARAM_LEN 16
#define MAX_INTERFACE_NUM 128 #define MAX_INTERFACE_NUM 128
#define MAX_ROUTING_LEN (32 * 3) #define MAX_MATCH_SET_LEN (32 * 3)
#define MAX_LPM_SIZE 20480 #define MAX_LPM_SIZE 20480
//#define MAX_LPM_SIZE 20480 //#define MAX_LPM_SIZE 20480
#define MAX_LPM_NUM (MAX_ROUTING_LEN + 8) #define MAX_LPM_NUM (MAX_MATCH_SET_LEN + 8)
#define MAX_DEST_MAPPING_NUM (65536 * 2) #define MAX_DEST_MAPPING_NUM (65536 * 2)
#define IPV6_MAX_EXTENSIONS 4 #define IPV6_MAX_EXTENSIONS 4
@ -48,9 +48,9 @@
#define OUTBOUND_LOGICAL_MASK 0xFE #define OUTBOUND_LOGICAL_MASK 0xFE
enum { enum {
DISABLE_L4_CHECKSUM_POLICY_ENABLE_L4_CHECKSUM, DisableL4ChecksumPolicy_EnableL4Checksum,
DISABLE_L4_CHECKSUM_POLICY_RESTORE, DisableL4ChecksumPolicy_Restore,
DISABLE_L4_CHECKSUM_POLICY_SET_ZERO, DisableL4ChecksumPolicy_SetZero,
}; };
// Param keys: // Param keys:
@ -182,28 +182,27 @@ struct {
__array(values, struct map_lpm_type); __array(values, struct map_lpm_type);
} lpm_array_map SEC(".maps"); } lpm_array_map SEC(".maps");
// Array of routing: enum __attribute__((packed)) MatchType {
enum ROUTING_TYPE {
/// WARNING: MUST SYNC WITH common/consts/ebpf.go. /// WARNING: MUST SYNC WITH common/consts/ebpf.go.
ROUTING_TYPE_DOMAIN_SET, MatchType_DomainSet,
ROUTING_TYPE_IP_SET, MatchType_IpSet,
ROUTING_TYPE_SOURCE_IP_SET, MatchType_SourceIpSet,
ROUTING_TYPE_PORT, MatchType_Port,
ROUTING_TYPE_SOURCE_PORT, MatchType_SourcePort,
ROUTING_TYPE_L4PROTO, MatchType_L4Proto,
ROUTING_TYPE_IPVERSION, MatchType_IpVersion,
ROUTING_TYPE_MAC, MatchType_Mac,
ROUTING_TYPE_FINAL, MatchType_Final,
}; };
enum L4PROTO_TYPE { enum L4ProtoType {
L4PROTO_TYPE_TCP = 1, L4ProtoType_TCP = 1,
L4PROTO_TYPE_UDP = 2, L4ProtoType_UDP = 2,
L4PROTO_TYPE_TCP_UDP = 3, L4ProtoType_X = 3,
}; };
enum IP_VERSION { enum IpVersion {
IPVERSION_4 = 1, IpVersion_4 = 1,
IPVERSION_6 = 2, IpVersion_6 = 2,
IPVERSION_X = 3, IpVersion_X = 3,
}; };
struct port_range { struct port_range {
__u16 port_start; __u16 port_start;
@ -211,7 +210,7 @@ struct port_range {
}; };
/* /*
Look at following rule: Rule is like as following:
domain(geosite:cn, suffix: google.com) && l4proto(tcp) -> my_group domain(geosite:cn, suffix: google.com) && l4proto(tcp) -> my_group
@ -225,10 +224,10 @@ struct match_set {
__u32 index; __u32 index;
struct port_range port_range; struct port_range port_range;
enum L4PROTO_TYPE l4proto_type; enum L4ProtoType l4proto_type;
enum IP_VERSION ip_version; enum IpVersion ip_version;
}; };
enum ROUTING_TYPE type; enum MatchType type;
bool not ; // A subrule flag (this is not a match_set flag). bool not ; // A subrule flag (this is not a match_set flag).
__u8 outbound; // User-defined value range is [0, 252]. __u8 outbound; // User-defined value range is [0, 252].
}; };
@ -236,12 +235,12 @@ struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32); __type(key, __u32);
__type(value, struct match_set); __type(value, struct match_set);
__uint(max_entries, MAX_ROUTING_LEN); __uint(max_entries, MAX_MATCH_SET_LEN);
// __uint(pinning, LIBBPF_PIN_BY_NAME); // __uint(pinning, LIBBPF_PIN_BY_NAME);
} routing_map SEC(".maps"); } routing_map SEC(".maps");
struct domain_routing { struct domain_routing {
__u32 bitmap[MAX_ROUTING_LEN / 32]; __u32 bitmap[MAX_MATCH_SET_LEN / 32];
}; };
struct { struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(type, BPF_MAP_TYPE_LRU_HASH);
@ -773,13 +772,13 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
#define _ipversion flag[1] #define _ipversion flag[1]
#define _hash flag[2] #define _hash flag[2]
/// TODO: BPF_MAP_UPDATE_BATCH ? /// TODO: BPF_MAP_UPDATE_BATCH ?
__u32 key = ROUTING_TYPE_L4PROTO; __u32 key = MatchType_L4Proto;
int ret; int ret;
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto, if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_l4proto,
BPF_ANY))) { BPF_ANY))) {
return ret; return ret;
}; };
key = ROUTING_TYPE_IPVERSION; key = MatchType_IpVersion;
if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion, if ((ret = bpf_map_update_elem(&l4proto_ipversion_map, &key, &_ipversion,
BPF_ANY))) { BPF_ANY))) {
return ret; return ret;
@ -788,24 +787,24 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
// Define variables for further use. // Define variables for further use.
__u16 h_dport; __u16 h_dport;
__u16 h_sport; __u16 h_sport;
if (_l4proto == L4PROTO_TYPE_TCP) { if (_l4proto == L4ProtoType_TCP) {
h_dport = bpf_ntohs(((struct tcphdr *)l4_hdr)->dest); h_dport = bpf_ntohs(((struct tcphdr *)l4_hdr)->dest);
h_sport = bpf_ntohs(((struct tcphdr *)l4_hdr)->source); h_sport = bpf_ntohs(((struct tcphdr *)l4_hdr)->source);
} else { } else {
h_dport = bpf_ntohs(((struct udphdr *)l4_hdr)->dest); h_dport = bpf_ntohs(((struct udphdr *)l4_hdr)->dest);
h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source); h_sport = bpf_ntohs(((struct udphdr *)l4_hdr)->source);
} }
key = ROUTING_TYPE_SOURCE_PORT; key = MatchType_SourcePort;
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY))) { if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_sport, BPF_ANY))) {
return ret; return ret;
}; };
key = ROUTING_TYPE_PORT; key = MatchType_Port;
if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY))) { if ((ret = bpf_map_update_elem(&h_port_map, &key, &h_dport, BPF_ANY))) {
return ret; return ret;
}; };
// Modify DNS upstream for routing. // Modify DNS upstream for routing.
if (h_dport == 53 && _l4proto == L4PROTO_TYPE_UDP) { if (h_dport == 53 && _l4proto == L4ProtoType_UDP) {
struct ip_port *upstream = struct ip_port *upstream =
bpf_map_lookup_elem(&dns_upstream_map, &zero_key); bpf_map_lookup_elem(&dns_upstream_map, &zero_key);
if (!upstream) { if (!upstream) {
@ -822,17 +821,17 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
__builtin_memcpy(lpm_key_daddr.data, daddr, IPV6_BYTE_LENGTH); __builtin_memcpy(lpm_key_daddr.data, daddr, IPV6_BYTE_LENGTH);
__builtin_memcpy(lpm_key_mac.data, mac, IPV6_BYTE_LENGTH); __builtin_memcpy(lpm_key_mac.data, mac, IPV6_BYTE_LENGTH);
// bpf_printk("mac: %pI6", mac); // bpf_printk("mac: %pI6", mac);
key = ROUTING_TYPE_IP_SET; key = MatchType_IpSet;
if ((ret = if ((ret =
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_daddr, BPF_ANY))) { bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_daddr, BPF_ANY))) {
return ret; return ret;
}; };
key = ROUTING_TYPE_SOURCE_IP_SET; key = MatchType_SourceIpSet;
if ((ret = if ((ret =
bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_saddr, BPF_ANY))) { bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_saddr, BPF_ANY))) {
return ret; return ret;
}; };
key = ROUTING_TYPE_MAC; key = MatchType_Mac;
if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_mac, BPF_ANY))) { if ((ret = bpf_map_update_elem(&lpm_key_map, &key, &lpm_key_mac, BPF_ANY))) {
return ret; return ret;
}; };
@ -849,7 +848,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
__u16 *p_u16; __u16 *p_u16;
#pragma unroll #pragma unroll
for (__u32 i = 0; i < MAX_ROUTING_LEN; i++) { for (__u32 i = 0; i < MAX_MATCH_SET_LEN; i++) {
__u32 k = i; // Clone to pass code checker. __u32 k = i; // Clone to pass code checker.
match_set = bpf_map_lookup_elem(&routing_map, &k); match_set = bpf_map_lookup_elem(&routing_map, &k);
if (!match_set) { if (!match_set) {
@ -896,7 +895,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
if (*p_u32 & match_set->__value) { if (*p_u32 & match_set->__value) {
good_subrule = true; good_subrule = true;
} }
} else if (match_set->type == ROUTING_TYPE_DOMAIN_SET) { } else if (match_set->type == MatchType_DomainSet) {
// bpf_printk("CHECK: domain, match_set->type: %u, not: %d, " // bpf_printk("CHECK: domain, match_set->type: %u, not: %d, "
// "outbound: %u", // "outbound: %u",
// match_set->type, match_set->not, match_set->outbound); // match_set->type, match_set->not, match_set->outbound);
@ -914,7 +913,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
if ((domain_routing->bitmap[i / 32] >> (i % 32)) & 1) { if ((domain_routing->bitmap[i / 32] >> (i % 32)) & 1) {
good_subrule = true; good_subrule = true;
} }
} else if (match_set->type == ROUTING_TYPE_FINAL) { } else if (match_set->type == MatchType_Final) {
// bpf_printk("CHECK: hit final"); // bpf_printk("CHECK: hit final");
good_subrule = true; good_subrule = true;
} else { } else {
@ -947,7 +946,7 @@ static int routing(__u32 flag[3], void *l4_hdr, __be32 saddr[4],
// bpf_printk("MATCHED: match_set->type: %u, match_set->not: %d", // bpf_printk("MATCHED: match_set->type: %u, match_set->not: %d",
// match_set->type, match_set->not ); // match_set->type, match_set->not );
if (match_set->outbound == OUTBOUND_DIRECT && h_dport == 53 && if (match_set->outbound == OUTBOUND_DIRECT && h_dport == 53 &&
_l4proto == L4PROTO_TYPE_UDP) { _l4proto == L4ProtoType_UDP) {
// DNS packet should go through control plane. // DNS packet should go through control plane.
return OUTBOUND_CONTROL_PLANE_DIRECT; return OUTBOUND_CONTROL_PLANE_DIRECT;
} }
@ -1044,11 +1043,11 @@ int tproxy_ingress(struct __sk_buff *skb) {
if (unlikely(tcp_state_syn)) { if (unlikely(tcp_state_syn)) {
// New TCP connection. // New TCP connection.
// bpf_printk("[%X]New Connection", bpf_ntohl(tcph->seq)); // bpf_printk("[%X]New Connection", bpf_ntohl(tcph->seq));
__u32 flag[3] = {L4PROTO_TYPE_TCP}; // TCP __u32 flag[3] = {L4ProtoType_TCP}; // TCP
if (ipv6h) { if (ipv6h) {
flag[1] = IPVERSION_6; flag[1] = IpVersion_6;
} else { } else {
flag[1] = IPVERSION_4; flag[1] = IpVersion_4;
} }
flag[2] = skb->hash; flag[2] = skb->hash;
__be32 mac[4] = { __be32 mac[4] = {
@ -1117,11 +1116,11 @@ int tproxy_ingress(struct __sk_buff *skb) {
new_hdr.port = udph->dest; new_hdr.port = udph->dest;
// Routing. It decides if we redirect traffic to control plane. // Routing. It decides if we redirect traffic to control plane.
__u32 flag[3] = {L4PROTO_TYPE_UDP}; __u32 flag[3] = {L4ProtoType_UDP};
if (ipv6h) { if (ipv6h) {
flag[1] = IPVERSION_6; flag[1] = IpVersion_6;
} else { } else {
flag[1] = IPVERSION_4; flag[1] = IpVersion_4;
} }
flag[2] = skb->hash; flag[2] = skb->hash;
__be32 mac[4] = { __be32 mac[4] = {
@ -1183,7 +1182,7 @@ int tproxy_ingress(struct __sk_buff *skb) {
if (*disable_l4_checksum) { if (*disable_l4_checksum) {
__u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl); __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl);
// Restore the checksum or set it zero. // Restore the checksum or set it zero.
if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) { if (*disable_l4_checksum == DisableL4ChecksumPolicy_SetZero) {
bak_cksm = 0; bak_cksm = 0;
} }
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0); bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);
@ -1351,7 +1350,7 @@ int tproxy_egress(struct __sk_buff *skb) {
if (*disable_l4_checksum) { if (*disable_l4_checksum) {
__u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl); __u32 l4_cksm_off = l4_checksum_off(l4_proto, ihl);
// Restore the checksum or set it zero. // Restore the checksum or set it zero.
if (*disable_l4_checksum == DISABLE_L4_CHECKSUM_POLICY_SET_ZERO) { if (*disable_l4_checksum == DisableL4ChecksumPolicy_SetZero) {
bak_cksm = 0; bak_cksm = 0;
} }
bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0); bpf_skb_store_bytes(skb, l4_cksm_off, &bak_cksm, sizeof(bak_cksm), 0);

View File

@ -74,7 +74,7 @@ func (b *RoutingMatcherBuilder) AddDomain(f *config_parser.Function, key string,
Domains: values, Domains: values,
}) })
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_DomainSet), Type: uint8(consts.RoutingType_DomainSet),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
}) })
@ -94,7 +94,7 @@ func (b *RoutingMatcherBuilder) AddSourceMac(f *config_parser.Function, macAddrs
lpmTrieIndex := len(b.SimulatedLpmTries) lpmTrieIndex := len(b.SimulatedLpmTries)
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_Mac), Type: uint8(consts.RoutingType_Mac),
Value: uint32(lpmTrieIndex), Value: uint32(lpmTrieIndex),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -109,7 +109,7 @@ func (b *RoutingMatcherBuilder) AddIp(f *config_parser.Function, values []netip.
lpmTrieIndex := len(b.SimulatedLpmTries) lpmTrieIndex := len(b.SimulatedLpmTries)
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_IpSet), Type: uint8(consts.RoutingType_IpSet),
Value: uint32(lpmTrieIndex), Value: uint32(lpmTrieIndex),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -123,7 +123,7 @@ func (b *RoutingMatcherBuilder) AddPort(f *config_parser.Function, values [][2]u
outbound = _outbound outbound = _outbound
} }
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_Port), Type: uint8(consts.RoutingType_Port),
Value: _bpfPortRange{ Value: _bpfPortRange{
PortStart: value[0], PortStart: value[0],
PortEnd: value[1], PortEnd: value[1],
@ -141,7 +141,7 @@ func (b *RoutingMatcherBuilder) AddSourceIp(f *config_parser.Function, values []
lpmTrieIndex := len(b.SimulatedLpmTries) lpmTrieIndex := len(b.SimulatedLpmTries)
b.SimulatedLpmTries = append(b.SimulatedLpmTries, values) b.SimulatedLpmTries = append(b.SimulatedLpmTries, values)
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_SourceIpSet), Type: uint8(consts.RoutingType_SourceIpSet),
Value: uint32(lpmTrieIndex), Value: uint32(lpmTrieIndex),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -155,7 +155,7 @@ func (b *RoutingMatcherBuilder) AddSourcePort(f *config_parser.Function, values
outbound = _outbound outbound = _outbound
} }
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_SourcePort), Type: uint8(consts.RoutingType_SourcePort),
Value: _bpfPortRange{ Value: _bpfPortRange{
PortStart: value[0], PortStart: value[0],
PortEnd: value[1], PortEnd: value[1],
@ -171,7 +171,7 @@ func (b *RoutingMatcherBuilder) AddL4Proto(f *config_parser.Function, values con
return return
} }
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_L4Proto), Type: uint8(consts.RoutingType_L4Proto),
Value: uint32(values), Value: uint32(values),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -183,7 +183,7 @@ func (b *RoutingMatcherBuilder) AddIpVersion(f *config_parser.Function, values c
return return
} }
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_IpVersion), Type: uint8(consts.RoutingType_IpVersion),
Value: uint32(values), Value: uint32(values),
Not: f.Not, Not: f.Not,
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -196,7 +196,7 @@ func (b *RoutingMatcherBuilder) AddFinal(outbound string) {
} }
b.Final = outbound b.Final = outbound
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint32(consts.RoutingType_Final), Type: uint8(consts.RoutingType_Final),
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
}) })
} }
@ -226,7 +226,7 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
} }
// Write routings. // Write routings.
// Final rule MUST be the last. // Final rule MUST be the last.
if b.rules[len(b.rules)-1].Type != uint32(consts.RoutingType_Final) { if b.rules[len(b.rules)-1].Type != uint8(consts.RoutingType_Final) {
b.err = fmt.Errorf("final rule MUST be the last") b.err = fmt.Errorf("final rule MUST be the last")
return b.err return b.err
} }
@ -239,4 +239,3 @@ func (b *RoutingMatcherBuilder) Build() (err error) {
} }
return nil return nil
} }

View File

@ -8,8 +8,8 @@ package control
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/mzz2017/softwind/pool"
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/pkg/pool"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
"net" "net"
"net/netip" "net/netip"

View File

@ -7,7 +7,7 @@ package control
import ( import (
"fmt" "fmt"
"github.com/v2rayA/dae/pkg/pool" "github.com/mzz2017/softwind/pool"
"golang.org/x/net/proxy" "golang.org/x/net/proxy"
"net" "net"
"net/netip" "net/netip"

View File

@ -1,72 +0,0 @@
/*
* SPDX-License-Identifier: AGPL-3.0-only
* Copyright (c) since 2022, v2rayA Organization <team@v2raya.org>
*/
// modified from https://github.com/nadoo/glider/blob/master/pool/buffer.go
package pool
import (
"math/bits"
"sync"
)
const (
// number of pools.
num = 17
maxsize = 1 << (num - 1)
)
var (
sizes [num]int
pools [num]sync.Pool
)
func init() {
for i := 0; i < num; i++ {
size := 1 << i
sizes[i] = size
pools[i].New = func() interface{} {
return make([]byte, size)
}
}
}
func GetClosestN(need int) (n int) {
// if need is exactly 2^n, return n-1
if need&(need-1) == 0 {
return bits.Len32(uint32(need)) - 1
}
// or return its closest n
return bits.Len32(uint32(need))
}
// Get gets a buffer from pool, size should in range: [1, 65536],
// otherwise, this function will call make([]byte, size) directly.
func Get(size int) []byte {
if size >= 1 && size <= maxsize {
i := GetClosestN(size)
return pools[i].Get().([]byte)[:size]
}
return make([]byte, size)
}
// GetZero returns buffer and set all the values to 0
func GetZero(size int) []byte {
b := Get(size)
for i := range b {
b[i] = 0
}
return b
}
// Put puts a buffer into pool.
func Put(buf []byte) {
if size := cap(buf); size >= 1 && size <= maxsize {
i := GetClosestN(size)
if i < num {
pools[i].Put(buf)
}
}
}