#include "ofp-errors.h"
#include "ofp-util.h"
#include "packets.h"
+#include "util.h"
struct ds;
struct match;
/* The comment on each of these indicates the member in "union mf_value" used
* to represent its value. */
-enum mf_field_id {
+enum OVS_PACKED_ENUM mf_field_id {
/* Metadata. */
+ MFF_DP_HASH, /* be32 */
+ MFF_RECIRC_ID, /* be32 */
MFF_TUN_ID, /* be64 */
MFF_TUN_SRC, /* be32 */
MFF_TUN_DST, /* be32 */
MFF_MPLS_BOS, /* u8 */
/* L3. */
+ /* Update mf_is_l3_or_higher() if MFF_IPV4_SRC is
+ * no longer the first element for a field of layer 3 or higher */
MFF_IPV4_SRC, /* be32 */
MFF_IPV4_DST, /* be32 */
/* L4. */
MFF_TCP_SRC, /* be16 (used for IPv4 or IPv6) */
MFF_TCP_DST, /* be16 (used for IPv4 or IPv6) */
+ MFF_TCP_FLAGS, /* be16, 12 bits (4 MSB zeroed,
+ * used for IPv4 or IPv6) */
MFF_UDP_SRC, /* be16 (used for IPv4 or IPv6) */
MFF_UDP_DST, /* be16 (used for IPv4 or IPv6) */
* A field may only be matched if the correct lower-level protocols are also
* matched. For example, the TCP port may be matched only if the Ethernet type
* matches ETH_TYPE_IP and the IP protocol matches IPPROTO_TCP. */
-enum mf_prereqs {
+enum OVS_PACKED_ENUM mf_prereqs {
MFP_NONE,
/* L2 requirements. */
/* Forms of partial-field masking allowed for a field.
*
* Every field may be masked as a whole. */
-enum mf_maskable {
+enum OVS_PACKED_ENUM mf_maskable {
MFM_NONE, /* No sub-field masking. */
MFM_FULLY, /* Every bit is individually maskable. */
};
/* How to format or parse a field's value. */
-enum mf_string {
+enum OVS_PACKED_ENUM mf_string {
/* Integer formats.
*
* The particular MFS_* constant sets the output format. On input, either
MFS_OFP_PORT_OXM, /* An OpenFlow port number or name (32-bit). */
MFS_FRAG, /* no, yes, first, later, not_later */
MFS_TNL_FLAGS, /* FLOW_TNL_F_* flags */
+ MFS_TCP_FLAGS, /* TCP_* flags */
};
struct mf_field {
*
* - NXM and OXM both define such a field: nxm_header and oxm_header will
* both be nonzero and different, similarly for nxm_name and oxm_name.
+ * In this case, 'oxm_version' is significant: if it is greater than
+ * OFP12_VERSION, then only that version of OpenFlow introduced this
+ * OXM header, so ovs-vswitchd should send 'nxm_header' instead with
+ * earlier protocol versions to avoid confusing controllers that were
+ * using a previous Open vSwitch extension.
*
* - Only NXM or only OXM defines such a field: nxm_header and oxm_header
* will both have the same value (either an OXM_* or NXM_* value) and
* NXM formatted match, since it will be an NXM_* constant when possible
* for compatibility with OpenFlow implementations that expect that, with
* OXM_* constants used for fields that OXM adds. Conversely, 'oxm_header'
- * is the header to use when outputting an OXM formatted match. */
+ * is the header to use when outputting an OXM formatted match to an
+ * OpenFlow connection of version 'oxm_version' or above (and otherwise
+ * 'nxm_header'). */
uint32_t nxm_header; /* An NXM_* (or OXM_*) constant. */
const char *nxm_name; /* The nxm_header constant's name. */
uint32_t oxm_header; /* An OXM_* (or NXM_*) constant. */
const char *oxm_name; /* The oxm_header constant's name */
+ enum ofp_version oxm_version; /* OpenFlow version that added oxm_header. */
/* Usable protocols.
* NXM and OXM are extensible, allowing later extensions to be sent in
enum ofputil_protocol usable_protocols; /* If fully/cidr masked. */
/* If partially/non-cidr masked. */
enum ofputil_protocol usable_protocols_bitwise;
+
+ int flow_be32ofs; /* Field's be32 offset in "struct flow", if prefix tree
+ * lookup is supported for the field, or -1. */
};
/* The representation of a field's value. */
BUILD_ASSERT_DECL(sizeof(union mf_value) == sizeof (union mf_subvalue));
/* Finding mf_fields. */
-const struct mf_field *mf_from_id(enum mf_field_id);
const struct mf_field *mf_from_name(const char *name);
const struct mf_field *mf_from_nxm_header(uint32_t nxm_header);
const struct mf_field *mf_from_nxm_name(const char *nxm_name);
+static inline const struct mf_field *
+mf_from_id(enum mf_field_id id)
+{
+ extern const struct mf_field mf_fields[MFF_N_IDS];
+ ovs_assert((unsigned int) id < MFF_N_IDS);
+ return &mf_fields[id];
+}
+
+/* NXM and OXM protocol headers. */
+uint32_t mf_oxm_header(enum mf_field_id, enum ofp_version oxm_version);
+
/* Inspecting wildcarded bits. */
bool mf_is_all_wild(const struct mf_field *, const struct flow_wildcards *);
bool mf_are_prereqs_ok(const struct mf_field *, const struct flow *);
void mf_mask_field_and_prereqs(const struct mf_field *, struct flow *mask);
+static inline bool
+mf_is_l3_or_higher(const struct mf_field *mf)
+{
+ return mf->id >= MFF_IPV4_SRC;
+}
+
/* Field values. */
bool mf_is_value_valid(const struct mf_field *, const union mf_value *value);
void mf_set_flow_value(const struct mf_field *, const union mf_value *value,
struct flow *);
bool mf_is_zero(const struct mf_field *, const struct flow *);
+void mf_mask_field(const struct mf_field *, struct flow *);
void mf_get(const struct mf_field *, const struct match *,
union mf_value *value, union mf_value *mask);
void mf_set_wild(const struct mf_field *, struct match *);
-void mf_random_value(const struct mf_field *, union mf_value *value);
-
/* Subfields. */
void mf_write_subfield_flow(const struct mf_subfield *,
const union mf_subvalue *, struct flow *);