Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
supercharge-xsy authored Jun 18, 2024
2 parents db33bfb + c3b6ec1 commit 3484959
Show file tree
Hide file tree
Showing 51 changed files with 1,400 additions and 481 deletions.
8 changes: 5 additions & 3 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ AllowShortIfStatementsOnASingleLine: false
# 允许短的循环保持在同一行
AllowShortLoopsOnASingleLine: false

# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
AlwaysBreakAfterReturnType: None

Expand Down Expand Up @@ -82,6 +82,8 @@ BraceWrapping:
BeforeCatch: false
# else之前
BeforeElse: false
# elseif之前
BeforeElseif: false
# 缩进大括号
IndentBraces: false
# 分离空函数
Expand All @@ -94,8 +96,8 @@ BraceWrapping:
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
BreakBeforeBinaryOperators: NonAssignment

# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似),
# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似),
# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似),
# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似),
# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom
# 注:这里认为语句块也属于函数
BreakBeforeBraces: Custom
Expand Down
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Author: LemmyHuang
# Create: 2021-12-08
VERSION ?= 1.0-dev
GIT_COMMIT_HASH ?= $(shell git rev-parse HEAD)
GIT_TREESTATE=$(shell if [ -n "$(git status --porcelain)" ]; then echo "dirty"; else echo "clean"; fi)
BUILD_DATE = $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
Expand Down Expand Up @@ -143,6 +142,7 @@ uninstall:
$(call printlog, UNINSTALL, $(INSTALL_BIN)/$(APPS3))
$(QUIET) rm -rf $(INSTALL_BIN)/$(APPS3)

.PHONY: build
build:
./kmesh_compile.sh

Expand All @@ -152,6 +152,15 @@ docker: build
format:
./hack/format.sh

.PHONY: test
ifeq ($(RUN_IN_CONTAINER),1)
test:
./hack/run-ut.sh --docker
else
test:
./hack/run-ut.sh --local
endif

clean:
$(QUIET) rm -rf ./out
$(QUIET) rm -rf ./config/linux-bpf.h
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ The Kmesh user space components are licensed under the
[Apache License, Version 2.0](./LICENSE).
The BPF code templates, ko(kernel module) and mesh data accelerate are dual-licensed under the
[General Public License, Version 2.0 (only)](./bpf/LICENSE.GPL-2.0)
and the [2-Clause BSD License](./bpf/LICENSE.GPL-2.0)
and the [2-Clause BSD License](./bpf/LICENSE.BSD-2-Clause)
(you can use the terms of either license, at your option).

## Credit
Expand Down
78 changes: 59 additions & 19 deletions bpf/include/bpf_common.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/* Copyright Authors of Kmesh */

#define map_of_manager kmesh_manage
#ifndef __KMESH_BPF_COMMON_H__
#define __KMESH_BPF_COMMON_H__

#include "common.h"

#define map_of_manager kmesh_manage
#define MAP_SIZE_OF_MANAGER 8192
/*0x3a1(929) is the specific port handled by the cni to enable kmesh*/
#define ENABLE_KMESH_PORT 0x3a1
Expand All @@ -16,6 +21,13 @@
#define AUTH_FORBID 1
#define AUTH_PROCESSING 2

struct manager_key {
union {
__u64 netns_cookie;
struct ip_addr addr;
};
};

typedef struct {
__u32 is_bypassed;
} manager_value_t;
Expand All @@ -32,61 +44,87 @@ typedef struct {
*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u64);
__type(key, struct manager_key);
__type(value, manager_value_t);
__uint(max_entries, MAP_SIZE_OF_MANAGER);
__uint(map_flags, 0);
} map_of_manager SEC(".maps");

static inline void record_manager_netns_cookie(struct bpf_map *map, struct bpf_sock_addr *ctx)
/*
* From v5.4, bpf_get_netns_cookie can be called for bpf cgroup hooks, from v5.15, it can be called for bpf sockops
* hook. Therefore, ensure that function is correctly used.
*/
static inline void record_manager_netns_cookie(struct bpf_sock_addr *ctx)
{
int err;
struct manager_key key = {0};
key.netns_cookie = bpf_get_netns_cookie(ctx);
manager_value_t value = {
.is_bypassed = 0,
};

__u64 cookie = bpf_get_netns_cookie(ctx);
err = bpf_map_update_elem(map, &cookie, &value, BPF_NOEXIST);
err = bpf_map_update_elem(&map_of_manager, &key, &value, BPF_NOEXIST);
if (err)
BPF_LOG(ERR, KMESH, "record netcookie failed!, err is %d\n", err);
}

