diff options
author | Justin Pettit <jpettit@ovn.org> | 2015-10-31 04:45:28 -0700 |
---|---|---|
committer | Justin Pettit <jpettit@ovn.org> | 2016-07-12 21:14:02 -0700 |
commit | b23ada8eecfdce7710cc4daa019539712a2c567a (patch) | |
tree | e6670fbf2b78988a128a31fd10ee3f29485ac3eb /lib | |
parent | 847b8b027af4401c8f1aff5e201a9cc84bb5fddb (diff) | |
download | openvswitch-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.c | 9 | ||||
-rw-r--r-- | lib/flow.h | 22 | ||||
-rw-r--r-- | lib/match.c | 15 | ||||
-rw-r--r-- | lib/meta-flow.c | 29 | ||||
-rw-r--r-- | lib/odp-util.c | 6 |
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) { |