This patch corresponds to a new feature that is now available in the net tree. I hence assumed that this patch had to be sent to iproute2 and not iproute2-next, please tell me if this is not OK, I'll then send a v2 towards iproute2-next.
Thanks. 2018-07-16 14:47 GMT+00:00 Mathieu Xhonneux <m.xhonn...@gmail.com>: > This patch adds support for the End.BPF action of the seg6local > lightweight tunnel. Functions from the BPF lightweight tunnel are > re-used in this patch. Example: > > $ ip -6 route add fc00::18 encap seg6local action End.BPF obj my_bpf.o > sec my_func dev eth0 > > $ ip -6 route show fc00::18 > fc00::18 encap seg6local action End.BPF my_bpf.o:[my_func] dev eth0 > metric 1024 pref medium > > Signed-off-by: Mathieu Xhonneux <m.xhonn...@gmail.com> > --- > ip/iproute_lwtunnel.c | 122 > +++++++++++++++++++++++++++++--------------------- > lib/bpf.c | 5 +++ > 2 files changed, 77 insertions(+), 50 deletions(-) > > diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c > index 46a212c8..71c3d8a4 100644 > --- a/ip/iproute_lwtunnel.c > +++ b/ip/iproute_lwtunnel.c > @@ -177,6 +177,7 @@ static const char > *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = { > [SEG6_LOCAL_ACTION_END_S] = "End.S", > [SEG6_LOCAL_ACTION_END_AS] = "End.AS", > [SEG6_LOCAL_ACTION_END_AM] = "End.AM", > + [SEG6_LOCAL_ACTION_END_BPF] = "End.BPF", > }; > > static const char *format_action_type(int action) > @@ -250,6 +251,15 @@ static void print_encap_seg6local(FILE *fp, struct > rtattr *encap) > print_string(PRINT_ANY, "oif", > "oif %s ", ll_index_to_name(oif)); > } > + > + if (tb[SEG6_LOCAL_BPF]) { > + struct rtattr *tb_bpf[LWT_BPF_PROG_MAX+1]; > + > + parse_rtattr_nested(tb_bpf, LWT_BPF_PROG_MAX, > tb[SEG6_LOCAL_BPF]); > + > + if (tb_bpf[LWT_BPF_PROG_NAME]) > + fprintf(fp, "%s ", > rta_getattr_str(tb_bpf[LWT_BPF_PROG_NAME])); > + } > } > > static void print_encap_mpls(FILE *fp, struct rtattr *encap) > @@ -546,11 +556,60 @@ static int parse_encap_seg6(struct rtattr *rta, size_t > len, int *argcp, > return 0; > } > > +struct lwt_x { > + struct rtattr *rta; > + size_t len; > +}; > + > +static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation) > +{ > + struct lwt_x *x = lwt_ptr; > + > + rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd); > + rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation, > + strlen(annotation) + 1); > +} > + > +static const struct bpf_cfg_ops bpf_cb_ops = { > + .ebpf_cb = bpf_lwt_cb, > +}; > + > +static int lwt_parse_bpf(struct rtattr *rta, size_t len, > + int *argcp, char ***argvp, > + int attr, const enum bpf_prog_type bpf_type) > +{ > + struct bpf_cfg_in cfg = { > + .type = bpf_type, > + .argc = *argcp, > + .argv = *argvp, > + }; > + struct lwt_x x = { > + .rta = rta, > + .len = len, > + }; > + struct rtattr *nest; > + int err; > + > + nest = rta_nest(rta, len, attr); > + err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x); > + if (err < 0) { > + fprintf(stderr, "Failed to parse eBPF program: %s\n", > + strerror(-err)); > + return -1; > + } > + rta_nest_end(rta, nest); > + > + *argcp = cfg.argc; > + *argvp = cfg.argv; > + > + return 0; > +} > + > static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, > char ***argvp) > { > int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0; > - int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0; > + int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0, bpf_ok = 0; > __u32 action = 0, table, iif, oif; > struct ipv6_sr_hdr *srh; > char **argv = *argvp; > @@ -627,6 +686,18 @@ static int parse_encap_seg6local(struct rtattr *rta, > size_t len, int *argcp, > } else { > continue; > } > + } else if (strcmp(*argv, "object-file") == 0 || > + strcmp(*argv, "obj") == 0 || > + strcmp(*argv, "object-pinned") == 0 || > + strcmp(*argv, "pinned") == 0 || > + strcmp(*argv, "fd") == 0) { > + if (bpf_ok++) { > + NEXT_ARG(); > + duparg2(*(argv-1), *argv); > + } > + if (lwt_parse_bpf(rta, len, &argc, &argv, > SEG6_LOCAL_BPF, > + BPF_PROG_TYPE_LWT_SEG6LOCAL) < 0) > + exit(-1); > } else { > break; > } > @@ -896,55 +967,6 @@ static int parse_encap_ip6(struct rtattr *rta, size_t > len, > return 0; > } > > -struct lwt_x { > - struct rtattr *rta; > - size_t len; > -}; > - > -static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation) > -{ > - struct lwt_x *x = lwt_ptr; > - > - rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd); > - rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation, > - strlen(annotation) + 1); > -} > - > -static const struct bpf_cfg_ops bpf_cb_ops = { > - .ebpf_cb = bpf_lwt_cb, > -}; > - > -static int lwt_parse_bpf(struct rtattr *rta, size_t len, > - int *argcp, char ***argvp, > - int attr, const enum bpf_prog_type bpf_type) > -{ > - struct bpf_cfg_in cfg = { > - .type = bpf_type, > - .argc = *argcp, > - .argv = *argvp, > - }; > - struct lwt_x x = { > - .rta = rta, > - .len = len, > - }; > - struct rtattr *nest; > - int err; > - > - nest = rta_nest(rta, len, attr); > - err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x); > - if (err < 0) { > - fprintf(stderr, "Failed to parse eBPF program: %s\n", > - strerror(-err)); > - return -1; > - } > - rta_nest_end(rta, nest); > - > - *argcp = cfg.argc; > - *argvp = cfg.argv; > - > - return 0; > -} > - > static void lwt_bpf_usage(void) > { > fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] > [ xmit BPF ] [...]\n"); > diff --git a/lib/bpf.c b/lib/bpf.c > index 4e26c0df..65e26989 100644 > --- a/lib/bpf.c > +++ b/lib/bpf.c > @@ -95,6 +95,11 @@ static const struct bpf_prog_meta __bpf_prog_meta[] = { > .subdir = "ip", > .section = ELF_SECTION_PROG, > }, > + [BPF_PROG_TYPE_LWT_SEG6LOCAL] = { > + .type = "lwt_seg6local", > + .subdir = "ip", > + .section = ELF_SECTION_PROG, > + }, > }; > > static bool bpf_map_offload_neutral(enum bpf_map_type type) > -- > 2.16.1 >