Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2017-07-25 11:59:13 -07:00
commit 08f5fdb201
6 changed files with 285 additions and 88 deletions

View File

@ -2524,6 +2524,13 @@ It must be an address on another interface of this host.
It is enabled by default. Note that a fixed ttl is incompatible
with this option: tunnelling with a fixed ttl always makes pmtu discovery.
\item \verb|ignore-df|
--- (only GRE tunnels) enable IPv4 DF flag suppression on this tunnel.
If is disabled by default. Enabling this option will cause IPv4
payloads to be handled like any other GRE payload,
regardless of the DF flag.
\item \verb|key K|, \verb|ikey K|, \verb|okey K|
--- (only GRE tunnels) use keyed GRE with key \verb|K|. \verb|K| is

View File

@ -766,6 +766,11 @@ static int netns_monitor(int argc, char **argv)
return 0;
}
static int invalid_name(const char *name)
{
return strchr(name, '/') || !strcmp(name, ".") || !strcmp(name, "..");
}
int do_netns(int argc, char **argv)
{
netns_nsid_socket_init();
@ -775,6 +780,11 @@ int do_netns(int argc, char **argv)
return netns_list(0, NULL);
}
if (argc > 1 && invalid_name(argv[1])) {
fprintf(stderr, "Invalid netns name \"%s\"\n", argv[1]);
exit(-1);
}
if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
(matches(*argv, "lst") == 0)) {
netns_map_init();

View File

@ -137,7 +137,7 @@ static int flush_update(void)
{
if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) {
perror("Failed to send flush request");
return -1;
return -2;
}
filter.flushp = 0;
return 0;
@ -319,6 +319,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
struct rtattr *tb[RTA_MAX+1];
int host_len, family;
__u32 table;
int ret;
SPRINT_BUF(b1);
static int hz;
@ -348,8 +349,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
struct nlmsghdr *fn;
if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
if (flush_update())
return -1;
if ((ret = flush_update()) < 0)
return ret;
}
fn = (struct nlmsghdr *)(filter.flushb + NLMSG_ALIGN(filter.flushp));
memcpy(fn, n, n->nlmsg_len);
@ -764,7 +765,7 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
NEXT_ARG();
if ((rtnh->rtnh_ifindex = ll_name_to_index(*argv)) == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", *argv);
exit(1);
return -1;
}
} else if (strcmp(*argv, "weight") == 0) {
unsigned int w;
@ -1396,6 +1397,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
char *od = NULL;
unsigned int mark = 0;
rtnl_filter_t filter_fn;
int ret;
if (action == IPROUTE_SAVE) {
if (save_route_prep())
@ -1604,12 +1606,12 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
for (;;) {
if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
perror("Cannot send dump request");
exit(1);
return -2;
}
filter.flushed = 0;
if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
fprintf(stderr, "Flush terminated\n");
exit(1);
return -2;
}
if (filter.flushed == 0) {
if (show_stats) {
@ -1622,13 +1624,13 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
return 0;
}
round++;
if (flush_update() < 0)
exit(1);
if ((ret = flush_update()) < 0)
return ret;
if (time(0) - start > 30) {
printf("\n*** Flush not completed after %ld seconds, %d entries remain ***\n",
(long)(time(0) - start), filter.flushed);
exit(1);
return -1;
}
if (show_stats) {
@ -1641,21 +1643,21 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
if (!filter.cloned) {
if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
perror("Cannot send dump request");
exit(1);
return -2;
}
} else {
if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
perror("Cannot send dump request");
exit(1);
return -2;
}
}
if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
return -2;
}
exit(0);
return 0;
}
@ -1761,7 +1763,7 @@ static int iproute_get(int argc, char **argv)
if (req.r.rtm_dst_len == 0) {
fprintf(stderr, "need at least a destination address\n");
exit(1);
return -1;
}
if (idev || odev) {
@ -1918,12 +1920,12 @@ static int iproute_restore(void)
int pos, prio;
if (route_dump_check_magic())
exit(-1);
return -1;
pos = ftell(stdin);
if (pos == -1) {
perror("Failed to restore: ftell");
exit(-1);
return -1;
}
for (prio = 0; prio < 3; prio++) {
@ -1931,15 +1933,15 @@ static int iproute_restore(void)
err = rtnl_from_file(stdin, &restore_handler, &prio);
if (err)
exit(err);
return -2;
if (fseek(stdin, pos, SEEK_SET) == -1) {
perror("Failed to restore: fseek");
exit(-1);
return -1;
}
}
exit(0);
return 0;
}
static int show_handler(const struct sockaddr_nl *nl,
@ -1953,9 +1955,12 @@ static int show_handler(const struct sockaddr_nl *nl,
static int iproute_showdump(void)
{
if (route_dump_check_magic())
exit(-1);
return -1;
exit(rtnl_from_file(stdin, &show_handler, NULL));
if (rtnl_from_file(stdin, &show_handler, NULL))
return -2;
return 0;
}
void iproute_reset_filter(int ifindex)

View File

@ -34,6 +34,7 @@ static void print_usage(FILE *f)
" [ ttl TTL ]\n"
" [ tos TOS ]\n"
" [ [no]pmtudisc ]\n"
" [ [no]ignore-df ]\n"
" [ dev PHYS_DEV ]\n"
" [ noencap ]\n"
" [ encap { fou | gue | none } ]\n"
@ -93,6 +94,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
__u16 encapsport = 0;
__u16 encapdport = 0;
__u8 metadata = 0;
__u8 ignore_df = 0;
__u32 fwmark = 0;
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
@ -164,6 +166,10 @@ get_failed:
if (greinfo[IFLA_GRE_COLLECT_METADATA])
metadata = 1;
if (greinfo[IFLA_GRE_IGNORE_DF])
ignore_df =
!!rta_getattr_u8(greinfo[IFLA_GRE_IGNORE_DF]);
if (greinfo[IFLA_GRE_FWMARK])
fwmark = rta_getattr_u32(greinfo[IFLA_GRE_FWMARK]);
}
@ -311,6 +317,13 @@ get_failed:
encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM;
} else if (strcmp(*argv, "external") == 0) {
metadata = 1;
} else if (strcmp(*argv, "ignore-df") == 0) {
ignore_df = 1;
} else if (strcmp(*argv, "noignore-df") == 0) {
/*
*only the lsb is significant, use 2 for presence
*/
ignore_df = 2;
} else if (strcmp(*argv, "fwmark") == 0) {
NEXT_ARG();
if (get_u32(&fwmark, *argv, 0))
@ -355,6 +368,9 @@ get_failed:
addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport));
addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport));
if (ignore_df)
addattr8(n, 1024, IFLA_GRE_IGNORE_DF, ignore_df & 1);
return 0;
}
@ -454,6 +470,9 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
else
fputs("external ", f);
if (tb[IFLA_GRE_IGNORE_DF] && rta_getattr_u8(tb[IFLA_GRE_IGNORE_DF]))
fputs("ignore-df ", f);
if (tb[IFLA_GRE_ENCAP_TYPE] &&
rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
__u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]);

