* [patch iproute2 repost 1/2] tc: push bpf common code into separate file
@ 2015-01-19 15:56 Jiri Pirko
2015-01-19 15:56 ` [patch iproute2 repost 2/2] tc: add support for BPF based actions Jiri Pirko
2015-02-05 18:39 ` [patch iproute2 repost 1/2] tc: push bpf common code into separate file Stephen Hemminger
0 siblings, 2 replies; 3+ messages in thread
From: Jiri Pirko @ 2015-01-19 15:56 UTC (permalink / raw)
To: netdev; +Cc: jhs, stephen
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
tc/Makefile | 2 +-
tc/f_bpf.c | 136 +++++--------------------------------------------------
tc/tc_bpf.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tc/tc_bpf.h | 28 ++++++++++++
4 files changed, 186 insertions(+), 126 deletions(-)
create mode 100644 tc/tc_bpf.c
create mode 100644 tc/tc_bpf.h
diff --git a/tc/Makefile b/tc/Makefile
index 9412094..15f68ce 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -1,5 +1,5 @@
TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o \
- tc_monitor.o m_police.o m_estimator.o m_action.o \
+ tc_monitor.o tc_bpf.o m_police.o m_estimator.o m_action.o \
m_ematch.o emp_ematch.yacc.o emp_ematch.lex.o
include ../Config
diff --git a/tc/f_bpf.c b/tc/f_bpf.c
index 48635a7..e2af94e 100644
--- a/tc/f_bpf.c
+++ b/tc/f_bpf.c
@@ -26,6 +26,7 @@
#include "utils.h"
#include "tc_util.h"
+#include "tc_bpf.h"
static void explain(void)
{
@@ -44,130 +45,6 @@ static void explain(void)
fprintf(stderr, "NOTE: CLASSID is parsed as hexadecimal input.\n");
}
-static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
- char **bpf_string, bool *need_release,
- const char separator)
-{
- char sp;
-
- if (from_file) {
- size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
- char *tmp_string;
- FILE *fp;
-
- tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
- tmp_string = malloc(tmp_len);
- if (tmp_string == NULL)
- return -ENOMEM;
-
- memset(tmp_string, 0, tmp_len);
-
- fp = fopen(arg, "r");
- if (fp == NULL) {
- perror("Cannot fopen");
- free(tmp_string);
- return -ENOENT;
- }
-
- if (!fgets(tmp_string, tmp_len, fp)) {
- free(tmp_string);
- fclose(fp);
- return -EIO;
- }
-
- fclose(fp);
-
- *need_release = true;
- *bpf_string = tmp_string;
- } else {
- *need_release = false;
- *bpf_string = arg;
- }
-
- if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
- sp != separator) {
- if (*need_release)
- free(*bpf_string);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int bpf_parse_ops(int argc, char **argv, struct nlmsghdr *n,
- bool from_file)
-{
- char *bpf_string, *token, separator = ',';
- struct sock_filter bpf_ops[BPF_MAXINSNS];
- int ret = 0, i = 0;
- bool need_release;
- __u16 bpf_len = 0;
-
- if (argc < 1)
- return -EINVAL;
- if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
- &need_release, separator))
- return -EINVAL;
- if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
- ret = -EINVAL;
- goto out;
- }
-
- token = bpf_string;
- while ((token = strchr(token, separator)) && (++token)[0]) {
- if (i >= bpf_len) {
- fprintf(stderr, "Real program length exceeds encoded "
- "length parameter!\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (sscanf(token, "%hu %hhu %hhu %u,",
- &bpf_ops[i].code, &bpf_ops[i].jt,
- &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
- fprintf(stderr, "Error at instruction %d!\n", i);
- ret = -EINVAL;
- goto out;
- }
-
- i++;
- }
-
- if (i != bpf_len) {
- fprintf(stderr, "Parsed program length is less than encoded"
- "length parameter!\n");
- ret = -EINVAL;
- goto out;
- }
-
- addattr_l(n, MAX_MSG, TCA_BPF_OPS_LEN, &bpf_len, sizeof(bpf_len));
- addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops,
- bpf_len * sizeof(struct sock_filter));
-out:
- if (need_release)
- free(bpf_string);
-
- return ret;
-}
-
-static void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
-{
- struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
- int i;
-
- if (len == 0)
- return;
-
- fprintf(f, "bytecode \'%u,", len);
-
- for (i = 0; i < len - 1; i++)
- fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
- ops[i].jf, ops[i].k);
-
- fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt,
- ops[i].jf, ops[i].k);
-}
-
static int bpf_parse_opt(struct filter_util *qu, char *handle,
int argc, char **argv, struct nlmsghdr *n)
{
@@ -195,6 +72,10 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
while (argc > 0) {
if (matches(*argv, "run") == 0) {
bool from_file;
+ struct sock_filter bpf_ops[BPF_MAXINSNS];
+ __u16 bpf_len;
+ int ret;
+
NEXT_ARG();
if (strcmp(*argv, "bytecode-file") == 0) {
from_file = true;
@@ -206,10 +87,15 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
return -1;
}
NEXT_ARG();
- if (bpf_parse_ops(argc, argv, n, from_file)) {
+ ret = bpf_parse_ops(argc, argv, bpf_ops, from_file);
+ if (ret < 0) {
fprintf(stderr, "Illegal \"bytecode\"\n");
return -1;
}
+ bpf_len = ret;
+ addattr16(n, MAX_MSG, TCA_BPF_OPS_LEN, bpf_len);
+ addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops,
+ bpf_len * sizeof(struct sock_filter));
} else if (matches(*argv, "classid") == 0 ||
strcmp(*argv, "flowid") == 0) {
unsigned handle;
diff --git a/tc/tc_bpf.c b/tc/tc_bpf.c
new file mode 100644
index 0000000..c6901d6
--- /dev/null
+++ b/tc/tc_bpf.c
@@ -0,0 +1,146 @@
+/*
+ * tc_bpf.c BPF common code
+ *
+ * This program is free software; you can distribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Daniel Borkmann <dborkman@redhat.com>
+ * Jiri Pirko <jiri@resnulli.us>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <linux/filter.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include "utils.h"
+#include "tc_util.h"
+#include "tc_bpf.h"
+
+int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
+ char **bpf_string, bool *need_release,
+ const char separator)
+{
+ char sp;
+
+ if (from_file) {
+ size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
+ char *tmp_string;
+ FILE *fp;
+
+ tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
+ tmp_string = malloc(tmp_len);
+ if (tmp_string == NULL)
+ return -ENOMEM;
+
+ memset(tmp_string, 0, tmp_len);
+
+ fp = fopen(arg, "r");
+ if (fp == NULL) {
+ perror("Cannot fopen");
+ free(tmp_string);
+ return -ENOENT;
+ }
+
+ if (!fgets(tmp_string, tmp_len, fp)) {
+ free(tmp_string);
+ fclose(fp);
+ return -EIO;
+ }
+
+ fclose(fp);
+
+ *need_release = true;
+ *bpf_string = tmp_string;
+ } else {
+ *need_release = false;
+ *bpf_string = arg;
+ }
+
+ if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
+ sp != separator) {
+ if (*need_release)
+ free(*bpf_string);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops,
+ bool from_file)
+{
+ char *bpf_string, *token, separator = ',';
+ int ret = 0, i = 0;
+ bool need_release;
+ __u16 bpf_len = 0;
+
+ if (argc < 1)
+ return -EINVAL;
+ if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
+ &need_release, separator))
+ return -EINVAL;
+ if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ token = bpf_string;
+ while ((token = strchr(token, separator)) && (++token)[0]) {
+ if (i >= bpf_len) {
+ fprintf(stderr, "Real program length exceeds encoded "
+ "length parameter!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (sscanf(token, "%hu %hhu %hhu %u,",
+ &bpf_ops[i].code, &bpf_ops[i].jt,
+ &bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
+ fprintf(stderr, "Error at instruction %d!\n", i);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ i++;
+ }
+
+ if (i != bpf_len) {
+ fprintf(stderr, "Parsed program length is less than encoded"
+ "length parameter!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = bpf_len;
+
+out:
+ if (need_release)
+ free(bpf_string);
+
+ return ret;
+}
+
+void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
+{
+ struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
+ int i;
+
+ if (len == 0)
+ return;
+
+ fprintf(f, "bytecode \'%u,", len);
+
+ for (i = 0; i < len - 1; i++)
+ fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
+ ops[i].jf, ops[i].k);
+
+ fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt,
+ ops[i].jf, ops[i].k);
+}
diff --git a/tc/tc_bpf.h b/tc/tc_bpf.h
new file mode 100644
index 0000000..08cca92
--- /dev/null
+++ b/tc/tc_bpf.h
@@ -0,0 +1,28 @@
+/*
+ * tc_bpf.h BPF common code
+ *
+ * This program is free software; you can distribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Daniel Borkmann <dborkman@redhat.com>
+ * Jiri Pirko <jiri@resnulli.us>
+ */
+
+#ifndef _TC_BPF_H_
+#define _TC_BPF_H_ 1
+
+#include <stdio.h>
+#include <linux/filter.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
+ char **bpf_string, bool *need_release,
+ const char separator);
+int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops,
+ bool from_file);
+void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len);
+
+#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* [patch iproute2 repost 2/2] tc: add support for BPF based actions
2015-01-19 15:56 [patch iproute2 repost 1/2] tc: push bpf common code into separate file Jiri Pirko
@ 2015-01-19 15:56 ` Jiri Pirko
2015-02-05 18:39 ` [patch iproute2 repost 1/2] tc: push bpf common code into separate file Stephen Hemminger
1 sibling, 0 replies; 3+ messages in thread
From: Jiri Pirko @ 2015-01-19 15:56 UTC (permalink / raw)
To: netdev; +Cc: jhs, stephen
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/linux/tc_act/tc_bpf.h | 31 +++++++
tc/Makefile | 1 +
tc/m_bpf.c | 183 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 215 insertions(+)
create mode 100644 include/linux/tc_act/tc_bpf.h
create mode 100644 tc/m_bpf.c
diff --git a/include/linux/tc_act/tc_bpf.h b/include/linux/tc_act/tc_bpf.h
new file mode 100644
index 0000000..5288bd7
--- /dev/null
+++ b/include/linux/tc_act/tc_bpf.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_TC_BPF_H
+#define __LINUX_TC_BPF_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_BPF 13
+
+struct tc_act_bpf {
+ tc_gen;
+};
+
+enum {
+ TCA_ACT_BPF_UNSPEC,
+ TCA_ACT_BPF_TM,
+ TCA_ACT_BPF_PARMS,
+ TCA_ACT_BPF_OPS_LEN,
+ TCA_ACT_BPF_OPS,
+ __TCA_ACT_BPF_MAX,
+};
+#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
+
+#endif
diff --git a/tc/Makefile b/tc/Makefile
index 15f68ce..d831a15 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -46,6 +46,7 @@ TCMODULES += m_skbedit.o
TCMODULES += m_csum.o
TCMODULES += m_simple.o
TCMODULES += m_vlan.o
+TCMODULES += m_bpf.o
TCMODULES += p_ip.o
TCMODULES += p_icmp.o
TCMODULES += p_tcp.o
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
new file mode 100644
index 0000000..611135e
--- /dev/null
+++ b/tc/m_bpf.c
@@ -0,0 +1,183 @@
+/*
+ * m_bpf.c BFP based action module
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Jiri Pirko <jiri@resnulli.us>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <linux/tc_act/tc_bpf.h>
+
+#include "utils.h"
+#include "rt_names.h"
+#include "tc_util.h"
+#include "tc_bpf.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... bpf ...\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " [inline]: run bytecode BPF_BYTECODE\n");
+ fprintf(stderr, " [from file]: run bytecode-file FILE\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
+ fprintf(stderr, " c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
+ fprintf(stderr, "Where FILE points to a file containing the BPF_BYTECODE string\n");
+ fprintf(stderr, "\nACTION_SPEC := ... look at individual actions\n");
+ fprintf(stderr, "NOTE: CLASSID is parsed as hexadecimal input.\n");
+}
+
+static void usage(void)
+{
+ explain();
+ exit(-1);
+}
+
+static int parse_bpf(struct action_util *a, int *argc_p, char ***argv_p,
+ int tca_id, struct nlmsghdr *n)
+{
+ int argc = *argc_p;
+ char **argv = *argv_p;
+ struct rtattr *tail;
+ struct tc_act_bpf parm = { 0 };
+ struct sock_filter bpf_ops[BPF_MAXINSNS];
+ __u16 bpf_len = 0;
+
+ if (matches(*argv, "bpf") != 0)
+ return -1;
+
+ NEXT_ARG();
+
+ while (argc > 0) {
+ if (matches(*argv, "run") == 0) {
+ bool from_file;
+ int ret;
+
+ NEXT_ARG();
+ if (strcmp(*argv, "bytecode-file") == 0) {
+ from_file = true;
+ } else if (strcmp(*argv, "bytecode") == 0) {
+ from_file = false;
+ } else {
+ fprintf(stderr, "unexpected \"%s\"\n", *argv);
+ explain();
+ return -1;
+ }
+ NEXT_ARG();
+ ret = bpf_parse_ops(argc, argv, bpf_ops, from_file);
+ if (ret < 0) {
+ fprintf(stderr, "Illegal \"bytecode\"\n");
+ return -1;
+ }
+ bpf_len = ret;
+ } else if (matches(*argv, "help") == 0) {
+ usage();
+ } else {
+ break;
+ }
+ argc--;
+ argv++;
+ }
+
+ parm.action = TC_ACT_PIPE;
+ if (argc) {
+ if (matches(*argv, "reclassify") == 0) {
+ parm.action = TC_ACT_RECLASSIFY;
+ NEXT_ARG();
+ } else if (matches(*argv, "pipe") == 0) {
+ parm.action = TC_ACT_PIPE;
+ NEXT_ARG();
+ } else if (matches(*argv, "drop") == 0 ||
+ matches(*argv, "shot") == 0) {
+ parm.action = TC_ACT_SHOT;
+ NEXT_ARG();
+ } else if (matches(*argv, "continue") == 0) {
+ parm.action = TC_ACT_UNSPEC;
+ NEXT_ARG();
+ } else if (matches(*argv, "pass") == 0) {
+ parm.action = TC_ACT_OK;
+ NEXT_ARG();
+ }
+ }
+
+ if (argc) {
+ if (matches(*argv, "index") == 0) {
+ NEXT_ARG();
+ if (get_u32(&parm.index, *argv, 10)) {
+ fprintf(stderr, "bpf: Illegal \"index\"\n");
+ return -1;
+ }
+ argc--;
+ argv++;
+ }
+ }
+
+ if (!bpf_len) {
+ fprintf(stderr, "bpf: Bytecode needs to be passed\n");
+ explain();
+ return -1;
+ }
+
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+ addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));
+ addattr16(n, MAX_MSG, TCA_ACT_BPF_OPS_LEN, bpf_len);
+ addattr_l(n, MAX_MSG, TCA_ACT_BPF_OPS, &bpf_ops,
+ bpf_len * sizeof(struct sock_filter));
+ tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
+
+ *argc_p = argc;
+ *argv_p = argv;
+ return 0;
+}
+
+static int print_bpf(struct action_util *au, FILE *f, struct rtattr *arg)
+{
+ struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
+ struct tc_act_bpf *parm;
+
+ if (arg == NULL)
+ return -1;
+
+ parse_rtattr_nested(tb, TCA_ACT_BPF_MAX, arg);
+
+ if (!tb[TCA_ACT_BPF_PARMS]) {
+ fprintf(f, "[NULL bpf parameters]");
+ return -1;
+ }
+ parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
+
+ fprintf(f, " bpf ");
+
+ if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN])
+ bpf_print_ops(f, tb[TCA_ACT_BPF_OPS],
+ rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
+
+ fprintf(f, "\n\tindex %d ref %d bind %d", parm->index, parm->refcnt,
+ parm->bindcnt);
+
+ if (show_stats) {
+ if (tb[TCA_ACT_BPF_TM]) {
+ struct tcf_t *tm = RTA_DATA(tb[TCA_ACT_BPF_TM]);
+ print_tm(f, tm);
+ }
+ }
+
+ fprintf(f, "\n ");
+
+ return 0;
+}
+
+struct action_util bpf_action_util = {
+ .id = "bpf",
+ .parse_aopt = parse_bpf,
+ .print_aopt = print_bpf,
+};
--
1.9.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [patch iproute2 repost 1/2] tc: push bpf common code into separate file
2015-01-19 15:56 [patch iproute2 repost 1/2] tc: push bpf common code into separate file Jiri Pirko
2015-01-19 15:56 ` [patch iproute2 repost 2/2] tc: add support for BPF based actions Jiri Pirko
@ 2015-02-05 18:39 ` Stephen Hemminger
1 sibling, 0 replies; 3+ messages in thread
From: Stephen Hemminger @ 2015-02-05 18:39 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, jhs
On Mon, 19 Jan 2015 16:56:29 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Both patches applied to net-next branch.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-02-05 18:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-19 15:56 [patch iproute2 repost 1/2] tc: push bpf common code into separate file Jiri Pirko
2015-01-19 15:56 ` [patch iproute2 repost 2/2] tc: add support for BPF based actions Jiri Pirko
2015-02-05 18:39 ` [patch iproute2 repost 1/2] tc: push bpf common code into separate file Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox