aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnsis Atteka <aatteka@nicira.com>2012-04-25 15:48:40 -0700
committerAnsis Atteka <aatteka@nicira.com>2012-04-26 15:22:48 -0700
commit47284b1fc6fe84a9b5b43b49bef868e4eb230cd1 (patch)
tree2d37c22ae94ddcaa1eafa9574bf3302f3e25ea6c /lib
parenta5f607bc8994e5ed870a62062df54e1b5753c6a2 (diff)
nicira-ext: Support masking of nd_target field
This commit adds support to specify a mask in CIDR format for the nd_target field. Signed-off-by: Ansis Atteka <aatteka@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/classifier.c26
-rw-r--r--lib/classifier.h2
-rw-r--r--lib/flow.c37
-rw-r--r--lib/flow.h17
-rw-r--r--lib/learn.c2
-rw-r--r--lib/meta-flow.c18
-rw-r--r--lib/nx-match.c8
-rw-r--r--lib/nx-match.h8
-rw-r--r--lib/ofp-util.c8
9 files changed, 76 insertions, 50 deletions
diff --git a/lib/classifier.c b/lib/classifier.c
index 122a6c6e..30cc31d3 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -415,8 +415,17 @@ cls_rule_set_ipv6_label(struct cls_rule *rule, ovs_be32 ipv6_label)
void
cls_rule_set_nd_target(struct cls_rule *rule, const struct in6_addr *target)
{
- rule->wc.wildcards &= ~FWW_ND_TARGET;
rule->flow.nd_target = *target;
+ rule->wc.nd_target_mask = in6addr_exact;
+}
+
+void
+cls_rule_set_nd_target_masked(struct cls_rule *rule,
+ const struct in6_addr *target,
+ const struct in6_addr *mask)
+{
+ rule->flow.nd_target = ipv6_addr_bitand(target, mask);
+ rule->wc.nd_target_mask = *mask;
}
/* Returns true if 'a' and 'b' have the same priority, wildcard the same
@@ -491,7 +500,7 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
if (rule->priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%d,", rule->priority);
@@ -669,11 +678,8 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
} else if (f->nw_proto == IPPROTO_ICMPV6) {
format_be16_masked(s, "icmp_type", f->tp_src, wc->tp_src_mask);
format_be16_masked(s, "icmp_code", f->tp_dst, wc->tp_dst_mask);
- if (!(w & FWW_ND_TARGET)) {
- ds_put_cstr(s, "nd_target=");
- print_ipv6_addr(s, &f->nd_target);
- ds_put_char(s, ',');
- }
+ format_ipv6_netmask(s, "nd_target", &f->nd_target,
+ &wc->nd_target_mask);
if (!(w & FWW_ARP_SHA)) {
ds_put_format(s, "nd_sll="ETH_ADDR_FMT",",
ETH_ADDR_ARGS(f->arp_sha));
@@ -1173,7 +1179,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 == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
@@ -1211,6 +1217,6 @@ flow_equal_except(const struct flow *a, const struct flow *b,
&wildcards->ipv6_src_mask)
&& ipv6_equal_except(&a->ipv6_dst, &b->ipv6_dst,
&wildcards->ipv6_dst_mask)
- && (wc & FWW_ND_TARGET
- || ipv6_addr_equals(&a->nd_target, &b->nd_target)));
+ && ipv6_equal_except(&a->nd_target, &b->nd_target,
+ &wildcards->nd_target_mask));
}
diff --git a/lib/classifier.h b/lib/classifier.h
index 84cb6028..48eb5962 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -135,6 +135,8 @@ void cls_rule_set_ipv6_dst_masked(struct cls_rule *, const struct in6_addr *,
const struct in6_addr *);
void cls_rule_set_ipv6_label(struct cls_rule *, ovs_be32);
void cls_rule_set_nd_target(struct cls_rule *, const struct in6_addr *);
+void cls_rule_set_nd_target_masked(struct cls_rule *, const struct in6_addr *,
+ const struct in6_addr *);
bool cls_rule_equal(const struct cls_rule *, const struct cls_rule *);
uint32_t cls_rule_hash(const struct cls_rule *, uint32_t basis);
diff --git a/lib/flow.c b/lib/flow.c
index 4d472312..ef1dd6d2 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -444,7 +444,7 @@ 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 == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
for (i = 0; i < FLOW_N_REGS; i++) {
flow->regs[i] &= wildcards->reg_masks[i];
@@ -497,9 +497,8 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
&wildcards->ipv6_src_mask);
flow->ipv6_dst = ipv6_addr_bitand(&flow->ipv6_dst,
&wildcards->ipv6_dst_mask);
- if (wc & FWW_ND_TARGET) {
- memset(&flow->nd_target, 0, sizeof flow->nd_target);
- }
+ flow->nd_target = ipv6_addr_bitand(&flow->nd_target,
+ &wildcards->nd_target_mask);
flow->skb_priority = 0;
}
@@ -507,7 +506,7 @@ 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 == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
fmd->tun_id = flow->tun_id;
fmd->tun_id_mask = htonll(UINT64_MAX);
@@ -596,7 +595,7 @@ flow_print(FILE *stream, const struct flow *flow)
void
flow_wildcards_init_catchall(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
wc->wildcards = FWW_ALL;
wc->tun_id_mask = htonll(0);
@@ -604,6 +603,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
wc->nw_dst_mask = htonl(0);
wc->ipv6_src_mask = in6addr_any;
wc->ipv6_dst_mask = in6addr_any;
+ wc->nd_target_mask = in6addr_any;
memset(wc->reg_masks, 0, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(0);
wc->nw_frag_mask = 0;
@@ -617,7 +617,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
void
flow_wildcards_init_exact(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
wc->wildcards = 0;
wc->tun_id_mask = htonll(UINT64_MAX);
@@ -625,6 +625,7 @@ flow_wildcards_init_exact(struct flow_wildcards *wc)
wc->nw_dst_mask = htonl(UINT32_MAX);
wc->ipv6_src_mask = in6addr_exact;
wc->ipv6_dst_mask = in6addr_exact;
+ wc->nd_target_mask = in6addr_exact;
memset(wc->reg_masks, 0xff, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(UINT16_MAX);
wc->nw_frag_mask = UINT8_MAX;
@@ -640,7 +641,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
if (wc->wildcards
|| wc->tun_id_mask != htonll(UINT64_MAX)
@@ -651,6 +652,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
|| wc->vlan_tci_mask != htons(UINT16_MAX)
|| !ipv6_mask_is_exact(&wc->ipv6_src_mask)
|| !ipv6_mask_is_exact(&wc->ipv6_dst_mask)
+ || !ipv6_mask_is_exact(&wc->nd_target_mask)
|| wc->nw_frag_mask != UINT8_MAX) {
return false;
}
@@ -671,7 +673,7 @@ flow_wildcards_is_catchall(const struct flow_wildcards *wc)
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
if (wc->wildcards != FWW_ALL
|| wc->tun_id_mask != htonll(0)
@@ -682,6 +684,7 @@ flow_wildcards_is_catchall(const struct flow_wildcards *wc)
|| wc->vlan_tci_mask != htons(0)
|| !ipv6_mask_is_any(&wc->ipv6_src_mask)
|| !ipv6_mask_is_any(&wc->ipv6_dst_mask)
+ || !ipv6_mask_is_any(&wc->nd_target_mask)
|| wc->nw_frag_mask != 0) {
return false;
}
@@ -705,7 +708,7 @@ flow_wildcards_combine(struct flow_wildcards *dst,
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
dst->wildcards = src1->wildcards | src2->wildcards;
dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask;
@@ -715,6 +718,8 @@ flow_wildcards_combine(struct flow_wildcards *dst,
&src2->ipv6_src_mask);
dst->ipv6_dst_mask = ipv6_addr_bitand(&src1->ipv6_dst_mask,
&src2->ipv6_dst_mask);
+ dst->nd_target_mask = ipv6_addr_bitand(&src1->nd_target_mask,
+ &src2->nd_target_mask);
for (i = 0; i < FLOW_N_REGS; i++) {
dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i];
}
@@ -730,7 +735,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 == 64 + FLOW_N_REGS * 4);
+ BUILD_ASSERT_DECL(sizeof *wc == 80 + FLOW_N_REGS * 4);
return hash_bytes(wc, sizeof *wc, basis);
}
@@ -742,7 +747,7 @@ flow_wildcards_equal(const struct flow_wildcards *a,
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
if (a->wildcards != b->wildcards
|| a->tun_id_mask != b->tun_id_mask
@@ -751,6 +756,7 @@ flow_wildcards_equal(const struct flow_wildcards *a,
|| a->vlan_tci_mask != b->vlan_tci_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)
|| a->tp_src_mask != b->tp_src_mask
|| a->tp_dst_mask != b->tp_dst_mask) {
return false;
@@ -774,7 +780,7 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
int i;
struct in6_addr ipv6_masked;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) {
@@ -792,6 +798,11 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
return true;
}
+ ipv6_masked = ipv6_addr_bitand(&a->nd_target_mask, &b->nd_target_mask);
+ if (!ipv6_addr_equals(&ipv6_masked, &b->nd_target_mask)) {
+ return true;
+ }
+
return (a->wildcards & ~b->wildcards
|| (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask
|| (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask
diff --git a/lib/flow.h b/lib/flow.h
index 5b389bca..41e63865 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -35,7 +35,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 9
+#define FLOW_WC_SEQ 10
#define FLOW_N_REGS 8
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
@@ -100,7 +100,7 @@ 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 == 9);
+BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 142 && FLOW_WC_SEQ == 10);
void flow_extract(struct ofpbuf *, uint32_t priority, ovs_be64 tun_id,
uint16_t in_port, struct flow *);
@@ -159,13 +159,12 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t;
#define FWW_NW_ECN ((OVS_FORCE flow_wildcards_t) (1 << 7))
#define FWW_ARP_SHA ((OVS_FORCE flow_wildcards_t) (1 << 8))
#define FWW_ARP_THA ((OVS_FORCE flow_wildcards_t) (1 << 9))
-#define FWW_ND_TARGET ((OVS_FORCE flow_wildcards_t) (1 << 10))
-#define FWW_IPV6_LABEL ((OVS_FORCE flow_wildcards_t) (1 << 11))
-#define FWW_NW_TTL ((OVS_FORCE flow_wildcards_t) (1 << 12))
-#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 13)) - 1))
+#define FWW_IPV6_LABEL ((OVS_FORCE flow_wildcards_t) (1 << 10))
+#define FWW_NW_TTL ((OVS_FORCE flow_wildcards_t) (1 << 11))
+#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 12)) - 1))
/* Remember to update FLOW_WC_SEQ when adding or removing FWW_*. */
-BUILD_ASSERT_DECL(FWW_ALL == ((1 << 13) - 1) && FLOW_WC_SEQ == 9);
+BUILD_ASSERT_DECL(FWW_ALL == ((1 << 12) - 1) && FLOW_WC_SEQ == 10);
/* Information on wildcards for a flow, as a supplement to "struct flow".
*
@@ -179,6 +178,8 @@ struct flow_wildcards {
ovs_be32 nw_dst_mask; /* 1-bit in each significant nw_dst bit. */
struct in6_addr ipv6_src_mask; /* 1-bit in each signficant ipv6_src bit. */
struct in6_addr ipv6_dst_mask; /* 1-bit in each signficant ipv6_dst bit. */
+ struct in6_addr nd_target_mask; /* 1-bit in each significant
+ nd_target bit. */
ovs_be16 vlan_tci_mask; /* 1-bit in each significant vlan_tci bit. */
ovs_be16 tp_src_mask; /* 1-bit in each significant tp_src bit. */
ovs_be16 tp_dst_mask; /* 1-bit in each significant tp_dst bit. */
@@ -187,7 +188,7 @@ struct flow_wildcards {
};
/* Remember to update FLOW_WC_SEQ when updating struct flow_wildcards. */
-BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 96 && FLOW_WC_SEQ == 9);
+BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 112 && FLOW_WC_SEQ == 10);
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 480ad909..7f30f6ee 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 == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
}
}
}
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 3db528fb..69226cbc 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -407,7 +407,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
{
MFF_ND_TARGET, "nd_target", NULL,
MF_FIELD_SIZES(ipv6),
- MFM_NONE, FWW_ND_TARGET,
+ MFM_CIDR, 0,
MFS_IPV6,
MFP_ND,
false,
@@ -553,7 +553,6 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
- case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
assert(mf->fww_bit != 0);
@@ -612,6 +611,9 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_IPV6_DST:
return ipv6_mask_is_any(&wc->ipv6_dst_mask);
+ case MFF_ND_TARGET:
+ return ipv6_mask_is_any(&wc->nd_target_mask);
+
case MFF_IP_FRAG:
return !(wc->nw_frag_mask & FLOW_NW_FRAG_MASK);
@@ -659,7 +661,6 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
- case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
assert(mf->fww_bit != 0);
@@ -729,6 +730,10 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
mask->ipv6 = wc->ipv6_dst_mask;
break;
+ case MFF_ND_TARGET:
+ mask->ipv6 = wc->nd_target_mask;
+ break;
+
case MFF_IP_FRAG:
mask->u8 = wc->nw_frag_mask & FLOW_NW_FRAG_MASK;
break;
@@ -1624,7 +1629,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
break;
case MFF_ND_TARGET:
- rule->wc.wildcards |= FWW_ND_TARGET;
+ memset(&rule->wc.nd_target_mask, 0, sizeof rule->wc.nd_target_mask);
memset(&rule->flow.nd_target, 0, sizeof rule->flow.nd_target);
break;
@@ -1676,7 +1681,6 @@ mf_set(const struct mf_field *mf,
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_TYPE:
case MFF_ICMPV6_CODE:
- case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
NOT_REACHED();
@@ -1742,6 +1746,10 @@ mf_set(const struct mf_field *mf,
cls_rule_set_ipv6_dst_masked(rule, &value->ipv6, &mask->ipv6);
break;
+ case MFF_ND_TARGET:
+ cls_rule_set_nd_target_masked(rule, &value->ipv6, &mask->ipv6);
+ break;
+
case MFF_IP_FRAG:
cls_rule_set_nw_frag_masked(rule, value->u8, mask->u8);
break;
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 0e61d352..91dd7fc5 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -471,7 +471,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr,
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
/* Metadata. */
if (!(wc & FWW_IN_PORT)) {
@@ -514,10 +514,8 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr,
if (flow->nw_proto == IPPROTO_ICMPV6
&& (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
flow->tp_src == htons(ND_NEIGHBOR_ADVERT))) {
- if (!(wc & FWW_ND_TARGET)) {
- nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
- &in6addr_exact);
- }
+ nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
+ &cr->wc.nd_target_mask);
if (!(wc & FWW_ARP_SHA)
&& flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 592d46fb..296a63a0 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 == 9);
+BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
/* Upper bound on the length of an nx_match. The longest nx_match (an
* IPV6 neighbor discovery message using 5 registers) would be:
*
@@ -111,7 +111,7 @@ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
* NXM_OF_IPV6_LABEL 4 4 -- 8
* NXM_OF_ICMP_TYPE 4 1 -- 5
* NXM_OF_ICMP_CODE 4 1 -- 5
- * NXM_NX_ND_TARGET 4 16 -- 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
* NXM_NX_REG_W(1) 4 4 4 12
@@ -123,11 +123,11 @@ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
* NXM_NX_REG_W(7) 4 4 4 12
* NXM_NX_TUN_ID_W 4 8 8 20
* -------------------------------------------
- * total 311
+ * total 327
*
* So this value is conservative.
*/
-#define NXM_MAX_LEN 384
+#define NXM_MAX_LEN 400
/* This is my guess at the length of a "typical" nx_match, for use in
* predicting space requirements. */
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 90475f7a..ae9b30d3 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -101,7 +101,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0
void
ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
@@ -109,7 +109,7 @@ ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
/* Wildcard fields that aren't defined by ofp_match or tun_id. */
wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_NW_ECN | FWW_NW_TTL
- | FWW_ND_TARGET | FWW_IPV6_LABEL);
+ | FWW_IPV6_LABEL);
if (ofpfw & OFPFW_NW_TOS) {
/* OpenFlow 1.0 defines a TOS wildcard, but it's much later in
@@ -1166,7 +1166,7 @@ ofputil_usable_protocols(const struct cls_rule *rule)
{
const struct flow_wildcards *wc = &rule->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
/* Only NXM supports separately wildcards the Ethernet multicast bit. */
if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) {
@@ -3810,7 +3810,7 @@ ofputil_normalize_rule(struct cls_rule *rule)
wc.wildcards |= FWW_IPV6_LABEL;
}
if (!(may_match & MAY_ND_TARGET)) {
- wc.wildcards |= FWW_ND_TARGET;
+ wc.nd_target_mask = in6addr_any;
}
/* Log any changes. */