281
lib/bpf.c
View File

@ -344,15 +344,24 @@ static void bpf_map_pin_report(const struct bpf_elf_map *pin,
fprintf(stderr, "\n");
}
static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
int length, enum bpf_prog_type type)
struct bpf_prog_data {
unsigned int type;
unsigned int jited;
};
struct bpf_map_ext {
struct bpf_prog_data owner;
};
static int bpf_derive_elf_map_from_fdinfo(int fd, struct bpf_elf_map *map,
struct bpf_map_ext *ext)
{
unsigned int val, owner_type = 0, owner_jited = 0;
char file[PATH_MAX], buff[4096];
struct bpf_elf_map tmp = {}, zero = {};
unsigned int val, owner_type = 0;
FILE *fp;
snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
memset(map, 0, sizeof(*map));
fp = fopen(file, "r");
if (!fp) {
@ -362,27 +371,48 @@ static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
while (fgets(buff, sizeof(buff), fp)) {
if (sscanf(buff, "map_type:\t%u", &val) == 1)
tmp.type = val;
map->type = val;
else if (sscanf(buff, "key_size:\t%u", &val) == 1)
tmp.size_key = val;
map->size_key = val;
else if (sscanf(buff, "value_size:\t%u", &val) == 1)
tmp.size_value = val;
map->size_value = val;
else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
tmp.max_elem = val;
map->max_elem = val;
else if (sscanf(buff, "map_flags:\t%i", &val) == 1)
tmp.flags = val;
map->flags = val;
else if (sscanf(buff, "owner_prog_type:\t%i", &val) == 1)
owner_type = val;
else if (sscanf(buff, "owner_jited:\t%i", &val) == 1)
owner_jited = val;
}
fclose(fp);
if (ext) {
memset(ext, 0, sizeof(*ext));
ext->owner.type = owner_type;
ext->owner.jited = owner_jited;
}
return 0;
}
static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
struct bpf_map_ext *ext, int length,
enum bpf_prog_type type)
{
struct bpf_elf_map tmp, zero = {};
int ret;
ret = bpf_derive_elf_map_from_fdinfo(fd, &tmp, ext);
if (ret < 0)
return ret;
/* The decision to reject this is on kernel side eventually, but
* at least give the user a chance to know what's wrong.
*/
if (owner_type && owner_type != type)
if (ext->owner.type && ext->owner.type != type)
fprintf(stderr, "Program array map owner types differ: %u (obj) != %u (pin)\n",
type, owner_type);
type, ext->owner.type);
if (!memcmp(&tmp, map, length)) {
return 0;
@ -429,6 +459,24 @@ static int bpf_mnt_fs(const char *target)
return 0;
}
static int bpf_mnt_check_target(const char *target)
{
struct stat sb = {};
int ret;
ret = stat(target, &sb);
if (ret) {
ret = mkdir(target, S_IRWXU);
if (ret) {
fprintf(stderr, "mkdir %s failed: %s\n", target,
strerror(errno));
return ret;
}
}
return 0;
}
static int bpf_valid_mntpt(const char *mnt, unsigned long magic)
{
struct statfs st_fs;
@ -441,6 +489,21 @@ static int bpf_valid_mntpt(const char *mnt, unsigned long magic)
return 0;
}
static const char *bpf_find_mntpt_single(unsigned long magic, char *mnt,
int len, const char *mntpt)
{
int ret;
ret = bpf_valid_mntpt(mntpt, magic);
if (!ret) {
strncpy(mnt, mntpt, len - 1);
mnt[len - 1] = 0;
return mnt;
}
return NULL;
}
static const char *bpf_find_mntpt(const char *fstype, unsigned long magic,
char *mnt, int len,
const char * const *known_mnts)
@ -452,11 +515,8 @@ static const char *bpf_find_mntpt(const char *fstype, unsigned long magic,
if (known_mnts) {
ptr = known_mnts;
while (*ptr) {
if (bpf_valid_mntpt(*ptr, magic) == 0) {
strncpy(mnt, *ptr, len - 1);
mnt[len - 1] = 0;
if (bpf_find_mntpt_single(magic, mnt, len, *ptr))
return mnt;
}
ptr++;
}
}
@ -634,6 +694,7 @@ static const char *bpf_get_work_dir(enum bpf_prog_type type)
static char bpf_wrk_dir[PATH_MAX];
static const char *mnt;
static bool bpf_mnt_cached;
const char *mnt_env = getenv(BPF_ENV_MNT);
static const char * const bpf_known_mnts[] = {
BPF_DIR_MNT,
"/bpf",
@ -652,13 +713,17 @@ static const char *bpf_get_work_dir(enum bpf_prog_type type)
return out;
}
mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_tmp, sizeof(bpf_tmp),
bpf_known_mnts);
if (mnt_env)
mnt = bpf_find_mntpt_single(BPF_FS_MAGIC, bpf_tmp,
sizeof(bpf_tmp), mnt_env);
else
mnt = bpf_find_mntpt("bpf", BPF_FS_MAGIC, bpf_tmp,
sizeof(bpf_tmp), bpf_known_mnts);
if (!mnt) {
mnt = getenv(BPF_ENV_MNT);
if (!mnt)
mnt = BPF_DIR_MNT;
ret = bpf_mnt_fs(mnt);
mnt = mnt_env ? : BPF_DIR_MNT;
ret = bpf_mnt_check_target(mnt);
if (!ret)
ret = bpf_mnt_fs(mnt);
if (ret) {
mnt = NULL;
goto out;
@ -882,6 +947,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
.argc = argc,
.argv = argv,
};
struct bpf_map_ext ext = {};
int ret, prog_fd, map_fd;
enum bpf_mode mode;
uint32_t map_key;
@ -908,7 +974,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
goto out_prog;
}
ret = bpf_map_selfcheck_pinned(map_fd, &test,
ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext,
offsetof(struct bpf_elf_map, max_elem),
type);
if (ret < 0) {
@ -981,7 +1047,12 @@ struct bpf_hash_entry {
struct bpf_hash_entry *next;
};
struct bpf_config {
unsigned int jit_enabled;
};
struct bpf_elf_ctx {
struct bpf_config cfg;
Elf *elf_fd;
GElf_Ehdr elf_hdr;
Elf_Data *sym_tab;
@ -989,6 +1060,7 @@ struct bpf_elf_ctx {
int obj_fd;
int map_fds[ELF_MAX_MAPS];
struct bpf_elf_map maps[ELF_MAX_MAPS];
struct bpf_map_ext maps_ext[ELF_MAX_MAPS];
int sym_num;
int map_num;
int map_len;
@ -1425,39 +1497,6 @@ static int bpf_find_map_id(const struct bpf_elf_ctx *ctx, uint32_t id)
return -ENOENT;
}
static int bpf_derive_elf_map_from_fdinfo(int fd, struct bpf_elf_map *map)
{
char file[PATH_MAX], buff[4096];
unsigned int val;
FILE *fp;
snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
memset(map, 0, sizeof(*map));
fp = fopen(file, "r");
if (!fp) {
fprintf(stderr, "No procfs support?!\n");
return -EIO;
}
while (fgets(buff, sizeof(buff), fp)) {
if (sscanf(buff, "map_type:\t%u", &val) == 1)
map->type = val;
else if (sscanf(buff, "key_size:\t%u", &val) == 1)
map->size_key = val;
else if (sscanf(buff, "value_size:\t%u", &val) == 1)
map->size_value = val;
else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
map->max_elem = val;
else if (sscanf(buff, "map_flags:\t%i", &val) == 1)
map->flags = val;
}
fclose(fp);
return 0;
}
static void bpf_report_map_in_map(int outer_fd, int inner_fd, uint32_t idx)
{
struct bpf_elf_map outer_map;
@ -1465,7 +1504,7 @@ static void bpf_report_map_in_map(int outer_fd, int inner_fd, uint32_t idx)
fprintf(stderr, "Cannot insert map into map! ");
ret = bpf_derive_elf_map_from_fdinfo(outer_fd, &outer_map);
ret = bpf_derive_elf_map_from_fdinfo(outer_fd, &outer_map, NULL);
if (!ret) {
if (idx >= outer_map.max_elem &&
outer_map.type == BPF_MAP_TYPE_ARRAY_OF_MAPS) {
@ -1484,14 +1523,15 @@ static bool bpf_is_map_in_map_type(const struct bpf_elf_map *map)
map->type == BPF_MAP_TYPE_HASH_OF_MAPS;
}
static int bpf_map_attach(const char *name, const struct bpf_elf_map *map,
struct bpf_elf_ctx *ctx, int *have_map_in_map)
static int bpf_map_attach(const char *name, struct bpf_elf_ctx *ctx,
const struct bpf_elf_map *map, struct bpf_map_ext *ext,
int *have_map_in_map)
{
int fd, ret, map_inner_fd = 0;
fd = bpf_probe_pinned(name, ctx, map->pinning);
if (fd > 0) {
ret = bpf_map_selfcheck_pinned(fd, map,
ret = bpf_map_selfcheck_pinned(fd, map, ext,
offsetof(struct bpf_elf_map,
id), ctx->type);
if (ret < 0) {
@ -1581,8 +1621,8 @@ static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx)
if (!map_name)
return -EIO;
fd = bpf_map_attach(map_name, &ctx->maps[i], ctx,
&have_map_in_map);
fd = bpf_map_attach(map_name, ctx, &ctx->maps[i],
&ctx->maps_ext[i], &have_map_in_map);
if (fd < 0)
return fd;
@ -1597,8 +1637,8 @@ static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx)
if (!map_name)
return -EIO;
fd = bpf_map_attach(map_name, &ctx->maps[i], ctx,
NULL);
fd = bpf_map_attach(map_name, ctx, &ctx->maps[i],
&ctx->maps_ext[i], NULL);
if (fd < 0)
return fd;
@ -1901,9 +1941,15 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section,
return fd;
}
struct bpf_tail_call_props {
unsigned int total;
unsigned int jited;
};
static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
struct bpf_elf_sec_data *data_relo,
struct bpf_elf_sec_data *data_insn)
struct bpf_elf_sec_data *data_insn,
struct bpf_tail_call_props *props)
{
Elf_Data *idata = data_insn->sec_data;
GElf_Shdr *rhdr = &data_relo->sec_hdr;
@ -1943,6 +1989,13 @@ static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
return -EINVAL;
if (!ctx->map_fds[rmap])
return -EINVAL;
if (ctx->maps[rmap].type == BPF_MAP_TYPE_PROG_ARRAY) {
props->total++;
if (ctx->maps_ext[rmap].owner.jited ||
(ctx->maps_ext[rmap].owner.type == 0 &&
ctx->cfg.jit_enabled))
props->jited++;
}
if (ctx->verbose)
fprintf(stderr, "Map \'%s\' (%d) injected into prog section \'%s\' at offset %u!\n",
@ -1964,6 +2017,8 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
int ret, idx, i, fd = -1;
for (i = 1; i < ctx->elf_hdr.e_shnum; i++) {
struct bpf_tail_call_props props = {};
ret = bpf_fill_section_data(ctx, i, &data_relo);
if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL)
continue;
@ -1979,7 +2034,7 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
*sseen = true;
ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn);
ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn, &props);
if (ret < 0) {
*lderr = true;
return ret;
@ -1994,6 +2049,16 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
fd = bpf_prog_attach(section, &prog, ctx);
if (fd < 0) {
*lderr = true;
if (props.total) {
if (ctx->cfg.jit_enabled &&
props.total != props.jited)
fprintf(stderr, "JIT enabled, but only %u/%u tail call maps in the program have JITed owner!\n",
props.jited, props.total);
if (!ctx->cfg.jit_enabled &&
props.jited)
fprintf(stderr, "JIT disabled, but %u/%u tail call maps in the program have JITed owner!\n",
props.jited, props.total);
}
return fd;
}
@ -2031,6 +2096,51 @@ static int bpf_find_map_by_id(struct bpf_elf_ctx *ctx, uint32_t id)
return -1;
}
struct bpf_jited_aux {
int prog_fd;
int map_fd;
struct bpf_prog_data prog;
struct bpf_map_ext map;
};
static int bpf_derive_prog_from_fdinfo(int fd, struct bpf_prog_data *prog)
{
char file[PATH_MAX], buff[4096];
unsigned int val;
FILE *fp;
snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
memset(prog, 0, sizeof(*prog));
fp = fopen(file, "r");
if (!fp) {
fprintf(stderr, "No procfs support?!\n");
return -EIO;
}
while (fgets(buff, sizeof(buff), fp)) {
if (sscanf(buff, "prog_type:\t%u", &val) == 1)
prog->type = val;
else if (sscanf(buff, "prog_jited:\t%u", &val) == 1)
prog->jited = val;
}
fclose(fp);
return 0;
}
static int bpf_tail_call_get_aux(struct bpf_jited_aux *aux)
{
struct bpf_elf_map tmp;
int ret;
ret = bpf_derive_elf_map_from_fdinfo(aux->map_fd, &tmp, &aux->map);
if (!ret)
ret = bpf_derive_prog_from_fdinfo(aux->prog_fd, &aux->prog);
return ret;
}
static int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx)
{
struct bpf_elf_sec_data data;
@ -2060,10 +2170,31 @@ static int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx)
ret = bpf_map_update(ctx->map_fds[idx], &key_id,
&fd, BPF_ANY);
if (ret < 0) {
if (errno == E2BIG)
struct bpf_jited_aux aux = {};
ret = -errno;
if (errno == E2BIG) {
fprintf(stderr, "Tail call key %u for map %u out of bounds?\n",
key_id, map_id);
return -errno;
return ret;
}
aux.map_fd = ctx->map_fds[idx];
aux.prog_fd = fd;
if (bpf_tail_call_get_aux(&aux))
return ret;
if (!aux.map.owner.type)
return ret;
if (aux.prog.type != aux.map.owner.type)
fprintf(stderr, "Tail call map owned by prog type %u, but prog type is %u!\n",
aux.map.owner.type, aux.prog.type);
if (aux.prog.jited != aux.map.owner.jited)
fprintf(stderr, "Tail call map %s jited, but prog %s!\n",
aux.map.owner.jited ? "is" : "not",
aux.prog.jited ? "is" : "not");
return ret;
}
ctx->sec_done[i] = true;
@ -2221,6 +2352,21 @@ static int bpf_elf_check_ehdr(const struct bpf_elf_ctx *ctx)
return 0;
}
static void bpf_get_cfg(struct bpf_elf_ctx *ctx)
{
static const char *path_jit = "/proc/sys/net/core/bpf_jit_enable";
int fd;
fd = open(path_jit, O_RDONLY);
if (fd > 0) {
char tmp[16] = {};
if (read(fd, tmp, sizeof(tmp)) > 0)
ctx->cfg.jit_enabled = atoi(tmp);
close(fd);
}
}
static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
enum bpf_prog_type type, bool verbose)
{
@ -2231,6 +2377,7 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
return ret;
memset(ctx, 0, sizeof(*ctx));
bpf_get_cfg(ctx);
ctx->verbose = verbose;
ctx->type = type;

View File

@ -49,6 +49,7 @@ ip-tunnel - tunnel configuration
.BR 6rd-reset " ]"
.br
.RB "[ [" no "]" pmtudisc " ]"
.RB "[ [" no "]" ignore-df " ]"
.RB "[ " dev
.IR PHYS_DEV " ]"
@ -175,6 +176,14 @@ It is enabled by default. Note that a fixed ttl is incompatible
with this option: tunneling with a fixed ttl always makes pmtu
discovery.
.TP
.B ignore-df
enable IPv4 DF suppression on this tunnel.
Normally datagrams that exceed the MTU will be fragmented; the presence
of the DF flag inhibits this, resulting instead in an ICMP Unreachable
(Fragmentation Required) message. Enabling this attribute casues the
DF flag to be ignored.
.TP
.BI key " K"
.TP