dect
/
libnl
Archived
13
0
Fork 0

Support for meta match

Syntax:
	meta(pktlen > 768)
This commit is contained in:
Thomas Graf 2010-10-31 23:13:01 +01:00
parent c7a673787b
commit 7903d6ab4b
8 changed files with 644 additions and 3 deletions

View 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

View File

@ -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
}

View 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

View File

@ -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 \
\

View File

@ -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
View 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);
}
/** @} */

View File

@ -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)

View File

@ -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; }
;