summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJustin Pettit <jpettit@ovn.org>2015-10-31 04:45:28 -0700
committerJustin Pettit <jpettit@ovn.org>2016-07-12 21:14:02 -0700
commitb23ada8eecfdce7710cc4daa019539712a2c567a (patch)
treee6670fbf2b78988a128a31fd10ee3f29485ac3eb /lib
parent847b8b027af4401c8f1aff5e201a9cc84bb5fddb (diff)
downloadopenvswitch-b23ada8eecfdce7710cc4daa019539712a2c567a.tar.gz
Introduce 128-bit xxregs.
These are needed to handle IPv6 addresses. Signed-off-by: Justin Pettit <jpettit@ovn.org> Acked-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/flow.c9
-rw-r--r--lib/flow.h22
-rw-r--r--lib/match.c15
-rw-r--r--lib/meta-flow.c29
-rw-r--r--lib/odp-util.c6
5 files changed, 81 insertions, 0 deletions
diff --git a/lib/flow.c b/lib/flow.c
index b97b85368..8842e8d78 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -1578,6 +1578,15 @@ flow_wildcards_set_xreg_mask(struct flow_wildcards *wc, int idx, uint64_t mask)
flow_set_xreg(&wc->masks, idx, mask);
}
+/* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'.
+ * (A 0-bit indicates a wildcard bit.) */
+void
+flow_wildcards_set_xxreg_mask(struct flow_wildcards *wc, int idx,
+ ovs_u128 mask)
+{
+ flow_set_xxreg(&wc->masks, idx, mask);
+}
+
/* Calculates the 5-tuple hash from the given miniflow.
* This returns the same value as flow_hash_5tuple for the corresponding
* flow. */
diff --git a/lib/flow.h b/lib/flow.h
index 547967741..4cff48cf6 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -119,6 +119,28 @@ flow_set_xreg(struct flow *flow, int idx, uint64_t value)
flow->regs[idx * 2 + 1] = value;
}
+static inline ovs_u128
+flow_get_xxreg(const struct flow *flow, int idx)
+{
+ ovs_u128 value;
+
+ value.u64.hi = (uint64_t) flow->regs[idx * 4] << 32;
+ value.u64.hi |= flow->regs[idx * 4 + 1];
+ value.u64.lo = (uint64_t) flow->regs[idx * 4 + 2] << 32;
+ value.u64.lo |= flow->regs[idx * 4 + 3];
+
+ return value;
+}
+
+static inline void
+flow_set_xxreg(struct flow *flow, int idx, ovs_u128 value)
+{
+ flow->regs[idx * 4] = value.u64.hi >> 32;
+ flow->regs[idx * 4 + 1] = value.u64.hi;
+ flow->regs[idx * 4 + 2] = value.u64.lo >> 32;
+ flow->regs[idx * 4 + 3] = value.u64.lo;
+}
+
static inline int
flow_compare_3way(const struct flow *a, const struct flow *b)
{
diff --git a/lib/match.c b/lib/match.c
index 906308b08..d5deb7dfd 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -133,6 +133,21 @@ match_set_xreg_masked(struct match *match, unsigned int xreg_idx,
}
void
+match_set_xxreg(struct match *match, unsigned int xxreg_idx, ovs_u128 value)
+{
+ match_set_xxreg_masked(match, xxreg_idx, value, OVS_U128_MAX);
+}
+
+void
+match_set_xxreg_masked(struct match *match, unsigned int xxreg_idx,
+ ovs_u128 value, ovs_u128 mask)
+{
+ ovs_assert(xxreg_idx < FLOW_N_XXREGS);
+ flow_wildcards_set_xxreg_mask(&match->wc, xxreg_idx, mask);
+ flow_set_xxreg(&match->flow, xxreg_idx, ovs_u128_and(value, mask));
+}
+
+void
match_set_actset_output(struct match *match, ofp_port_t actset_output)
{
match->wc.masks.actset_output = u16_to_ofp(UINT16_MAX);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index e160de171..af579a20d 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -237,6 +237,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
return !wc->masks.regs[mf->id - MFF_REG0];
CASE_MFF_XREGS:
return !flow_get_xreg(&wc->masks, mf->id - MFF_XREG0);
+ CASE_MFF_XXREGS: {
+ ovs_u128 value = flow_get_xxreg(&wc->masks, mf->id - MFF_XXREG0);
+ return ovs_u128_is_zero(value);
+ }
case MFF_ACTSET_OUTPUT:
return !wc->masks.actset_output;
@@ -526,6 +530,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
case MFF_CT_LABEL:
CASE_MFF_REGS:
CASE_MFF_XREGS:
+ CASE_MFF_XXREGS:
case MFF_ETH_SRC:
case MFF_ETH_DST:
case MFF_ETH_TYPE:
@@ -705,6 +710,10 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
value->be64 = htonll(flow_get_xreg(flow, mf->id - MFF_XREG0));
break;
+ CASE_MFF_XXREGS:
+ value->be128 = hton128(flow_get_xxreg(flow, mf->id - MFF_XXREG0));
+ break;
+
case MFF_ETH_SRC:
value->mac = flow->dl_src;
break;
@@ -963,6 +972,10 @@ mf_set_value(const struct mf_field *mf,
match_set_xreg(match, mf->id - MFF_XREG0, ntohll(value->be64));
break;
+ CASE_MFF_XXREGS:
+ match_set_xxreg(match, mf->id - MFF_XXREG0, ntoh128(value->be128));
+ break;
+
case MFF_ETH_SRC:
match_set_dl_src(match, value->mac);
break;
@@ -1273,6 +1286,10 @@ mf_set_flow_value(const struct mf_field *mf,
flow_set_xreg(flow, mf->id - MFF_XREG0, ntohll(value->be64));
break;
+ CASE_MFF_XXREGS:
+ flow_set_xxreg(flow, mf->id - MFF_XXREG0, ntoh128(value->be128));
+ break;
+
case MFF_ETH_SRC:
flow->dl_src = value->mac;
break;
@@ -1598,6 +1615,12 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
match_set_xreg_masked(match, mf->id - MFF_XREG0, 0, 0);
break;
+ CASE_MFF_XXREGS: {
+ match_set_xxreg_masked(match, mf->id - MFF_XXREG0, OVS_U128_ZERO,
+ OVS_U128_ZERO);
+ break;
+ }
+
case MFF_ETH_SRC:
match->flow.dl_src = eth_addr_zero;
match->wc.masks.dl_src = eth_addr_zero;
@@ -1863,6 +1886,12 @@ mf_set(const struct mf_field *mf,
ntohll(value->be64), ntohll(mask->be64));
break;
+ CASE_MFF_XXREGS: {
+ match_set_xxreg_masked(match, mf->id - MFF_XXREG0,
+ ntoh128(value->be128), ntoh128(mask->be128));
+ break;
+ }
+
case MFF_PKT_MARK:
match_set_pkt_mark_masked(match, ntohl(value->be32),
ntohl(mask->be32));
diff --git a/lib/odp-util.c b/lib/odp-util.c
index fd1ca9b5f..b0977ded8 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2991,6 +2991,12 @@ format_u128(struct ds *ds, const ovs_u128 *key, const ovs_u128 *mask,
}
}
+/* Read the string from 's_' as a 128-bit value. If the string contains
+ * a "/", the rest of the string will be treated as a 128-bit mask.
+ *
+ * If either the value or mask is larger than 64 bits, the string must
+ * be in hexadecimal.
+ */
static int
scan_u128(const char *s_, ovs_u128 *value, ovs_u128 *mask)
{