From: Joe Stringer Date: Tue, 26 Jun 2012 13:09:44 +0000 (+1200) Subject: Add OXM_OF_METADATA field as a step toward OpenFlow 1.1 support. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=969fc56c2abb0c3a1bf0225032250aa537df55a3;p=openvswitch Add OXM_OF_METADATA field as a step toward OpenFlow 1.1 support. Signed-off-by: Joe Stringer Signed-off-by: Ben Pfaff --- diff --git a/NEWS b/NEWS index d3cfe138..c2ec9539 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ post-v1.7.0 - Allow support for arbitrary Ethernet masks. (Previously, only the multicast bit in the destination address could be individually masked.) + - New field OXM_OF_METADATA, to align with OpenFlow 1.1. - Additional protocols are not mirrored and dropped when forward-bpdu is false. For a full list, see the ovs-vswitchd.conf.db man page. - Open vSwitch now sends RARP packets in situations where it previously diff --git a/lib/classifier.c b/lib/classifier.c index d19840ce..0541b5c0 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -118,6 +118,20 @@ cls_rule_set_reg_masked(struct cls_rule *rule, unsigned int reg_idx, rule->flow.regs[reg_idx] = value & mask; } +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) { @@ -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 9e4b33e2..ec7316cd 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/flow.c b/lib/flow.c index 46e0e2d2..d90a7380 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -444,12 +444,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 +499,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 +526,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 +593,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 +603,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 +618,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 +628,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 +645,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 +654,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 +680,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 +689,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 +718,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 +733,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 +748,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 +760,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 +797,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 +835,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 2958ff56..0e014212 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; + ovs_be64 metadata_mask; + uint32_t regs[FLOW_N_REGS]; /* Registers. */ uint32_t reg_masks[FLOW_N_REGS]; /* 1-bit in each significant regs bit. */ @@ -92,14 +96,14 @@ 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 *); @@ -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 cbecb10d..5478b748 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/meta-flow.c b/lib/meta-flow.c index e7b860b2..c2086909 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -55,6 +55,15 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { true, NXM_NX_TUN_ID, "NXM_NX_TUN_ID", NXM_NX_TUN_ID, "NXM_NX_TUN_ID", + }, { + MFF_METADATA, "metadata", NULL, + MF_FIELD_SIZES(be64), + MFM_FULLY, 0, + MFS_HEXADECIMAL, + MFP_NONE, + true, + OXM_OF_METADATA, "OXM_OF_METADATA", + OXM_OF_METADATA, "OXM_OF_METADATA", }, { MFF_IN_PORT, "in_port", NULL, MF_FIELD_SIZES(be16), @@ -563,6 +572,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: @@ -673,6 +684,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: @@ -872,6 +886,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: @@ -962,6 +977,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); @@ -1130,6 +1148,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)); @@ -1300,6 +1321,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); @@ -1479,6 +1503,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; @@ -1698,6 +1724,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: @@ -1857,6 +1886,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 82bb13f9..0967633f 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 920184ca..92e94f88 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 22db4778..c814275f 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -90,9 +90,9 @@ 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: + * IPV6 neighbor discovery message using all the registers) would be: * * header value mask total * ------ ----- ---- ----- @@ -122,8 +122,9 @@ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11); * NXM_NX_REG_W(6) 4 4 4 12 * NXM_NX_REG_W(7) 4 4 4 12 * NXM_NX_TUN_ID_W 4 8 8 20 + * OXM_OF_METADATA 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 9f77c5a0..cf9d93fa 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -113,6 +113,13 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, } } + if (pin.fmd.metadata_mask) { + ds_put_format(string, " metadata=0x%"PRIx64, ntohll(pin.fmd.metadata)); + if (pin.fmd.metadata_mask != htonll(UINT64_MAX)) { + ds_put_format(string, "/0x%"PRIx64, ntohll(pin.fmd.metadata_mask)); + } + } + for (i = 0; i < FLOW_N_REGS; i++) { if (pin.fmd.reg_masks[i]) { ds_put_format(string, " reg%d=0x%"PRIx32, i, pin.fmd.regs[i]); diff --git a/lib/ofp-util.c b/lib/ofp-util.c index cc3c9fdf..0ad23c7d 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; @@ -2371,6 +2375,9 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin, pin->fmd.tun_id = rule.flow.tun_id; pin->fmd.tun_id_mask = rule.wc.tun_id_mask; + pin->fmd.metadata = rule.flow.metadata; + pin->fmd.metadata_mask = rule.wc.metadata_mask; + memcpy(pin->fmd.regs, rule.flow.regs, sizeof pin->fmd.regs); memcpy(pin->fmd.reg_masks, rule.wc.reg_masks, sizeof pin->fmd.reg_masks); @@ -2423,6 +2430,9 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin, cls_rule_init_catchall(&rule, 0); cls_rule_set_tun_id_masked(&rule, pin->fmd.tun_id, pin->fmd.tun_id_mask); + cls_rule_set_metadata_masked(&rule, pin->fmd.metadata, + pin->fmd.metadata_mask); + for (i = 0; i < FLOW_N_REGS; i++) { cls_rule_set_reg_masked(&rule, i, pin->fmd.regs[i], diff --git a/tests/ofp-print.at b/tests/ofp-print.at index b302dee8..c7b4ddb4 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 @@ -762,20 +762,21 @@ AT_CLEANUP AT_SETUP([NXT_PACKET_IN]) AT_KEYWORDS([ofp-print]) AT_CHECK([ovs-ofctl ofp-print "\ -01 04 00 aa 00 00 00 00 00 00 23 20 00 00 00 11 \ +01 04 00 ba 00 00 00 00 00 00 23 20 00 00 00 11 \ ff ff ff ff 00 40 01 07 00 00 00 00 00 00 00 09 \ -00 3a 00 00 00 00 00 00 00 00 00 02 00 01 00 01 \ +00 4e 00 00 00 00 00 00 00 00 00 02 00 01 00 01 \ 20 08 00 00 00 00 00 00 00 06 00 01 00 04 00 00 \ 00 01 00 01 02 04 00 00 00 02 00 01 04 04 00 00 \ 00 03 00 01 06 04 00 00 00 04 00 01 08 04 00 00 \ -00 05 00 00 00 00 00 00 00 00 82 82 82 82 82 82 \ +00 05 80 00 05 10 5a 5a 5a 5a 5a 5a 5a 5a ff ff \ +00 00 ff ff 00 00 00 00 00 00 82 82 82 82 82 82 \ 80 81 81 81 81 81 81 00 00 50 08 00 45 00 00 28 \ 00 00 00 00 00 06 32 05 53 53 53 53 54 54 54 54 \ 00 55 00 56 00 00 00 00 00 00 00 00 50 00 00 00 \ 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 +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x5a5a00005a5a0000/0xffff0000ffff0000 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) +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 9c3e0dc9..924e97ac 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -96,8 +96,8 @@ AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --pidfile 2> ofctl_mo AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout]) 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) +NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 tun_id=0x0 metadata=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,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. @@ -318,32 +318,32 @@ 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 +NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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. @@ -355,32 +355,32 @@ 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 +NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1 tun_id=0x0 metadata=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,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 +NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x0 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,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 dbe31c4c..28adf74d 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,37 @@ 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: +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + +dnl This test checks that metadata is encoded in packet_in structures, +dnl supported by NXAST. +AT_SETUP([ofproto - packet-out with metadata (NXM)]) +OVS_VSWITCHD_START + +# Start a monitor listening for packet-ins. +AT_CHECK([ovs-ofctl -P nxm monitor br0 --detach --no-chdir --pidfile]) +ovs-appctl -t ovs-ofctl ofctl/send 0109000c0123456700000080 +ovs-appctl -t ovs-ofctl ofctl/barrier +ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log +AT_CAPTURE_FILE([monitor.log]) + +# Send a packet-out with a load action to set some metadata, and forward to controller +AT_CHECK([ovs-ofctl packet-out br0 none 'load(0xfafafafa5a5a5a5a->OXM_OF_METADATA[[0..63]]), controller' '0001020304050010203040501234']) + +# Stop the monitor and check its output. +ovs-appctl -t ovs-ofctl ofctl/barrier +ovs-appctl -t ovs-ofctl exit + +AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl +NXT_PACKET_IN: total_len=14 in_port=NONE tun_id=0x0 metadata=0xfafafafa5a5a5a5a reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 (via action) data_len=14 (unbuffered) +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_BARRIER_REPLY: ]) diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index e45a4039..491e0ab3 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -933,12 +933,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 @@ -976,6 +994,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) @@ -1106,6 +1130,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)