static inline void set_netns_bypass_value(struct bpf_sock_addr *sock_addr, int new_bypass_value)
/*
* From v5.4, bpf_get_netns_cookie can be called for bpf cgroup hooks, from v5.15, it can be called for bpf sockops
* hook. Therefore, ensure that function is correctly used.
*/
static inline void set_netns_bypass_value(struct bpf_sock_addr *ctx, int new_bypass_value)
{
__u64 cookie = bpf_get_netns_cookie(sock_addr);
manager_value_t *current_value = bpf_map_lookup_elem(&map_of_manager, &cookie);
struct manager_key key = {0};
key.netns_cookie = bpf_get_netns_cookie(ctx);
manager_value_t *current_value = bpf_map_lookup_elem(&map_of_manager, &key);
if (!current_value || current_value->is_bypassed == new_bypass_value)
return;

current_value->is_bypassed = new_bypass_value;

int err = bpf_map_update_elem(&map_of_manager, &cookie, current_value, BPF_EXIST);
int err = bpf_map_update_elem(&map_of_manager, &key, current_value, BPF_EXIST);
if (err)
BPF_LOG(ERR, KMESH, "set netcookie failed!, err is %d\n", err);
}

/*
* From v5.4, bpf_get_netns_cookie can be called for bpf cgroup hooks, from v5.15, it can be called for bpf sockops
* hook. Therefore, ensure that function is correctly used.
*/
static inline bool is_kmesh_enabled(struct bpf_sock_addr *ctx)
{
__u64 cookie = bpf_get_netns_cookie(ctx);
return bpf_map_lookup_elem(&map_of_manager, &cookie);
struct manager_key key = {0};
key.netns_cookie = bpf_get_netns_cookie(ctx);
return bpf_map_lookup_elem(&map_of_manager, &key);
}

/*
* From v5.4, bpf_get_netns_cookie can be called for bpf cgroup hooks, from v5.15, it can be called for bpf sockops
* hook. Therefore, ensure that function is correctly used.
*/
static inline bool is_bypass_enabled(struct bpf_sock_addr *ctx)
{
__u64 cookie = bpf_get_netns_cookie(ctx);
manager_value_t *value = bpf_map_lookup_elem(&map_of_manager, &cookie);
struct manager_key key = {0};
key.netns_cookie = bpf_get_netns_cookie(ctx);
manager_value_t *value = bpf_map_lookup_elem(&map_of_manager, &key);

if (!value)
return false;

return value->is_bypassed;
}

static inline void remove_manager_netns_cookie(struct bpf_map *map, struct bpf_sock_addr *ctx)
/*
* From v5.4, bpf_get_netns_cookie can be called for bpf cgroup hooks, from v5.15, it can be called for bpf sockops
* hook. Therefore, ensure that function is correctly used.
*/
static inline void remove_manager_netns_cookie(struct bpf_sock_addr *ctx)
{
int err;
__u64 cookie = bpf_get_netns_cookie(ctx);
err = bpf_map_delete_elem(map, &cookie);
struct manager_key key = {0};
key.netns_cookie = bpf_get_netns_cookie(ctx);

err = bpf_map_delete_elem(&map_of_manager, &key);
if (err && err != -ENOENT)
BPF_LOG(ERR, KMESH, "remove netcookie failed!, err is %d\n", err);
}
Expand Down Expand Up @@ -126,14 +164,14 @@ static inline bool conn_from_cni_sim_delete(struct bpf_sock_addr *ctx)
static inline bool handle_kmesh_manage_process(struct bpf_sock_addr *ctx)
{
if (conn_from_cni_sim_add(ctx)) {
record_manager_netns_cookie(&map_of_manager, ctx);
record_manager_netns_cookie(ctx);
// return failed, cni sim connect 0.0.0.1:929(0x3a1)
// A normal program will not connect to this IP address
return true;
}

if (conn_from_cni_sim_delete(ctx)) {
remove_manager_netns_cookie(&map_of_manager, ctx);
remove_manager_netns_cookie(ctx);
return true;
}
return false;
Expand All @@ -155,4 +193,6 @@ static inline bool handle_bypass_process(struct bpf_sock_addr *ctx)
return true;
}
return false;
}
}

#endif
30 changes: 28 additions & 2 deletions bpf/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,32 @@
#endif
#define SEC_TAIL(ID, KEY) SEC(__stringify(ID) "/" __stringify(KEY))

struct ip_addr {
union {
__u32 ip4;
__u32 ip6[4];
};
};
#define IPV6_ADDR_LEN 16

