+/* 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 24
+
+#define FLOW_N_REGS 8
+BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
+
+/* 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
+
+/* Fragment bits, used for IPv4 and IPv6, always zero for non-IP flows. */
+#define FLOW_NW_FRAG_ANY (1 << 0) /* Set for any IP frag. */
+#define FLOW_NW_FRAG_LATER (1 << 1) /* Set for IP frag with nonzero offset. */
+#define FLOW_NW_FRAG_MASK (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER)
+
+BUILD_ASSERT_DECL(FLOW_NW_FRAG_ANY == NX_IP_FRAG_ANY);
+BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER);
+
+#define FLOW_TNL_F_DONT_FRAGMENT (1 << 0)
+#define FLOW_TNL_F_CSUM (1 << 1)
+#define FLOW_TNL_F_KEY (1 << 2)
+
+const char *flow_tun_flag_to_string(uint32_t flags);
+
+struct flow_tnl {
+ ovs_be64 tun_id;
+ ovs_be32 ip_src;
+ ovs_be32 ip_dst;
+ uint16_t flags;
+ uint8_t ip_tos;
+ uint8_t ip_ttl;
+};
+
+/* Unfortunately, a "struct flow" sometimes has to handle OpenFlow port
+ * numbers and other times datapath (dpif) port numbers. This union allows
+ * access to both. */
+union flow_in_port {
+ ofp_port_t ofp_port;
+ odp_port_t odp_port;
+};
+
+/* Maximum number of supported MPLS labels. */
+#define FLOW_MAX_MPLS_LABELS 3
+
+/*
+ * A flow in the network.
+ *
+ * Must be initialized to all zeros to make any compiler-induced padding
+ * zeroed. Helps also in keeping unused fields (such as mutually exclusive
+ * IPv4 and IPv6 addresses) zeroed out.
+ *
+ * The meaning of 'in_port' is context-dependent. In most cases, it is a
+ * 16-bit OpenFlow 1.0 port number. In the software datapath interface (dpif)
+ * layer and its implementations (e.g. dpif-linux, dpif-netdev), it is instead
+ * a 32-bit datapath port number.
+ *
+ * The fields are organized in four segments to facilitate staged lookup, where
+ * lower layer fields are first used to determine if the later fields need to
+ * be looked at. This enables better wildcarding for datapath flows.
+ */
+struct flow {
+ /* L1 */
+ struct flow_tnl tunnel; /* Encapsulating tunnel parameters. */
+ ovs_be64 metadata; /* OpenFlow Metadata. */
+ uint32_t regs[FLOW_N_REGS]; /* Registers. */
+ uint32_t skb_priority; /* Packet priority for QoS. */
+ uint32_t pkt_mark; /* Packet mark. */
+ union flow_in_port in_port; /* Input port.*/
+
+ /* L2 */
+ uint8_t dl_src[6]; /* Ethernet source address. */
+ uint8_t dl_dst[6]; /* Ethernet destination address. */
+ ovs_be16 dl_type; /* Ethernet frame type. */
+ ovs_be16 vlan_tci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
+ ovs_be32 mpls_lse[FLOW_MAX_MPLS_LABELS]; /* MPLS label stack entry. */
+
+ /* L3 */
+ struct in6_addr ipv6_src; /* IPv6 source address. */
+ struct in6_addr ipv6_dst; /* IPv6 destination address. */
+ struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */
+ ovs_be32 ipv6_label; /* IPv6 flow label. */
+ ovs_be32 nw_src; /* IPv4 source address. */
+ ovs_be32 nw_dst; /* IPv4 destination address. */
+ uint8_t nw_frag; /* FLOW_FRAG_* flags. */
+ uint8_t nw_tos; /* IP ToS (including DSCP and ECN). */
+ uint8_t nw_ttl; /* IP TTL/Hop Limit. */
+ uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */
+ uint8_t arp_sha[6]; /* ARP/ND source hardware address. */
+ uint8_t arp_tha[6]; /* ARP/ND target hardware address. */
+ ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
+ ovs_be16 pad; /* Padding. */
+
+ /* L4 */
+ ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */
+ ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port.
+ * Keep last for the BUILD_ASSERT_DECL below */
+};
+BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
+
+#define FLOW_U32S (sizeof(struct flow) / 4)
+
+/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
+BUILD_ASSERT_DECL(offsetof(struct flow, tp_dst) + 2
+ == sizeof(struct flow_tnl) + 164
+ && FLOW_WC_SEQ == 24);
+
+/* Incremental points at which flow classification may be performed in
+ * segments.
+ * This is located here since this is dependent on the structure of the
+ * struct flow defined above:
+ * Each offset must be on a distint, successive U32 boundary srtictly
+ * within the struct flow. */
+enum {
+ FLOW_SEGMENT_1_ENDS_AT = offsetof(struct flow, dl_src),
+ FLOW_SEGMENT_2_ENDS_AT = offsetof(struct flow, ipv6_src),
+ FLOW_SEGMENT_3_ENDS_AT = offsetof(struct flow, tp_src),
+};
+BUILD_ASSERT_DECL(FLOW_SEGMENT_1_ENDS_AT % 4 == 0);
+BUILD_ASSERT_DECL(FLOW_SEGMENT_2_ENDS_AT % 4 == 0);
+BUILD_ASSERT_DECL(FLOW_SEGMENT_3_ENDS_AT % 4 == 0);
+BUILD_ASSERT_DECL( 0 < FLOW_SEGMENT_1_ENDS_AT);
+BUILD_ASSERT_DECL(FLOW_SEGMENT_1_ENDS_AT < FLOW_SEGMENT_2_ENDS_AT);
+BUILD_ASSERT_DECL(FLOW_SEGMENT_2_ENDS_AT < FLOW_SEGMENT_3_ENDS_AT);
+BUILD_ASSERT_DECL(FLOW_SEGMENT_3_ENDS_AT < sizeof(struct flow));
+
+extern const uint8_t flow_segment_u32s[];
+
+/* Represents the metadata fields of struct flow. */
+struct flow_metadata {
+ ovs_be64 tun_id; /* Encapsulating tunnel ID. */
+ ovs_be32 tun_src; /* Tunnel outer IPv4 src addr */
+ ovs_be32 tun_dst; /* Tunnel outer IPv4 dst addr */
+ ovs_be64 metadata; /* OpenFlow 1.1+ metadata field. */
+ uint32_t regs[FLOW_N_REGS]; /* Registers. */
+ uint32_t pkt_mark; /* Packet mark. */
+ ofp_port_t in_port; /* OpenFlow port or zero. */
+};
+
+void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark,
+ const struct flow_tnl *, const union flow_in_port *in_port,
+ struct flow *);
+
+void flow_zero_wildcards(struct flow *, const struct flow_wildcards *);
+void flow_unwildcard_tp_ports(const struct flow *, struct flow_wildcards *);
+void flow_get_metadata(const struct flow *, struct flow_metadata *);
+
+char *flow_to_string(const struct flow *);
+void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
+ uint32_t flags, char del);
+void format_flags_masked(struct ds *ds, const char *name,
+ const char *(*bit_to_string)(uint32_t),
+ uint32_t flags, uint32_t mask);
+
+void flow_format(struct ds *, const struct flow *);
+void flow_print(FILE *, const struct flow *);
+static inline int flow_compare_3way(const struct flow *, const struct flow *);
+static inline bool flow_equal(const struct flow *, const struct flow *);
+static inline size_t flow_hash(const struct flow *, uint32_t basis);
+
+void flow_set_dl_vlan(struct flow *, ovs_be16 vid);
+void flow_set_vlan_vid(struct flow *, ovs_be16 vid);
+void flow_set_vlan_pcp(struct flow *, uint8_t pcp);
+
+int flow_count_mpls_labels(const struct flow *, struct flow_wildcards *);
+int flow_count_common_mpls_labels(const struct flow *a, int an,
+ const struct flow *b, int bn,
+ struct flow_wildcards *wc);
+void flow_push_mpls(struct flow *, int n, ovs_be16 mpls_eth_type,
+ struct flow_wildcards *);
+bool flow_pop_mpls(struct flow *, int n, ovs_be16 eth_type,
+ struct flow_wildcards *);
+void flow_set_mpls_label(struct flow *, int idx, ovs_be32 label);
+void flow_set_mpls_ttl(struct flow *, int idx, uint8_t ttl);
+void flow_set_mpls_tc(struct flow *, int idx, uint8_t tc);
+void flow_set_mpls_bos(struct flow *, int idx, uint8_t stack);
+void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse);
+
+void flow_compose(struct ofpbuf *, const struct flow *);