summaryrefslogtreecommitdiff
path: root/bpf/bpf_obj.cpp
blob: 3aeff200cdd976b93cfb21fd9870835340b4e78c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>

#ifdef SUPPORT_BPF
#include "bpf_config_user.h"

#define MIN(a, b) ((a) > (b) ? (b) : (a))

struct bpf_obj_ctx
{
    char obj_file[1024];
    struct bpf_config config;

    int prog_fd;
    struct bpf_object *prog_obj;
};

void bpf_obj_unload(struct bpf_obj_ctx *ctx)
{
    if (ctx)
    {
        if (ctx->prog_fd > 0)
        {
            close(ctx->prog_fd);
        }

        if (ctx->prog_obj)
        {
            bpf_object__close(ctx->prog_obj);
            ctx->prog_obj = NULL;
        }

        free(ctx);
        ctx = NULL;
    }
}

/*
 * queue_num : same as worker thread number
 * hash_mode : 2: hash with src/dst addr
 *             4: hash with src/dst addr and src/dst port
 * debug_log : 0 for disable(only use for debug, printf bpf debug log(cat /sys/kernel/debug/tracing/trace_pipe)
 */
struct bpf_obj_ctx *bpf_obj_load(const char *obj_file, uint32_t queue_num, uint32_t hash_mode, uint32_t debug_log)
{
    struct bpf_obj_ctx *ctx = (struct bpf_obj_ctx *)calloc(1, sizeof(struct bpf_obj_ctx));

    strncpy(ctx->obj_file, obj_file, MIN(strlen(obj_file), sizeof(ctx->obj_file)));
    bpf_config_set_queue_num(&ctx->config, queue_num);
    bpf_config_set_hash_mode(&ctx->config, hash_mode);
    bpf_config_set_debug_log(&ctx->config, debug_log);

#if (LIBBPF_MAJOR_VERSION > 0 || (LIBBPF_MAJOR_VERSION == 0 && LIBBPF_MINOR_VERSION >= 7))
    struct bpf_program *prog;
    ctx->prog_obj = bpf_object__open_file(ctx->obj_file, NULL);
    if (ctx->prog_obj == NULL)
    {
        printf("ERROR: Unable to open bpf object %s, %s.\n", ctx->obj_file, strerror(errno));
        goto error;
    }

    prog = bpf_object__find_program_by_name(ctx->prog_obj, "bpf_tun_rss_steering");
    if (!prog)
    {
        printf("ERROR: Unable to get bpf program from object %s, %s.\n", ctx->obj_file, strerror(errno));
        goto error;
    }

    bpf_program__set_type(prog, BPF_PROG_TYPE_SOCKET_FILTER);
    if (bpf_object__load(ctx->prog_obj))
    {
        printf("ERROR: Unable to load bpf object %s, %s.\n", ctx->obj_file, strerror(errno));
        goto error;
    }

    ctx->prog_fd = bpf_program__fd(prog);
    if (ctx->prog_fd < 0)
    {
        printf("ERROR: Unable to get bpf program fd from object %s, %s.\n", ctx->obj_file, strerror(errno));
        goto error;
    }
#else
    if (bpf_prog_load(ctx->obj_file, BPF_PROG_TYPE_SOCKET_FILTER, &ctx->prog_obj, &ctx->prog_fd) < 0)
    {
        printf("ERROR: Unable to load bpf object %s, %s.\n", ctx->obj_file, strerror(errno));
        goto error;
    }
#endif

    if (bpf_config_update_map(&ctx->config, ctx->prog_obj) == -1)
    {
        goto error;
    }

    return ctx;

error:
    bpf_obj_unload(ctx);

    return NULL;
}

/*
 * return  0 : success
 * return -1 : error
 */
int bpf_obj_attach(struct bpf_obj_ctx *ctx, int fd)
{
    if (ctx && ctx->prog_fd > 0)
    {
        if (ioctl(fd, TUNSETSTEERINGEBPF, (void *)&ctx->prog_fd) == -1)
        {
            printf("ERROR: Unable to set bpf on sockfd %d, %s.\n", fd, strerror(errno));
            return -1;
        }
        else
        {
            printf("Set TUNSETSTEERINGEBPF on fd: %d\n", fd);
            return 0;
        }
    }
    else
    {
        return -1;
    }
}
#else

struct bpf_obj_ctx
{
};

#include <sys/types.h>

void bpf_obj_unload(struct bpf_obj_ctx *ctx)
{
    printf("ERROR: BPF feature not support on current system\n");
}

struct bpf_obj_ctx *bpf_obj_load(const char *obj_file, uint32_t queue_num, uint32_t hash_mode, uint32_t debug_log)
{
    printf("ERROR: BPF feature not support on current system\n");
    return NULL;
}

int bpf_obj_attach(struct bpf_obj_ctx *ctx, int fd)
{
    printf("ERROR: BPF feature not support on current system\n");
    return -1;
}
#endif