/*
eBPF verifier verifies the eBPF PROG, including the read and write permissions of the CTX parameters. In the V4 and V6
scenarios, the governance logic is similar except for the address information. However, the eBPF verifier strictly
checks the read and write operations of the ctx members. For example, v6-related variables cannot be read or written in
the v4 context. Therefore, to reuse the governance logic, kmesh_context defined to cache the input and output
information related to the address.
*/
struct kmesh_context {
// input
struct bpf_sock_addr *ctx;
struct ip_addr orig_dst_addr;

// output
struct ip_addr dnat_ip;
__u32 dnat_port;
bool via_waypoint;
};

static inline void *kmesh_map_lookup_elem(void *map, const void *key)
{
return bpf_map_lookup_elem(map, key);
Expand All @@ -53,12 +79,12 @@ static inline int kmesh_map_update_elem(void *map, const void *key, const void *
}

#if OE_23_03
#define bpf__strncmp bpf_strncmp
#define bpf__strncmp bpf_strncmp
#define GET_SKOPS_REMOTE_PORT(sk_ops) (__u16)((sk_ops)->remote_port)
#else
#define GET_SKOPS_REMOTE_PORT(sk_ops) (__u16)((sk_ops)->remote_port >> 16)
#endif

#define GET_SKOPS_LOCAL_PORT(sk_ops) (__u16)((sk_ops)->local_port)

#endif // _COMMON_H_
#endif // _COMMON_H_
27 changes: 23 additions & 4 deletions bpf/kmesh/workload/cgroup_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
#include <linux/in.h>
#include <linux/bpf.h>
#include <linux/tcp.h>
#include <sys/socket.h>
#include "bpf_log.h"
#include "ctx/sock_addr.h"
#include "frontend.h"
#include "bpf_common.h"

static inline int sock4_traffic_control(struct bpf_sock_addr *ctx)
static inline int sock4_traffic_control(struct kmesh_context *kmesh_ctx)
{
int ret;
frontend_value *frontend_v = NULL;
struct bpf_sock_addr *ctx = kmesh_ctx->ctx;

if (ctx->protocol != IPPROTO_TCP)
return 0;

DECLARE_FRONTEND_KEY(ctx, frontend_k);
DECLARE_FRONTEND_KEY(ctx, &kmesh_ctx->orig_dst_addr, frontend_k);

DECLARE_VAR_IPV4(ctx->user_ip4, ip);
BPF_LOG(DEBUG, KMESH, "origin addr=[%pI4h:%u]\n", &ip, bpf_ntohs(ctx->user_port));
Expand All @@ -27,7 +29,7 @@ static inline int sock4_traffic_control(struct bpf_sock_addr *ctx)
}

BPF_LOG(DEBUG, KMESH, "bpf find frontend addr=[%pI4h:%u]\n", &ip, bpf_ntohs(ctx->user_port));
ret = frontend_manager(ctx, frontend_v);
ret = frontend_manager(kmesh_ctx, frontend_v);
if (ret != 0) {
if (ret != -ENOENT)
BPF_LOG(ERR, KMESH, "frontend_manager failed, ret:%d\n", ret);
Expand All @@ -40,6 +42,12 @@ static inline int sock4_traffic_control(struct bpf_sock_addr *ctx)
SEC("cgroup/connect4")
int cgroup_connect4_prog(struct bpf_sock_addr *ctx)
{
struct kmesh_context kmesh_ctx = {0};
kmesh_ctx.ctx = ctx;
kmesh_ctx.orig_dst_addr.ip4 = ctx->user_ip4;
kmesh_ctx.dnat_ip.ip4 = ctx->user_ip4;
kmesh_ctx.dnat_port = ctx->user_port;

if (handle_kmesh_manage_process(ctx) || !is_kmesh_enabled(ctx)) {
return CGROUP_SOCK_OK;
}
Expand All @@ -48,8 +56,19 @@ int cgroup_connect4_prog(struct bpf_sock_addr *ctx)
return CGROUP_SOCK_OK;
}

int ret = sock4_traffic_control(ctx);
int ret = sock4_traffic_control(&kmesh_ctx);
if (ret) {
BPF_LOG(ERR, KMESH, "sock_traffic_control failed: %d\n", ret);
return CGROUP_SOCK_OK;
}

SET_CTX_ADDRESS4(ctx, &kmesh_ctx.dnat_ip, kmesh_ctx.dnat_port);
if (kmesh_ctx.via_waypoint) {
kmesh_workload_tail_call(ctx, TAIL_CALL_CONNECT4_INDEX);

// if tail call failed will run this code
BPF_LOG(ERR, KMESH, "workload tail call failed, err is %d\n", ret);
}
return CGROUP_SOCK_OK;
}

Expand Down
Loading

0 comments on commit 3484959

Please sign in to comment.