From 79fe0f4611b60fe0fdf43206bc06201fd724a18d Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 28 Jul 2014 09:50:37 -0700 Subject: [PATCH] meta-flow: Add 64-bit registers. These 64-bit registers are intended to conform with the OpenFlow 1.5 draft specification. EXT-244. Signed-off-by: Ben Pfaff Acked-by: Jarno Rajahalme --- NEWS | 2 ++ include/openflow/openflow-1.2.h | 4 +++ lib/flow.c | 8 ++++++ lib/flow.h | 22 +++++++++++++++ lib/match.c | 15 +++++++++++ lib/match.h | 5 +++- lib/meta-flow.c | 47 +++++++++++++++++++++++++++++++++ lib/meta-flow.h | 20 +++++++++++++- tests/ovs-ofctl.at | 8 ++++++ utilities/ovs-ofctl.8.in | 17 +++++++++++- 10 files changed, 145 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index d7c0d0ad4..742ae22a0 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ Post-v2.3.0 release. The protocol is documented at http://tools.ietf.org/html/draft-gross-geneve-00 - The OVS database now reports controller rate limiting statistics. + - OpenFlow: + * OpenFlow 1.5 (draft) extended registers are now supported. v2.3.0 - xx xxx xxxx diff --git a/include/openflow/openflow-1.2.h b/include/openflow/openflow-1.2.h index d25f2dc43..1069f4e0e 100644 --- a/include/openflow/openflow-1.2.h +++ b/include/openflow/openflow-1.2.h @@ -68,6 +68,7 @@ enum ofp12_oxm_class { OFPXMC12_NXM_0 = 0x0000, /* Backward compatibility with NXM */ OFPXMC12_NXM_1 = 0x0001, /* Backward compatibility with NXM */ OFPXMC12_OPENFLOW_BASIC = 0x8000, /* Basic class for OpenFlow */ + OFPXMC15_PACKET_REGS = 0x8001, /* Packet registers (pipeline fields). */ OFPXMC12_EXPERIMENTER = 0xffff, /* Experimenter class */ }; @@ -197,6 +198,9 @@ enum oxm12_ofb_match_fields { #define OXM_OF_TCP_FLAGS OXM_HEADER (OFPXMT15_OFB_TCP_FLAGS, 2) #define OXM_OF_TCP_FLAGS_W OXM_HEADER_W (OFPXMT15_OFB_TCP_FLAGS, 2) +#define OXM_OF_PKT_REG(N) (NXM_HEADER (OFPXMC15_PACKET_REGS, N, 8)) +#define OXM_OF_PKT_REG_W(N) (NXM_HEADER_W(OFPXMC15_PACKET_REGS, N, 8)) + /* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate * special conditions. */ diff --git a/lib/flow.c b/lib/flow.c index 330a458f6..5e040151f 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -898,6 +898,14 @@ flow_wildcards_set_reg_mask(struct flow_wildcards *wc, int idx, uint32_t mask) wc->masks.regs[idx] = mask; } +/* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'. + * (A 0-bit indicates a wildcard bit.) */ +void +flow_wildcards_set_xreg_mask(struct flow_wildcards *wc, int idx, uint64_t mask) +{ + flow_set_xreg(&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 1bce46c56..3b8d24d8f 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -40,9 +40,16 @@ struct pkt_metadata; * failures in places which likely need to be updated. */ #define FLOW_WC_SEQ 27 +/* Number of Open vSwitch extension 32-bit registers. */ #define FLOW_N_REGS 8 BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS); +/* Number of OpenFlow 1.5+ 64-bit registers. + * + * Each of these overlays a pair of Open vSwitch 32-bit registers, so there + * are half as many of them.*/ +#define FLOW_N_XREGS (FLOW_N_REGS / 2) + /* Used for struct flow's dl_type member for frames that have no Ethernet * type, that is, pure 802.2 frames. */ #define FLOW_DL_TYPE_NONE 0x5ff @@ -208,6 +215,19 @@ void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse); void flow_compose(struct ofpbuf *, const struct flow *); +static inline uint64_t +flow_get_xreg(const struct flow *flow, int idx) +{ + return ((uint64_t) flow->regs[idx * 2] << 32) | flow->regs[idx * 2 + 1]; +} + +static inline void +flow_set_xreg(struct flow *flow, int idx, uint64_t value) +{ + flow->regs[idx * 2] = value >> 32; + flow->regs[idx * 2 + 1] = value; +} + static inline int flow_compare_3way(const struct flow *a, const struct flow *b) { @@ -291,6 +311,8 @@ bool flow_wildcards_is_catchall(const struct flow_wildcards *); void flow_wildcards_set_reg_mask(struct flow_wildcards *, int idx, uint32_t mask); +void flow_wildcards_set_xreg_mask(struct flow_wildcards *, + int idx, uint64_t mask); void flow_wildcards_and(struct flow_wildcards *dst, const struct flow_wildcards *src1, diff --git a/lib/match.c b/lib/match.c index 58fa0e45f..83649064f 100644 --- a/lib/match.c +++ b/lib/match.c @@ -200,6 +200,21 @@ match_set_reg_masked(struct match *match, unsigned int reg_idx, match->flow.regs[reg_idx] = value & mask; } +void +match_set_xreg(struct match *match, unsigned int xreg_idx, uint64_t value) +{ + match_set_xreg_masked(match, xreg_idx, value, UINT64_MAX); +} + +void +match_set_xreg_masked(struct match *match, unsigned int xreg_idx, + uint64_t value, uint64_t mask) +{ + ovs_assert(xreg_idx < FLOW_N_XREGS); + flow_wildcards_set_xreg_mask(&match->wc, xreg_idx, mask); + flow_set_xreg(&match->flow, xreg_idx, value & mask); +} + void match_set_metadata(struct match *match, ovs_be64 metadata) { diff --git a/lib/match.h b/lib/match.h index 1246b2029..ce9fb28b7 100644 --- a/lib/match.h +++ b/lib/match.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,9 @@ void match_set_recirc_id_masked(struct match *, uint32_t value, uint32_t mask); void match_set_reg(struct match *, unsigned int reg_idx, uint32_t value); void match_set_reg_masked(struct match *, unsigned int reg_idx, uint32_t value, uint32_t mask); +void match_set_xreg(struct match *, unsigned int xreg_idx, uint64_t value); +void match_set_xreg_masked(struct match *, unsigned int xreg_idx, + uint64_t value, uint64_t mask); void match_set_metadata(struct match *, ovs_be64 metadata); void match_set_metadata_masked(struct match *, ovs_be64 metadata, ovs_be64 mask); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index e980a2a85..b76c11d2c 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -234,6 +234,29 @@ const struct mf_field mf_fields[MFF_N_IDS] = { REGISTER(7), #else #error "Need to update mf_fields[] to match FLOW_N_REGS" +#endif + +#define XREGISTER(IDX) \ + { \ + MFF_XREG##IDX, "xreg" #IDX, NULL, \ + MF_FIELD_SIZES(be64), \ + MFM_FULLY, \ + MFS_HEXADECIMAL, \ + MFP_NONE, \ + true, \ + OXM_OF_PKT_REG(IDX), "OXM_OF_PKT_REG" #IDX, \ + OXM_OF_PKT_REG(IDX), "OXM_OF_PKT_REG" #IDX, OFP15_VERSION, \ + OFPUTIL_P_NXM_OXM_ANY, \ + OFPUTIL_P_NXM_OXM_ANY, \ + -1, \ + } +#if FLOW_N_XREGS == 4 + XREGISTER(0), + XREGISTER(1), + XREGISTER(2), + XREGISTER(3), +#else +#error "Need to update mf_fields[] to match FLOW_N_XREGS" #endif /* ## -- ## */ @@ -922,6 +945,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) return !wc->masks.pkt_mark; CASE_MFF_REGS: return !wc->masks.regs[mf->id - MFF_REG0]; + CASE_MFF_XREGS: + return !flow_get_xreg(&wc->masks, mf->id - MFF_XREG0); case MFF_ETH_SRC: return eth_addr_is_zero(wc->masks.dl_src); @@ -1160,6 +1185,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_SKB_PRIORITY: case MFF_PKT_MARK: CASE_MFF_REGS: + CASE_MFF_XREGS: case MFF_ETH_SRC: case MFF_ETH_DST: case MFF_ETH_TYPE: @@ -1290,6 +1316,10 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, value->be32 = htonl(flow->regs[mf->id - MFF_REG0]); break; + CASE_MFF_XREGS: + value->be64 = htonll(flow_get_xreg(flow, mf->id - MFF_XREG0)); + break; + case MFF_ETH_SRC: memcpy(value->mac, flow->dl_src, ETH_ADDR_LEN); break; @@ -1492,6 +1522,10 @@ mf_set_value(const struct mf_field *mf, match_set_reg(match, mf->id - MFF_REG0, ntohl(value->be32)); break; + CASE_MFF_XREGS: + match_set_xreg(match, mf->id - MFF_XREG0, ntohll(value->be64)); + break; + case MFF_ETH_SRC: match_set_dl_src(match, value->mac); break; @@ -1711,6 +1745,10 @@ mf_set_flow_value(const struct mf_field *mf, flow->regs[mf->id - MFF_REG0] = ntohl(value->be32); break; + CASE_MFF_XREGS: + flow_set_xreg(flow, mf->id - MFF_XREG0, ntohll(value->be64)); + break; + case MFF_ETH_SRC: memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN); break; @@ -1928,6 +1966,10 @@ mf_set_wild(const struct mf_field *mf, struct match *match) match_set_reg_masked(match, mf->id - MFF_REG0, 0, 0); break; + CASE_MFF_XREGS: + match_set_xreg_masked(match, mf->id - MFF_XREG0, 0, 0); + break; + case MFF_ETH_SRC: memset(match->flow.dl_src, 0, ETH_ADDR_LEN); memset(match->wc.masks.dl_src, 0, ETH_ADDR_LEN); @@ -2151,6 +2193,11 @@ mf_set(const struct mf_field *mf, ntohl(value->be32), ntohl(mask->be32)); break; + CASE_MFF_XREGS: + match_set_xreg_masked(match, mf->id - MFF_XREG0, + ntohll(value->be64), ntohll(mask->be64)); + break; + case MFF_PKT_MARK: match_set_pkt_mark_masked(match, ntohl(value->be32), ntohl(mask->be32)); diff --git a/lib/meta-flow.h b/lib/meta-flow.h index 155ae3489..0af3888e3 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -58,6 +58,15 @@ enum OVS_PACKED_ENUM mf_field_id { MFF_REG7, /* be32 */ #else #error "Need to update MFF_REG* to match FLOW_N_REGS" +#endif + +#if FLOW_N_XREGS == 4 + MFF_XREG0, /* be32 */ + MFF_XREG1, /* be32 */ + MFF_XREG2, /* be32 */ + MFF_XREG3, /* be32 */ +#else +#error "Need to update MFF_REG* to match FLOW_N_XREGS" #endif /* L2. */ @@ -141,7 +150,7 @@ struct mf_bitmap { #define MF_BITMAP_INITIALIZER { { [0] = 0 } } /* Use this macro as CASE_MFF_REGS: in a switch statement to choose all of the - * MFF_REGx cases. */ + * MFF_REGn cases. */ #if FLOW_N_REGS == 8 #define CASE_MFF_REGS \ case MFF_REG0: case MFF_REG1: case MFF_REG2: case MFF_REG3: \ @@ -150,6 +159,15 @@ struct mf_bitmap { #error "Need to update CASE_MFF_REGS to match FLOW_N_REGS" #endif +/* Use this macro as CASE_MFF_XREGS: in a switch statement to choose all of the + * MFF_REGn cases. */ +#if FLOW_N_XREGS == 4 +#define CASE_MFF_XREGS \ + case MFF_XREG0: case MFF_XREG1: case MFF_XREG2: case MFF_XREG3 +#else +#error "Need to update CASE_MFF_XREGS to match FLOW_N_XREGS" +#endif + /* Prerequisites for matching a field. * * A field may only be matched if the correct lower-level protocols are also diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index a093e85f1..6e828372b 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -35,6 +35,14 @@ for test_case in \ 'reg6=6/1 NXM,OXM' \ 'reg7=7 NXM,OXM' \ 'reg7=7/1 NXM,OXM' \ + 'xreg0=0 NXM,OXM' \ + 'xreg0=0/1 NXM,OXM' \ + 'xreg1=1 NXM,OXM' \ + 'xreg1=1/1 NXM,OXM' \ + 'xreg2=2 NXM,OXM' \ + 'xreg2=2/3 NXM,OXM' \ + 'xreg3=3 NXM,OXM' \ + 'xreg3=3/5 NXM,OXM' \ 'dl_src=00:11:22:33:44:55 any' \ 'dl_src=00:11:22:33:44:55/00:ff:ff:ff:ff:ff NXM,OXM,OpenFlow11' \ 'dl_dst=00:11:22:33:44:55 any' \ diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 63f4feed9..53b341109 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1084,7 +1084,22 @@ indicates that the corresponding bit in \fIvalue\fR must match exactly, and a 0-bit wildcards that bit. .IP When a packet enters an OpenFlow switch, all of the registers are set -to 0. Only explicit Nicira extension actions change register values. +to 0. Only explicit actions change register values. +. +.IP "\fBxreg\fIidx\fB=\fIvalue\fR[\fB/\fImask\fR]" +Matches \fIvalue\fR either exactly or with optional \fImask\fR in +64-bit ``extended register'' number \fIidx\fR. Each of the 64-bit +extended registers overlays two of the 32-bit registers: \fBxreg0\fR +overlays \fBreg0\fR and \fBreg1\fR, with \fBreg0\fR supplying the +most-significant bits of \fBxreg0\fR and \fBreg1\fR the +least-significant. f\fBxreg1\fR similarly overlays \fBreg2\fR and +\fBreg3\fR, and so on. +.IP +These fields were added in Open vSwitch 2.3 to conform with the +OpenFlow 1.5 (draft) specification. OpenFlow 1.5 calls these fields +just the ``packet registers,'' but Open vSwitch already had 32-bit +registers by that name, which is why Open vSwitch refers to the +standard registers as ``extended registers''. . .IP \fBpkt_mark=\fIvalue\fR[\fB/\fImask\fR] Matches packet metadata mark \fIvalue\fR either exactly or with optional