Support for meta match
Syntax: meta(pktlen > 768)
This commit is contained in:
parent
c7a673787b
commit
7903d6ab4b
8 changed files with 644 additions and 3 deletions
89
include/linux/tc_ematch/tc_em_meta.h
Normal file
89
include/linux/tc_ematch/tc_em_meta.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
#ifndef __LINUX_TC_EM_META_H
|
||||
#define __LINUX_TC_EM_META_H
|
||||
|
||||
enum {
|
||||
TCA_EM_META_UNSPEC,
|
||||
TCA_EM_META_HDR,
|
||||
TCA_EM_META_LVALUE,
|
||||
TCA_EM_META_RVALUE,
|
||||
__TCA_EM_META_MAX
|
||||
};
|
||||
#define TCA_EM_META_MAX (__TCA_EM_META_MAX - 1)
|
||||
|
||||
struct tcf_meta_val {
|
||||
__u16 kind;
|
||||
__u8 shift;
|
||||
__u8 op;
|
||||
};
|
||||
|
||||
#define TCF_META_TYPE_MASK (0xf << 12)
|
||||
#define TCF_META_TYPE(kind) (((kind) & TCF_META_TYPE_MASK) >> 12)
|
||||
#define TCF_META_ID_MASK 0x7ff
|
||||
#define TCF_META_ID(kind) ((kind) & TCF_META_ID_MASK)
|
||||
|
||||
enum {
|
||||
TCF_META_TYPE_VAR,
|
||||
TCF_META_TYPE_INT,
|
||||
__TCF_META_TYPE_MAX
|
||||
};
|
||||
#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1)
|
||||
|
||||
enum {
|
||||
TCF_META_ID_VALUE,
|
||||
TCF_META_ID_RANDOM,
|
||||
TCF_META_ID_LOADAVG_0,
|
||||
TCF_META_ID_LOADAVG_1,
|
||||
TCF_META_ID_LOADAVG_2,
|
||||
TCF_META_ID_DEV,
|
||||
TCF_META_ID_PRIORITY,
|
||||
TCF_META_ID_PROTOCOL,
|
||||
TCF_META_ID_PKTTYPE,
|
||||
TCF_META_ID_PKTLEN,
|
||||
TCF_META_ID_DATALEN,
|
||||
TCF_META_ID_MACLEN,
|
||||
TCF_META_ID_NFMARK,
|
||||
TCF_META_ID_TCINDEX,
|
||||
TCF_META_ID_RTCLASSID,
|
||||
TCF_META_ID_RTIIF,
|
||||
TCF_META_ID_SK_FAMILY,
|
||||
TCF_META_ID_SK_STATE,
|
||||
TCF_META_ID_SK_REUSE,
|
||||
TCF_META_ID_SK_BOUND_IF,
|
||||
TCF_META_ID_SK_REFCNT,
|
||||
TCF_META_ID_SK_SHUTDOWN,
|
||||
TCF_META_ID_SK_PROTO,
|
||||
TCF_META_ID_SK_TYPE,
|
||||
TCF_META_ID_SK_RCVBUF,
|
||||
TCF_META_ID_SK_RMEM_ALLOC,
|
||||
TCF_META_ID_SK_WMEM_ALLOC,
|
||||
TCF_META_ID_SK_OMEM_ALLOC,
|
||||
TCF_META_ID_SK_WMEM_QUEUED,
|
||||
TCF_META_ID_SK_RCV_QLEN,
|
||||
TCF_META_ID_SK_SND_QLEN,
|
||||
TCF_META_ID_SK_ERR_QLEN,
|
||||
TCF_META_ID_SK_FORWARD_ALLOCS,
|
||||
TCF_META_ID_SK_SNDBUF,
|
||||
TCF_META_ID_SK_ALLOCS,
|
||||
TCF_META_ID_SK_ROUTE_CAPS,
|
||||
TCF_META_ID_SK_HASH,
|
||||
TCF_META_ID_SK_LINGERTIME,
|
||||
TCF_META_ID_SK_ACK_BACKLOG,
|
||||
TCF_META_ID_SK_MAX_ACK_BACKLOG,
|
||||
TCF_META_ID_SK_PRIO,
|
||||
TCF_META_ID_SK_RCVLOWAT,
|
||||
TCF_META_ID_SK_RCVTIMEO,
|
||||
TCF_META_ID_SK_SNDTIMEO,
|
||||
TCF_META_ID_SK_SENDMSG_OFF,
|
||||
TCF_META_ID_SK_WRITE_PENDING,
|
||||
TCF_META_ID_VLAN_TAG,
|
||||
TCF_META_ID_RXHASH,
|
||||
__TCF_META_ID_MAX
|
||||
};
|
||||
#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
|
||||
|
||||
struct tcf_meta_hdr {
|
||||
struct tcf_meta_val left;
|
||||
struct tcf_meta_val right;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -86,6 +86,7 @@ extern int rtnl_ematch_parse_expr(const char *, char **,
|
|||
|
||||
extern char * rtnl_ematch_offset2txt(uint8_t, uint16_t,
|
||||
char *, size_t);
|
||||
extern char * rtnl_ematch_opnd2txt(uint8_t, char *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
41
include/netlink/route/cls/ematch/meta.h
Normal file
41
include/netlink/route/cls/ematch/meta.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* netlink/route/cls/ematch/meta.h Metadata Match
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_CLS_EMATCH_META_H_
|
||||
#define NETLINK_CLS_EMATCH_META_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <linux/tc_ematch/tc_em_meta.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct rtnl_meta_value;
|
||||
|
||||
extern struct rtnl_meta_value * rtnl_meta_value_alloc_int(uint64_t);
|
||||
extern struct rtnl_meta_value * rtnl_meta_value_alloc_var(void *, size_t);
|
||||
extern struct rtnl_meta_value * rtnl_meta_value_alloc_id(uint8_t, uint16_t,
|
||||
uint8_t, uint64_t);
|
||||
extern void rtnl_meta_value_put(struct rtnl_meta_value *);
|
||||
|
||||
extern void rtnl_ematch_meta_set_lvalue(struct rtnl_ematch *,
|
||||
struct rtnl_meta_value *);
|
||||
void rtnl_ematch_meta_set_rvalue(struct rtnl_ematch *,
|
||||
struct rtnl_meta_value *);
|
||||
extern void rtnl_ematch_meta_set_operand(struct rtnl_ematch *, uint8_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -56,6 +56,7 @@ libnl_route_la_SOURCES = \
|
|||
route/cls/ematch.c \
|
||||
route/cls/ematch/container.c route/cls/ematch/cmp.c \
|
||||
route/cls/ematch/nbyte.c route/cls/ematch/text.c \
|
||||
route/cls/ematch/meta.c \
|
||||
\
|
||||
route/link/api.c route/link/vlan.c \
|
||||
\
|
||||
|
|
|
@ -682,4 +682,18 @@ char *rtnl_ematch_offset2txt(uint8_t layer, uint16_t offset, char *buf, size_t l
|
|||
return buf;
|
||||
}
|
||||
|
||||
static const char *operand_txt[] = {
|
||||
[TCF_EM_OPND_EQ] = "=",
|
||||
[TCF_EM_OPND_LT] = "<",
|
||||
[TCF_EM_OPND_GT] = ">",
|
||||
};
|
||||
|
||||
char *rtnl_ematch_opnd2txt(uint8_t opnd, char *buf, size_t len)
|
||||
{
|
||||
snprintf(buf, len, "%s",
|
||||
opnd <= ARRAY_SIZE(operand_txt) ? operand_txt[opnd] : "?");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
291
lib/route/cls/ematch/meta.c
Normal file
291
lib/route/cls/ematch/meta.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* lib/route/cls/ematch/meta.c Metadata Match
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup ematch
|
||||
* @defgroup em_meta Metadata Match
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <netlink/route/cls/ematch/meta.h>
|
||||
|
||||
struct rtnl_meta_value
|
||||
{
|
||||
uint8_t mv_type;
|
||||
uint8_t mv_shift;
|
||||
uint16_t mv_id;
|
||||
size_t mv_len;
|
||||
};
|
||||
|
||||
struct meta_data
|
||||
{
|
||||
struct rtnl_meta_value * left;
|
||||
struct rtnl_meta_value * right;
|
||||
uint8_t opnd;
|
||||
};
|
||||
|
||||
static struct rtnl_meta_value *meta_alloc(uint8_t type, uint16_t id,
|
||||
uint8_t shift, void *data,
|
||||
size_t len)
|
||||
{
|
||||
struct rtnl_meta_value *value;
|
||||
|
||||
if (!(value = calloc(1, sizeof(*value) + len)))
|
||||
return NULL;
|
||||
|
||||
value->mv_type = type;
|
||||
value->mv_id = id;
|
||||
value->mv_shift = shift;
|
||||
value->mv_len = len;
|
||||
|
||||
memcpy(value + 1, data, len);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
struct rtnl_meta_value *rtnl_meta_value_alloc_int(uint64_t value)
|
||||
{
|
||||
return meta_alloc(TCF_META_TYPE_INT, TCF_META_ID_VALUE, 0, &value, 8);
|
||||
}
|
||||
|
||||
struct rtnl_meta_value *rtnl_meta_value_alloc_var(void *data, size_t len)
|
||||
{
|
||||
return meta_alloc(TCF_META_TYPE_VAR, TCF_META_ID_VALUE, 0, data, len);
|
||||
}
|
||||
|
||||
struct rtnl_meta_value *rtnl_meta_value_alloc_id(uint8_t type, uint16_t id,
|
||||
uint8_t shift, uint64_t mask)
|
||||
{
|
||||
size_t masklen = 0;
|
||||
|
||||
if (id > TCF_META_ID_MAX)
|
||||
return NULL;
|
||||
|
||||
if (mask) {
|
||||
if (type == TCF_META_TYPE_VAR)
|
||||
return NULL;
|
||||
|
||||
masklen = 8;
|
||||
}
|
||||
|
||||
return meta_alloc(type, id, shift, &mask, masklen);
|
||||
}
|
||||
|
||||
void rtnl_meta_value_put(struct rtnl_meta_value *mv)
|
||||
{
|
||||
free(mv);
|
||||
}
|
||||
|
||||
void rtnl_ematch_meta_set_lvalue(struct rtnl_ematch *e, struct rtnl_meta_value *v)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
m->left = v;
|
||||
}
|
||||
|
||||
void rtnl_ematch_meta_set_rvalue(struct rtnl_ematch *e, struct rtnl_meta_value *v)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
m->right = v;
|
||||
}
|
||||
|
||||
void rtnl_ematch_meta_set_operand(struct rtnl_ematch *e, uint8_t opnd)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
m->opnd = opnd;
|
||||
}
|
||||
|
||||
static struct nla_policy meta_policy[TCA_EM_META_MAX+1] = {
|
||||
[TCA_EM_META_HDR] = { .minlen = sizeof(struct tcf_meta_hdr) },
|
||||
[TCA_EM_META_LVALUE] = { .minlen = 1, },
|
||||
[TCA_EM_META_RVALUE] = { .minlen = 1, },
|
||||
};
|
||||
|
||||
static int meta_parse(struct rtnl_ematch *e, void *data, size_t len)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
struct nlattr *tb[TCA_EM_META_MAX+1];
|
||||
struct rtnl_meta_value *v;
|
||||
struct tcf_meta_hdr *hdr;
|
||||
void *vdata = NULL;
|
||||
size_t vlen = 0;
|
||||
int err;
|
||||
|
||||
if ((err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy)) < 0)
|
||||
return err;
|
||||
|
||||
if (!tb[TCA_EM_META_HDR])
|
||||
return -NLE_MISSING_ATTR;
|
||||
|
||||
hdr = nla_data(tb[TCA_EM_META_HDR]);
|
||||
|
||||
if (tb[TCA_EM_META_LVALUE]) {
|
||||
vdata = nla_data(tb[TCA_EM_META_LVALUE]);
|
||||
vlen = nla_len(tb[TCA_EM_META_LVALUE]);
|
||||
}
|
||||
|
||||
v = meta_alloc(TCF_META_TYPE(hdr->left.kind),
|
||||
TCF_META_ID(hdr->left.kind),
|
||||
hdr->left.shift, vdata, vlen);
|
||||
if (!v)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
m->left = v;
|
||||
|
||||
vlen = 0;
|
||||
if (tb[TCA_EM_META_RVALUE]) {
|
||||
vdata = nla_data(tb[TCA_EM_META_RVALUE]);
|
||||
vlen = nla_len(tb[TCA_EM_META_RVALUE]);
|
||||
}
|
||||
|
||||
v = meta_alloc(TCF_META_TYPE(hdr->right.kind),
|
||||
TCF_META_ID(hdr->right.kind),
|
||||
hdr->right.shift, vdata, vlen);
|
||||
if (!v) {
|
||||
rtnl_meta_value_put(m->left);
|
||||
return -NLE_NOMEM;
|
||||
}
|
||||
|
||||
m->right = v;
|
||||
m->opnd = hdr->left.op;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct trans_tbl meta_int[] = {
|
||||
__ADD(TCF_META_ID_VLAN_TAG, vlan)
|
||||
__ADD(TCF_META_ID_PKTLEN, pktlen)
|
||||
};
|
||||
|
||||
static char *int_id2str(int id, char *buf, size_t size)
|
||||
{
|
||||
return __type2str(id, buf, size, meta_int, ARRAY_SIZE(meta_int));
|
||||
}
|
||||
|
||||
static struct trans_tbl meta_var[] = {
|
||||
__ADD(TCF_META_ID_DEV,devname)
|
||||
__ADD(TCF_META_ID_SK_BOUND_IF,sk_bound_if)
|
||||
};
|
||||
|
||||
static char *var_id2str(int id, char *buf, size_t size)
|
||||
{
|
||||
return __type2str(id, buf, size, meta_var, ARRAY_SIZE(meta_var));
|
||||
}
|
||||
|
||||
static void dump_value(struct rtnl_meta_value *v, struct nl_dump_params *p)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
switch (v->mv_type) {
|
||||
case TCF_META_TYPE_INT:
|
||||
if (v->mv_id == TCF_META_ID_VALUE) {
|
||||
nl_dump(p, "%u",
|
||||
*(uint32_t *) (v + 1));
|
||||
} else {
|
||||
nl_dump(p, "%s",
|
||||
int_id2str(v->mv_id, buf, sizeof(buf)));
|
||||
|
||||
if (v->mv_shift)
|
||||
nl_dump(p, " >> %u", v->mv_shift);
|
||||
|
||||
if (v->mv_len == 4)
|
||||
nl_dump(p, " & %#x", *(uint32_t *) (v + 1));
|
||||
else if (v->mv_len == 8)
|
||||
nl_dump(p, " & %#x", *(uint64_t *) (v + 1));
|
||||
}
|
||||
break;
|
||||
|
||||
case TCF_META_TYPE_VAR:
|
||||
if (v->mv_id == TCF_META_ID_VALUE) {
|
||||
nl_dump(p, "%s", (char *) (v + 1));
|
||||
} else {
|
||||
nl_dump(p, "%s",
|
||||
var_id2str(v->mv_id, buf, sizeof(buf)));
|
||||
|
||||
if (v->mv_shift)
|
||||
nl_dump(p, " >> %u", v->mv_shift);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void meta_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
char buf[32];
|
||||
|
||||
nl_dump(p, "meta(");
|
||||
dump_value(m->left, p);
|
||||
|
||||
nl_dump(p, " %s ", rtnl_ematch_opnd2txt(m->opnd, buf, sizeof(buf)));
|
||||
|
||||
dump_value(m->right, p);
|
||||
nl_dump(p, ")");
|
||||
}
|
||||
|
||||
static int meta_fill(struct rtnl_ematch *e, struct nl_msg *msg)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
struct tcf_meta_hdr hdr;
|
||||
|
||||
if (!(m->left && m->right))
|
||||
return -NLE_MISSING_ATTR;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.left.kind = (m->left->mv_type << 12) & TCF_META_TYPE_MASK;
|
||||
hdr.left.kind |= m->left->mv_id & TCF_META_ID_MASK;
|
||||
hdr.left.shift = m->left->mv_shift;
|
||||
hdr.left.op = m->opnd;
|
||||
hdr.right.kind = (m->right->mv_type << 12) & TCF_META_TYPE_MASK;
|
||||
hdr.right.kind |= m->right->mv_id & TCF_META_ID_MASK;
|
||||
|
||||
NLA_PUT(msg, TCA_EM_META_HDR, sizeof(hdr), &hdr);
|
||||
|
||||
if (m->left->mv_len)
|
||||
NLA_PUT(msg, TCA_EM_META_LVALUE, m->left->mv_len, (m->left + 1));
|
||||
|
||||
if (m->right->mv_len)
|
||||
NLA_PUT(msg, TCA_EM_META_RVALUE, m->right->mv_len, (m->right + 1));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_NOMEM;
|
||||
}
|
||||
|
||||
static void meta_free(struct rtnl_ematch *e)
|
||||
{
|
||||
struct meta_data *m = rtnl_ematch_data(e);
|
||||
free(m->left);
|
||||
free(m->right);
|
||||
}
|
||||
|
||||
static struct rtnl_ematch_ops meta_ops = {
|
||||
.eo_kind = TCF_EM_META,
|
||||
.eo_name = "meta",
|
||||
.eo_minlen = sizeof(struct tcf_meta_hdr),
|
||||
.eo_datalen = sizeof(struct meta_data),
|
||||
.eo_parse = meta_parse,
|
||||
.eo_dump = meta_dump,
|
||||
.eo_fill = meta_fill,
|
||||
.eo_free = meta_free,
|
||||
};
|
||||
|
||||
static void __init meta_init(void)
|
||||
{
|
||||
rtnl_ematch_register(&meta_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -78,10 +78,14 @@ lt |
|
|||
[cC][mM][pP] { yylval->i = TCF_EM_CMP; return EMATCH_CMP; }
|
||||
[pP][aA][tT][tT][eE][rR][nN] { yylval->i = TCF_EM_NBYTE; return EMATCH_NBYTE; }
|
||||
[tT][eE][xX][tT] { yylval->i = TCF_EM_TEXT; return EMATCH_TEXT; }
|
||||
[mM][eE][tT][aA] { yylval->i = TCF_EM_META; return EMATCH_META; }
|
||||
|
||||
"(" return KW_OPEN;
|
||||
")" return KW_CLOSE;
|
||||
[mM][aA][sS][kK] return KW_MASK;
|
||||
[mM][aA][sS][kK] |
|
||||
"&" return KW_MASK;
|
||||
[sS][hH][iI][fF][tT] |
|
||||
">>" return KW_SHIFT;
|
||||
[aA][tT] return KW_AT;
|
||||
"+" return KW_PLUS;
|
||||
[fF][rR][oO][mM] return KW_FROM;
|
||||
|
@ -99,6 +103,56 @@ lt |
|
|||
[tT][rR][aA][nN][sS][pP][oO][rR][tT] |
|
||||
[tT][cC][pP] { yylval->i = TCF_LAYER_TRANSPORT; return LAYER; }
|
||||
|
||||
random return META_RANDOM;
|
||||
loadavg_0 return META_LOADAVG_0;
|
||||
loadavg_1 return META_LOADAVG_1;
|
||||
loadavg_2 return META_LOADAVG_2;
|
||||
dev return META_DEV;
|
||||
prio return META_PRIO;
|
||||
proto return META_PROTO;
|
||||
pkttype return META_PKTTYPE;
|
||||
pktlen return META_PKTLEN;
|
||||
datalen return META_DATALEN;
|
||||
maclen return META_MACLEN;
|
||||
mark return META_MARK;
|
||||
tcindex return META_TCINDEX;
|
||||
rtclassid return META_RTCLASSID;
|
||||
rtiif return META_RTIIF;
|
||||
sk_family return META_SK_FAMILY;
|
||||
sk_state return META_SK_STATE;
|
||||
sk_reuse return META_SK_REUSE;
|
||||
sk_refcnt return META_SK_REFCNT;
|
||||
sk_rcvbuf return META_SK_RCVBUF;
|
||||
sk_sndbuf return META_SK_SNDBUF;
|
||||
sk_shutdown return META_SK_SHUTDOWN;
|
||||
sk_proto return META_SK_PROTO;
|
||||
sk_type return META_SK_TYPE;
|
||||
sk_rmem_alloc return META_SK_RMEM_ALLOC;
|
||||
sk_wmem_alloc return META_SK_WMEM_ALLOC;
|
||||
sk_wmem_queued return META_SK_WMEM_QUEUED;
|
||||
sk_rcv_qlen return META_SK_RCV_QLEN;
|
||||
sk_snd_qlen return META_SK_SND_QLEN;
|
||||
sk_err_qlen return META_SK_ERR_QLEN;
|
||||
sk_forward_allocs return META_SK_FORWARD_ALLOCS;
|
||||
sk_allocs return META_SK_ALLOCS;
|
||||
sk_route_caps return META_SK_ROUTE_CAPS;
|
||||
sk_hash return META_SK_HASH;
|
||||
sk_lingertime return META_SK_LINGERTIME;
|
||||
sk_ack_backlog return META_SK_ACK_BACKLOG;
|
||||
sk_max_ack_backlog return META_SK_MAX_ACK_BACKLOG;
|
||||
sk_prio return META_SK_PRIO;
|
||||
sk_rcvlowat return META_SK_RCVLOWAT;
|
||||
sk_rcvtimeo return META_SK_RCVTIMEO;
|
||||
sk_sndtimeo return META_SK_SNDTIMEO;
|
||||
sk_sendmsg_off return META_SK_SENDMSG_OFF;
|
||||
sk_write_pending return META_SK_WRITE_PENDING;
|
||||
vlan return META_VLAN;
|
||||
rxhash return META_RXHASH;
|
||||
|
||||
devname return META_DEVNAME;
|
||||
sk_bound_if return META_SK_BOUND_IF;
|
||||
|
||||
|
||||
[^ \t\r\n+()=<>&|\"]+ {
|
||||
yylval->s = strdup(yytext);
|
||||
if (yylval->s == NULL)
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
#include <netlink/route/cls/ematch/cmp.h>
|
||||
#include <netlink/route/cls/ematch/nbyte.h>
|
||||
#include <netlink/route/cls/ematch/text.h>
|
||||
#include <netlink/route/cls/ematch/meta.h>
|
||||
|
||||
#define META_ALLOC rtnl_meta_value_alloc_id
|
||||
#define META_ID(name) TCF_META_ID_##name
|
||||
#define META_INT TCF_META_TYPE_INT
|
||||
#define META_VAR TCF_META_TYPE_VAR
|
||||
%}
|
||||
|
||||
%error-verbose
|
||||
|
@ -35,7 +41,9 @@
|
|||
struct ematch_quoted q;
|
||||
struct rtnl_ematch * e;
|
||||
struct rtnl_pktloc * loc;
|
||||
struct rtnl_meta_value *mv;
|
||||
uint32_t i;
|
||||
uint64_t i64;
|
||||
char * s;
|
||||
}
|
||||
|
||||
|
@ -54,29 +62,82 @@ static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const
|
|||
%token <i> KW_CLOSE ")"
|
||||
%token <i> KW_PLUS "+"
|
||||
%token <i> KW_MASK "mask"
|
||||
%token <i> KW_SHIFT ">>"
|
||||
%token <i> KW_AT "at"
|
||||
%token <i> EMATCH_CMP "cmp"
|
||||
%token <i> EMATCH_NBYTE "pattern"
|
||||
%token <i> EMATCH_TEXT "text"
|
||||
%token <i> EMATCH_META "meta"
|
||||
%token <i> KW_EQ "="
|
||||
%token <i> KW_GT ">"
|
||||
%token <i> KW_LT "<"
|
||||
%token <i> KW_FROM "from"
|
||||
%token <i> KW_TO "to"
|
||||
|
||||
%token <i> META_RANDOM "random"
|
||||
%token <i> META_LOADAVG_0 "loadavg_0"
|
||||
%token <i> META_LOADAVG_1 "loadavg_1"
|
||||
%token <i> META_LOADAVG_2 "loadavg_2"
|
||||
%token <i> META_DEV "dev"
|
||||
%token <i> META_PRIO "prio"
|
||||
%token <i> META_PROTO "proto"
|
||||
%token <i> META_PKTTYPE "pkttype"
|
||||
%token <i> META_PKTLEN "pktlen"
|
||||
%token <i> META_DATALEN "datalen"
|
||||
%token <i> META_MACLEN "maclen"
|
||||
%token <i> META_MARK "mark"
|
||||
%token <i> META_TCINDEX "tcindex"
|
||||
%token <i> META_RTCLASSID "rtclassid"
|
||||
%token <i> META_RTIIF "rtiif"
|
||||
%token <i> META_SK_FAMILY "sk_family"
|
||||
%token <i> META_SK_STATE "sk_state"
|
||||
%token <i> META_SK_REUSE "sk_reuse"
|
||||
%token <i> META_SK_REFCNT "sk_refcnt"
|
||||
%token <i> META_SK_RCVBUF "sk_rcvbuf"
|
||||
%token <i> META_SK_SNDBUF "sk_sndbuf"
|
||||
%token <i> META_SK_SHUTDOWN "sk_shutdown"
|
||||
%token <i> META_SK_PROTO "sk_proto"
|
||||
%token <i> META_SK_TYPE "sk_type"
|
||||
%token <i> META_SK_RMEM_ALLOC "sk_rmem_alloc"
|
||||
%token <i> META_SK_WMEM_ALLOC "sk_wmem_alloc"
|
||||
%token <i> META_SK_WMEM_QUEUED "sk_wmem_queued"
|
||||
%token <i> META_SK_RCV_QLEN "sk_rcv_qlen"
|
||||
%token <i> META_SK_SND_QLEN "sk_snd_qlen"
|
||||
%token <i> META_SK_ERR_QLEN "sk_err_qlen"
|
||||
%token <i> META_SK_FORWARD_ALLOCS "sk_forward_allocs"
|
||||
%token <i> META_SK_ALLOCS "sk_allocs"
|
||||
%token <i> META_SK_ROUTE_CAPS "sk_route_caps"
|
||||
%token <i> META_SK_HASH "sk_hash"
|
||||
%token <i> META_SK_LINGERTIME "sk_lingertime"
|
||||
%token <i> META_SK_ACK_BACKLOG "sk_ack_backlog"
|
||||
%token <i> META_SK_MAX_ACK_BACKLOG "sk_max_ack_backlog"
|
||||
%token <i> META_SK_PRIO "sk_prio"
|
||||
%token <i> META_SK_RCVLOWAT "sk_rcvlowat"
|
||||
%token <i> META_SK_RCVTIMEO "sk_rcvtimeo"
|
||||
%token <i> META_SK_SNDTIMEO "sk_sndtimeo"
|
||||
%token <i> META_SK_SENDMSG_OFF "sk_sendmsg_off"
|
||||
%token <i> META_SK_WRITE_PENDING "sk_write_pending"
|
||||
%token <i> META_VLAN "vlan"
|
||||
%token <i> META_RXHASH "rxhash"
|
||||
%token <i> META_DEVNAME "devname"
|
||||
%token <i> META_SK_BOUND_IF "sk_bound_if"
|
||||
|
||||
%token <s> STR
|
||||
|
||||
%token <q> QUOTED
|
||||
|
||||
%type <i> mask align operand
|
||||
%type <i> align operand shift meta_int_id meta_var_id
|
||||
%type <i64> mask
|
||||
%type <e> expr match ematch
|
||||
%type <cmp> cmp_expr cmp_match
|
||||
%type <loc> pktloc text_from text_to
|
||||
%type <q> pattern
|
||||
%type <mv> meta_value
|
||||
|
||||
%destructor { free($$); NL_DBG(2, "string destructor\n"); } <s>
|
||||
%destructor { rtnl_pktloc_put($$); NL_DBG(2, "pktloc destructor\n"); } <loc>
|
||||
%destructor { free($$.data); NL_DBG(2, "quoted destructor\n"); } <q>
|
||||
%destructor { rtnl_meta_value_put($$); NL_DBG(2, "meta value destructor\n"); } <mv>
|
||||
|
||||
%start input
|
||||
|
||||
|
@ -178,6 +239,24 @@ ematch:
|
|||
rtnl_pktloc_put($6);
|
||||
}
|
||||
|
||||
$$ = e;
|
||||
}
|
||||
| EMATCH_META "(" meta_value operand meta_value ")"
|
||||
{
|
||||
struct rtnl_ematch *e;
|
||||
|
||||
if (!(e = rtnl_ematch_alloc())) {
|
||||
asprintf(errp, "Unable to allocate ematch object");
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
if (rtnl_ematch_set_kind(e, TCF_EM_META) < 0)
|
||||
BUG();
|
||||
|
||||
rtnl_ematch_meta_set_lvalue(e, $3);
|
||||
rtnl_ematch_meta_set_rvalue(e, $5);
|
||||
rtnl_ematch_meta_set_operand(e, $4);
|
||||
|
||||
$$ = e;
|
||||
}
|
||||
/* CONTAINER */
|
||||
|
@ -249,6 +328,70 @@ text_to:
|
|||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
meta_value:
|
||||
QUOTED
|
||||
{ $$ = rtnl_meta_value_alloc_var($1.data, $1.len); }
|
||||
| NUMBER
|
||||
{ $$ = rtnl_meta_value_alloc_int($1); }
|
||||
| meta_int_id shift mask
|
||||
{ $$ = META_ALLOC(META_INT, $1, $2, $3); }
|
||||
| meta_var_id shift
|
||||
{ $$ = META_ALLOC(META_VAR, $1, $2, 0); }
|
||||
;
|
||||
|
||||
meta_int_id:
|
||||
META_RANDOM { $$ = META_ID(RANDOM); }
|
||||
|META_LOADAVG_0 { $$ = META_ID(LOADAVG_0); }
|
||||
|META_LOADAVG_1 { $$ = META_ID(LOADAVG_1); }
|
||||
|META_LOADAVG_2 { $$ = META_ID(LOADAVG_2); }
|
||||
| META_DEV { $$ = META_ID(DEV); }
|
||||
| META_PRIO { $$ = META_ID(PRIORITY); }
|
||||
| META_PROTO { $$ = META_ID(PROTOCOL); }
|
||||
| META_PKTTYPE { $$ = META_ID(PKTTYPE); }
|
||||
| META_PKTLEN { $$ = META_ID(PKTLEN); }
|
||||
| META_DATALEN { $$ = META_ID(DATALEN); }
|
||||
| META_MACLEN { $$ = META_ID(MACLEN); }
|
||||
| META_MARK { $$ = META_ID(NFMARK); }
|
||||
| META_TCINDEX { $$ = META_ID(TCINDEX); }
|
||||
| META_RTCLASSID { $$ = META_ID(RTCLASSID); }
|
||||
| META_RTIIF { $$ = META_ID(RTIIF); }
|
||||
| META_SK_FAMILY { $$ = META_ID(SK_FAMILY); }
|
||||
| META_SK_STATE { $$ = META_ID(SK_STATE); }
|
||||
| META_SK_REUSE { $$ = META_ID(SK_REUSE); }
|
||||
| META_SK_REFCNT { $$ = META_ID(SK_REFCNT); }
|
||||
| META_SK_RCVBUF { $$ = META_ID(SK_RCVBUF); }
|
||||
| META_SK_SNDBUF { $$ = META_ID(SK_SNDBUF); }
|
||||
| META_SK_SHUTDOWN { $$ = META_ID(SK_SHUTDOWN); }
|
||||
| META_SK_PROTO { $$ = META_ID(SK_PROTO); }
|
||||
| META_SK_TYPE { $$ = META_ID(SK_TYPE); }
|
||||
| META_SK_RMEM_ALLOC { $$ = META_ID(SK_RMEM_ALLOC); }
|
||||
| META_SK_WMEM_ALLOC { $$ = META_ID(SK_WMEM_ALLOC); }
|
||||
| META_SK_WMEM_QUEUED { $$ = META_ID(SK_WMEM_QUEUED); }
|
||||
| META_SK_RCV_QLEN { $$ = META_ID(SK_RCV_QLEN); }
|
||||
| META_SK_SND_QLEN { $$ = META_ID(SK_SND_QLEN); }
|
||||
| META_SK_ERR_QLEN { $$ = META_ID(SK_ERR_QLEN); }
|
||||
| META_SK_FORWARD_ALLOCS { $$ = META_ID(SK_FORWARD_ALLOCS); }
|
||||
| META_SK_ALLOCS { $$ = META_ID(SK_ALLOCS); }
|
||||
| META_SK_ROUTE_CAPS { $$ = META_ID(SK_ROUTE_CAPS); }
|
||||
| META_SK_HASH { $$ = META_ID(SK_HASH); }
|
||||
| META_SK_LINGERTIME { $$ = META_ID(SK_LINGERTIME); }
|
||||
| META_SK_ACK_BACKLOG { $$ = META_ID(SK_ACK_BACKLOG); }
|
||||
| META_SK_MAX_ACK_BACKLOG { $$ = META_ID(SK_MAX_ACK_BACKLOG); }
|
||||
| META_SK_PRIO { $$ = META_ID(SK_PRIO); }
|
||||
| META_SK_RCVLOWAT { $$ = META_ID(SK_RCVLOWAT); }
|
||||
| META_SK_RCVTIMEO { $$ = META_ID(SK_RCVTIMEO); }
|
||||
| META_SK_SNDTIMEO { $$ = META_ID(SK_SNDTIMEO); }
|
||||
| META_SK_SENDMSG_OFF { $$ = META_ID(SK_SENDMSG_OFF); }
|
||||
| META_SK_WRITE_PENDING { $$ = META_ID(SK_WRITE_PENDING); }
|
||||
| META_VLAN { $$ = META_ID(VLAN_TAG); }
|
||||
| META_RXHASH { $$ = META_ID(RXHASH); }
|
||||
;
|
||||
|
||||
meta_var_id:
|
||||
META_DEVNAME { $$ = META_ID(DEV); }
|
||||
| META_SK_BOUND_IF { $$ = META_ID(SK_BOUND_IF); }
|
||||
;
|
||||
|
||||
/*
|
||||
* pattern
|
||||
*/
|
||||
|
@ -333,7 +476,14 @@ align:
|
|||
mask:
|
||||
/* empty */
|
||||
{ $$ = 0; }
|
||||
| "mask" NUMBER
|
||||
| KW_MASK NUMBER
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
shift:
|
||||
/* empty */
|
||||
{ $$ = 0; }
|
||||
| KW_SHIFT NUMBER
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue