Skip to content

Commit

Permalink
flow: Support OF1.5+ (draft) actset_output field.
Browse files Browse the repository at this point in the history
This field allows a flow table to match on the output port currently in the
action set.

ONF-JIRA: EXT-233
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Jarno Rajahalme <[email protected]>
  • Loading branch information
blp committed Nov 4, 2014
1 parent e6556fe commit c61f387
Show file tree
Hide file tree
Showing 17 changed files with 209 additions and 31 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Post-v2.3.0
release. See ovs-vswitchd(8) for details.
- OpenFlow:
* OpenFlow 1.5 (draft) extended registers are now supported.
* The OpenFlow 1.5 (draft) actset_output field is now supported.
* OpenFlow 1.5 (draft) Copy-Field action is now supported.
* OpenFlow 1.5 (draft) masked Set-Field action is now supported.
* OpenFlow 1.3+ table features requests are now supported (read-only).
Expand Down
1 change: 1 addition & 0 deletions build-aux/extract-ofp-fields
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ OXM_CLASSES = {"NXM_OF_": (0, 0x0000),
"NXM_NX_": (0, 0x0001),
"OXM_OF_": (0, 0x8000),
"OXM_OF_PKT_REG": (0, 0x8001),
"ONFOXM_ET_": (0x4f4e4600, 0xffff),

# This is the experimenter OXM class for Nicira, which is the
# one that OVS would be using instead of NXM_OF_ and NXM_NX_
Expand Down
7 changes: 4 additions & 3 deletions include/openflow/openflow-1.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
* --------------- --------------------------------------
* 0x0000 not assigned a meaning by OpenFlow 1.0
* 0x0001...0xfeff "physical" ports
* 0xff00...0xfff7 "reserved" but not assigned a meaning by OpenFlow 1.0
* 0xfff8...0xffff "reserved" OFPP_* ports with assigned meanings
* 0xff00...0xfff6 "reserved" but not assigned a meaning by OpenFlow 1.x
* 0xfff7...0xffff "reserved" OFPP_* ports with assigned meanings
*/

/* Ranges. */
#define OFPP_MAX OFP_PORT_C(0xff00) /* Max # of switch ports. */
#define OFPP_FIRST_RESV OFP_PORT_C(0xfff8) /* First assigned reserved port. */
#define OFPP_FIRST_RESV OFP_PORT_C(0xfff7) /* First assigned reserved port. */
#define OFPP_LAST_RESV OFP_PORT_C(0xffff) /* Last assigned reserved port. */

/* Reserved output "ports". */
#define OFPP_UNSET OFP_PORT_C(0xfff7) /* For OXM_OF_ACTSET_OUTPUT only. */
#define OFPP_IN_PORT OFP_PORT_C(0xfff8) /* Where the packet came in. */
#define OFPP_TABLE OFP_PORT_C(0xfff9) /* Perform actions in flow table. */
#define OFPP_NORMAL OFP_PORT_C(0xfffa) /* Process with normal L2/L3. */
Expand Down
19 changes: 11 additions & 8 deletions lib/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ BUILD_ASSERT_DECL(offsetof(struct flow, nw_frag) + 3

/* TCP flags in the first half of a BE32, zeroes in the other half. */
BUILD_ASSERT_DECL(offsetof(struct flow, tcp_flags) + 2
== offsetof(struct flow, pad) &&
== offsetof(struct flow, pad2) &&
offsetof(struct flow, tcp_flags) / 4
== offsetof(struct flow, pad) / 4);
== offsetof(struct flow, pad2) / 4);
#if WORDS_BIGENDIAN
#define TCP_FLAGS_BE32(tcp_ctl) ((OVS_FORCE ovs_be32)TCP_FLAGS_BE16(tcp_ctl) \
<< 16)
Expand Down Expand Up @@ -121,7 +121,7 @@ struct mf_ctx {
* away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are
* defined as macros. */

#if (FLOW_WC_SEQ != 27)
#if (FLOW_WC_SEQ != 28)
#define MINIFLOW_ASSERT(X) ovs_assert(X)
BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime "
"assertions enabled. Consider updating FLOW_WC_SEQ after "
Expand Down Expand Up @@ -668,7 +668,7 @@ flow_unwildcard_tp_ports(const struct flow *flow, struct flow_wildcards *wc)
void
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

fmd->dp_hash = flow->dp_hash;
fmd->recirc_id = flow->recirc_id;
Expand Down Expand Up @@ -815,7 +815,7 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
memset(&wc->masks, 0x0, sizeof wc->masks);

/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

if (flow->tunnel.ip_dst) {
if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
Expand All @@ -840,6 +840,8 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, dp_hash);
WC_MASK_FIELD(wc, in_port);

/* actset_output wildcarded. */

WC_MASK_FIELD(wc, dl_dst);
WC_MASK_FIELD(wc, dl_src);
WC_MASK_FIELD(wc, dl_type);
Expand Down Expand Up @@ -910,7 +912,7 @@ uint64_t
flow_wc_map(const struct flow *flow)
{
/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

uint64_t map = (flow->tunnel.ip_dst) ? MINIFLOW_MAP(tunnel) : 0;

Expand Down Expand Up @@ -962,10 +964,11 @@ void
flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc)
{
/* Update this function whenever struct flow changes. */
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata);
memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
wc->masks.actset_output = 0;
}

/* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or
Expand Down Expand Up @@ -1519,7 +1522,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type,
flow->mpls_lse[0] = set_mpls_lse_values(ttl, tc, 1, htonl(label));

/* Clear all L3 and L4 fields. */
BUILD_ASSERT(FLOW_WC_SEQ == 27);
BUILD_ASSERT(FLOW_WC_SEQ == 28);
memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0,
sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT);
}
Expand Down
11 changes: 7 additions & 4 deletions lib/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct pkt_metadata;
/* 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 27
#define FLOW_WC_SEQ 28

/* Number of Open vSwitch extension 32-bit registers. */
#define FLOW_N_REGS 8
Expand Down Expand Up @@ -102,6 +102,8 @@ struct flow {
uint32_t pkt_mark; /* Packet mark. */
uint32_t recirc_id; /* Must be exact match. */
union flow_in_port in_port; /* Input port.*/
ofp_port_t actset_output; /* Output port in action set. */
ovs_be16 pad1; /* Pad to 32 bits. */

/* L2, Order the same as in the Ethernet header! */
uint8_t dl_dst[ETH_ADDR_LEN]; /* Ethernet destination address. */
Expand All @@ -124,7 +126,7 @@ struct flow {
uint8_t arp_tha[ETH_ADDR_LEN]; /* ARP/ND target hardware address. */
struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */
ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
ovs_be16 pad; /* Padding. */
ovs_be16 pad2; /* Pad to 32 bits. */

/* L4 */
ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */
Expand All @@ -144,6 +146,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
#define FLOW_MAX_PACKET_U32S (FLOW_U32S \
/* Unused in datapath */ - FLOW_U32_SIZE(regs) \
- FLOW_U32_SIZE(metadata) \
- FLOW_U32_SIZE(actset_output) \
/* L2.5/3 */ - FLOW_U32_SIZE(nw_src) \
- FLOW_U32_SIZE(nw_dst) \
- FLOW_U32_SIZE(mpls_lse) \
Expand All @@ -153,8 +156,8 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);

/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(offsetof(struct flow, dp_hash) + sizeof(uint32_t)
== sizeof(struct flow_tnl) + 176
&& FLOW_WC_SEQ == 27);
== sizeof(struct flow_tnl) + 180
&& FLOW_WC_SEQ == 28);

/* Incremental points at which flow classification may be performed in
* segments.
Expand Down
15 changes: 14 additions & 1 deletion lib/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ match_set_xreg_masked(struct match *match, unsigned int xreg_idx,
flow_set_xreg(&match->flow, xreg_idx, 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);
match->flow.actset_output = actset_output;
}

void
match_set_metadata(struct match *match, ovs_be64 metadata)
{
Expand Down Expand Up @@ -863,7 +870,7 @@ match_format(const struct match *match, struct ds *s, int priority)

int i;

BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

if (priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%d,", priority);
Expand All @@ -885,6 +892,12 @@ match_format(const struct match *match, struct ds *s, int priority)
ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority);
}

if (wc->masks.actset_output) {
ds_put_cstr(s, "actset_output=");
ofputil_format_port(f->actset_output, s);
ds_put_char(s, ',');
}

if (wc->masks.dl_type) {
skip_type = true;
if (f->dl_type == htons(ETH_TYPE_IP)) {
Expand Down
1 change: 1 addition & 0 deletions lib/match.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ void match_set_reg_masked(struct match *, unsigned int reg_idx,
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_actset_output(struct match *, ofp_port_t actset_output);
void match_set_metadata(struct match *, ovs_be64 metadata);
void match_set_metadata_masked(struct match *,
ovs_be64 metadata, ovs_be64 mask);
Expand Down
29 changes: 23 additions & 6 deletions lib/meta-flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ 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_ACTSET_OUTPUT:
return !wc->masks.actset_output;

case MFF_ETH_SRC:
return eth_addr_is_zero(wc->masks.dl_src);
Expand Down Expand Up @@ -397,7 +399,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
case MFF_ND_TLL:
return true;

case MFF_IN_PORT_OXM: {
case MFF_IN_PORT_OXM:
case MFF_ACTSET_OUTPUT: {
ofp_port_t port;
return !ofputil_port_from_ofp11(value->be32, &port);
}
Expand Down Expand Up @@ -485,6 +488,9 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
case MFF_IN_PORT_OXM:
value->be32 = ofputil_port_to_ofp11(flow->in_port.ofp_port);
break;
case MFF_ACTSET_OUTPUT:
value->be32 = ofputil_port_to_ofp11(flow->actset_output);
break;

case MFF_SKB_PRIORITY:
value->be32 = htonl(flow->skb_priority);
Expand Down Expand Up @@ -691,6 +697,12 @@ mf_set_value(const struct mf_field *mf,
match_set_in_port(match, port);
break;
}
case MFF_ACTSET_OUTPUT: {
ofp_port_t port;
ofputil_port_from_ofp11(value->be32, &port);
match_set_actset_output(match, port);
break;
}

case MFF_SKB_PRIORITY:
match_set_skb_priority(match, ntohl(value->be32));
Expand Down Expand Up @@ -908,12 +920,12 @@ mf_set_flow_value(const struct mf_field *mf,
flow->in_port.ofp_port = u16_to_ofp(ntohs(value->be16));
break;

case MFF_IN_PORT_OXM: {
ofp_port_t port;
ofputil_port_from_ofp11(value->be32, &port);
flow->in_port.ofp_port = port;
case MFF_IN_PORT_OXM:
ofputil_port_from_ofp11(value->be32, &flow->in_port.ofp_port);
break;
case MFF_ACTSET_OUTPUT:
ofputil_port_from_ofp11(value->be32, &flow->actset_output);
break;
}

case MFF_SKB_PRIORITY:
flow->skb_priority = ntohl(value->be32);
Expand Down Expand Up @@ -1163,6 +1175,10 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
match->flow.in_port.ofp_port = 0;
match->wc.masks.in_port.ofp_port = 0;
break;
case MFF_ACTSET_OUTPUT:
match->flow.actset_output = 0;
match->wc.masks.actset_output = 0;
break;

case MFF_SKB_PRIORITY:
match->flow.skb_priority = 0;
Expand Down Expand Up @@ -1354,6 +1370,7 @@ mf_set(const struct mf_field *mf,
case MFF_RECIRC_ID:
case MFF_IN_PORT:
case MFF_IN_PORT_OXM:
case MFF_ACTSET_OUTPUT:
case MFF_SKB_PRIORITY:
case MFF_ETH_TYPE:
case MFF_DL_VLAN:
Expand Down
13 changes: 13 additions & 0 deletions lib/meta-flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,19 @@ enum OVS_PACKED_ENUM mf_field_id {
*/
MFF_IN_PORT_OXM,

/* "actset_output".
*
* Type: be32.
* Maskable: no.
* Formatting: OpenFlow 1.1+ port.
* Prerequisites: none.
* Access: read-only.
* NXM: none.
* OXM: ONFOXM_ET_ACTSET_OUTPUT(43) since OF1.3 and v2.4,
* OXM_OF_ACTSET_OUTPUT(43) since OF1.5 and v2.4.
*/
MFF_ACTSET_OUTPUT,

/* "skb_priority".
*
* Designates the queue to which output will be directed. The value in
Expand Down
6 changes: 5 additions & 1 deletion lib/nx-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
int match_len;
int i;

BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

/* Metadata. */
if (match->wc.masks.dp_hash) {
Expand All @@ -839,6 +839,10 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
htons(ofp_to_u16(in_port)));
}
}
if (match->wc.masks.actset_output) {
nxm_put_32(b, MFF_ACTSET_OUTPUT, oxm,
ofputil_port_to_ofp11(flow->actset_output));
}

/* Ethernet. */
nxm_put_eth_masked(b, MFF_ETH_SRC, oxm,
Expand Down
2 changes: 1 addition & 1 deletion lib/odp-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void odp_portno_names_destroy(struct hmap *portno_names);
* add another field and forget to adjust this value.
*/
#define ODPUTIL_FLOW_KEY_BYTES 512
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

/* A buffer with sufficient size and alignment to hold an nlattr-formatted flow
* key. An array of "struct nlattr" might not, in theory, be sufficiently
Expand Down
5 changes: 3 additions & 2 deletions lib/ofp-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 28);

/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
Expand Down Expand Up @@ -6020,7 +6020,8 @@ ofputil_port_to_ofp11(ofp_port_t ofp10_port)
OFPUTIL_NAMED_PORT(ALL) \
OFPUTIL_NAMED_PORT(CONTROLLER) \
OFPUTIL_NAMED_PORT(LOCAL) \
OFPUTIL_NAMED_PORT(ANY)
OFPUTIL_NAMED_PORT(ANY) \
OFPUTIL_NAMED_PORT(UNSET)

/* For backwards compatibility, so that "none" is recognized as OFPP_ANY */
#define OFPUTIL_NAMED_PORTS_WITH_NONE \
Expand Down
Loading

0 comments on commit c61f387

Please sign in to comment.