Signed-off-by: Joe Stringer <[email protected]>
---
v2: Uses only OXM_OF_METADATA
I've added to flow_extract() so it sets the metadata field in the rule.
ofproto-dpif.c, handle_miss_upcalls() - Question. I've made this function set
the metadata based on the miss structure, is this sufficient? Do I need to
change anything about how the miss structure interacts with the new metadata
field?
Also in ofproto-dpif.c, in ofproto_unixctl_trace() I've added an extra argument
to specify the metadata, is there some corresponding documentation that I
should change along with this?
---
lib/classifier.c | 30 ++++++++++++++++++++++++-
lib/classifier.h | 3 ++
lib/dpif-linux.c | 2 +-
lib/dpif-netdev.c | 4 +-
lib/flow.c | 40 +++++++++++++++++++++++-----------
lib/flow.h | 17 +++++++++-----
lib/learn.c | 2 +-
lib/learning-switch.c | 2 +-
lib/meta-flow.c | 30 +++++++++++++++++++++++++
lib/meta-flow.h | 1 +
lib/nx-match.c | 5 +++-
lib/nx-match.h | 5 ++-
lib/ofp-print.c | 2 +-
lib/ofp-util.c | 18 +++++++++------
ofproto/ofproto-dpif.c | 15 +++++++-----
ofproto/ofproto.c | 4 +-
tests/ofp-print.at | 4 +-
tests/ofproto-dpif.at | 56 ++++++++++++++++++++++++------------------------
tests/ofproto.at | 10 ++++----
tests/ovs-ofctl.at | 36 ++++++++++++++++++++++++++++--
tests/test-flows.c | 2 +-
21 files changed, 204 insertions(+), 84 deletions(-)
diff --git a/lib/classifier.c b/lib/classifier.c
index d19840c..0541b5c 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -119,6 +119,20 @@ cls_rule_set_reg_masked(struct cls_rule *rule, unsigned
int reg_idx,
}
void
+cls_rule_set_metadata(struct cls_rule *rule, ovs_be64 metadata)
+{
+ cls_rule_set_metadata_masked(rule, metadata, htonll(UINT64_MAX));
+}
+
+void
+cls_rule_set_metadata_masked(struct cls_rule *rule, ovs_be64 metadata,
+ ovs_be64 mask)
+{
+ rule->wc.metadata_mask = mask;
+ rule->flow.metadata = metadata & mask;
+}
+
+void
cls_rule_set_tun_id(struct cls_rule *rule, ovs_be64 tun_id)
{
cls_rule_set_tun_id_masked(rule, tun_id, htonll(UINT64_MAX));
@@ -525,7 +539,7 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
if (rule->priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%d,", rule->priority);
@@ -595,6 +609,17 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
ntohll(f->tun_id), ntohll(wc->tun_id_mask));
break;
}
+ switch (wc->metadata_mask) {
+ case 0:
+ break;
+ case CONSTANT_HTONLL(UINT64_MAX):
+ ds_put_format(s, "metadata=%#"PRIx64",", ntohll(f->metadata));
+ break;
+ default:
+ ds_put_format(s, "metadata=%#"PRIx64"/%#"PRIx64",",
+ ntohll(f->metadata), ntohll(wc->metadata_mask));
+ break;
+ }
if (!(w & FWW_IN_PORT)) {
ds_put_format(s, "in_port=%"PRIu16",", f->in_port);
}
@@ -1188,7 +1213,7 @@ flow_equal_except(const struct flow *a, const struct flow
*b,
const flow_wildcards_t wc = wildcards->wildcards;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
@@ -1197,6 +1222,7 @@ flow_equal_except(const struct flow *a, const struct flow
*b,
}
return (!((a->tun_id ^ b->tun_id) & wildcards->tun_id_mask)
+ && !((a->metadata ^ b->metadata) & wildcards->metadata_mask)
&& !((a->nw_src ^ b->nw_src) & wildcards->nw_src_mask)
&& !((a->nw_dst ^ b->nw_dst) & wildcards->nw_dst_mask)
&& (wc & FWW_IN_PORT || a->in_port == b->in_port)
diff --git a/lib/classifier.h b/lib/classifier.h
index 9e4b33e..ec7316c 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -90,6 +90,9 @@ void cls_rule_zero_wildcarded_fields(struct cls_rule *);
void cls_rule_set_reg(struct cls_rule *, unsigned int reg_idx, uint32_t value);
void cls_rule_set_reg_masked(struct cls_rule *, unsigned int reg_idx,
uint32_t value, uint32_t mask);
+void cls_rule_set_metadata(struct cls_rule *, ovs_be64 metadata);
+void cls_rule_set_metadata_masked(struct cls_rule *, ovs_be64 metadata,
+ ovs_be64 mask);
void cls_rule_set_tun_id(struct cls_rule *, ovs_be64 tun_id);
void cls_rule_set_tun_id_masked(struct cls_rule *,
ovs_be64 tun_id, ovs_be64 mask);
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 62f6917..ee4da19 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -1378,7 +1378,7 @@ dpif_linux_vport_send(int dp_ifindex, uint32_t port_no,
uint64_t action;
ofpbuf_use_const(&packet, data, size);
- flow_extract(&packet, 0, htonll(0), 0, &flow);
+ flow_extract(&packet, 0, htonll(0), htonll(0), 0, &flow);
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &flow);
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index cade79e..a0c26e1 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -904,7 +904,7 @@ dpif_netdev_execute(struct dpif *dpif, const struct
dpif_execute *execute)
ofpbuf_reserve(©, DP_NETDEV_HEADROOM);
ofpbuf_put(©, execute->packet->data, execute->packet->size);
- flow_extract(©, 0, 0, -1, &key);
+ flow_extract(©, 0, 0, 0, -1, &key);
error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
&key);
if (!error) {
@@ -1002,7 +1002,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct
dp_netdev_port *port,
if (packet->size < ETH_HEADER_LEN) {
return;
}
- flow_extract(packet, 0, 0, port->port_no, &key);
+ flow_extract(packet, 0, 0, 0, port->port_no, &key);
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
dp_netdev_flow_used(flow, &key, packet);
diff --git a/lib/flow.c b/lib/flow.c
index 46e0e2d..ee0a87e 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -312,8 +312,8 @@ invalid:
}
-/* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
- * 'ofp_in_port'.
+/* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id',
+ * 'metadata' and 'ofp_in_port'.
*
* Initializes 'packet' header pointers as follows:
*
@@ -331,7 +331,7 @@ invalid:
*/
void
flow_extract(struct ofpbuf *packet, uint32_t skb_priority, ovs_be64 tun_id,
- uint16_t ofp_in_port, struct flow *flow)
+ ovs_be64 metadata, uint16_t ofp_in_port, struct flow *flow)
{
struct ofpbuf b = *packet;
struct eth_header *eth;
@@ -340,6 +340,7 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority,
ovs_be64 tun_id,
memset(flow, 0, sizeof *flow);
flow->tun_id = tun_id;
+ flow->metadata = metadata;
flow->in_port = ofp_in_port;
flow->skb_priority = skb_priority;
@@ -444,12 +445,13 @@ flow_zero_wildcards(struct flow *flow, const struct
flow_wildcards *wildcards)
const flow_wildcards_t wc = wildcards->wildcards;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
for (i = 0; i < FLOW_N_REGS; i++) {
flow->regs[i] &= wildcards->reg_masks[i];
}
flow->tun_id &= wildcards->tun_id_mask;
+ flow->metadata &= wildcards->metadata_mask;
flow->nw_src &= wildcards->nw_src_mask;
flow->nw_dst &= wildcards->nw_dst_mask;
if (wc & FWW_IN_PORT) {
@@ -498,11 +500,14 @@ flow_zero_wildcards(struct flow *flow, const struct
flow_wildcards *wildcards)
void
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
fmd->tun_id = flow->tun_id;
fmd->tun_id_mask = htonll(UINT64_MAX);
+ fmd->metadata = flow->metadata;
+ fmd->metadata_mask = htonll(UINT64_MAX);
+
memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
memset(fmd->reg_masks, 0xff, sizeof fmd->reg_masks);
@@ -522,9 +527,11 @@ flow_format(struct ds *ds, const struct flow *flow)
{
ds_put_format(ds, "priority:%"PRIu32
",tunnel:%#"PRIx64
+ ",metadata:%#"PRIx64
",in_port:%04"PRIx16,
flow->skb_priority,
ntohll(flow->tun_id),
+ ntohll(flow->metadata),
flow->in_port);
ds_put_format(ds, ",tci(");
@@ -587,7 +594,7 @@ flow_print(FILE *stream, const struct flow *flow)
void
flow_wildcards_init_catchall(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
wc->wildcards = FWW_ALL;
wc->tun_id_mask = htonll(0);
@@ -597,6 +604,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
wc->ipv6_dst_mask = in6addr_any;
wc->nd_target_mask = in6addr_any;
memset(wc->reg_masks, 0, sizeof wc->reg_masks);
+ wc->metadata_mask = htonll(0);
wc->vlan_tci_mask = htons(0);
wc->nw_frag_mask = 0;
wc->tp_src_mask = htons(0);
@@ -611,7 +619,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
void
flow_wildcards_init_exact(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
wc->wildcards = 0;
wc->tun_id_mask = htonll(UINT64_MAX);
@@ -621,6 +629,7 @@ flow_wildcards_init_exact(struct flow_wildcards *wc)
wc->ipv6_dst_mask = in6addr_exact;
wc->nd_target_mask = in6addr_exact;
memset(wc->reg_masks, 0xff, sizeof wc->reg_masks);
+ wc->metadata_mask = htonll(UINT64_MAX);
wc->vlan_tci_mask = htons(UINT16_MAX);
wc->nw_frag_mask = UINT8_MAX;
wc->tp_src_mask = htons(UINT16_MAX);
@@ -637,7 +646,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
if (wc->wildcards
|| wc->tun_id_mask != htonll(UINT64_MAX)
@@ -646,6 +655,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
|| wc->tp_src_mask != htons(UINT16_MAX)
|| wc->tp_dst_mask != htons(UINT16_MAX)
|| wc->vlan_tci_mask != htons(UINT16_MAX)
+ || wc->metadata_mask != htonll(UINT64_MAX)
|| !eth_mask_is_exact(wc->dl_src_mask)
|| !eth_mask_is_exact(wc->dl_dst_mask)
|| !ipv6_mask_is_exact(&wc->ipv6_src_mask)
@@ -671,7 +681,7 @@ flow_wildcards_is_catchall(const struct flow_wildcards *wc)
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
if (wc->wildcards != FWW_ALL
|| wc->tun_id_mask != htonll(0)
@@ -680,6 +690,7 @@ flow_wildcards_is_catchall(const struct flow_wildcards *wc)
|| wc->tp_src_mask != htons(0)
|| wc->tp_dst_mask != htons(0)
|| wc->vlan_tci_mask != htons(0)
+ || wc->metadata_mask != htonll(0)
|| !eth_addr_is_zero(wc->dl_src_mask)
|| !eth_addr_is_zero(wc->dl_dst_mask)
|| !ipv6_mask_is_any(&wc->ipv6_src_mask)
@@ -708,7 +719,7 @@ flow_wildcards_combine(struct flow_wildcards *dst,
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
dst->wildcards = src1->wildcards | src2->wildcards;
dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask;
@@ -723,6 +734,7 @@ flow_wildcards_combine(struct flow_wildcards *dst,
for (i = 0; i < FLOW_N_REGS; i++) {
dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i];
}
+ dst->metadata_mask = src1->metadata_mask & src2->metadata_mask;
dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask;
dst->tp_src_mask = src1->tp_src_mask & src2->tp_src_mask;
dst->tp_dst_mask = src1->tp_dst_mask & src2->tp_dst_mask;
@@ -737,7 +749,7 @@ flow_wildcards_hash(const struct flow_wildcards *wc,
uint32_t basis)
/* If you change struct flow_wildcards and thereby trigger this
* assertion, please check that the new struct flow_wildcards has no holes
* in it before you update the assertion. */
- BUILD_ASSERT_DECL(sizeof *wc == 88 + FLOW_N_REGS * 4);
+ BUILD_ASSERT_DECL(sizeof *wc == 96 + FLOW_N_REGS * 4);
return hash_bytes(wc, sizeof *wc, basis);
}
@@ -749,13 +761,14 @@ flow_wildcards_equal(const struct flow_wildcards *a,
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
if (a->wildcards != b->wildcards
|| a->tun_id_mask != b->tun_id_mask
|| a->nw_src_mask != b->nw_src_mask
|| a->nw_dst_mask != b->nw_dst_mask
|| a->vlan_tci_mask != b->vlan_tci_mask
+ || a->metadata_mask != b->metadata_mask
|| !ipv6_addr_equals(&a->ipv6_src_mask, &b->ipv6_src_mask)
|| !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)
|| !ipv6_addr_equals(&a->nd_target_mask, &b->nd_target_mask)
@@ -785,7 +798,7 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
uint8_t eth_masked[ETH_ADDR_LEN];
struct in6_addr ipv6_masked;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) {
@@ -823,6 +836,7 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
|| (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask
|| (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask
|| (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask
+ || (a->metadata_mask & b->metadata_mask) != b->metadata_mask
|| (a->tp_src_mask & b->tp_src_mask) != b->tp_src_mask
|| (a->tp_dst_mask & b->tp_dst_mask) != b->tp_dst_mask);
}
diff --git a/lib/flow.h b/lib/flow.h
index 2958ff5..7fd4553 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -34,7 +34,7 @@ struct ofpbuf;
/* This sequence number should be incremented whenever anything involving flows
* or the wildcarding of flows changes. This will cause build assertion
* failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 11
+#define FLOW_WC_SEQ 12
#define FLOW_N_REGS 8
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
@@ -53,6 +53,7 @@ BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER);
struct flow {
ovs_be64 tun_id; /* Encapsulating tunnel ID. */
+ ovs_be64 metadata; /* OpenFlow Metadata. */
struct in6_addr ipv6_src; /* IPv6 source address. */
struct in6_addr ipv6_dst; /* IPv6 destination address. */
struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */
@@ -84,6 +85,9 @@ struct flow_metadata {
ovs_be64 tun_id; /* Encapsulating tunnel ID. */
ovs_be64 tun_id_mask; /* 1-bit in each significant tun_id bit.*/
+ ovs_be64 metadata; /* OpenFlow 1.1+ Metadata field. */
+ ovs_be64 metadata_mask; /* 1-bit in each significant tun_id bit.*/
+
uint32_t regs[FLOW_N_REGS]; /* Registers. */
uint32_t reg_masks[FLOW_N_REGS]; /* 1-bit in each significant regs bit. */
@@ -92,17 +96,17 @@ struct flow_metadata {
/* Assert that there are FLOW_SIG_SIZE bytes of significant data in "struct
* flow", followed by FLOW_PAD_SIZE bytes of padding. */
-#define FLOW_SIG_SIZE (110 + FLOW_N_REGS * 4)
+#define FLOW_SIG_SIZE (118 + FLOW_N_REGS * 4)
#define FLOW_PAD_SIZE 2
BUILD_ASSERT_DECL(offsetof(struct flow, nw_frag) == FLOW_SIG_SIZE - 1);
BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nw_frag) == 1);
BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
-BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 142 && FLOW_WC_SEQ == 11);
+BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 150 && FLOW_WC_SEQ == 12);
void flow_extract(struct ofpbuf *, uint32_t priority, ovs_be64 tun_id,
- uint16_t in_port, struct flow *);
+ ovs_be64 metadata, uint16_t in_port, struct flow *);
void flow_zero_wildcards(struct flow *, const struct flow_wildcards *);
void flow_get_metadata(const struct flow *, struct flow_metadata *);
@@ -158,7 +162,7 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t;
#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 9)) - 1))
/* Remember to update FLOW_WC_SEQ when adding or removing FWW_*. */
-BUILD_ASSERT_DECL(FWW_ALL == ((1 << 9) - 1) && FLOW_WC_SEQ == 11);
+BUILD_ASSERT_DECL(FWW_ALL == ((1 << 9) - 1) && FLOW_WC_SEQ == 12);
/* Information on wildcards for a flow, as a supplement to "struct flow".
*
@@ -166,6 +170,7 @@ BUILD_ASSERT_DECL(FWW_ALL == ((1 << 9) - 1) && FLOW_WC_SEQ
== 11);
* the rest of the members. */
struct flow_wildcards {
ovs_be64 tun_id_mask; /* 1-bit in each significant tun_id bit. */
+ ovs_be64 metadata_mask; /* 1-bit in each significant metadata bit. */
flow_wildcards_t wildcards; /* 1-bit in each FWW_* wildcarded field. */
uint32_t reg_masks[FLOW_N_REGS]; /* 1-bit in each significant regs bit. */
ovs_be32 nw_src_mask; /* 1-bit in each significant nw_src bit. */
@@ -184,7 +189,7 @@ struct flow_wildcards {
};
/* Remember to update FLOW_WC_SEQ when updating struct flow_wildcards. */
-BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 120 && FLOW_WC_SEQ == 11);
+BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 128 && FLOW_WC_SEQ == 12);
void flow_wildcards_init_catchall(struct flow_wildcards *);
void flow_wildcards_init_exact(struct flow_wildcards *);
diff --git a/lib/learn.c b/lib/learn.c
index cbecb10..5478b74 100644
--- a/lib/learn.c
+++ b/lib/learn.c
@@ -184,7 +184,7 @@ learn_check(const struct nx_action_learn *learn, const
struct flow *flow)
* prerequisites. No prerequisite depends on the value of
* a field that is wider than 64 bits. So just skip
* setting it entirely. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
}
}
}
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 6b74f82..bba663b 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -465,7 +465,7 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn,
pkt_ofs = offsetof(struct ofp_packet_in, data);
pkt_len = ntohs(opi->header.length) - pkt_ofs;
ofpbuf_use_const(&pkt, opi->data, pkt_len);
- flow_extract(&pkt, 0, 0, in_port, &flow);
+ flow_extract(&pkt, 0, htonll(0), htonll(0), in_port, &flow);
/* Choose output port. */
out_port = lswitch_choose_destination(sw, &flow);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index b3a4bff..2d67869 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -56,6 +56,15 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
NXM_NX_TUN_ID, "NXM_NX_TUN_ID",
0, NULL,
}, {
+ MFF_METADATA, "metadata", NULL,
+ MF_FIELD_SIZES(be64),
+ MFM_FULLY, 0,
+ MFS_HEXADECIMAL,
+ MFP_NONE,
+ true,
+ 0, NULL,
+ OXM_OF_METADATA, "OXM_OF_METADATA",
+ }, {
MFF_IN_PORT, "in_port", NULL,
MF_FIELD_SIZES(be16),
MFM_NONE, FWW_IN_PORT,
@@ -590,6 +599,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct
flow_wildcards *wc)
case MFF_TUN_ID:
return !wc->tun_id_mask;
+ case MFF_METADATA:
+ return !wc->metadata_mask;
#if FLOW_N_REGS > 0
case MFF_REG0:
@@ -700,6 +711,9 @@ mf_get_mask(const struct mf_field *mf, const struct
flow_wildcards *wc,
case MFF_TUN_ID:
mask->be64 = wc->tun_id_mask;
break;
+ case MFF_METADATA:
+ mask->be64 = wc->metadata_mask;
+ break;
#if FLOW_N_REGS > 0
case MFF_REG0:
@@ -899,6 +913,7 @@ mf_is_value_valid(const struct mf_field *mf, const union
mf_value *value)
{
switch (mf->id) {
case MFF_TUN_ID:
+ case MFF_METADATA:
case MFF_IN_PORT:
#if FLOW_N_REGS > 0
case MFF_REG0:
@@ -989,6 +1004,9 @@ mf_get_value(const struct mf_field *mf, const struct flow
*flow,
case MFF_TUN_ID:
value->be64 = flow->tun_id;
break;
+ case MFF_METADATA:
+ value->be64 = flow->metadata;
+ break;
case MFF_IN_PORT:
value->be16 = htons(flow->in_port);
@@ -1157,6 +1175,9 @@ mf_set_value(const struct mf_field *mf,
case MFF_TUN_ID:
cls_rule_set_tun_id(rule, value->be64);
break;
+ case MFF_METADATA:
+ cls_rule_set_metadata(rule, value->be64);
+ break;
case MFF_IN_PORT:
cls_rule_set_in_port(rule, ntohs(value->be16));
@@ -1327,6 +1348,9 @@ mf_set_flow_value(const struct mf_field *mf,
case MFF_TUN_ID:
flow->tun_id = value->be64;
break;
+ case MFF_METADATA:
+ flow->metadata = value->be64;
+ break;
case MFF_IN_PORT:
flow->in_port = ntohs(value->be16);
@@ -1506,6 +1530,8 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule
*rule)
case MFF_TUN_ID:
cls_rule_set_tun_id_masked(rule, htonll(0), htonll(0));
break;
+ case MFF_METADATA:
+ cls_rule_set_metadata_masked(rule, htonll(0), htonll(0));
case MFF_IN_PORT:
rule->wc.wildcards |= FWW_IN_PORT;
@@ -1725,6 +1751,9 @@ mf_set(const struct mf_field *mf,
case MFF_TUN_ID:
cls_rule_set_tun_id_masked(rule, value->be64, mask->be64);
break;
+ case MFF_METADATA:
+ cls_rule_set_metadata_masked(rule, value->be64, mask->be64);
+ break;
#if FLOW_N_REGS > 0
case MFF_REG0:
@@ -1884,6 +1913,7 @@ mf_random_value(const struct mf_field *mf, union mf_value
*value)
switch (mf->id) {
case MFF_TUN_ID:
+ case MFF_METADATA:
case MFF_IN_PORT:
#if FLOW_N_REGS > 0
case MFF_REG0:
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index ffde5cc..287ad67 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -32,6 +32,7 @@ struct ds;
enum mf_field_id {
/* Metadata. */
MFF_TUN_ID, /* be64 */
+ MFF_METADATA, /* be64 */
MFF_IN_PORT, /* be16 */
#if FLOW_N_REGS > 0
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 920184c..92e94f8 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -487,7 +487,7 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct
cls_rule *cr,
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* Metadata. */
if (!(wc & FWW_IN_PORT)) {
@@ -584,6 +584,9 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct
cls_rule *cr,
htonl(flow->regs[i]), htonl(cr->wc.reg_masks[i]));
}
+ /* OpenFlow 1.1+ Metadata. */
+ nxm_put_64m(b, OXM_OF_METADATA, flow->metadata, cr->wc.metadata_mask);
+
/* Cookie. */
nxm_put_64m(b, NXM_NX_COOKIE, cookie, cookie_mask);
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 22db477..ea6047c 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -90,7 +90,7 @@ void nxm_decode(struct mf_subfield *, ovs_be32 header,
ovs_be16 ofs_nbits);
void nxm_decode_discrete(struct mf_subfield *, ovs_be32 header,
ovs_be16 ofs, ovs_be16 n_bits);
-BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* Upper bound on the length of an nx_match. The longest nx_match (an
* IPV6 neighbor discovery message using 5 registers) would be:
*
@@ -111,6 +111,7 @@ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
* NXM_OF_IPV6_LABEL 4 4 -- 8
* NXM_OF_ICMP_TYPE 4 1 -- 5
* NXM_OF_ICMP_CODE 4 1 -- 5
+ * NXM_OF_METADATA 4 8 8 20
* NXM_NX_ND_TARGET 4 16 16 36
* NXM_NX_ND_SLL 4 6 -- 10
* NXM_NX_REG_W(0) 4 4 4 12
@@ -123,7 +124,7 @@ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
* NXM_NX_REG_W(7) 4 4 4 12
* NXM_NX_TUN_ID_W 4 8 8 20
* -------------------------------------------
- * total 333
+ * total 353
*
* So this value is conservative.
*/
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 9f77c5a..3916934 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -61,7 +61,7 @@ ofp_packet_to_string(const void *data, size_t len)
struct flow flow;
ofpbuf_use_const(&buf, data, len);
- flow_extract(&buf, 0, 0, 0, &flow);
+ flow_extract(&buf, 0, htonll(0), htonll(0), 0, &flow);
flow_format(&ds, &flow);
if (buf.l7) {
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 6d820b2..776f167 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -103,7 +103,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
@@ -416,9 +416,8 @@ ofputil_cls_rule_from_ofp11_match(const struct ofp11_match
*match,
}
if (match->metadata_mask != htonll(UINT64_MAX)) {
- /* Metadata field not yet supported because we haven't decided how to
- * map it onto our existing fields (or whether to add a new field). */
- return OFPERR_OFPBMC_BAD_FIELD;
+ cls_rule_set_metadata_masked(rule, match->metadata,
+ ~match->metadata_mask);
}
return 0;
@@ -512,8 +511,8 @@ ofputil_cls_rule_to_ofp11_match(const struct cls_rule *rule,
wc |= OFPFW11_MPLS_LABEL;
wc |= OFPFW11_MPLS_TC;
- /* Metadata field not yet supported */
- match->metadata_mask = htonll(UINT64_MAX);
+ match->metadata = rule->flow.metadata;
+ match->metadata_mask = ~rule->wc.metadata_mask;
match->wildcards = htonl(wc);
}
@@ -1442,7 +1441,7 @@ ofputil_usable_protocols(const struct cls_rule *rule)
{
const struct flow_wildcards *wc = &rule->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* NXM and OF1.1+ supports bitwise matching on ethernet addresses. */
if (!eth_mask_is_exact(wc->dl_src_mask)
@@ -1454,6 +1453,11 @@ ofputil_usable_protocols(const struct cls_rule *rule)
return OFPUTIL_P_NXM_ANY;
}
+ /* NXM and OF1.1+ support matching metadata. */
+ if (wc->metadata_mask != htonll(0)) {
+ return OFPUTIL_P_NXM_ANY;
+ }
+
/* Only NXM supports matching ARP hardware addresses. */
if (!(wc->wildcards & FWW_ARP_SHA) || !(wc->wildcards & FWW_ARP_THA)) {
return OFPUTIL_P_NXM_ANY;
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 962df15..55abff8 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3044,7 +3044,8 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct
dpif_upcall *upcalls,
continue;
}
flow_extract(upcall->packet, miss->flow.skb_priority,
- miss->flow.tun_id, miss->flow.in_port, &miss->flow);
+ miss->flow.tun_id, miss->flow.metadata,
+ miss->flow.in_port, &miss->flow);
/* Add other packets to a to-do list. */
hash = flow_hash(&miss->flow, 0);
@@ -4673,7 +4674,7 @@ send_packet(const struct ofport_dpif *ofport, struct
ofpbuf *packet)
struct flow flow;
int error;
- flow_extract((struct ofpbuf *) packet, 0, 0, 0, &flow);
+ flow_extract((struct ofpbuf *) packet, 0, 0, 0, 0, &flow);
odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port,
flow.vlan_tci);
if (odp_port != ofport->odp_port) {
@@ -6652,14 +6653,16 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int
argc, const char *argv[],
packet = ofpbuf_new(0);
flow_compose(packet, &flow);
}
- } else if (argc == 6) {
+ } else if (argc == 7) {
/* ofproto/trace dpname priority tun_id in_port packet */
const char *priority_s = argv[2];
const char *tun_id_s = argv[3];
- const char *in_port_s = argv[4];
- const char *packet_s = argv[5];
+ const char *metadata_s = argv[4];
+ const char *in_port_s = argv[5];
+ const char *packet_s = argv[6];
uint16_t in_port = ofp_port_to_odp_port(atoi(in_port_s));
ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
+ ovs_be64 metadata = htonll(strtoull(metadata_s, NULL, 0));
uint32_t priority = atoi(priority_s);
const char *msg;
@@ -6674,7 +6677,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int
argc, const char *argv[],
ds_put_cstr(&result, s);
free(s);
- flow_extract(packet, priority, tun_id, in_port, &flow);
+ flow_extract(packet, priority, tun_id, metadata, in_port, &flow);
initial_tci = flow.vlan_tci;
} else {
unixctl_command_reply_error(conn, "Bad command syntax");
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index f538869..4c6a9b8 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1872,7 +1872,7 @@ rule_execute(struct rule *rule, uint16_t in_port, struct
ofpbuf *packet)
assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
- flow_extract(packet, 0, 0, in_port, &flow);
+ flow_extract(packet, 0, 0, 0, in_port, &flow);
return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet);
}
@@ -2039,7 +2039,7 @@ handle_packet_out(struct ofconn *ofconn, const struct
ofp_packet_out *opo)
}
/* Send out packet. */
- flow_extract(payload, 0, 0, po.in_port, &flow);
+ flow_extract(payload, 0, 0, 0, po.in_port, &flow);
error = p->ofproto_class->packet_out(p, payload, &flow,
po.actions, po.n_actions);
ofpbuf_delete(payload);
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index b302dee..844e538 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -278,7 +278,7 @@ c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \
50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \
"], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60
buffer=0x00000111
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:06) type:0800 proto:6 tos:0 ttl:64
ip(192.168.0.1->192.168.0.2) port(10031->0) tcp_csum:26e8
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:06) type:0800 proto:6 tos:0 ttl:64
ip(192.168.0.1->192.168.0.2) port(10031->0) tcp_csum:26e8
])
AT_CLEANUP
@@ -775,7 +775,7 @@ ff ff ff ff 00 40 01 07 00 00 00 00 00 00 00 09 \
31 6d 00 00 00 00 00 00 00 00 \
"], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action)
data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
])
AT_CLEANUP
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 9c3e0dc..fe76fcd 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -97,7 +97,7 @@ AT_CHECK([ovs-appctl ofproto/trace br0
'in_port(1),eth(src=50:54:00:00:00:05,dst
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 tun_id=0x0 reg0=0x0
reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 (via
invalid_ttl) data_len=42 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:1 tos:0 ttl:1
ip(192.168.0.1->192.168.0.2)
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:1 tos:0 ttl:1
ip(192.168.0.1->192.168.0.2)
])
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -262,13 +262,13 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
])
dnl Singleton controller action.
@@ -281,13 +281,13 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(10:11:11:11:11:11->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
])
dnl Modified controller action.
@@ -300,13 +300,13 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
dnl
OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:15,pcp:0)
mac(30:33:33:33:33:33->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->10) tcp_csum:0
])
dnl Checksum TCP.
@@ -319,31 +319,31 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 tun_id=0x0 reg0=0x0
reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 (via action)
data_len=60 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
dnl
NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0
dnl
NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->192.168.0.2) port(8->11) tcp_csum:1a03
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->192.168.0.2) port(8->11) tcp_csum:1a03
dnl
NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(8->11) tcp_csum:3205
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(8->11) tcp_csum:3205
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->11) tcp_csum:31b8
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->11) tcp_csum:31b8
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d
])
dnl Checksum UDP.
@@ -356,31 +356,31 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 tun_id=0x0 reg0=0x0
reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 (via action)
data_len=60 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(20:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234
dnl
NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1
tun_id=0x0 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x0 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->192.168.0.2) port(8->11) udp_csum:2c37
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->192.168.0.2) port(8->11) udp_csum:2c37
dnl
NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(8->11) udp_csum:4439
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(8->11) udp_csum:4439
dnl
NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->11) udp_csum:43ec
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->11) udp_csum:43ec
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1
dnl
NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1
tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 reg5=0x0 reg6=0x0
reg7=0x0 (via action) data_len=64 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(vlan:80,pcp:0)
mac(80:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0
ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1
])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
diff --git a/tests/ofproto.at b/tests/ofproto.at
index dbe31c4..8312ce5 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -580,21 +580,21 @@ check_async () {
ovs-ofctl -v packet-out br0 none controller '0001020304050010203040501234'
if test X"$1" = X"OFPR_ACTION"; then shift;
echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via action)
data_len=14 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)"
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)"
fi
# OFPT_PACKET_IN, OFPR_NO_MATCH (controller_id=123)
ovs-ofctl -v packet-out br0 none 'controller(reason=no_match,id=123)'
'0001020304050010203040501234'
if test X"$1" = X"OFPR_NO_MATCH"; then shift;
echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via
no_match) data_len=14 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)"
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)"
fi
# OFPT_PACKET_IN, OFPR_INVALID_TTL (controller_id=0)
ovs-ofctl packet-out br0 none dec_ttl
'002583dfb4000026b98cb0f908004500003fb7e200000011339bac11370dac100002d7730035002b8f6d86fb0100000100000000000006626c702d7873066e696369726103636f6d00000f00'
if test X"$1" = X"OFPR_INVALID_TTL"; then shift;
echo >>expout "OFPT_PACKET_IN: total_len=76 in_port=NONE (via
invalid_ttl) data_len=76 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(00:26:b9:8c:b0:f9->00:25:83:df:b4:00) type:0800 proto:17 tos:0 ttl:0
ip(172.17.55.13->172.16.0.2) port(55155->53) udp_csum:8f6d"
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(00:26:b9:8c:b0:f9->00:25:83:df:b4:00) type:0800 proto:17 tos:0 ttl:0
ip(172.17.55.13->172.16.0.2) port(55155->53) udp_csum:8f6d"
fi
# OFPT_PORT_STATUS, OFPPR_ADD
@@ -692,9 +692,9 @@ ovs-appctl -t ovs-ofctl exit
AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl
OFPT_PACKET_IN: total_len=14 in_port=NONE (via action) data_len=14 (unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)
OFPT_PACKET_IN: total_len=14 in_port=CONTROLLER (via action) data_len=14
(unbuffered)
-priority:0,tunnel:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:5678 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)
+priority:0,tunnel:0,metadata:0,in_port:0000,tci(0)
mac(00:10:20:30:40:50->00:01:02:03:04:05) type:5678 proto:0 tos:0 ttl:0
ip(0.0.0.0->0.0.0.0)
OFPT_BARRIER_REPLY:
])
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index a4fa7e4..21b2711 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -931,12 +931,30 @@ dnl mpls_label and mpls_tc must be ignored if dl_type is
not MPLS:
0000 00 00 1234 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
12345678 5a 000000 0000000000000000ffffffffffffffff
-dnl metadata match not yet supported:
-# bad ofp11_match: OFPBMC_BAD_FIELD
+dnl metadata match:
+# metadata=0x1234567890abcdef
+0000 0058 00000000 000003ff dnl
+000000000000ffffffffffff 000000000000ffffffffffff dnl
+0000 00 00 0000 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
+00000000 00 000000 1234567890abcdef0000000000000000
+
+dnl metadata match:
+# metadata=0x5555555555555555/0x5555555555555555
0000 0058 00000000 000003ff dnl
000000000000ffffffffffff 000000000000ffffffffffff dnl
0000 00 00 0000 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
-00000000 00 000000 0000000000000001fffffffffffffffe
+00000000 00 000000 5555555555555555aaaaaaaaaaaaaaaa
+
+dnl metadata match:
+# metadata=0x1234000090ab0000/0xffff0000ffff0000
+# 74: 56 -> 00
+# 75: 78 -> 00
+# 78: cd -> 00
+# 79: ef -> 00
+0000 0058 00000000 000003ff dnl
+000000000000ffffffffffff 000000000000ffffffffffff dnl
+0000 00 00 0000 00 00 00000000ffffffff 00000000ffffffff 0000 0000 dnl
+00000000 00 000000 1234567890abcdef0000ffff0000ffff
])
sed '/^[[#&]]/d' < test-data > input.txt
@@ -974,6 +992,12 @@ AT_DATA([oxm.txt], [dnl
OXM_OF_IN_PORT(00000000)
OXM_OF_IN_PORT(fffffffe)
+# metadata
+OXM_OF_METADATA(5a5a5a5a5a5a5a5a)
+OXM_OF_METADATA_W(0000000000000000/00000000ffffffff)
+OXM_OF_METADATA_W(1234567890abcdef/ffff0000ffff0000)
+OXM_OF_METADATA_W(1234567890abcdef/ffffffffffffffff)
+
# eth dst
OXM_OF_ETH_DST(0002e30f80a4)
OXM_OF_ETH_DST_W(010000000000/010000000000)
@@ -1104,6 +1128,12 @@ AT_CHECK([ovs-ofctl --strict parse-oxm < oxm.txt], [0],
[dnl
OXM_OF_IN_PORT(00000000)
OXM_OF_IN_PORT(fffffffe)
+# metadata
+OXM_OF_METADATA(5a5a5a5a5a5a5a5a)
+OXM_OF_METADATA_W(0000000000000000/00000000ffffffff)
+OXM_OF_METADATA_W(1234000090ab0000/ffff0000ffff0000)
+OXM_OF_METADATA(1234567890abcdef)
+
# eth dst
OXM_OF_ETH_DST(0002e30f80a4)
OXM_OF_ETH_DST_W(010000000000/010000000000)
diff --git a/tests/test-flows.c b/tests/test-flows.c
index 33417e0..b36226b 100644
--- a/tests/test-flows.c
+++ b/tests/test-flows.c
@@ -68,7 +68,7 @@ main(int argc OVS_UNUSED, char *argv[])
ovs_fatal(retval, "error reading pcap file");
}
- flow_extract(packet, 0, 0, 1, &flow);
+ flow_extract(packet, 0, 0, 0, 1, &flow);
cls_rule_init_exact(&flow, 0, &rule);
ofputil_cls_rule_to_ofp10_match(&rule, &extracted_match);
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev