summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2014-01-16 17:22:56 +0000
committerPatrick McHardy <kaber@trash.net>2014-01-16 17:22:56 +0000
commit3b457d49854503807fa019d9c44a9daf6c79dba0 (patch)
tree8c1b1e7a2443ac6cb1f1a4a561bf717cc1dd1246
parentd357cdd882cc0cf6afb15686834f5d9d6efab57f (diff)
parent86b965bdab8dc8735c4a846ec09bfbbadfae780b (diff)
Merge remote-tracking branch 'origin/master' into next-3.14
Signed-off-by: Patrick McHardy <kaber@trash.net> Conflicts: src/payload.c
-rw-r--r--include/datatype.h7
-rw-r--r--src/datatype.c3
-rw-r--r--src/expression.c6
-rw-r--r--src/meta.c1
-rw-r--r--src/parser.y29
-rw-r--r--src/proto.c2
-rw-r--r--src/segtree.c43
7 files changed, 79 insertions, 12 deletions
diff --git a/include/datatype.h b/include/datatype.h
index 9f8b44ae..9e609cf2 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -85,8 +85,15 @@ enum byteorder {
struct expr;
+/**
+ * enum datatype_flags
+ *
+ * @DTYPE_F_ALLOC: datatype is dynamically allocated
+ * @DTYPE_F_PREFIX: preferred representation for ranges is a prefix
+ */
enum datatype_flags {
DTYPE_F_ALLOC = (1 << 0),
+ DTYPE_F_PREFIX = (1 << 1),
};
/**
diff --git a/src/datatype.c b/src/datatype.c
index e228f530..5e4aacdf 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -398,6 +398,7 @@ const struct datatype ipaddr_type = {
.basetype = &integer_type,
.print = ipaddr_type_print,
.parse = ipaddr_type_parse,
+ .flags = DTYPE_F_PREFIX,
};
static void ip6addr_type_print(const struct expr *expr)
@@ -455,6 +456,7 @@ const struct datatype ip6addr_type = {
.basetype = &integer_type,
.print = ip6addr_type_print,
.parse = ip6addr_type_parse,
+ .flags = DTYPE_F_PREFIX,
};
static void inet_protocol_type_print(const struct expr *expr)
@@ -680,6 +682,7 @@ const struct datatype mark_type = {
.basefmt = "0x%.8Zx",
.print = mark_type_print,
.parse = mark_type_parse,
+ .flags = DTYPE_F_PREFIX,
};
static void time_type_print(const struct expr *expr)
diff --git a/src/expression.c b/src/expression.c
index 518f71c8..a12133c8 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -691,7 +691,11 @@ struct expr *mapping_expr_alloc(const struct location *loc,
static void map_expr_print(const struct expr *expr)
{
expr_print(expr->map);
- printf(" map ");
+ if (expr->mappings->ops->type == EXPR_SET_REF &&
+ expr->mappings->set->datatype->type == TYPE_VERDICT)
+ printf(" vmap ");
+ else
+ printf(" map ");
expr_print(expr->mappings);
}
diff --git a/src/meta.c b/src/meta.c
index 098728bb..0a3df39f 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -61,6 +61,7 @@ static const struct datatype realm_type = {
.basetype = &integer_type,
.print = realm_type_print,
.parse = realm_type_parse,
+ .flags = DTYPE_F_PREFIX,
};
static void tchandle_type_print(const struct expr *expr)
diff --git a/src/parser.y b/src/parser.y
index 89d6279c..05fe8bcb 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <inttypes.h>
#include <netinet/ip.h>
+#include <netinet/if_ether.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
@@ -1482,6 +1483,13 @@ vlan_hdr_expr : VLAN vlan_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_vlan, $2);
}
+ | VLAN
+ {
+ uint16_t data = ETH_P_8021Q;
+ $$ = constant_expr_alloc(&@$, &ethertype_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
;
vlan_hdr_field : ID { $$ = VLANHDR_VID; }
@@ -1494,6 +1502,13 @@ arp_hdr_expr : ARP arp_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_arp, $2);
}
+ | ARP
+ {
+ uint16_t data = ETH_P_ARP;
+ $$ = constant_expr_alloc(&@$, &ethertype_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
;
arp_hdr_field : HTYPE { $$ = ARPHDR_HRD; }
@@ -1507,6 +1522,13 @@ ip_hdr_expr : IP ip_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_ip, $2);
}
+ | IP
+ {
+ uint16_t data = ETH_P_IP;
+ $$ = constant_expr_alloc(&@$, &ethertype_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
;
ip_hdr_field : VERSION { $$ = IPHDR_VERSION; }
@@ -1548,6 +1570,13 @@ ip6_hdr_expr : IP6 ip6_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_ip6, $2);
}
+ | IP6
+ {
+ uint16_t data = ETH_P_IPV6;
+ $$ = constant_expr_alloc(&@$, &ethertype_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
;
ip6_hdr_field : VERSION { $$ = IP6HDR_VERSION; }
diff --git a/src/proto.c b/src/proto.c
index 4d4925b0..cc073af0 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -743,7 +743,7 @@ static const struct symbol_table ethertype_tbl = {
.symbols = {
SYMBOL("ip", ETH_P_IP),
SYMBOL("arp", ETH_P_ARP),
- SYMBOL("ipv6", ETH_P_IPV6),
+ SYMBOL("ip6", ETH_P_IPV6),
SYMBOL("vlan", ETH_P_8021Q),
SYMBOL_LIST_END
},
diff --git a/src/segtree.c b/src/segtree.c
index 5426e24f..1a21c6c1 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -509,10 +509,11 @@ static struct expr *expr_value(struct expr *expr)
void interval_map_decompose(struct expr *set)
{
- struct expr *ranges[set->size];
- struct expr *i, *next, *low = NULL;
+ struct expr *ranges[set->size * 2];
+ struct expr *i, *next, *low = NULL, *end;
unsigned int n, size;
mpz_t range, p;
+ bool interval;
mpz_init(range);
mpz_init(p);
@@ -520,8 +521,20 @@ void interval_map_decompose(struct expr *set)
size = set->size;
n = 0;
+ interval = false;
list_for_each_entry_safe_reverse(i, next, &set->expressions, list) {
compound_expr_remove(set, i);
+
+ if (i->flags & EXPR_F_INTERVAL_END)
+ interval = false;
+ else if (interval) {
+ end = expr_clone(expr_value(i));
+ end->flags |= EXPR_F_INTERVAL_END;
+ ranges[n++] = end;
+ size++;
+ } else
+ interval = true;
+
ranges[n++] = i;
}
@@ -552,7 +565,9 @@ void interval_map_decompose(struct expr *set)
if (!mpz_cmp_ui(range, 0))
compound_expr_add(set, low);
- else if (!range_is_prefix(range) || mpz_cmp_ui(p, 0)) {
+ else if ((!range_is_prefix(range) ||
+ !(i->dtype->flags & DTYPE_F_PREFIX)) ||
+ mpz_cmp_ui(p, 0)) {
struct expr *tmp;
tmp = constant_expr_alloc(&low->location, low->dtype,
@@ -567,8 +582,6 @@ void interval_map_decompose(struct expr *set)
tmp = mapping_expr_alloc(&tmp->location, tmp, low->right);
compound_expr_add(set, tmp);
-
- low = expr_get(tmp->right);
} else {
struct expr *prefix;
unsigned int prefix_len;
@@ -576,13 +589,9 @@ void interval_map_decompose(struct expr *set)
prefix_len = expr_value(i)->len - mpz_scan0(range, 0);
prefix = prefix_expr_alloc(&low->location, expr_value(low),
prefix_len);
-
- if (low->ops->type == EXPR_MAPPING) {
+ if (low->ops->type == EXPR_MAPPING)
prefix = mapping_expr_alloc(&low->location, prefix,
low->right);
- /* Update mapping of "low" to the current mapping */
- low->right = expr_get(i->right);
- }
compound_expr_add(set, prefix);
}
@@ -593,4 +602,18 @@ void interval_map_decompose(struct expr *set)
}
expr_free(i);
}
+
+ /* Unclosed interval */
+ if (low != NULL) {
+ i = constant_expr_alloc(&low->location, low->dtype,
+ low->byteorder, expr_value(low)->len,
+ NULL);
+ mpz_init_bitmask(i->value, i->len);
+
+ i = range_expr_alloc(&low->location, expr_value(low), i);
+ if (low->ops->type == EXPR_MAPPING)
+ i = mapping_expr_alloc(&i->location, i, low->right);
+
+ compound_expr_add(set, i);
+ }
}