fix(ebpf): optimize code complexity

This commit is contained in:
mzz2017
2023-04-04 23:29:30 +08:00
parent 85343ac141
commit 099c51a95e

View File

@ -926,7 +926,7 @@ decap_after_udp_hdr(struct __sk_buff *skb, __u8 ipversion, __u8 ihl,
// Do not use __always_inline here because this function is too heavy. // Do not use __always_inline here because this function is too heavy.
// low -> high: outbound(8b) mark(32b) unused(23b) sign(1b) // low -> high: outbound(8b) mark(32b) unused(23b) sign(1b)
static __s64 __attribute__((noinline)) static __s64 __attribute__((noinline))
routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4], route(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
const __be32 daddr[4], const __be32 mac[4]) { const __be32 daddr[4], const __be32 mac[4]) {
#define _l4proto_type flag[0] #define _l4proto_type flag[0]
#define _ipversion_type flag[1] #define _ipversion_type flag[1]
@ -995,7 +995,8 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
// Rule is like: domain(suffix:baidu.com, suffix:google.com) && port(443) -> // Rule is like: domain(suffix:baidu.com, suffix:google.com) && port(443) ->
// proxy Subrule is like: domain(suffix:baidu.com, suffix:google.com) Match // proxy Subrule is like: domain(suffix:baidu.com, suffix:google.com) Match
// set is like: suffix:baidu.com // set is like: suffix:baidu.com
__u8 must_goodsubrule_badrule = 0; volatile __u8 isdns_must_goodsubrule_badrule =
(h_dport == 53 && _l4proto_type == L4ProtoType_UDP) << 3;
struct domain_routing *domain_routing; struct domain_routing *domain_routing;
__u32 *p_u32; __u32 *p_u32;
__u16 *p_u16; __u16 *p_u16;
@ -1009,7 +1010,7 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
if (unlikely(!match_set)) { if (unlikely(!match_set)) {
return -EFAULT; return -EFAULT;
} }
if ((must_goodsubrule_badrule & 0b1) || (must_goodsubrule_badrule & 0b10)) { if (isdns_must_goodsubrule_badrule & 0b11) {
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
key = match_set->type; key = match_set->type;
bpf_printk("key(match_set->type): %llu", key); bpf_printk("key(match_set->type): %llu", key);
@ -1035,7 +1036,7 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
} }
if (bpf_map_lookup_elem(lpm, lpm_key)) { if (bpf_map_lookup_elem(lpm, lpm_key)) {
// match_set hits. // match_set hits.
must_goodsubrule_badrule |= 0b10; isdns_must_goodsubrule_badrule |= 0b10;
} }
} else if ((p_u16 = bpf_map_lookup_elem(&h_port_map, &key))) { } else if ((p_u16 = bpf_map_lookup_elem(&h_port_map, &key))) {
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
@ -1048,7 +1049,7 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
#endif #endif
if (*p_u16 >= match_set->port_range.port_start && if (*p_u16 >= match_set->port_range.port_start &&
*p_u16 <= match_set->port_range.port_end) { *p_u16 <= match_set->port_range.port_end) {
must_goodsubrule_badrule |= 0b10; isdns_must_goodsubrule_badrule |= 0b10;
} }
} else if ((p_u32 = bpf_map_lookup_elem(&l4proto_ipversion_map, &key))) { } else if ((p_u32 = bpf_map_lookup_elem(&l4proto_ipversion_map, &key))) {
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
@ -1057,42 +1058,45 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
match_set->type, match_set->not, match_set->outbound); match_set->type, match_set->not, match_set->outbound);
#endif #endif
if (*p_u32 & *(__u32 *)&match_set->__value) { if (*p_u32 & *(__u32 *)&match_set->__value) {
must_goodsubrule_badrule |= 0b10; isdns_must_goodsubrule_badrule |= 0b10;
} }
} else if (match_set->type == MatchType_DomainSet) {
#ifdef __DEBUG_ROUTING
bpf_printk("CHECK: domain, match_set->type: %u, not: %d, "
"outbound: %u",
match_set->type, match_set->not, match_set->outbound);
#endif
// Get domain routing bitmap.
domain_routing = bpf_map_lookup_elem(&domain_routing_map, daddr);
if (!domain_routing) {
// No domain corresponding to IP.
goto before_next_loop;
}
// We use key instead of k to pass checker.
if ((domain_routing->bitmap[i / 32] >> (i % 32)) & 1) {
must_goodsubrule_badrule |= 0b10;
}
} else if (match_set->type == MatchType_ProcessName) {
if (_is_wan && equal16(match_set->pname, _pname)) {
must_goodsubrule_badrule |= 0b10;
}
} else if (match_set->type == MatchType_Fallback) {
#ifdef __DEBUG_ROUTING
bpf_printk("CHECK: hit fallback");
#endif
must_goodsubrule_badrule |= 0b10;
} else { } else {
switch (key) {
case MatchType_DomainSet:
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
bpf_printk("CHECK: <unknown>, 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);
#endif #endif
return -EINVAL;
// Get domain routing bitmap.
domain_routing = bpf_map_lookup_elem(&domain_routing_map, daddr);
// We use key instead of k to pass checker.
if (domain_routing &&
(domain_routing->bitmap[i / 32] >> (i % 32)) & 1) {
isdns_must_goodsubrule_badrule |= 0b10;
}
break;
case MatchType_ProcessName:
if (_is_wan && equal16(match_set->pname, _pname)) {
isdns_must_goodsubrule_badrule |= 0b10;
}
break;
case MatchType_Fallback:
#ifdef __DEBUG_ROUTING
bpf_printk("CHECK: hit fallback");
#endif
isdns_must_goodsubrule_badrule |= 0b10;
break;
default:
#ifdef __DEBUG_ROUTING
bpf_printk("CHECK: <unknown>, match_set->type: %u, not: %d, "
"outbound: %u",
match_set->type, match_set->not, match_set->outbound);
#endif
return -EINVAL;
}
} }
before_next_loop: before_next_loop:
@ -1104,13 +1108,13 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
// We are now at end of rule, or next match_set belongs to another // We are now at end of rule, or next match_set belongs to another
// subrule. // subrule.
if ((must_goodsubrule_badrule & 0b10) > 0 == match_set->not ) { if ((isdns_must_goodsubrule_badrule & 0b10) > 0 == match_set->not ) {
// This subrule does not hit. // This subrule does not hit.
must_goodsubrule_badrule |= 0b1; isdns_must_goodsubrule_badrule |= 0b1;
} }
// Reset good_subrule. // Reset good_subrule.
must_goodsubrule_badrule &= ~0b10; isdns_must_goodsubrule_badrule &= ~0b10;
} }
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
bpf_printk("_bad_rule: %d", bad_rule); bpf_printk("_bad_rule: %d", bad_rule);
@ -1119,7 +1123,7 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
OUTBOUND_LOGICAL_MASK) { OUTBOUND_LOGICAL_MASK) {
// Tail of a rule (line). // Tail of a rule (line).
// Decide whether to hit. // Decide whether to hit.
if (!(must_goodsubrule_badrule & 0b1)) { if (!(isdns_must_goodsubrule_badrule & 0b1)) {
#ifdef __DEBUG_ROUTING #ifdef __DEBUG_ROUTING
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 );
@ -1127,22 +1131,24 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
// DNS requests should routed by control plane if outbound is not // DNS requests should routed by control plane if outbound is not
// must_direct. // must_direct.
if (match_set->outbound == OUTBOUND_MUST_RULES) {
must_goodsubrule_badrule |= 0b100; if (unlikely(match_set->outbound == OUTBOUND_MUST_RULES)) {
continue; isdns_must_goodsubrule_badrule |= 0b100;
} else {
if (isdns_must_goodsubrule_badrule & 0b100) {
match_set->must = true;
}
if (!match_set->must && (isdns_must_goodsubrule_badrule & 0b1000)) {
return (__s64)OUTBOUND_CONTROL_PLANE_ROUTING |
((__s64)match_set->mark << 8) |
((__s64)match_set->must << 40);
} else {
return (__s64)match_set->outbound | ((__s64)match_set->mark << 8) |
((__s64)match_set->must << 40);
}
} }
if (must_goodsubrule_badrule & 0b100) {
match_set->must = true;
}
if (!match_set->must && h_dport == 53 &&
_l4proto_type == L4ProtoType_UDP) {
return (__s64)OUTBOUND_CONTROL_PLANE_ROUTING |
((__s64)match_set->mark << 8) | ((__s64)match_set->must << 40);
}
return (__s64)match_set->outbound | ((__s64)match_set->mark << 8) |
((__s64)match_set->must << 40);
} }
must_goodsubrule_badrule &= ~0b1; isdns_must_goodsubrule_badrule &= ~0b1;
} }
} }
bpf_printk("No match_set hits. Did coder forget to sync " bpf_printk("No match_set hits. Did coder forget to sync "
@ -1329,7 +1335,7 @@ new_connection:
(ethh.h_source[4] << 8) + (ethh.h_source[5])), (ethh.h_source[4] << 8) + (ethh.h_source[5])),
}; };
__s64 s64_ret; __s64 s64_ret;
if ((s64_ret = routing(flag, l4hdr, tuples.sip.u6_addr32, if ((s64_ret = route(flag, l4hdr, tuples.sip.u6_addr32,
tuples.dip.u6_addr32, mac)) < 0) { tuples.dip.u6_addr32, mac)) < 0) {
bpf_printk("shot routing: %d", s64_ret); bpf_printk("shot routing: %d", s64_ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
@ -1623,7 +1629,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
(ethh.h_source[4] << 8) + (ethh.h_source[5])), (ethh.h_source[4] << 8) + (ethh.h_source[5])),
}; };
__s64 s64_ret; __s64 s64_ret;
if ((s64_ret = routing(flag, &tcph, tuples.sip.u6_addr32, if ((s64_ret = route(flag, &tcph, tuples.sip.u6_addr32,
tuples.dip.u6_addr32, mac)) < 0) { tuples.dip.u6_addr32, mac)) < 0) {
bpf_printk("shot routing: %d", s64_ret); bpf_printk("shot routing: %d", s64_ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
@ -1735,7 +1741,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
(ethh.h_source[4] << 8) + (ethh.h_source[5])), (ethh.h_source[4] << 8) + (ethh.h_source[5])),
}; };
__s64 s64_ret; __s64 s64_ret;
if ((s64_ret = routing(flag, &udph, tuples.sip.u6_addr32, if ((s64_ret = route(flag, &udph, tuples.sip.u6_addr32,
tuples.dip.u6_addr32, mac)) < 0) { tuples.dip.u6_addr32, mac)) < 0) {
bpf_printk("shot routing: %d", s64_ret); bpf_printk("shot routing: %d", s64_ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
@ -2060,8 +2066,7 @@ static int __always_inline _update_map_elem_by_cookie(const __u64 cookie) {
For string like: /usr/lib/sddm/sddm-helper --socket /tmp/sddm-auth1 For string like: /usr/lib/sddm/sddm-helper --socket /tmp/sddm-auth1
We extract "sddm-helper" from it. We extract "sddm-helper" from it.
*/ */
unsigned long loc, j; unsigned long loc, j, last_slash = -1;
unsigned long last_slash = -1;
#pragma unroll #pragma unroll
for (loc = 0, j = 0; j < MAX_ARG_LEN_TO_PROBE; for (loc = 0, j = 0; j < MAX_ARG_LEN_TO_PROBE;
++j, loc = ((loc + 1) & (MAX_ARG_SCANNER_BUFFER_SIZE - 1))) { ++j, loc = ((loc + 1) & (MAX_ARG_SCANNER_BUFFER_SIZE - 1))) {