Message ID | 20180716144741.20478-1-m.xhonneux@gmail.com |
---|---|
State | Changes Requested, archived |
Delegated to: | stephen hemminger |
Headers | show |
Series | [iproute2] ip: add support for seg6local End.BPF action | expand |
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.xhonneux@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.xhonneux@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 >
On Mon, 16 Jul 2018 14:47:41 +0000 Mathieu Xhonneux <m.xhonneux@gmail.com> wrote: > 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.xhonneux@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])); > + } > } Please use print_string to support JSON output.
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)
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.xhonneux@gmail.com> --- ip/iproute_lwtunnel.c | 122 +++++++++++++++++++++++++++++--------------------- lib/bpf.c | 5 +++ 2 files changed, 77 insertions(+), 50 deletions(-)