Re: [PATCH iproute2 -net-next] lwt: BPF support for LWT

2016-12-13 Thread Thomas Graf
On 13 December 2016 at 00:41, Stephen Hemminger
 wrote:
> I went ahead and fixed these.

Thanks for fixing it up Stephen.


Re: [PATCH iproute2 -net-next] lwt: BPF support for LWT

2016-12-13 Thread Stephen Hemminger
On Mon, 12 Dec 2016 01:14:35 +0100
Daniel Borkmann  wrote:

> +
> +static int lwt_parse_bpf(struct rtattr *rta, size_t len, int *argcp, char 
> ***argvp,
> +  int attr, const enum bpf_prog_type bpf_type)

Please break long lines like this.


> +
> + /* argv is currently the first unparsed argument,
> +  * but the lwt_parse_encap() caller will move to the next,
> +  * so step back */
> + *argcp = argc + 1;

iproute2 uses kernel comment style. 

I went ahead and fixed these.


[PATCH iproute2 -net-next] lwt: BPF support for LWT

2016-12-11 Thread Daniel Borkmann
From: Thomas Graf 

Adds support to configure BPF programs as nexthop actions via the LWT
framework.

Example:
   ip route add 192.168.253.2/32 \
 encap bpf out obj lwt_len_hist_kern.o section len_hist \
 dev veth0

Signed-off-by: Thomas Graf 
---
 include/bpf_api.h  |   5 ++
 ip/iproute_lwtunnel.c  | 186 +
 lib/bpf.c  |  18 +
 man/man8/ip-route.8.in |  41 ++-
 4 files changed, 235 insertions(+), 15 deletions(-)

diff --git a/include/bpf_api.h b/include/bpf_api.h
index 72578c9..d132471 100644
--- a/include/bpf_api.h
+++ b/include/bpf_api.h
@@ -87,6 +87,11 @@
__section(ELF_SECTION_ACTION)
 #endif
 
+#ifndef __section_lwt_entry
+# define __section_lwt_entry   \
+   __section(ELF_SECTION_PROG)
+#endif
+
 #ifndef __section_license
 # define __section_license \
__section(ELF_SECTION_LICENSE)
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index b656143..6c1f8fb 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -24,20 +24,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "iproute_lwtunnel.h"
-
-static int read_encap_type(const char *name)
-{
-   if (strcmp(name, "mpls") == 0)
-   return LWTUNNEL_ENCAP_MPLS;
-   else if (strcmp(name, "ip") == 0)
-   return LWTUNNEL_ENCAP_IP;
-   else if (strcmp(name, "ip6") == 0)
-   return LWTUNNEL_ENCAP_IP6;
-   else if (strcmp(name, "ila") == 0)
-   return LWTUNNEL_ENCAP_ILA;
-   else
-   return LWTUNNEL_ENCAP_NONE;
-}
+#include "bpf_util.h"
 
 static const char *format_encap_type(int type)
 {
@@ -50,11 +37,44 @@ static const char *format_encap_type(int type)
return "ip6";
case LWTUNNEL_ENCAP_ILA:
return "ila";
+   case LWTUNNEL_ENCAP_BPF:
+   return "bpf";
default:
return "unknown";
}
 }
 
+static void encap_type_usage(void)
+{
+   int i;
+
+   fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
+
+   for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++)
+   fprintf(stderr, "%s %s\n", format_encap_type(i),
+   i == 1 ? "TYPE := " : "  ");
+
+   exit(-1);
+}
+
+static int read_encap_type(const char *name)
+{
+   if (strcmp(name, "mpls") == 0)
+   return LWTUNNEL_ENCAP_MPLS;
+   else if (strcmp(name, "ip") == 0)
+   return LWTUNNEL_ENCAP_IP;
+   else if (strcmp(name, "ip6") == 0)
+   return LWTUNNEL_ENCAP_IP6;
+   else if (strcmp(name, "ila") == 0)
+   return LWTUNNEL_ENCAP_ILA;
+   else if (strcmp(name, "bpf") == 0)
+   return LWTUNNEL_ENCAP_BPF;
+   else if (strcmp(name, "help") == 0)
+   encap_type_usage();
+
+   return LWTUNNEL_ENCAP_NONE;
+}
+
 static void print_encap_mpls(FILE *fp, struct rtattr *encap)
 {
struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
@@ -159,6 +179,34 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
 }
 
+static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
+const char *str)
+{
+   struct rtattr *tb[LWT_BPF_PROG_MAX+1];
+
+   parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
+   fprintf(fp, "%s ", str);
+
+   if (tb[LWT_BPF_PROG_NAME])
+   fprintf(fp, "%s ", rta_getattr_str(tb[LWT_BPF_PROG_NAME]));
+}
+
+static void print_encap_bpf(FILE *fp, struct rtattr *encap)
+{
+   struct rtattr *tb[LWT_BPF_MAX+1];
+
+   parse_rtattr_nested(tb, LWT_BPF_MAX, encap);
+
+   if (tb[LWT_BPF_IN])
+   print_encap_bpf_prog(fp, tb[LWT_BPF_IN], "in");
+   if (tb[LWT_BPF_OUT])
+   print_encap_bpf_prog(fp, tb[LWT_BPF_OUT], "out");
+   if (tb[LWT_BPF_XMIT])
+   print_encap_bpf_prog(fp, tb[LWT_BPF_XMIT], "xmit");
+   if (tb[LWT_BPF_XMIT_HEADROOM])
+   fprintf(fp, "%d ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM]));
+}
+
 void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
  struct rtattr *encap)
 {
@@ -184,6 +232,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
case LWTUNNEL_ENCAP_IP6:
print_encap_ip6(fp, encap);
break;
+   case LWTUNNEL_ENCAP_BPF:
+   print_encap_bpf(fp, encap);
+   break;
}
 }
 
@@ -365,6 +416,109 @@ static int parse_encap_ip6(struct rtattr *rta, size_t 
len, int *argcp, char ***a
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);
+