diff --git a/bpf/include/bpf_helper_defs_ext.h b/bpf/include/bpf_helper_defs_ext.h index 7bd9549b8..fc1c6b351 100644 --- a/bpf/include/bpf_helper_defs_ext.h +++ b/bpf/include/bpf_helper_defs_ext.h @@ -10,9 +10,8 @@ * By default, these IDs are in the 5.10 kernel with kmesh kernel patches. */ -static void *(*bpf_strncpy)(char *dst, __u32 dst_size, char *src) = (void *)171; -static void *(*bpf_strnstr)(void *s1, void *s2, __u32 size) = (void *)172; -static __u64 (*bpf_strnlen)(char *buff, __u32 size) = (void *)173; -static __u64 (*bpf__strncmp)(const char *s1, __u32 s1_size, const char *s2) = (void *)174; -static long (*bpf_parse_header_msg)(struct bpf_mem_ptr *msg) = (void *)175; -static void *(*bpf_get_msg_header_element)(void *name) = (void *)176; +static int (*bpf_km_strnstr)( + struct bpf_sock_addr *ctx, const char *key, int key_sz, const char *subptr, int subptr_sz) = (void *)163; +static int (*bpf_km_strncmp)( + struct bpf_sock_addr *ctx, const char *key, int key_sz, const char *subptr, int subptr_sz) = (void *)164; +static long (*bpf_parse_header_msg)(struct bpf_sock_addr *ctx) = (void *)165; diff --git a/bpf/kmesh/ads/cgroup_sock.c b/bpf/kmesh/ads/cgroup_sock.c index 7293f104a..c6dbe1588 100644 --- a/bpf/kmesh/ads/cgroup_sock.c +++ b/bpf/kmesh/ads/cgroup_sock.c @@ -12,11 +12,14 @@ #include "cluster.h" #include "bpf_common.h" +#if ENHANCED_KERNEL +#include "route_config.h" +#endif #if KMESH_ENABLE_IPV4 #if KMESH_ENABLE_HTTP static const char kmesh_module_name[] = "kmesh_defer"; - +static char kmesh_module_name_get[16]; static inline int sock4_traffic_control(struct bpf_sock_addr *ctx) { int ret; @@ -39,18 +42,19 @@ static inline int sock4_traffic_control(struct bpf_sock_addr *ctx) BPF_LOG(DEBUG, KMESH, "bpf find listener addr=[%s:%u]\n", ip2str(&ip, 1), bpf_ntohs(ctx->user_port)); #if ENHANCED_KERNEL - // todo build when kernel support http parse and route - // defer conn - ret = bpf_setsockopt(ctx, IPPROTO_TCP, TCP_ULP, (void *)kmesh_module_name, sizeof(kmesh_module_name)); - if (ret) - BPF_LOG(ERR, KMESH, "bpf set sockopt failed! ret:%d\n", ret); -#else // KMESH_ENABLE_HTTP - ret = listener_manager(ctx, listener, NULL); + ret = bpf_getsockopt(ctx, IPPROTO_TCP, TCP_ULP, (void *)kmesh_module_name_get, 16); + BPF_LOG(DEBUG, KMESH, "kmesh_module_name_get:%s ret:%d\n", kmesh_module_name_get, ret); + if (ret != 0 || bpf__strncmp(kmesh_module_name_get, 16, kmesh_module_name)) { + ret = bpf_setsockopt(ctx, IPPROTO_TCP, TCP_ULP, (void *)kmesh_module_name, sizeof(kmesh_module_name)); + if (ret) + BPF_LOG(ERR, KMESH, "bpf set sockopt failed! ret %d\n", ret); + return 0; + } +#endif + ret = listener_manager(ctx, listener, ctx); if (ret != 0) { BPF_LOG(ERR, KMESH, "listener_manager failed, ret %d\n", ret); - return ret; } -#endif // KMESH_ENABLE_HTTP return 0; } diff --git a/bpf/kmesh/ads/include/circuit_breaker.h b/bpf/kmesh/ads/include/circuit_breaker.h index b4106c5bd..187aafc44 100644 --- a/bpf/kmesh/ads/include/circuit_breaker.h +++ b/bpf/kmesh/ads/include/circuit_breaker.h @@ -4,6 +4,7 @@ #include "bpf_log.h" #include "kmesh_common.h" #include "bpf_common.h" +#include "cluster/cluster.pb-c.h" #ifndef __KMESH_CIRCUIT_BREAKER_H__ #define __KMESH_CIRCUIT_BREAKER_H__ diff --git a/bpf/kmesh/ads/include/filter.h b/bpf/kmesh/ads/include/filter.h index 467d57264..53adbe722 100644 --- a/bpf/kmesh/ads/include/filter.h +++ b/bpf/kmesh/ads/include/filter.h @@ -128,10 +128,10 @@ int filter_manager(ctx_buff_t *ctx) kmesh_tail_delete_ctx(&ctx_key); switch (filter->config_type_case) { -#ifndef CGROUP_SOCK_MANAGE +#if ENHANCED_KERNEL case LISTENER__FILTER__CONFIG_TYPE_HTTP_CONNECTION_MANAGER: http_conn = KMESH_GET_PTR_VAL(filter->http_connection_manager, Filter__HttpConnectionManager); - ret = bpf_parse_header_msg(ctx_val->msg); + ret = bpf_parse_header_msg(ctx); if (GET_RET_PROTO_TYPE(ret) != PROTO_HTTP_1_1) { BPF_LOG(DEBUG, FILTER, "http filter manager,only support http1.1 this version"); break; diff --git a/bpf/kmesh/ads/include/kmesh_common.h b/bpf/kmesh/ads/include/kmesh_common.h index 2a9c62010..9f7173d79 100644 --- a/bpf/kmesh/ads/include/kmesh_common.h +++ b/bpf/kmesh/ads/include/kmesh_common.h @@ -34,7 +34,6 @@ struct bpf_mem_ptr { __u32 size; }; -#if !ENHANCED_KERNEL static inline int bpf__strncmp(const char *dst, int n, const char *src) { if (dst == NULL || src == NULL) @@ -69,7 +68,6 @@ static inline char *bpf_strncpy(char *dst, int n, const char *src) } return dst; } -#endif typedef Core__SocketAddress address_t; @@ -81,6 +79,8 @@ enum kmesh_l7_proto_type { PROTO_UNKNOW = 0, PROTO_HTTP_1_1, PROTO_HTTP_2_0 }; enum kmesh_l7_msg_type { MSG_UNKNOW = 0, MSG_REQUEST, MSG_MID_REPONSE, MSG_FINAL_RESPONSE }; +enum kmesh_strncmp_type { STRNCMP_FAILED = 0, STRNCMP_PREFIX, STRNCMP_EXACT }; + #define KMESH_PROTO_TYPE_WIDTH (8) #define GET_RET_PROTO_TYPE(n) ((n)&0xff) #define GET_RET_MSG_TYPE(n) (((n) >> KMESH_PROTO_TYPE_WIDTH) & 0xff) diff --git a/bpf/kmesh/ads/include/route_config.h b/bpf/kmesh/ads/include/route_config.h index d0fca66bd..7de4a6c50 100644 --- a/bpf/kmesh/ads/include/route_config.h +++ b/bpf/kmesh/ads/include/route_config.h @@ -28,8 +28,8 @@ static inline Route__RouteConfiguration *map_lookup_route_config(const char *rou return kmesh_map_lookup_elem(&map_of_router_config, route_name); } -static inline int -virtual_host_match_check(Route__VirtualHost *virt_host, address_t *addr, ctx_buff_t *ctx, struct bpf_mem_ptr *host) +static inline int virtual_host_match_check( +Route__VirtualHost *virt_host, address_t *addr, ctx_buff_t *ctx, char *host_key, int host_key_len) { int i; void *domains = NULL; @@ -37,15 +37,6 @@ virtual_host_match_check(Route__VirtualHost *virt_host, address_t *addr, ctx_buf void *ptr; __u32 ptr_length; - if (!host) - return 0; - - ptr = _(host->ptr); - if (!ptr) - return 0; - - ptr_length = _(host->size); - if (!virt_host->domains) return 0; @@ -65,14 +56,8 @@ virtual_host_match_check(Route__VirtualHost *virt_host, address_t *addr, ctx_buf if (((char *)domain)[0] == '*' && ((char *)domain)[1] == '\0') return 1; - if (bpf_strnstr(ptr, domain, ptr_length) != NULL) { - BPF_LOG( - DEBUG, - ROUTER_CONFIG, - "match virtual_host, name=\"%s\"\n", - (char *)KMESH_GET_PTR_VAL(virt_host->name, char *)); + if (bpf_km_strnstr(ctx, host_key, host_key_len, domain, BPF_DATA_MAX_LEN) != 0) return 1; - } } return 0; @@ -95,7 +80,7 @@ virtual_host_match(Route__RouteConfiguration *route_config, address_t *addr, ctx Route__VirtualHost *virt_host = NULL; Route__VirtualHost *virt_host_allow_any = NULL; char host_key[5] = {'H', 'o', 's', 't', '\0'}; - struct bpf_mem_ptr *host; + int host_key_len = 5; if (route_config->n_virtual_hosts <= 0 || route_config->n_virtual_hosts > KMESH_PER_VIRT_HOST_NUM) { BPF_LOG(WARN, ROUTER_CONFIG, "invalid virt hosts num=%d\n", route_config->n_virtual_hosts); @@ -108,12 +93,6 @@ virtual_host_match(Route__RouteConfiguration *route_config, address_t *addr, ctx return NULL; } - host = bpf_get_msg_header_element(host_key); - if (!host) { - BPF_LOG(ERR, ROUTER_CONFIG, "failed to get URI in msg\n"); - return NULL; - } - for (i = 0; i < KMESH_PER_VIRT_HOST_NUM; i++) { if (i >= route_config->n_virtual_hosts) { break; @@ -128,27 +107,34 @@ virtual_host_match(Route__RouteConfiguration *route_config, address_t *addr, ctx continue; } - if (virtual_host_match_check(virt_host, addr, ctx, host)) + if (virtual_host_match_check(virt_host, addr, ctx, host_key, host_key_len)) { + BPF_LOG( + DEBUG, + ROUTER_CONFIG, + "match virtual_host, name=\"%s\"\n", + (char *)KMESH_GET_PTR_VAL(virt_host->name, char *)); return virt_host; + } } // allow_any as the default virt_host - if (virt_host_allow_any && virtual_host_match_check(virt_host_allow_any, addr, ctx, host)) + if (virt_host_allow_any && virtual_host_match_check(virt_host_allow_any, addr, ctx, host_key, host_key_len)) return virt_host_allow_any; return NULL; } -static inline bool check_header_value_match(char *target, struct bpf_mem_ptr *head, bool exact) +static inline bool check_header_value_match(struct bpf_sock_addr *ctx, char *header_name, char *target, bool exact) { - BPF_LOG(DEBUG, ROUTER_CONFIG, "header match, is exact:%d value:%s\n", exact, target); - long target_length = bpf_strnlen(target, BPF_DATA_MAX_LEN); - if (!exact) - return (bpf__strncmp(target, target_length, _(head->ptr)) == 0); - if (target_length != _(head->size)) - return false; - return (bpf__strncmp(target, target_length, _(head->ptr)) == 0); + int ret = 0; + ret = bpf_km_strncmp(ctx, header_name, BPF_DATA_MAX_LEN, target, BPF_DATA_MAX_LEN); + if (ret == STRNCMP_EXACT) { + return true; + } else if (ret == STRNCMP_PREFIX && !exact) { + return true; + } + return false; } -static inline bool check_headers_match(Route__RouteMatch *match) +static inline bool check_headers_match(struct bpf_sock_addr *ctx, Route__RouteMatch *match) { int i; void *ptrs = NULL; @@ -182,19 +168,15 @@ static inline bool check_headers_match(Route__RouteMatch *match) BPF_LOG(ERR, ROUTER_CONFIG, "failed to get match headers in route match\n"); return false; } - msg_header = (struct bpf_mem_ptr *)bpf_get_msg_header_element(header_name); - if (!msg_header) { - BPF_LOG(DEBUG, ROUTER_CONFIG, "failed to get header value form msg\n"); - return false; - } - BPF_LOG(DEBUG, ROUTER_CONFIG, "header match check, name:%s\n", header_name); + switch (header_match->header_match_specifier_case) { case ROUTE__HEADER_MATCHER__HEADER_MATCH_SPECIFIER_EXACT_MATCH: { config_header_value = KMESH_GET_PTR_VAL(header_match->exact_match, char *); if (config_header_value == NULL) { BPF_LOG(ERR, ROUTER_CONFIG, "failed to get config_header_value\n"); + return false; } - if (!check_header_value_match(config_header_value, msg_header, true)) { + if (!check_header_value_match(ctx, header_name, config_header_value, true)) { return false; } break; @@ -203,8 +185,9 @@ static inline bool check_headers_match(Route__RouteMatch *match) config_header_value = KMESH_GET_PTR_VAL(header_match->prefix_match, char *); if (config_header_value == NULL) { BPF_LOG(ERR, ROUTER_CONFIG, "prefix:failed to get config_header_value\n"); + return false; } - if (!check_header_value_match(config_header_value, msg_header, false)) { + if (!check_header_value_match(ctx, header_name, config_header_value, false)) { return false; } break; @@ -223,10 +206,8 @@ virtual_host_route_match_check(Route__Route *route, address_t *addr, ctx_buff_t Route__RouteMatch *match; char *prefix; void *ptr; - - ptr = _(msg->ptr); - if (!ptr) - return 0; + char all_header[4] = {'A', 'l', 'l', '\0'}; + int all_header_len = 4; if (!route->match) return 0; @@ -239,10 +220,11 @@ virtual_host_route_match_check(Route__Route *route, address_t *addr, ctx_buff_t if (!prefix) return 0; - if (bpf_strnstr(ptr, prefix, BPF_DATA_MAX_LEN) == NULL) + if (bpf_km_strnstr(ctx, all_header, all_header_len, prefix, BPF_DATA_MAX_LEN) == 0) { return 0; + } - if (!check_headers_match(match)) + if (!check_headers_match(ctx, match)) return 0; BPF_LOG(DEBUG, ROUTER_CONFIG, "match route, name=\"%s\"\n", (char *)KMESH_GET_PTR_VAL(route->name, char *)); diff --git a/bpf/kmesh/ads/sockops.c b/bpf/kmesh/ads/sockops.c index fcd15e4fc..e7800842f 100644 --- a/bpf/kmesh/ads/sockops.c +++ b/bpf/kmesh/ads/sockops.c @@ -4,45 +4,11 @@ #include #include "bpf_log.h" #include "ctx/sock_ops.h" -#include "listener.h" -#include "listener/listener.pb-c.h" -#include "filter.h" -#include "route_config.h" -#include "cluster.h" #include "circuit_breaker.h" #if KMESH_ENABLE_IPV4 #if KMESH_ENABLE_HTTP -static int sockops_traffic_control(struct bpf_sock_ops *skops, struct bpf_mem_ptr *msg) -{ - int ret; - /* 1 lookup listener */ - DECLARE_VAR_ADDRESS(skops, addr); - addr.port = GET_SKOPS_REMOTE_PORT(skops); - - Listener__Listener *listener = map_lookup_listener(&addr); - - if (!listener) { - addr.ipv4 = 0; - listener = map_lookup_listener(&addr); - if (!listener) { - /* no match vip/nodeport listener */ - return 0; - } - } - - DECLARE_VAR_IPV4(skops->remote_ip4, ip) - BPF_LOG( - DEBUG, - SOCKOPS, - "sockops_traffic_control listener=\"%s\", addr=[%s:%u]\n", - (char *)KMESH_GET_PTR_VAL(listener->name, char *), - ip2str(&ip, 1), - bpf_ntohs(skops->remote_port)); - return listener_manager(skops, listener, msg); -} - SEC("sockops") int sockops_prog(struct bpf_sock_ops *skops) { @@ -53,10 +19,6 @@ int sockops_prog(struct bpf_sock_ops *skops) return BPF_OK; switch (skops->op) { - case BPF_SOCK_OPS_TCP_DEFER_CONNECT_CB: - msg = (struct bpf_mem_ptr *)BPF_CONSTRUCT_PTR(skops->args[0], skops->args[1]); - (void)sockops_traffic_control(skops, msg); - break; case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: if (bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG) != 0) { BPF_LOG(ERR, SOCKOPS, "set sockops cb failed!\n"); diff --git a/bpf/kmesh/ads/tracepoint.c b/bpf/kmesh/ads/tracepoint.c deleted file mode 100644 index c24af007d..000000000 --- a/bpf/kmesh/ads/tracepoint.c +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -/* Copyright Authors of Kmesh */ - -#include -#include -#include - -#define KMESH_DELAY_ERROR -1000 - -struct context { - int *err; -}; - -SEC("raw_tracepoint.w") -int connect_ret(struct context *ctx) -{ - if (*ctx->err == KMESH_DELAY_ERROR) - *ctx->err = 0; - return 0; -} - -char _license[] SEC("license") = "Dual BSD/GPL"; -__u32 _version SEC("version") = 1; diff --git a/daemon/manager/manager.go b/daemon/manager/manager.go index 18d9e757c..cee6980ef 100644 --- a/daemon/manager/manager.go +++ b/daemon/manager/manager.go @@ -34,6 +34,7 @@ import ( "kmesh.net/kmesh/pkg/bpf/restart" "kmesh.net/kmesh/pkg/cni" "kmesh.net/kmesh/pkg/controller" + "kmesh.net/kmesh/pkg/kolog" "kmesh.net/kmesh/pkg/logger" "kmesh.net/kmesh/pkg/status" ) @@ -93,6 +94,7 @@ func Execute(configs *options.BootstrapConfigs) error { stopCh := make(chan struct{}) defer close(stopCh) + kolog.KmeshModuleLog(stopCh) c := controller.NewController(configs, bpfLoader.GetBpfKmesh(), bpfLoader.GetBpfWorkload()) if err := c.Start(stopCh); err != nil { return err diff --git a/kernel/ko_src/kmesh/defer_connect.c b/kernel/ko_src/kmesh/defer_connect.c index ef7d1d7aa..1c9f6a936 100644 --- a/kernel/ko_src/kmesh/defer_connect.c +++ b/kernel/ko_src/kmesh/defer_connect.c @@ -18,18 +18,31 @@ #include #include +#include "defer_connect.h" + static struct proto *kmesh_defer_proto = NULL; -#define KMESH_DELAY_ERROR -1000 +static struct proto_ops *kmesh_defer_proto_ops = NULL; + +#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, uaddr, t_ctx) \ + ({ \ + int __ret = -1; \ + if (t_ctx == NULL) { \ + __ret = -EINVAL; \ + } else { \ + __ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, CGROUP_INET4_CONNECT, t_ctx); \ + } \ + __ret; \ + }) static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size) { struct bpf_mem_ptr tmpMem = {0}; void *kbuf = NULL; size_t kbuf_size; - struct sockaddr_in addr_in; long timeo = 1; const struct iovec *iov; - struct bpf_sock_ops_kern sock_ops; + struct bpf_sock_addr_kern sock_addr; + struct sockaddr_in uaddr; void __user *ubase; int err; u32 dport, daddr; @@ -53,10 +66,13 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size) goto connect; kbuf = (void *)kmalloc(kbuf_size, GFP_KERNEL); - if (!kbuf) + if (!kbuf) { + LOG(KERN_ERR, "kbuf kmalloc failed\n"); return -EFAULT; + } if (copy_from_user(kbuf, ubase, kbuf_size)) { + LOG(KERN_ERR, "copy_from_user failed\n"); err = -EFAULT; goto out; } @@ -83,29 +99,16 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size) goto out; } #else - memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); - if (sk_fullsock(sk)) { - sock_ops.is_fullsock = 1; - sock_owned_by_me(sk); - } - sock_ops.sk = sk; - sock_ops.op = BPF_SOCK_OPS_TCP_DEFER_CONNECT_CB; - sock_ops.args[0] = ((u64)(&tmpMem) & U32_MAX); - sock_ops.args[1] = (((u64)(&tmpMem) >> 32) & U32_MAX); - - (void)BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops); - if (sock_ops.replylong[2] && sock_ops.replylong[3]) { - daddr = sock_ops.replylong[2]; - dport = sock_ops.replylong[3]; - } + uaddr.sin_family = AF_INET; + uaddr.sin_addr.s_addr = daddr; + uaddr.sin_port = dport; + err = BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, (struct sockaddr *)&uaddr, &tmpMem); #endif connect: - addr_in.sin_family = AF_INET; - addr_in.sin_addr.s_addr = daddr; - addr_in.sin_port = dport; - err = sk->sk_prot->connect(sk, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in)); - inet_sk(sk)->bpf_defer_connect = 0; + err = sk->sk_prot->connect(sk, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_in)); + inet_sk(sk)->defer_connect = 0; if (unlikely(err)) { + LOG(KERN_ERR, "connect failed:%d\n", err); tcp_set_state(sk, TCP_CLOSE); sk->sk_route_caps = 0; inet_sk(sk)->inet_dport = 0; @@ -125,9 +128,8 @@ static int defer_connect_and_sendmsg(struct sock *sk, struct msghdr *msg, size_t struct socket *sock; int err = 0; - if (unlikely(inet_sk(sk)->bpf_defer_connect == 1)) { + if (unlikely(inet_sk(sk)->defer_connect == 1)) { lock_sock(sk); - inet_sk(sk)->defer_connect = 0; err = defer_connect(sk, msg, size); if (err) { @@ -148,35 +150,29 @@ static int defer_tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) int ret; ret = defer_connect_and_sendmsg(sk, msg, size); - if (ret) + if (ret) { + LOG(KERN_ERR, "defer_connect_and_sendmsg failed, ret:%d\n", ret); return ret; + } return tcp_sendmsg(sk, msg, size); } static int defer_tcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - /* Kmesh is not compatible with defer_connect, so we - * need to check whether defer_connect is set to 1. - * Kmesh reuses the defer_connect flag to enable the - * epoll to be triggered normally. - */ - if (inet_sk(sk)->defer_connect == 1) - return -ENOTSUPP; - /* bpf_defer_connect is 0 when you first enter the connection. + /* defer_connect is 0 when you first enter the connection. * When you delay link establishment from sendmsg, the value - * of bpf_defer_connect should be 1 and the normal connect function + * of defer_connect should be 1 and the normal connect function * needs to be used. */ - if (inet_sk(sk)->bpf_defer_connect) + if (inet_sk(sk)->defer_connect) return tcp_v4_connect(sk, uaddr, addr_len); - inet_sk(sk)->bpf_defer_connect = 1; inet_sk(sk)->defer_connect = 1; sk->sk_dport = ((struct sockaddr_in *)uaddr)->sin_port; sk_daddr_set(sk, ((struct sockaddr_in *)uaddr)->sin_addr.s_addr); sk->sk_socket->state = SS_CONNECTING; tcp_set_state(sk, TCP_SYN_SENT); - return KMESH_DELAY_ERROR; + return 0; } static int kmesh_build_proto(struct sock *sk) @@ -202,8 +198,10 @@ static struct tcp_ulp_ops kmesh_defer_ulp_ops __read_mostly = { int __init defer_conn_init(void) { kmesh_defer_proto = kmalloc(sizeof(struct proto), GFP_ATOMIC); - if (!kmesh_defer_proto) + if (!kmesh_defer_proto) { + LOG(KERN_ERR, "kmesh_defer_proto kmalloc failed\n"); return -ENOMEM; + } *kmesh_defer_proto = tcp_prot; kmesh_defer_proto->connect = defer_tcp_connect; kmesh_defer_proto->sendmsg = defer_tcp_sendmsg; diff --git a/kernel/ko_src/kmesh/defer_connect.h b/kernel/ko_src/kmesh/defer_connect.h index 88d186f18..caedd7106 100644 --- a/kernel/ko_src/kmesh/defer_connect.h +++ b/kernel/ko_src/kmesh/defer_connect.h @@ -4,6 +4,8 @@ #ifndef KMESH_DEFER_CONN_H #define KMESH_DEFER_CONN_H +#include "kmesh_parse_protocol_data.h" + int __init defer_conn_init(void); void __exit defer_conn_exit(void); diff --git a/kernel/ko_src/kmesh/kmesh_main.c b/kernel/ko_src/kmesh/kmesh_main.c index 7eeaf29b1..d07389db2 100644 --- a/kernel/ko_src/kmesh/kmesh_main.c +++ b/kernel/ko_src/kmesh/kmesh_main.c @@ -19,12 +19,16 @@ static int __init kmesh_init(void) int ret; ret = defer_conn_init(); - if (ret) + if (ret){ + LOG(KERN_ERR, "defer_conn_init failed:%d\n", ret); return ret; + } ret = proto_common_init(); - if (ret) + if (ret) { + LOG(KERN_ERR, "proto_common_init failed:%d\n", ret); return ret; + } ret = kmesh_register_http_1_1_init(); return ret; diff --git a/kernel/ko_src/kmesh/kmesh_parse_http_1_1.c b/kernel/ko_src/kmesh/kmesh_parse_http_1_1.c index bd1ee4a33..aa2da65ad 100644 --- a/kernel/ko_src/kmesh/kmesh_parse_http_1_1.c +++ b/kernel/ko_src/kmesh/kmesh_parse_http_1_1.c @@ -36,9 +36,9 @@ enum state { ST_HEAD_END }; -u32 parse_http_1_1_request(const struct bpf_mem_ptr *msg); +u32 parse_http_1_1_request(const struct bpf_sock_addr_kern *ctx); -u32 parse_http_1_1_respond(const struct bpf_mem_ptr *msg); +u32 parse_http_1_1_respond(const struct bpf_sock_addr_kern *ctx); static enum state __parse_request_startline( const struct bpf_mem_ptr *msg, @@ -121,6 +121,8 @@ static enum state __parse_request_startline( } failed: + if (current_state != ST_FIELD_NAME_START) + LOG(KERN_ERR, "__parse_request_startline failed, current_state:%d, char: %c\n", current_state, ch); return current_state; } @@ -131,8 +133,10 @@ static bool parse_request_startline(const struct bpf_mem_ptr *msg, struct bpf_me struct kmesh_data_node *URI = new_kmesh_data_node(URI_STRING_LENGTH); struct kmesh_data_node *http_version = new_kmesh_data_node(VERSION_STRING_LENGTH); - if (IS_ERR(method) || IS_ERR(URI) || IS_ERR(http_version)) + if (IS_ERR(method) || IS_ERR(URI) || IS_ERR(http_version)) { + LOG(KERN_ERR, "parse_request new kmesh_data_node failed\n"); goto failed; + } current_state = __parse_request_startline(msg, context, method, URI, http_version); if (current_state != ST_FIELD_NAME_START) @@ -232,6 +236,8 @@ static enum state __parse_respose_startline( } } failed: + if (current_state != ST_FIELD_NAME_START) + LOG(KERN_ERR, "__parse_respose_startline failed, current_state:%d, char: %c\n", current_state, ch); return current_state; } @@ -242,8 +248,10 @@ static bool parse_respose_startline(const struct bpf_mem_ptr *msg, struct bpf_me struct kmesh_data_node *status_code = new_kmesh_data_node(STATUS_STRING_LENGTH); struct kmesh_data_node *reason = new_kmesh_data_node(REASON_STRING_LENGTH); - if (IS_ERR(http_version) || IS_ERR(status_code) || IS_ERR(reason)) + if (IS_ERR(http_version) || IS_ERR(status_code) || IS_ERR(reason)) { + LOG(KERN_ERR, "parse_respose new kmesh_data_node failed\n"); goto failed; + } current_state = __parse_respose_startline(msg, context, http_version, status_code, reason); if (current_state != ST_FIELD_NAME_START) @@ -279,8 +287,10 @@ static bool parse_header(struct bpf_mem_ptr *context) ch = ((char *)context->ptr)[i]; switch (current_state) { case ST_FIELD_NAME_START: - if (ch == FIELD_SPLIT) + if (ch == FIELD_SPLIT) { + LOG("Invalid field split detected, char:%c, current_state:%d\n", ch, current_state); return false; + } if (ch == CR) { current_state = ST_HEAD_END; break; @@ -315,15 +325,20 @@ static bool parse_header(struct bpf_mem_ptr *context) current_state = ST_NEW_LINE; break; case ST_NEW_LINE: - if (unlikely(ch != LF)) - return false; - if (field_name_end_position < field_name_begin_position) + if (unlikely(ch != LF)) { + LOG("Expected LF but got another character:%c, current_state:%d\n", ch, current_state); return false; - if (field_value_end_position < field_value_begin_position) + } + if (field_name_end_position < field_name_begin_position || + field_value_end_position < field_value_begin_position) { + LOG("Invalid field name or value positions, char:%c, current_state:%d\n", ch, current_state); return false; + } new_field = new_kmesh_data_node(field_name_end_position - field_name_begin_position + 2); - if (IS_ERR(new_field)) + if (IS_ERR(new_field)) { + LOG("Failed to create new field node, char:%c, current_state:%d\n", ch, current_state); return false; + } (void)strncpy( new_field->keystring, ((char *)context->ptr) + field_name_begin_position, @@ -347,8 +362,10 @@ static bool parse_header(struct bpf_mem_ptr *context) current_state = ST_FIELD_NAME_START; break; case ST_HEAD_END: - if (ch != LF) + if (ch != LF) { + LOG("Expected LF but got another character:%c, current_state:%d\n", ch, current_state); return false; + } head_end = true; break; default: @@ -356,15 +373,24 @@ static bool parse_header(struct bpf_mem_ptr *context) break; } } - if (current_state != ST_HEAD_END) + if (current_state != ST_HEAD_END) { + LOG("parse_header failed, current_state:%d\n", current_state); return false; - + } return true; } -u32 parse_http_1_1_request(const struct bpf_mem_ptr *msg) +u32 parse_http_1_1_request(const struct bpf_sock_addr_kern *ctx) { + struct bpf_mem_ptr *msg = NULL; struct bpf_mem_ptr context = {0}; + if (ctx->t_ctx != NULL) { + msg = ctx->t_ctx; + } else { + LOG("t_ctx is NULL, parse request failed\n"); + return PROTO_UNKNOW; + } + u32 ret = 0; if (parse_request_startline(msg, &context) == false) { kmesh_protocol_data_clean_all(); @@ -383,9 +409,17 @@ u32 parse_http_1_1_request(const struct bpf_mem_ptr *msg) return ret; } -u32 parse_http_1_1_respond(const struct bpf_mem_ptr *msg) +u32 parse_http_1_1_respond(const struct bpf_sock_addr_kern *ctx) { + struct bpf_mem_ptr *msg = NULL; struct bpf_mem_ptr context = {0}; + if (ctx->t_ctx != NULL) { + msg = ctx->t_ctx; + } else { + LOG("t_ctx is NULL, parse respond failed\n"); + return PROTO_UNKNOW; + } + u32 ret = 0; if (parse_respose_startline(msg, &context) == false) { kmesh_protocol_data_clean_all(); diff --git a/kernel/ko_src/kmesh/kmesh_parse_protocol_data.c b/kernel/ko_src/kmesh/kmesh_parse_protocol_data.c index 7cbf9e091..29057bc4e 100644 --- a/kernel/ko_src/kmesh/kmesh_parse_protocol_data.c +++ b/kernel/ko_src/kmesh/kmesh_parse_protocol_data.c @@ -15,14 +15,14 @@ struct kmesh_data_node *new_kmesh_data_node(u32 name_field_length) { struct kmesh_data_node *new = (struct kmesh_data_node *)kmalloc(sizeof(struct kmesh_data_node), GFP_ATOMIC); if (unlikely(!new)) { - (void)pr_err("[kmesh data node] alloc data node memory failed! no memory!\n"); + LOG("[kmesh data node] alloc data node memory failed! no memory!\n"); return ERR_PTR(-ENOMEM); } (void)memset(new, 0x0, sizeof(struct kmesh_data_node)); new->keystring = (char *)kmalloc(name_field_length * sizeof(char), GFP_ATOMIC); if (unlikely(!new->keystring)) { kfree(new); - (void)pr_err("[kmesh data node] alloc data node key memory failed! no memory!\n"); + LOG("[kmesh data node] alloc data node key memory failed! no memory!\n"); return ERR_PTR(-ENOMEM); } (void)memset(new->keystring, 0x0, sizeof(char) * name_field_length); @@ -118,13 +118,18 @@ void kmesh_protocol_data_clean_allcpu(void) } } -typedef u32 (*bpf_parse_protocol_func)(struct bpf_mem_ptr *msg); +typedef u32 (*bpf_parse_protocol_func)(struct bpf_sock_addr_kern *ctx); extern bpf_parse_protocol_func parse_protocol_func; -typedef struct bpf_mem_ptr *(*bpf_get_protocol_element_func)(char *key); -extern bpf_get_protocol_element_func get_protocol_element_func; +typedef int (*bpf_km_strnstr_func)( + struct bpf_sock_addr_kern *ctx, const char *key, int key_sz, const char *subptr, int subptr_sz); +extern bpf_km_strnstr_func km_strnstr_func; -static u32 parse_protocol_impl(struct bpf_mem_ptr *msg) +typedef int (*bpf_km_strncmp_func)( + struct bpf_sock_addr_kern *ctx, const char *key, int key_sz, const char *subptr, int subptr_sz); +extern bpf_km_strncmp_func km_strncmp_func; + +static u32 parse_protocol_impl(struct bpf_sock_addr_kern *ctx) { u32 ret; struct msg_protocol *cur; @@ -133,37 +138,73 @@ static u32 parse_protocol_impl(struct bpf_mem_ptr *msg) { if (!cur->parse_protocol_msg) continue; - ret = cur->parse_protocol_msg(msg); + ret = cur->parse_protocol_msg(ctx); if (ret) break; } return ret; } -static struct bpf_mem_ptr *get_protocol_element_impl(char *key) +static int +bpf_km_strnstr_impl(struct bpf_sock_addr_kern *ctx, const char *key, int key_sz, const char *subptr, int subptr_len) { - struct kmesh_data_node *data = kmesh_protocol_data_search(key); + struct bpf_mem_ptr *msg = NULL; + struct kmesh_data_node *data = NULL; + + if (strcmp(key, "All") == 0) { + msg = (struct bpf_mem_ptr *)(ctx->t_ctx); + if (strnstr(msg->ptr, subptr, subptr_len) != NULL) { + return 1; + } else { + return 0; + } + } + + data = kmesh_protocol_data_search(key); if (!data) - return NULL; - return &data->value; + return 0; + msg = &(data->value); + if (strnstr(msg->ptr, subptr, subptr_len) != NULL) + return 1; + return 0; +} + +static int +bpf_km_strncmp_impl(struct bpf_sock_addr_kern *ctx, const char *key, int key_sz, const char *subptr, int subptr_len) +{ + struct kmesh_data_node *data = NULL; + subptr_len = strnlen(subptr, subptr_len); + int ret = 0; + + data = kmesh_protocol_data_search(key); + if (!data) + return 0; + ret = strncmp((data->value).ptr, subptr, subptr_len); + if (ret == 0 && ((data->value).size) == subptr_len) { + return STRNCMP_EXACT; + } else if (ret == 0) { + return STRNCMP_PREFIX; + } + return STRNCMP_FAILED; } int __init proto_common_init(void) { parse_protocol_func = parse_protocol_impl; - get_protocol_element_func = get_protocol_element_impl; + km_strnstr_func = bpf_km_strnstr_impl; + km_strncmp_func = bpf_km_strncmp_impl; /* add protocol list */ g_kmesh_data_root = alloc_percpu(struct rb_root); if (!g_kmesh_data_root) return -ENOMEM; - return 0; } void __exit proto_common_exit(void) { parse_protocol_func = NULL; - get_protocol_element_func = NULL; + km_strnstr_func = NULL; + km_strncmp_func = NULL; kmesh_protocol_data_clean_allcpu(); free_percpu(g_kmesh_data_root); } diff --git a/kernel/ko_src/kmesh/kmesh_parse_protocol_data.h b/kernel/ko_src/kmesh/kmesh_parse_protocol_data.h index 5ce5be236..c2d06e836 100644 --- a/kernel/ko_src/kmesh/kmesh_parse_protocol_data.h +++ b/kernel/ko_src/kmesh/kmesh_parse_protocol_data.h @@ -12,11 +12,19 @@ #include #include #include +#include + +struct bpf_mem_ptr { + void *ptr; + __u32 size; +}; enum kmesh_l7_proto_type { PROTO_UNKNOW = 0, PROTO_HTTP_1_1, PROTO_HTTP_2_0 }; enum kmesh_l7_msg_type { MSG_UNKNOW = 0, MSG_REQUEST, MSG_MID_REPONSE, MSG_FINAL_RESPONSE }; +enum kmesh_strncmp_type { STRNCMP_FAILED = 0, STRNCMP_PREFIX, STRNCMP_EXACT }; + #define KMESH_PROTO_TYPE_WIDTH (8) #define SET_RET_PROTO_TYPE(n, type) (n) = (((n)&0xff00) | ((u32)(type)&0xff)) @@ -25,6 +33,8 @@ enum kmesh_l7_msg_type { MSG_UNKNOW = 0, MSG_REQUEST, MSG_MID_REPONSE, MSG_FINAL #define SET_RET_MSG_TYPE(n, type) (n) = (((n)&0xff) | (((u32)(type)&0xff) << KMESH_PROTO_TYPE_WIDTH)) #define GET_RET_MSG_TYPE(n) (((n) >> KMESH_PROTO_TYPE_WIDTH) & 0xff) +#define LOG(level, fmt, ...) printk(level "Kmesh_module: " fmt, ##__VA_ARGS__) + struct kmesh_data_node { struct rb_node node; char *keystring; @@ -33,7 +43,7 @@ struct kmesh_data_node { struct msg_protocol { struct list_head list; - u32 (*parse_protocol_msg)(const struct bpf_mem_ptr *msg); + u32 (*parse_protocol_msg)(const struct bpf_sock_addr_kern *msg); }; extern struct rb_root *g_kmesh_data_root; diff --git a/pkg/bpf/ads/loader_enhanced.go b/pkg/bpf/ads/loader_enhanced.go index 0be22da24..f9831c7e0 100644 --- a/pkg/bpf/ads/loader_enhanced.go +++ b/pkg/bpf/ads/loader_enhanced.go @@ -29,6 +29,7 @@ import ( "github.com/cilium/ebpf" "kmesh.net/kmesh/daemon/options" + "kmesh.net/kmesh/pkg/bpf/general" "kmesh.net/kmesh/pkg/bpf/utils" "kmesh.net/kmesh/pkg/logger" ) @@ -36,17 +37,13 @@ import ( var log = logger.NewLoggerScope("bpf_ads") type BpfAds struct { - TracePoint BpfTracePoint - SockConn BpfSockConn - SockOps BpfSockOps - Tc *general.BpfTCGeneral + SockConn BpfSockConn + SockOps BpfSockOps + Tc *general.BpfTCGeneral } func NewBpfAds(cfg *options.BpfConfig) (*BpfAds, error) { sc := &BpfAds{} - if err := sc.TracePoint.NewBpf(cfg); err != nil { - return nil, err - } if err := sc.SockOps.NewBpf(cfg); err != nil { return nil, err @@ -105,11 +102,18 @@ func (sc *BpfAds) GetKmeshConfigMap() *ebpf.Map { return sc.SockConn.KmConfigmap } -func (sc *BpfAds) Load() error { - if err := sc.TracePoint.Load(); err != nil { +func (sc *BpfSockConn) RouteLoad() error { + err := sc.KmCgrptailcall.Update( + uint32(KMESH_TAIL_CALL_ROUTER_CONFIG), + uint32(sc.RouteConfigManager.FD()), + ebpf.UpdateAny) + if err != nil { return err } + return nil +} +func (sc *BpfAds) Load() error { if err := sc.SockOps.Load(); err != nil { return err } @@ -118,6 +122,10 @@ func (sc *BpfAds) Load() error { return err } + if err := sc.SockConn.RouteLoad(); err != nil { + return err + } + if err := sc.Tc.LoadTC(); err != nil { return err } @@ -128,41 +136,37 @@ func (sc *BpfAds) Load() error { func (sc *BpfAds) ApiEnvCfg() error { var err error - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmeshSockopsMaps.KmListener, "Listener"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshCgroupSockMaps.KmListener, "Listener"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmRouterconfig, "RouteConfiguration"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshCgroupSockMaps.KmRouterconfig, "RouteConfiguration"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmCluster, "Cluster"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshCgroupSockMaps.KmCluster, "Cluster"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmeshMap64, "KmeshMap64"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshMap64, "KmeshMap64"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmeshMap192, "KmeshMap192"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshMap192, "KmeshMap192"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmeshMap296, "KmeshMap296"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshMap296, "KmeshMap296"); err != nil { return err } - if err = utils.SetEnvByBpfMapId(sc.SockOps.KmeshMap1600, "KmeshMap1600"); err != nil { + if err = utils.SetEnvByBpfMapId(sc.SockConn.KmeshMap1600, "KmeshMap1600"); err != nil { return err } return nil } func (sc *BpfAds) Attach() error { - if err := sc.TracePoint.Attach(); err != nil { - return err - } - if err := sc.SockOps.Attach(); err != nil { return err } @@ -174,10 +178,6 @@ func (sc *BpfAds) Attach() error { } func (sc *BpfAds) Detach() error { - if err := sc.TracePoint.Detach(); err != nil { - return err - } - if err := sc.SockOps.Detach(); err != nil { return err } @@ -194,7 +194,7 @@ func (sc *BpfAds) Detach() error { } func (sc *BpfAds) GetClusterStatsMap() *ebpf.Map { - return sc.SockOps.KmeshSockopsMaps.KmClusterstats + return sc.SockConn.KmeshCgroupSockMaps.KmClusterstats } func AdsL7Enabled() bool { diff --git a/pkg/bpf/ads/sock_ops.go b/pkg/bpf/ads/sock_ops.go index 5117d429e..cebee39d9 100644 --- a/pkg/bpf/ads/sock_ops.go +++ b/pkg/bpf/ads/sock_ops.go @@ -87,70 +87,6 @@ func (sc *BpfSockOps) loadKmeshSockopsObjects() (*ebpf.CollectionSpec, error) { return spec, nil } - -func (sc *BpfSockOps) loadKmeshFilterObjects() (*ebpf.CollectionSpec, error) { - var ( - err error - spec *ebpf.CollectionSpec - opts ebpf.CollectionOptions - ) - - opts.Maps.PinPath = sc.Info.MapPath - err = sc.KmSkopstailcall.Update( - uint32(KMESH_TAIL_CALL_FILTER_CHAIN), - uint32(sc.FilterChainManager.FD()), - ebpf.UpdateAny) - if err != nil { - return nil, err - } - - err = sc.KmSkopstailcall.Update( - uint32(KMESH_TAIL_CALL_FILTER), - uint32(sc.FilterManager.FD()), - ebpf.UpdateAny) - if err != nil { - return nil, err - } - - return spec, nil -} - -func (sc *BpfSockOps) loadRouteConfigObjects() (*ebpf.CollectionSpec, error) { - var ( - err error - spec *ebpf.CollectionSpec - opts ebpf.CollectionOptions - ) - opts.Maps.PinPath = sc.Info.MapPath - err = sc.KmSkopstailcall.Update( - uint32(KMESH_TAIL_CALL_ROUTER_CONFIG), - uint32(sc.RouteConfigManager.FD()), - ebpf.UpdateAny) - if err != nil { - return nil, err - } - - return spec, nil -} - -func (sc *BpfSockOps) loadKmeshClusterObjects() (*ebpf.CollectionSpec, error) { - var ( - err error - spec *ebpf.CollectionSpec - opts ebpf.CollectionOptions - ) - opts.Maps.PinPath = sc.Info.MapPath - err = sc.KmSkopstailcall.Update( - uint32(KMESH_TAIL_CALL_CLUSTER), - uint32(sc.ClusterManager.FD()), - ebpf.UpdateAny) - if err != nil { - return nil, err - } - - return spec, nil -} - func (sc *BpfSockOps) Load() error { /* load kmesh sockops main bpf prog */ spec, err := sc.loadKmeshSockopsObjects() @@ -162,19 +98,6 @@ func (sc *BpfSockOps) Load() error { sc.Info.Type = prog.Type sc.Info.AttachType = prog.AttachType - /* load kmesh sockops tail call bpf prog */ - if _, err := sc.loadKmeshFilterObjects(); err != nil { - return err - } - - if _, err := sc.loadRouteConfigObjects(); err != nil { - return err - } - - if _, err := sc.loadKmeshClusterObjects(); err != nil { - return err - } - return nil } diff --git a/pkg/bpf/ads/trace_point.go b/pkg/bpf/ads/trace_point.go deleted file mode 100644 index 1cafd4f7b..000000000 --- a/pkg/bpf/ads/trace_point.go +++ /dev/null @@ -1,135 +0,0 @@ -//go:build enhanced -// +build enhanced - -/* - * Copyright The Kmesh Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ads - -import ( - "os" - "path/filepath" - "syscall" - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - - bpf2go "kmesh.net/kmesh/bpf/kmesh/bpf2go/kernelnative/enhanced" - "kmesh.net/kmesh/daemon/options" - "kmesh.net/kmesh/pkg/bpf/general" - "kmesh.net/kmesh/pkg/bpf/restart" - "kmesh.net/kmesh/pkg/constants" - helper "kmesh.net/kmesh/pkg/utils" -) - -type BpfTracePoint struct { - Info general.BpfInfo - Link link.Link - bpf2go.KmeshTracePointObjects -} - -func (sc *BpfTracePoint) NewBpf(cfg *options.BpfConfig) error { - sc.Info.MapPath = cfg.BpfFsPath + "/bpf_kmesh/map/" - sc.Info.BpfFsPath = cfg.BpfFsPath + "/bpf_kmesh/tracepoint/" - sc.Info.Cgroup2Path = cfg.Cgroup2Path - - if err := os.MkdirAll(sc.Info.MapPath, - syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR| - syscall.S_IRGRP|syscall.S_IXGRP); err != nil && !os.IsExist(err) { - return err - } - - if err := os.MkdirAll(sc.Info.BpfFsPath, - syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR| - syscall.S_IRGRP|syscall.S_IXGRP); err != nil && !os.IsExist(err) { - return err - } - - return nil -} - -func (sc *BpfTracePoint) loadKmeshTracePointObjects() (*ebpf.CollectionSpec, error) { - var ( - err error - spec *ebpf.CollectionSpec - opts ebpf.CollectionOptions - ) - if helper.KernelVersionLowerThan5_13() { - spec, err = bpf2go.LoadKmeshTracePointCompat() - } else { - spec, err = bpf2go.LoadKmeshTracePoint() - } - if err != nil || spec == nil { - return nil, err - } - - for _, v := range spec.Programs { - if v.Name == "connect_ret" { - v.Type = ebpf.RawTracepointWritable - } - } - - if err = spec.LoadAndAssign(&sc.KmeshTracePointObjects, &opts); err != nil { - return nil, err - } - - return spec, nil -} - -func (sc *BpfTracePoint) Load() error { - if _, err := sc.loadKmeshTracePointObjects(); err != nil { - return err - } - return nil -} - -func (sc *BpfTracePoint) Attach() error { - var err error - tpopt := link.RawTracepointOptions{ - Name: "connect_ret", - Program: sc.KmeshTracePointObjects.ConnectRet, - } - - pinPath := filepath.Join(sc.Info.BpfFsPath, constants.Prog_link) - if restart.GetStartType() == restart.Restart { - sc.Link, err = link.LoadPinnedLink(pinPath, &ebpf.LoadPinOptions{}) - if err != nil { - return err - } - } else { - sc.Link, err = link.AttachRawTracepoint(tpopt) - if err != nil { - return err - } - - if err := sc.Link.Pin(pinPath); err != nil { - return err - } - - } - return nil -} - -func (sc *BpfTracePoint) Detach() error { - if err := sc.KmeshTracePointObjects.Close(); err != nil { - return err - } - - if sc.Link != nil { - return sc.Link.Close() - } - return nil -} diff --git a/pkg/kolog/kolog.go b/pkg/kolog/kolog.go new file mode 100644 index 000000000..3dcb86206 --- /dev/null +++ b/pkg/kolog/kolog.go @@ -0,0 +1,102 @@ +/* + * Copyright The Kmesh Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kolog + +import ( + "bufio" + "fmt" + "os/exec" + "regexp" + "strings" + "time" + + "kmesh.net/kmesh/pkg/logger" +) + +var ( + log = logger.NewLoggerScope("Kmesh_module") +) + +func parseLogTime(line string) (time.Time, error) { + re := regexp.MustCompile(`\[(\w{3} \w{3} \d{1,2} \d{2}:\d{2}:\d{2} \d{4})\]`) + match := re.FindStringSubmatch(line) + if len(match) < 2 { + return time.Time{}, fmt.Errorf("no time match found") + } + + logTime, err := time.Parse("Mon Jan 2 15:04:05 2006", match[1]) + if err != nil { + return time.Time{}, err + } + return logTime, nil +} + +func KmeshModuleLog(stopCh <-chan struct{}) { + go func() { + cmd := exec.Command("dmesg", "-wT") + + stdout, err := cmd.StdoutPipe() + if err != nil { + log.Errorf("Error creating stdout pipe: %v", err) + return + } + + startTime := time.Now() + if err := cmd.Start(); err != nil { + log.Errorf("Error starting command: %v", err) + return + } + + scanner := bufio.NewScanner(stdout) + for { + select { + case <-stopCh: + if cmd.Process != nil { + if err := cmd.Process.Kill(); err != nil { + log.Errorf("Error killing process: %v", err) + } else { + if processState, err := cmd.Process.Wait(); err != nil { + log.Errorf("Error waiting for process: %v, processState:%v", err, processState) + } + } + } + return + default: + if !scanner.Scan() { + if err := scanner.Err(); err != nil { + log.Errorf("Error reading from stdout: %v", err) + } + break + } + line := scanner.Text() + + if !strings.Contains(line, "Kmesh_module") { + continue + } + logTime, err := parseLogTime(line) + if err != nil { + log.Errorf("Error parsing log time: %v", err) + log.Info(line) + continue + } + if logTime.After(startTime) { + log.Info(line) + } + } + } + }() +}