diff options
Diffstat (limited to 'package/libs/libnftnl/patches/101-expr-add-flow-offload-expression.patch')
-rw-r--r-- | package/libs/libnftnl/patches/101-expr-add-flow-offload-expression.patch | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/package/libs/libnftnl/patches/101-expr-add-flow-offload-expression.patch b/package/libs/libnftnl/patches/101-expr-add-flow-offload-expression.patch new file mode 100644 index 0000000..c7d3676 --- /dev/null +++ b/package/libs/libnftnl/patches/101-expr-add-flow-offload-expression.patch @@ -0,0 +1,259 @@ +From: Pablo Neira Ayuso <pablo@netfilter.org> +Date: Sun, 3 Dec 2017 21:05:54 +0100 +Subject: [PATCH] expr: add flow offload expression + +This patch adds the new "flow_offload" expression to select what flows +are offloaded to an existing flowtable. + +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + create mode 100644 src/expr/flow_offload.c + +--- a/include/libnftnl/expr.h ++++ b/include/libnftnl/expr.h +@@ -221,6 +221,10 @@ enum { + }; + + enum { ++ NFTNL_EXPR_FLOW_TABLE_NAME = NFTNL_EXPR_BASE, ++}; ++ ++enum { + NFTNL_EXPR_FWD_SREG_DEV = NFTNL_EXPR_BASE, + }; + +--- a/include/linux/netfilter/nf_tables.h ++++ b/include/linux/netfilter/nf_tables.h +@@ -952,6 +952,17 @@ enum nft_ct_attributes { + }; + #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) + ++/** ++ * enum nft_flow_attributes - ct offload expression attributes ++ * @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING) ++ */ ++enum nft_offload_attributes { ++ NFTA_FLOW_UNSPEC, ++ NFTA_FLOW_TABLE_NAME, ++ __NFTA_FLOW_MAX, ++}; ++#define NFTA_FLOW_MAX (__NFTA_FLOW_MAX - 1) ++ + enum nft_limit_type { + NFT_LIMIT_PKTS, + NFT_LIMIT_PKT_BYTES +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -32,6 +32,7 @@ libnftnl_la_SOURCES = utils.c \ + expr/data_reg.c \ + expr/dup.c \ + expr/exthdr.c \ ++ expr/flow_offload.c \ + expr/fib.c \ + expr/fwd.c \ + expr/limit.c \ +--- /dev/null ++++ b/src/expr/flow_offload.c +@@ -0,0 +1,184 @@ ++#include "internal.h" ++ ++#include <stdio.h> ++#include <stdint.h> ++#include <string.h> /* for memcpy */ ++#include <arpa/inet.h> ++#include <errno.h> ++#include <libmnl/libmnl.h> ++#include <linux/netfilter/nf_tables.h> ++#include <libnftnl/rule.h> ++#include <libnftnl/expr.h> ++ ++struct nftnl_expr_flow { ++ char *table_name; ++}; ++ ++static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type, ++ const void *data, uint32_t data_len) ++{ ++ struct nftnl_expr_flow *flow = nftnl_expr_data(e); ++ ++ switch (type) { ++ case NFTNL_EXPR_FLOW_TABLE_NAME: ++ flow->table_name = strdup((const char *)data); ++ if (!flow->table_name) ++ return -1; ++ break; ++ default: ++ return -1; ++ } ++ return 0; ++} ++ ++static const void *nftnl_expr_flow_get(const struct nftnl_expr *e, ++ uint16_t type, uint32_t *data_len) ++{ ++ struct nftnl_expr_flow *flow = nftnl_expr_data(e); ++ ++ switch(type) { ++ case NFTNL_EXPR_FLOW_TABLE_NAME: ++ *data_len = strlen(flow->table_name) + 1; ++ return flow->table_name; ++ } ++ return NULL; ++} ++ ++static int nftnl_expr_flow_cb(const struct nlattr *attr, void *data) ++{ ++ const struct nlattr **tb = data; ++ int type = mnl_attr_get_type(attr); ++ ++ if (mnl_attr_type_valid(attr, NFTA_FLOW_MAX) < 0) ++ return MNL_CB_OK; ++ ++ switch(type) { ++ case NFTA_FLOW_TABLE_NAME: ++ if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) ++ abi_breakage(); ++ break; ++ } ++ ++ tb[type] = attr; ++ return MNL_CB_OK; ++} ++ ++static void nftnl_expr_flow_build(struct nlmsghdr *nlh, ++ const struct nftnl_expr *e) ++{ ++ struct nftnl_expr_flow *flow = nftnl_expr_data(e); ++ ++ if (e->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) ++ mnl_attr_put_strz(nlh, NFTA_FLOW_TABLE_NAME, flow->table_name); ++} ++ ++static int nftnl_expr_flow_parse(struct nftnl_expr *e, struct nlattr *attr) ++{ ++ struct nftnl_expr_flow *flow = nftnl_expr_data(e); ++ struct nlattr *tb[NFTA_FLOW_MAX+1] = {}; ++ int ret = 0; ++ ++ if (mnl_attr_parse_nested(attr, nftnl_expr_flow_cb, tb) < 0) ++ return -1; ++ ++ if (tb[NFTA_FLOW_TABLE_NAME]) { ++ flow->table_name = ++ strdup(mnl_attr_get_str(tb[NFTA_FLOW_TABLE_NAME])); ++ if (!flow->table_name) ++ return -1; ++ e->flags |= (1 << NFTNL_EXPR_FLOW_TABLE_NAME); ++ } ++ ++ return ret; ++} ++ ++static int ++nftnl_expr_flow_json_parse(struct nftnl_expr *e, json_t *root, ++ struct nftnl_parse_err *err) ++{ ++#ifdef JSON_PARSING ++ const char *table_name; ++ ++ table_name = nftnl_jansson_parse_str(root, "flowtable", err); ++ if (table_name != NULL) ++ nftnl_expr_set_str(e, NFTNL_EXPR_FLOW_TABLE_NAME, table_name); ++ ++ return 0; ++#else ++ errno = EOPNOTSUPP; ++ return -1; ++#endif ++} ++ ++static int nftnl_expr_flow_export(char *buf, size_t size, ++ const struct nftnl_expr *e, int type) ++{ ++ struct nftnl_expr_flow *l = nftnl_expr_data(e); ++ NFTNL_BUF_INIT(b, buf, size); ++ ++ if (e->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) ++ nftnl_buf_str(&b, type, l->table_name, SET); ++ ++ return nftnl_buf_done(&b); ++} ++ ++static int nftnl_expr_flow_snprintf_default(char *buf, size_t size, ++ const struct nftnl_expr *e) ++{ ++ int remain = size, offset = 0, ret; ++ struct nftnl_expr_flow *l = nftnl_expr_data(e); ++ ++ ret = snprintf(buf, remain, "flowtable %s ", l->table_name); ++ SNPRINTF_BUFFER_SIZE(ret, remain, offset); ++ ++ return offset; ++} ++ ++static int nftnl_expr_flow_snprintf(char *buf, size_t size, uint32_t type, ++ uint32_t flags, const struct nftnl_expr *e) ++{ ++ switch(type) { ++ case NFTNL_OUTPUT_DEFAULT: ++ return nftnl_expr_flow_snprintf_default(buf, size, e); ++ case NFTNL_OUTPUT_XML: ++ case NFTNL_OUTPUT_JSON: ++ return nftnl_expr_flow_export(buf, size, e, type); ++ default: ++ break; ++ } ++ return -1; ++} ++ ++static void nftnl_expr_flow_free(const struct nftnl_expr *e) ++{ ++ struct nftnl_expr_flow *flow = nftnl_expr_data(e); ++ ++ xfree(flow->table_name); ++} ++ ++static bool nftnl_expr_flow_cmp(const struct nftnl_expr *e1, ++ const struct nftnl_expr *e2) ++{ ++ struct nftnl_expr_flow *l1 = nftnl_expr_data(e1); ++ struct nftnl_expr_flow *l2 = nftnl_expr_data(e2); ++ bool eq = true; ++ ++ if (e1->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) ++ eq &= !strcmp(l1->table_name, l2->table_name); ++ ++ return eq; ++} ++ ++struct expr_ops expr_ops_flow = { ++ .name = "flow_offload", ++ .alloc_len = sizeof(struct nftnl_expr_flow), ++ .max_attr = NFTA_FLOW_MAX, ++ .free = nftnl_expr_flow_free, ++ .cmp = nftnl_expr_flow_cmp, ++ .set = nftnl_expr_flow_set, ++ .get = nftnl_expr_flow_get, ++ .parse = nftnl_expr_flow_parse, ++ .build = nftnl_expr_flow_build, ++ .snprintf = nftnl_expr_flow_snprintf, ++ .json_parse = nftnl_expr_flow_json_parse, ++}; +--- a/src/expr_ops.c ++++ b/src/expr_ops.c +@@ -33,6 +33,7 @@ extern struct expr_ops expr_ops_target; + extern struct expr_ops expr_ops_dynset; + extern struct expr_ops expr_ops_hash; + extern struct expr_ops expr_ops_fib; ++extern struct expr_ops expr_ops_flow; + + static struct expr_ops expr_ops_notrack = { + .name = "notrack", +@@ -69,6 +70,7 @@ static struct expr_ops *expr_ops[] = { + &expr_ops_hash, + &expr_ops_fib, + &expr_ops_objref, ++ &expr_ops_flow, + NULL, + }; + |